diff --git a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md index 89421da2d..be6c6f848 100644 --- a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md +++ b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md @@ -95,7 +95,7 @@ Example: >| Variable | Description | Notes | >|----------|-------------|-------| >| `APP` | Application name | Must match ct\AppName.sh | ->| `TAGS` | Proxmox display tags without Spaces, only ; | Limit the number | +>| `var_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 | @@ -193,13 +193,13 @@ wget -q unzip -q ``` -- If a command does not come with this functionality use `&>/dev/null` to suppress it's output. +- If a command does not come with this functionality use `$STD` to suppress it's output. Example: ```bash -php artisan migrate --force &>/dev/null -php artisan config:clear &>/dev/null +$STD php artisan migrate --force +$STD php artisan config:clear ``` ### 3.5 **Backups** @@ -247,7 +247,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no automatic update function for ${APP}." + msg_error "Currently we don't provide an update function for this ${APP}." exit } ``` diff --git a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh index ff8d03c27..b61262bb1 100644 --- a/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh +++ b/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh @@ -8,7 +8,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m # App Default Values APP="[APP_NAME]" # Name of the app (e.g. Google, Adventurelog, Apache-Guacamole" -TAGS="[TAGS]" +var_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 diff --git a/.github/autolabeler-config.json b/.github/autolabeler-config.json index 399004ee1..5406bdaa4 100644 --- a/.github/autolabeler-config.json +++ b/.github/autolabeler-config.json @@ -1,17 +1,5 @@ { - "breaking change": [ - { - "fileStatus": "renamed", - "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"], - "excludeGlobs": [] - }, - { - "fileStatus": "removed", - "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"], - "excludeGlobs": [] - } - ], "new script": [ { "fileStatus": "added", @@ -33,10 +21,17 @@ "excludeGlobs": [] } ], - "rename script": [ + "maintenance": [ { - "fileStatus": "renamed", - "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"], + "fileStatus": null, + "includeGlobs": ["*.md", ".github/**", "misc/*.func", "ct/create_lxc.sh", "api/**"], + "excludeGlobs": [] + } + ], + "core": [ + { + "fileStatus": null, + "includeGlobs": ["misc/*.func", "ct/create_lxc.sh"], "excludeGlobs": [] } ], @@ -47,20 +42,28 @@ "excludeGlobs": [] } ], - "maintenance": [ - { - "fileStatus": null, - "includeGlobs": ["*.md", ".github/**", "misc/*.func", "ct/create_lxc.sh"], - "excludeGlobs": ["misc/api.func"] - } - ], - "api": [ + "api": [ { "fileStatus": null, "includeGlobs": ["api/**", "misc/api.func"], "excludeGlobs": [] } ], + "github": [ + { + "fileStatus": null, + "includeGlobs": [".github/**"], + "excludeGlobs": [] + } + ], + "json": [ + { + "fileStatus": "modified", + "includeGlobs": ["json/**"], + "excludeGlobs": [] + } + ], + "high risk": [ { "fileStatus": null, @@ -68,4 +71,6 @@ "excludeGlobs": [] } ] -} + + +} \ No newline at end of file diff --git a/.github/changelog-pr-config.json b/.github/changelog-pr-config.json index 8168251b6..2c62aa3f0 100644 --- a/.github/changelog-pr-config.json +++ b/.github/changelog-pr-config.json @@ -1,42 +1,97 @@ [ - { - "title": "πŸ’₯ Breaking Changes", - "labels": ["breaking change"] - }, { "title": "πŸ†• New Scripts", "labels": ["new script"] }, { "title": "πŸš€ Updated Scripts", - "labels": ["update script"] - }, - { - "title": "🐞 Bug Fixes (Updated Scripts)", - "labels": ["update script", "bugfix"] - }, - { - "title": "✨ Feature Updates (Updated Scripts)", - "labels": ["update script", "feature"] - }, - { - "title": "✨ New Features", - "labels": ["feature"] - }, - { - "title": "🌐 Website", - "labels": ["website"] - }, - { - "title": "πŸ“‘ API", - "labels": ["api"] + "labels": ["update script"], + "subCategories": [ + { + "title": "🐞 Bug Fixes", + "labels": ["bugfix"], + "notes" : [] + }, + { + "title": "✨ New Features", + "labels": ["feature"], + "notes" : [] + }, + { + "title": "πŸ’₯ Breaking Changes", + "labels": ["breaking change"], + "notes" : [] + } + ] }, { "title": "🧰 Maintenance", - "labels": ["maintenance"] + "labels": ["maintenance"], + "subCategories": [ + { + "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": "🌐 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"] } ] diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 11a90a774..d669ec78a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,25 +1,25 @@ ## ✍️ Description - ## πŸ”— Related PR / Discussion / Issue + Link: # - - ## βœ… Prerequisites + Before this PR can be reviewed, the following must be completed: + - [] **Self-review performed** – Code follows established patterns and conventions. - [] **Testing performed** – Changes have been thoroughly tested and verified. - ## πŸ› οΈ Type of Change -Select all that apply: -- [] 🐞 **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. +Select all that apply: + +- [] πŸ†• **New script** – A fully functional and tested script or script set. +- [] 🐞 **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. ## πŸ“‹ Additional Information (optional) diff --git a/.github/runner/docker/gh-runner-self.dockerfile b/.github/runner/docker/gh-runner-self.dockerfile new file mode 100644 index 000000000..e5ae072ab --- /dev/null +++ b/.github/runner/docker/gh-runner-self.dockerfile @@ -0,0 +1,68 @@ +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 diff --git a/.github/workflows/auto-update-app-headers.yml b/.github/workflows/auto-update-app-headers.yml index 5e447ea54..b6c4f2b77 100644 --- a/.github/workflows/auto-update-app-headers.yml +++ b/.github/workflows/auto-update-app-headers.yml @@ -10,7 +10,7 @@ on: jobs: update-app-files: - runs-on: ubuntu-latest + runs-on: runner-cluster-htl-set permissions: contents: write diff --git a/.github/workflows/close-discussion.yml b/.github/workflows/close-discussion.yml new file mode 100644 index 000000000..dd9a80b33 --- /dev/null +++ b/.github/workflows/close-discussion.yml @@ -0,0 +1,122 @@ +name: Close Discussion on PR Merge + +on: + pull_request: + types: [closed] + +jobs: + close-discussion: + 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 }} + PR_BODY: ${{ github.event.pull_request.body }} + PR_NUMBER: ${{ github.event.pull_request.number }} + REPO_OWNER: ${{ github.repository_owner }} + REPO_NAME: ${{ github.event.repository.name }} + run: | + npx zx << 'EOF' + import { graphql } from "@octokit/graphql"; + (async function() { + try { + const token = process.env.GITHUB_TOKEN; + const prBody = process.env.PR_BODY; + const prNumber = process.env.PR_NUMBER; + const owner = process.env.REPO_OWNER; + const repo = process.env.REPO_NAME; + + if (!token || !prBody || !prNumber || !owner || !repo) { + console.log("Missing required environment variables."); + process.exit(1); + } + + 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}`); + console.log(`PR Number: ${prNumber}`); + console.log(`Repository: ${owner}/${repo}`); + + const graphqlWithAuth = graphql.defaults({ + headers: { authorization: `Bearer ${token}` }, + }); + + const discussionQuery = ` + query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { + discussion(number: $number) { + id + } + } + } + `; + + 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; + } + + console.log(`GraphQL Discussion ID: ${discussionQLId}`); + + 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}`); + + 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); + return; + } + })(); + EOF \ No newline at end of file diff --git a/.github/workflows/create-docker-for-runner.yml b/.github/workflows/create-docker-for-runner.yml new file mode 100644 index 000000000..c9fef0a5c --- /dev/null +++ b/.github/workflows/create-docker-for-runner.yml @@ -0,0 +1,37 @@ +name: Build and Publish Docker Image + +on: + push: + branches: + - main + paths: + - '.github/runner/docker/**' + schedule: + - cron: '0 0 * * *' + +jobs: + build: + 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 diff --git a/.github/workflows/delete-json-branch.yml b/.github/workflows/delete-json-branch.yml index e4cdcf24f..b72868402 100644 --- a/.github/workflows/delete-json-branch.yml +++ b/.github/workflows/delete-json-branch.yml @@ -9,7 +9,7 @@ on: jobs: delete_branch: - runs-on: ubuntu-latest + runs-on: runner-cluster-htl-set steps: - name: Checkout the code uses: actions/checkout@v3 diff --git a/.github/workflows/frontend-cicd.yml b/.github/workflows/frontend-cicd.yml index dd242f6ef..c4f1a6418 100644 --- a/.github/workflows/frontend-cicd.yml +++ b/.github/workflows/frontend-cicd.yml @@ -27,7 +27,7 @@ concurrency: jobs: build: - runs-on: ubuntu-latest + runs-on: runner-cluster-htl-set defaults: run: working-directory: frontend # Set default working directory for all run steps diff --git a/.github/workflows/script-test.yml b/.github/workflows/script-test.yml index 6b9e100eb..5c8803907 100644 --- a/.github/workflows/script-test.yml +++ b/.github/workflows/script-test.yml @@ -13,7 +13,7 @@ jobs: run-install-script: runs-on: pvenode steps: - - name: Checkout PR branch (supports forks) + - name: Checkout PR branch uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.ref }} @@ -37,7 +37,8 @@ jobs: echo "Changed files: $CHANGED_FILES" echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Get scripts id: check-install-script @@ -61,59 +62,71 @@ jobs: 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 [[ $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 + 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 - 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" + 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 -s 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 - continue - fi - echo "Found install script for $STRIPPED_NAME" - chmod +x "$INSTALL_SCRIPT" - RUNNING_FILE=$FILE - 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 -s 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 + fi + done + set -e # Restore exit-on-error - name: Cleanup PVE Node run: | @@ -125,35 +138,40 @@ jobs: pct stop $container_id pct destroy $container_id fi - done - + done + - name: Post error comments run: | ERROR="false" - SEARCH_LINE=".github/workflows/scripts/app-test/pr-build.func: line 253:" + 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.*||") - echo "Posting error message for $FILE" - echo ${CLEANED_ERROR_MSG} - gh pr comment ${{ github.event.pull_request.number }} \ - --repo ${{ github.repository }} \ - --body ":warning: The script _**$FILE**_ failed with the following message:
${CLEANED_ERROR_MSG}
" - - - ERROR="true" + COMMENT_BODY=":warning: The script _**$FILE**_ failed with the following message:
${CLEANED_ERROR_MSG}
" + + # 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 - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Fail if error - if: ${{ env.ERROR == 'true' }} - run: exit 1 + + diff --git a/.github/workflows/script_format.yml b/.github/workflows/script_format.yml new file mode 100644 index 000000000..a86a512b4 --- /dev/null +++ b/.github/workflows/script_format.yml @@ -0,0 +1,243 @@ +name: Script Format Check +permissions: + pull-requests: write +on: + pull_request_target: + branches: + - main + paths: + - 'install/*.sh' + - 'ct/*.sh' + +jobs: + run-install-script: + 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 -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" ]] && + echo "Line 2 was $SECOND_LINE | Should be: source <(curl -s 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]}'" >> "$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:
${ERROR_MSG}
" + + + 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 diff --git a/.github/workflows/scripts/app-test/pr-alpine-install.func b/.github/workflows/scripts/app-test/pr-alpine-install.func index 39a6a82fb..ae3bc174d 100644 --- a/.github/workflows/scripts/app-test/pr-alpine-install.func +++ b/.github/workflows/scripts/app-test/pr-alpine-install.func @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Copyright (c) 2021-2025 community-scripts ORG -# Author: michelroegl-brunner +# Author: Michel Roegl-Brunner (michelroegl-brunner) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE color() { @@ -11,7 +11,7 @@ catch_errors() { trap 'error_handler $LINENO "$BASH_COMMAND"' ERR } - +# This function handles errors error_handler() { local line_number="$1" local command="$2" @@ -21,8 +21,8 @@ error_handler() { exit 0 } verb_ip6() { - STD="" - return + STD="" + return } msg_info() { @@ -30,13 +30,13 @@ msg_info() { echo -ne "${msg}\n" } -msg_ok() { +msg_ok() { local msg="$1" echo -e "${msg}\n" } msg_error() { - + local msg="$1" echo -e "${msg}\n" } @@ -71,7 +71,7 @@ network_check() { } update_os() { - msg_info "Updating Container OS" + msg_info "Updating Container OS" apk update apk upgrade msg_ok "Updated Container OS" @@ -82,7 +82,5 @@ motd_ssh() { } customize() { - return -} - - + return +} \ No newline at end of file diff --git a/.github/workflows/scripts/app-test/pr-build.func b/.github/workflows/scripts/app-test/pr-build.func index 360c15ede..4ca15d099 100644 --- a/.github/workflows/scripts/app-test/pr-build.func +++ b/.github/workflows/scripts/app-test/pr-build.func @@ -6,12 +6,13 @@ 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 +header_info() { + return } base_settings() { @@ -20,10 +21,10 @@ base_settings() { DISK_SIZE="4" CORE_COUNT="1" RAM_SIZE="1024" - VERBOSE="${1:-no}" + VERBOSE="no" PW="" CT_ID=$NEXTID - HN="Testing" + HN=$NSAPP BRG="vmbr0" NET="dhcp" GATE="" @@ -106,7 +107,7 @@ catch_errors() { } # This function handles errors -error_handler() { +error_handler() { local line_number="$1" local command="$2" SCRIPT_NAME=$(basename "$0") @@ -120,17 +121,17 @@ msg_info() { echo -ne "${msg}\n" } -msg_ok() { +msg_ok() { local msg="$1" echo -e "${msg}\n" } msg_error() { - + local msg="$1" echo -e "${msg}\n" } -start(){ +start() { base_settings return } @@ -146,9 +147,9 @@ build_container() { TEMP_DIR=$(mktemp -d) pushd $TEMP_DIR >/dev/null if [ "$var_os" == "alpine" ]; then - export FUNCTIONS_FILE_PATH="$(cat /root/actions-runner/_work/ProxmoxVE/ProxmoxVE/.github/workflows/scripts/app-test/pr-alpine-install.func)" + 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="$(cat /root/actions-runner/_work/ProxmoxVE/ProxmoxVE/.github/workflows/scripts/app-test/pr-install.func)" + 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" @@ -182,9 +183,8 @@ build_container() { " echo "Container ID: $CTID" - # This executes create_lxc.sh and creates the container and .conf file - bash /root/actions-runner/_work/ProxmoxVE/ProxmoxVE/.github/workflows/scripts/app-test/pr-create-lxc.sh + bash -c "$(wget -qLO - 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 @@ -233,6 +233,7 @@ EOF fi fi fi + # This starts the container and executes -install.sh msg_info "Starting LXC Container" pct start "$CTID" @@ -242,7 +243,7 @@ EOF msg_error "No install script found for $APP" exit 1 fi - if [ "$var_os" == "alpine" ]; then + if [ "$var_os" == "alpine" ]; then sleep 3 pct exec "$CTID" -- /bin/sh -c 'cat </etc/apk/repositories http://dl-cdn.alpinelinux.org/alpine/latest-stable/main @@ -250,11 +251,10 @@ 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)" $var_install.sh + 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) - return -} +description() { + IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1) +} \ No newline at end of file diff --git a/.github/workflows/scripts/app-test/pr-create-lxc.sh b/.github/workflows/scripts/app-test/pr-create-lxc.sh index 6ca899cf4..0bb2a9d2f 100644 --- a/.github/workflows/scripts/app-test/pr-create-lxc.sh +++ b/.github/workflows/scripts/app-test/pr-create-lxc.sh @@ -11,8 +11,9 @@ catch_errors() { trap 'error_handler $LINENO "$BASH_COMMAND"' ERR } +# This function handles errors error_handler() { - local exit_code="$?" + 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" @@ -20,7 +21,7 @@ error_handler() { exit 100 } verb_ip6() { - return + return } msg_info() { @@ -28,18 +29,17 @@ msg_info() { echo -ne "${msg}\n" } -msg_ok() { +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." @@ -64,9 +64,12 @@ function select_storage() { CONTENT='vztmpl' CONTENT_LABEL='Container template' ;; - *) false || { msg_error "Invalid storage class."; exit 201; };; + *) false || { + msg_error "Invalid storage class." + exit 201 + } ;; esac - + # This Queries all storage locations local -a MENU while read -r line; do @@ -80,23 +83,32 @@ function select_storage() { fi MENU+=("$TAG" "$ITEM" "OFF") done < <(pvesm status -content $CONTENT | awk 'NR>1') - + # Select storage location - if [ $((${#MENU[@]}/3)) -eq 1 ]; then + if [ $((${#MENU[@]} / 3)) -eq 1 ]; then printf ${MENU[0]} else - msg_error "STORAGE ISSUES!" - exit 202 + 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 +} -[[ "${CTID:-}" ]] || { msg_error "You need to set 'CTID' variable."; exit 203; } -[[ "${PCT_OSTYPE:-}" ]] || { msg_error "You need to set 'PCT_OSTYPE' variable."; exit 204; } - -[ "$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 @@ -110,10 +122,12 @@ 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; } +[ ${#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" @@ -121,28 +135,29 @@ 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; } + { + 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 +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 - [[ -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 + msg_error "A problem occurred while trying to create container after re-downloading template." + exit 200 fi - +fi diff --git a/.github/workflows/scripts/app-test/pr-install.func b/.github/workflows/scripts/app-test/pr-install.func index 49195f365..1719a1a9e 100644 --- a/.github/workflows/scripts/app-test/pr-install.func +++ b/.github/workflows/scripts/app-test/pr-install.func @@ -1,31 +1,31 @@ #!/usr/bin/env bash # Copyright (c) 2021-2025 community-scripts ORG -# Author: michelroegl-brunner +# Author: Michel Roegl-Brunner (michelroegl-brunner) # License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE color() { return } -SCRIPT_NAME="${BASH_SOURCE[0]:-unknown_script}" catch_errors() { - set -Euoe pipefail + set -Euo pipefail trap 'error_handler $LINENO "$BASH_COMMAND"' ERR } error_handler() { local line_number="$1" local command="$2" - local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command '$command'" - echo -e "\n$error_message" - exit 300 + 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]}" "$*" - } + STD="silent" + silent() { + "$@" >/dev/null 2>&1 || error_handler "${BASH_LINENO[0]}" "$*" + } + return } msg_info() { @@ -33,19 +33,21 @@ msg_info() { echo -ne "${msg}\n" } -msg_ok() { +msg_ok() { local msg="$1" echo -e "${msg}\n" } msg_error() { - + local msg="$1" echo -e "${msg}\n" } - RETRY_NUM=10 - RETRY_EVERY=3 + +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 @@ -53,12 +55,11 @@ setting_up_container() { 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 - echo 1>&2 -en "No Network! " sleep $RETRY_EVERY done if [ "$(hostname -I)" = "" ]; then @@ -68,8 +69,6 @@ setting_up_container() { fi rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED systemctl disable -q --now systemd-networkd-wait-online.service - msg_ok "Set up Container OS" - msg_ok "Network Connected: $(hostname -I)" } network_check() { @@ -79,11 +78,10 @@ network_check() { } update_os() { - msg_info "Updating Container OS" - apt-get update - apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade + 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 - msg_ok "Updated Container OS" } motd_ssh() { @@ -91,5 +89,5 @@ motd_ssh() { } customize() { - return + return } \ No newline at end of file diff --git a/.github/workflows/update-json-date.yml b/.github/workflows/update-json-date.yml index 7e9c24973..26957e50c 100644 --- a/.github/workflows/update-json-date.yml +++ b/.github/workflows/update-json-date.yml @@ -10,7 +10,7 @@ on: jobs: update-app-files: - runs-on: ubuntu-latest + runs-on: runner-cluster-htl-set permissions: contents: write diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c8de4823..0a1ba15ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,217 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit > [!NOTE] All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment. -> [!IMPORTANT] -Do not break established syntax in this file, as it is automatically updated by a Github Workflow +## 2025-03-03 + +### πŸ†• New Scripts + + - Habitica [@tremor021](https://github.com/tremor021) ([#2779](https://github.com/community-scripts/ProxmoxVE/pull/2779)) + +### πŸš€ Updated Scripts + + - #### 🐞 Bug Fixes + + - Zigbee2Mqtt Use fixed pnpm Version 10.4.1 [@MickLesk](https://github.com/MickLesk) ([#2805](https://github.com/community-scripts/ProxmoxVE/pull/2805)) + - Linkwarden: Fix & Update Monolith-Installation [@MickLesk](https://github.com/MickLesk) ([#2787](https://github.com/community-scripts/ProxmoxVE/pull/2787)) + + - #### ✨ New Features + + - Feature: MinIO use now static port 9001 [@MickLesk](https://github.com/MickLesk) ([#2786](https://github.com/community-scripts/ProxmoxVE/pull/2786)) + - Feature Template Path for Mountings [@MickLesk](https://github.com/MickLesk) ([#2785](https://github.com/community-scripts/ProxmoxVE/pull/2785)) + +### 🌐 Website + + - #### ✨ New Features + + - Feature: Website - show default OS [@MickLesk](https://github.com/MickLesk) ([#2790](https://github.com/community-scripts/ProxmoxVE/pull/2790)) + + - #### πŸ“ Script Information + + - Update zigbee2mqtt.json - make sure link is clickable [@gurtjun](https://github.com/gurtjun) ([#2802](https://github.com/community-scripts/ProxmoxVE/pull/2802)) + +## 2025-03-02 + +### πŸš€ Updated Scripts + + - #### 🐞 Bug Fixes + + - Fix gpg Repo for nzbget [@flatlinebb](https://github.com/flatlinebb) ([#2774](https://github.com/community-scripts/ProxmoxVE/pull/2774)) + +## 2025-03-01 + +### πŸš€ Updated Scripts + + - #### 🐞 Bug Fixes + + - Firefly III: FIx Ownership for OAuth Key [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2759](https://github.com/community-scripts/ProxmoxVE/pull/2759)) + - homarr: double restart to fix homarr migration [@CrazyWolf13](https://github.com/CrazyWolf13) ([#2757](https://github.com/community-scripts/ProxmoxVE/pull/2757)) + + - #### ✨ New Features + + - ActualBudget: New Installation Script with new Repo [@MickLesk](https://github.com/MickLesk) ([#2770](https://github.com/community-scripts/ProxmoxVE/pull/2770)) + + - #### πŸ’₯ Breaking Changes + + - Breaking: Remove Update Function for Actual Budget until it fixed [@MickLesk](https://github.com/MickLesk) ([#2768](https://github.com/community-scripts/ProxmoxVE/pull/2768)) + +### 🧰 Maintenance + + - #### 🐞 Bug Fixes + + - Remove Note on Changelog [@MickLesk](https://github.com/MickLesk) ([#2758](https://github.com/community-scripts/ProxmoxVE/pull/2758)) + - Fix Release Creation if Changelog.md to long [@MickLesk](https://github.com/MickLesk) ([#2752](https://github.com/community-scripts/ProxmoxVE/pull/2752)) + +## 2025-02-28 + +### 🧰 Maintenance + + - #### ✨ New Features + + - Shell Format Workflow [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2400](https://github.com/community-scripts/ProxmoxVE/pull/2400)) + + - #### πŸ“‚ Github + + - Update all Action to new selfhosted Runner Cluster [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2739](https://github.com/community-scripts/ProxmoxVE/pull/2739)) + - Update Script Test Workflow [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2741](https://github.com/community-scripts/ProxmoxVE/pull/2741)) + +## 2025-02-27 + +### πŸ†• New Scripts + + - web-check [@CrazyWolf13](https://github.com/CrazyWolf13) ([#2662](https://github.com/community-scripts/ProxmoxVE/pull/2662)) +- Pelican Panel [@bvdberg01](https://github.com/bvdberg01) ([#2678](https://github.com/community-scripts/ProxmoxVE/pull/2678)) +- Pelican Wings [@bvdberg01](https://github.com/bvdberg01) ([#2677](https://github.com/community-scripts/ProxmoxVE/pull/2677)) +- ByteStash [@tremor021](https://github.com/tremor021) ([#2680](https://github.com/community-scripts/ProxmoxVE/pull/2680)) + +### πŸš€ Updated Scripts + + - ByteStash: Removed sed, app supports Node v22 now [@tremor021](https://github.com/tremor021) ([#2728](https://github.com/community-scripts/ProxmoxVE/pull/2728)) +- Keycloak: Update installation script [@tremor021](https://github.com/tremor021) ([#2714](https://github.com/community-scripts/ProxmoxVE/pull/2714)) +- ByteStash: Fix Node 22 compatibility (thanks t2lc) [@tremor021](https://github.com/tremor021) ([#2705](https://github.com/community-scripts/ProxmoxVE/pull/2705)) + + - #### 🐞 Bug Fixes + + - EOF not detected [@CrazyWolf13](https://github.com/CrazyWolf13) ([#2726](https://github.com/community-scripts/ProxmoxVE/pull/2726)) + - Zitadel-install.sh: Remove one version file and update to our standard [@bvdberg01](https://github.com/bvdberg01) ([#2710](https://github.com/community-scripts/ProxmoxVE/pull/2710)) + - Outline: Change key to hex32 [@tremor021](https://github.com/tremor021) ([#2709](https://github.com/community-scripts/ProxmoxVE/pull/2709)) + - Typo in update scripts [@bvdberg01](https://github.com/bvdberg01) ([#2707](https://github.com/community-scripts/ProxmoxVE/pull/2707)) + - SFTPGo Remove unneeded RELEASE variable [@MickLesk](https://github.com/MickLesk) ([#2683](https://github.com/community-scripts/ProxmoxVE/pull/2683)) + +### 🧰 Maintenance + + - #### 🐞 Bug Fixes + + - Update install.func: Change Line Number for Error message. [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2690](https://github.com/community-scripts/ProxmoxVE/pull/2690)) + + - #### πŸ“‚ Github + + - New Workflow to close Script Request Discussions on PR merge [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2688](https://github.com/community-scripts/ProxmoxVE/pull/2688)) + - Improve Script-Test Workflow [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2712](https://github.com/community-scripts/ProxmoxVE/pull/2712)) + - Switch all actions to self-hosted Runners [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2711](https://github.com/community-scripts/ProxmoxVE/pull/2711)) + +### 🌐 Website + + - #### ✨ New Features + + - Use HTML button element for copying to clipboard [@scallaway](https://github.com/scallaway) ([#2720](https://github.com/community-scripts/ProxmoxVE/pull/2720)) + - Add basic pagination to Data Viewer [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2715](https://github.com/community-scripts/ProxmoxVE/pull/2715)) + + - #### πŸ“ Script Information + + - wger - Add HTTPS instructions to the website [@tremor021](https://github.com/tremor021) ([#2695](https://github.com/community-scripts/ProxmoxVE/pull/2695)) + +## 2025-02-26 + +### πŸ†• New Scripts + + - New Script: Outline [@tremor021](https://github.com/tremor021) ([#2653](https://github.com/community-scripts/ProxmoxVE/pull/2653)) + +### πŸš€ Updated Scripts + + - Fix: SABnzbd - Removed few artefacts in the code preventing the update [@tremor021](https://github.com/tremor021) ([#2670](https://github.com/community-scripts/ProxmoxVE/pull/2670)) + + - #### 🐞 Bug Fixes + + - Fix: Homarr - Manually correct db-migration wrong-folder [@CrazyWolf13](https://github.com/CrazyWolf13) ([#2676](https://github.com/community-scripts/ProxmoxVE/pull/2676)) + - Kimai: add local.yaml & fix path permissions [@MickLesk](https://github.com/MickLesk) ([#2646](https://github.com/community-scripts/ProxmoxVE/pull/2646)) + - PiHole: Fix Unbound sed for DNS [@MickLesk](https://github.com/MickLesk) ([#2647](https://github.com/community-scripts/ProxmoxVE/pull/2647)) + - Alpine IT-Tools fix typo "unexpected EOF while looking for matching `"' [@MickLesk](https://github.com/MickLesk) ([#2644](https://github.com/community-scripts/ProxmoxVE/pull/2644)) + +### 🧰 Maintenance + + - #### πŸ“‚ Github + + - [gh] Furhter Impove Changelog Workflow [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2655](https://github.com/community-scripts/ProxmoxVE/pull/2655)) + +### 🌐 Website + + - #### 🐞 Bug Fixes + + - Website: PocketID Change of website and documentation links [@schneider-de-com](https://github.com/schneider-de-com) ([#2643](https://github.com/community-scripts/ProxmoxVE/pull/2643)) + + - #### πŸ“ Script Information + + - Fix: Graylog - Improve application description for website [@tremor021](https://github.com/tremor021) ([#2658](https://github.com/community-scripts/ProxmoxVE/pull/2658)) + +## 2025-02-25 + +### Changes + +### ✨ New Features + +- Update Tailscale: Add Tag when installation is finished [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2633](https://github.com/community-scripts/ProxmoxVE/pull/2633)) + +### πŸš€ Updated Scripts + + #### 🐞 Bug Fixes + + - Fix Omada installer [@JcMinarro](https://github.com/JcMinarro) ([#2625](https://github.com/community-scripts/ProxmoxVE/pull/2625)) + +### 🌐 Website + +- Update Tailscale-lxc Json: Add message for Supported OS [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2629](https://github.com/community-scripts/ProxmoxVE/pull/2629)) + +### 🧰 Maintenance + +- [gh] Updated Changelog Workflow [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2632](https://github.com/community-scripts/ProxmoxVE/pull/2632)) + +## 2025-02-24 + +### Changes + +### πŸ†• New Scripts + +- New Script: wger [@tremor021](https://github.com/tremor021) ([#2574](https://github.com/community-scripts/ProxmoxVE/pull/2574)) +- New Script: VictoriaMetrics [@tremor021](https://github.com/tremor021) ([#2565](https://github.com/community-scripts/ProxmoxVE/pull/2565)) +- New Script: Authelia [@thost96](https://github.com/thost96) ([#2060](https://github.com/community-scripts/ProxmoxVE/pull/2060)) +- New Script: Jupyter Notebook [@Dave-code-creater](https://github.com/Dave-code-creater) ([#2561](https://github.com/community-scripts/ProxmoxVE/pull/2561)) + +### 🐞 Bug Fixes + +- Fix Docmost: default upload size and saving data when updating [@bvdberg01](https://github.com/bvdberg01) ([#2598](https://github.com/community-scripts/ProxmoxVE/pull/2598)) +- Fix: homarr db migration [@CrazyWolf13](https://github.com/CrazyWolf13) ([#2575](https://github.com/community-scripts/ProxmoxVE/pull/2575)) +- Fix: Wireguard - Restart wgdashboard automatically after update [@LostALice](https://github.com/LostALice) ([#2587](https://github.com/community-scripts/ProxmoxVE/pull/2587)) +- Fix: Authelia Unbound Variable Argon2id [@MickLesk](https://github.com/MickLesk) ([#2604](https://github.com/community-scripts/ProxmoxVE/pull/2604)) +- Fix: Omada check for AVX Support and use the correct MongoDB Version [@MickLesk](https://github.com/MickLesk) ([#2600](https://github.com/community-scripts/ProxmoxVE/pull/2600)) +- Fix: Update-Script Firefly III based on their docs [@MickLesk](https://github.com/MickLesk) ([#2534](https://github.com/community-scripts/ProxmoxVE/pull/2534)) + +### ✨ New Features + +- Feature: Template-Check, Better Handling of Downloads, Better Network… [@MickLesk](https://github.com/MickLesk) ([#2592](https://github.com/community-scripts/ProxmoxVE/pull/2592)) +- Feature: Possibility to perform updates in silent / verbose (+ logging) [@MickLesk](https://github.com/MickLesk) ([#2583](https://github.com/community-scripts/ProxmoxVE/pull/2583)) +- Feature: Use Verbose Mode for all Scripts (removed &>/dev/null) [@MickLesk](https://github.com/MickLesk) ([#2596](https://github.com/community-scripts/ProxmoxVE/pull/2596)) + +### 🌐 Website + +- Fix: Authelia - Make user enter their domain manually [@tremor021](https://github.com/tremor021) ([#2618](https://github.com/community-scripts/ProxmoxVE/pull/2618)) +- Website: Change Info for PiHole Password [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2602](https://github.com/community-scripts/ProxmoxVE/pull/2602)) +- Fix: Jupyter Json (missing logo & improve name on website) [@MickLesk](https://github.com/MickLesk) ([#2584](https://github.com/community-scripts/ProxmoxVE/pull/2584)) + +### 🧰 Maintenance + +- [gh] Update Script Test Workflow [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2599](https://github.com/community-scripts/ProxmoxVE/pull/2599)) +- [gh] Contributor-Guide: Update AppName.md & AppName.sh [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#2603](https://github.com/community-scripts/ProxmoxVE/pull/2603)) ## 2025-02-23 diff --git a/ct/2fauth.sh b/ct/2fauth.sh index 503f2f917..6a88d6a9e 100644 --- a/ct/2fauth.sh +++ b/ct/2fauth.sh @@ -35,8 +35,8 @@ function update_script() { if [[ "${RELEASE}" != "$(cat /opt/2fauth_version.txt)" ]] || [[ ! -f /opt/2fauth_version.txt ]]; then msg_info "Updating $APP to ${RELEASE}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade # Creating Backup msg_info "Creating Backup" @@ -55,7 +55,7 @@ function update_script() { chmod -R 755 "/opt/2fauth" export COMPOSER_ALLOW_SUPERUSER=1 - composer install --no-dev --prefer-source &>/dev/null + $STD composer install --no-dev --prefer-source php artisan 2fauth:install diff --git a/ct/actualbudget.sh b/ct/actualbudget.sh index e3675fe13..8512b1712 100644 --- a/ct/actualbudget.sh +++ b/ct/actualbudget.sh @@ -28,89 +28,8 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit 1 fi - - RELEASE=$(curl -s https://api.github.com/repos/actualbudget/actual/releases/latest | \ - grep "tag_name" | awk -F '"' '{print substr($4, 2)}') - - 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}" - cd /tmp - wget -q "https://github.com/actualbudget/actual-server/archive/refs/tags/v${RELEASE}.tar.gz" - - mv /opt/actualbudget /opt/actualbudget_bak - tar -xzf "v${RELEASE}.tar.gz" &>/dev/null - mv *ctual-server-* /opt/actualbudget - - mkdir -p /opt/actualbudget-data/{server-files,upload,migrate,user-files,migrations,config} - for dir in server-files .migrate user-files migrations; do - if [[ -d /opt/actualbudget_bak/$dir ]]; then - mv /opt/actualbudget_bak/$dir/* /opt/actualbudget-data/$dir/ 2>/dev/null || true - fi - done - if [[ -f /opt/actualbudget-data/migrate/.migrations ]]; then - sed -i 's/null/1732656575219/g' /opt/actualbudget-data/migrate/.migrations - sed -i 's/null/1732656575220/g' /opt/actualbudget-data/migrate/.migrations - fi - if [[ -f /opt/actualbudget/server-files/account.sqlite ]] && [[ ! -f /opt/actualbudget-data/server-files/account.sqlite ]]; then - mv /opt/actualbudget/server-files/account.sqlite /opt/actualbudget-data/server-files/account.sqlite - fi - - if [[ -f /opt/actualbudget_bak/.env ]]; then - mv /opt/actualbudget_bak/.env /opt/actualbudget-data/.env - else - cat < /opt/actualbudget-data/.env -ACTUAL_UPLOAD_DIR=/opt/actualbudget-data/upload -ACTUAL_DATA_DIR=/opt/actualbudget-data -ACTUAL_SERVER_FILES_DIR=/opt/actualbudget-data/server-files -ACTUAL_USER_FILES=/opt/actualbudget-data/user-files -PORT=5006 -ACTUAL_TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128,fc00::/7" -ACTUAL_HTTPS_KEY=/opt/actualbudget/selfhost.key -ACTUAL_HTTPS_CERT=/opt/actualbudget/selfhost.crt -EOF - fi - cd /opt/actualbudget - yarn install &>/dev/null - echo "${RELEASE}" > /opt/actualbudget_version.txt - msg_ok "Updated ${APP}" - - msg_info "Starting ${APP}" - cat < /etc/systemd/system/actualbudget.service -[Unit] -Description=Actual Budget Service -After=network.target - -[Service] -Type=simple -User=root -Group=root -WorkingDirectory=/opt/actualbudget -EnvironmentFile=/opt/actualbudget-data/.env -ExecStart=/usr/bin/yarn start -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -EOF - - systemctl daemon-reload - systemctl start actualbudget - msg_ok "Started ${APP}" - - msg_info "Cleaning Up" - rm -rf /opt/actualbudget_bak - rm -rf "/tmp/v${RELEASE}.tar.gz" - msg_ok "Cleaned" - msg_ok "Updated Successfully" - else - msg_ok "No update required. ${APP} is already at ${RELEASE}" - fi - exit 0 + msg_error "Due to major changes in the Actual Budget repository, we are currently unable to provide updates. Please check back later." + exit } start diff --git a/ct/adventurelog.sh b/ct/adventurelog.sh index 0b05d6055..8136ee204 100644 --- a/ct/adventurelog.sh +++ b/ct/adventurelog.sh @@ -43,15 +43,15 @@ function update_script() { 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 - 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 + $STD pip install --upgrade pip + $STD pip install -r requirements.txt + $STD python3 manage.py collectstatic --noinput + $STD python3 manage.py migrate mv /opt/adventurelog-backup/frontend/.env /opt/adventurelog/frontend/.env cd /opt/adventurelog/frontend - pnpm install &>/dev/null - pnpm run build &>/dev/null + $STD pnpm install + $STD pnpm run build echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP}" diff --git a/ct/agentdvr.sh b/ct/agentdvr.sh index 23f5a7695..2c6766c1a 100644 --- a/ct/agentdvr.sh +++ b/ct/agentdvr.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/alpine-it-tools.sh b/ct/alpine-it-tools.sh index d24f267f6..40d9d087c 100644 --- a/ct/alpine-it-tools.sh +++ b/ct/alpine-it-tools.sh @@ -30,7 +30,7 @@ if [ ! -d /usr/share/nginx/html ]; then fi RELEASE=$(curl -s https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4) -if [ "${RELEASE}" != "$(cat /opt/${APP}_version.txt 2>/dev/null)" ] || [ ! -f /opt/${APP}_version.txt ]; then +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" diff --git a/ct/apache-cassandra.sh b/ct/apache-cassandra.sh index 0a11f2201..d2134f929 100644 --- a/ct/apache-cassandra.sh +++ b/ct/apache-cassandra.sh @@ -28,7 +28,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/apache-couchdb.sh b/ct/apache-couchdb.sh index e6e6e168e..169cf01ee 100644 --- a/ct/apache-couchdb.sh +++ b/ct/apache-couchdb.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/apache-guacamole.sh b/ct/apache-guacamole.sh index 9379aa876..9fa7a7161 100644 --- a/ct/apache-guacamole.sh +++ b/ct/apache-guacamole.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "Ther is currently no automatic update function for ${APP}." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/apt-cacher-ng.sh b/ct/apt-cacher-ng.sh index eb91296cc..66244598b 100644 --- a/ct/apt-cacher-ng.sh +++ b/ct/apt-cacher-ng.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/aria2.sh b/ct/aria2.sh index 1b9029769..08b25d3c8 100644 --- a/ct/aria2.sh +++ b/ct/aria2.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/authelia.sh b/ct/authelia.sh new file mode 100644 index 000000000..de6eb07ca --- /dev/null +++ b/ct/authelia.sh @@ -0,0 +1,55 @@ +#!/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: thost96 (thost96) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://www.authelia.com/ + +APP="Authelia" +TAGS="" +var_cpu="1" +var_ram="512" +var_disk="2" +var_os="debian" +var_version="12" +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 -s 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 + wget -q "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}" diff --git a/ct/authentik.sh b/ct/authentik.sh index 77f0ddb8d..18e7cc365 100644 --- a/ct/authentik.sh +++ b/ct/authentik.sh @@ -40,11 +40,11 @@ function update_script() { tar -xzf authentik.tar.gz -C /opt/authentik --strip-components 1 --overwrite rm -rf authentik.tar.gz cd /opt/authentik/website - npm install &>/dev/null - npm run build-bundled &>/dev/null + $STD npm install + $STD npm run build-bundled cd /opt/authentik/web - npm install &>/dev/null - npm run build &>/dev/null + $STD npm install + $STD npm run build msg_ok "Built ${APP} website" msg_info "Building ${APP} server" @@ -56,15 +56,15 @@ function update_script() { msg_info "Installing Python Dependencies" cd /opt/authentik - 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 + $STD poetry install --only=main --no-ansi --no-interaction --no-root + $STD poetry export --without-hashes --without-urls -f requirements.txt --output requirements.txt + $STD pip install --no-cache-dir -r requirements.txt + $STD pip install . 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 + $STD bash /opt/authentik/lifecycle/ak migrate echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/bazarr.sh b/ct/bazarr.sh index 1802d72a2..b329fadcd 100755 --- a/ct/bazarr.sh +++ b/ct/bazarr.sh @@ -25,8 +25,8 @@ function update_script() { check_container_resources if [[ ! -d /var/lib/bazarr/ ]]; then msg_error "No ${APP} Installation Found!"; exit; fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/beszel.sh b/ct/beszel.sh index c159800be..1ed2b1560 100644 --- a/ct/beszel.sh +++ b/ct/beszel.sh @@ -28,7 +28,7 @@ function update_script() { exit fi /opt/beszel/beszel update - msg_error "Ther is currently no automatic update function for ${APP}." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/blocky.sh b/ct/blocky.sh index 667e52433..84e480779 100644 --- a/ct/blocky.sh +++ b/ct/blocky.sh @@ -25,8 +25,8 @@ function update_script() { check_container_resources if [[ ! -d /var ]]; then msg_error "No ${APP} Installation Found!"; exit; fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/bookstack.sh b/ct/bookstack.sh index dbd21336b..65631d7bf 100644 --- a/ct/bookstack.sh +++ b/ct/bookstack.sh @@ -39,12 +39,13 @@ function update_script() { unzip -q /opt/v${RELEASE}.zip -d /opt mv /opt/BookStack-${RELEASE} /opt/bookstack cp /opt/bookstack-backup/.env /opt/bookstack/.env - cp -r /opt/bookstack-backup/public/uploads/* /opt/bookstack/public/uploads/ 2>/dev/null || true - cp -r /opt/bookstack-backup/storage/uploads/* /opt/bookstack/storage/uploads/ 2>/dev/null || true - cp -r /opt/bookstack-backup/themes/* /opt/bookstack/themes/ 2>/dev/null || true + cp -r /opt/bookstack-backup/public/uploads/* /opt/bookstack/public/uploads/ || true + cp -r /opt/bookstack-backup/storage/uploads/* /opt/bookstack/storage/uploads/ || true + cp -r /opt/bookstack-backup/themes/* /opt/bookstack/themes/ || true cd /opt/bookstack - COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev &>/dev/null - php artisan migrate --force &>/dev/null + export COMPOSER_ALLOW_SUPERUSER=1 + $STD composer install --no-dev + $STD php artisan migrate --force chown www-data:www-data -R /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage chmod -R 755 /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage chmod -R 775 /opt/bookstack/storage /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads diff --git a/ct/bytestash.sh b/ct/bytestash.sh new file mode 100644 index 000000000..52384e2c4 --- /dev/null +++ b/ct/bytestash.sh @@ -0,0 +1,73 @@ +#!/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/jordan-dalby/ByteStash + +APP="ByteStash" +var_tags="code" +var_disk="4" +var_cpu="1" +var_ram="1024" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/bytestash ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/jordan-dalby/ByteStash/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 bytestash-backend + systemctl stop bytestash-frontend + msg_ok "Services Stopped" + + msg_info "Updating ${APP} to ${RELEASE}" + temp_file=$(mktemp) + wget -q "https://github.com/jordan-dalby/ByteStash/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file + tar zxf $temp_file + rm -rf /opt/bytestash/server/node_modules + rm -rf /opt/bytestash/client/node_modules + cp -rf ByteStash-${RELEASE}/* /opt/bytestash + cd /opt/bytestash/server + $STD npm install + cd /opt/bytestash/client + $STD npm install + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated ${APP}" + + msg_info "Starting Services" + systemctl start bytestash-backend + systemctl start bytestash-frontend + msg_ok "Started Services" + + msg_info "Cleaning Up" + rm -f $temp_file + msg_ok "Cleaned" + msg_ok "Updated Successfully" + 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}:3000${CL}" diff --git a/ct/caddy.sh b/ct/caddy.sh index d7993fa94..781b9b896 100644 --- a/ct/caddy.sh +++ b/ct/caddy.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/calibre-web.sh b/ct/calibre-web.sh index 91c61d1d5..535711da6 100644 --- a/ct/calibre-web.sh +++ b/ct/calibre-web.sh @@ -115,10 +115,10 @@ function update_script() { echo "${options[*]}" ) echo $cps_options >/opt/calibre-web/options.txt - pip install --upgrade calibreweb[$cps_options] &>/dev/null + $STD pip install --upgrade calibreweb[$cps_options] else rm -rf /opt/calibre-web/options.txt - pip install --upgrade calibreweb &>/dev/null + $STD pip install --upgrade calibreweb fi msg_info "Starting ${APP}" diff --git a/ct/casaos.sh b/ct/casaos.sh index 3da5f3147..d6b3f96a1 100644 --- a/ct/casaos.sh +++ b/ct/casaos.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/changedetection.sh b/ct/changedetection.sh index f4714018d..17b8877b4 100644 --- a/ct/changedetection.sh +++ b/ct/changedetection.sh @@ -31,31 +31,31 @@ function update_script() { if ! dpkg -s libjpeg-dev >/dev/null 2>&1; then msg_info "Installing Dependencies" - apt-get update - apt-get install -y libjpeg-dev + $STD apt-get update + $STD apt-get install -y libjpeg-dev msg_ok "Updated Dependencies" fi msg_info "Updating ${APP}" - pip3 install changedetection.io --upgrade &>/dev/null + $STD pip3 install changedetection.io --upgrade msg_ok "Updated ${APP}" msg_info "Updating Playwright" - pip3 install playwright --upgrade &>/dev/null + $STD pip3 install playwright --upgrade msg_ok "Updated Playwright" if [[ -f /etc/systemd/system/browserless.service ]]; then msg_info "Updating Browserless (Patience)" - git -C /opt/browserless/ fetch --all &>/dev/null - git -C /opt/browserless/ reset --hard origin/main &>/dev/null - npm update --prefix /opt/browserless &>/dev/null - /opt/browserless/node_modules/playwright-core/cli.js install --with-deps &>/dev/null + $STD git -C /opt/browserless/ fetch --all + $STD git -C /opt/browserless/ reset --hard origin/main + $STD npm update --prefix /opt/browserless + $STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps # Update Chrome separately, as it has to be done with the force option. Otherwise the installation of other browsers will not be done if Chrome is already installed. - /opt/browserless/node_modules/playwright-core/cli.js install --force chrome &>/dev/null - /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit &>/dev/null - npm run build --prefix /opt/browserless &>/dev/null - npm run build:function --prefix /opt/browserless &>/dev/null - npm prune production --prefix /opt/browserless &>/dev/null + $STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome + $STD /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit + $STD npm run build --prefix /opt/browserless + $STD npm run build:function --prefix /opt/browserless + $STD npm prune production --prefix /opt/browserless systemctl restart browserless msg_ok "Updated Browserless" else diff --git a/ct/channels.sh b/ct/channels.sh index 01f315d43..218122708 100644 --- a/ct/channels.sh +++ b/ct/channels.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/checkmk.sh b/ct/checkmk.sh index af006c041..d7daba209 100644 --- a/ct/checkmk.sh +++ b/ct/checkmk.sh @@ -30,14 +30,14 @@ function update_script() { RELEASE=$(curl -fsSL https://api.github.com/repos/checkmk/checkmk/tags | grep "name" | awk '{print substr($2, 3, length($2)-4) }' | tr ' ' '\n' | grep -v '\-rc' | sort -V | tail -n 1) if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then msg_info "Updating ${APP} to v${RELEASE}" - omd stop monitoring &>/dev/null - omd cp monitoring monitoringbackup &>/dev/null + $STD omd stop monitoring + $STD omd cp monitoring monitoringbackup wget -q https://download.checkmk.com/checkmk/${RELEASE}/check-mk-raw-${RELEASE}_0.bookworm_amd64.deb -O /opt/checkmk.deb - apt-get install -y /opt/checkmk.deb &>/dev/null - omd --force -V ${RELEASE}.cre update --conflict=install monitoring &>/dev/null - omd start monitoring &>/dev/null - omd -f rm monitoringbackup &>/dev/null - omd cleanup &>/dev/null + $STD apt-get install -y /opt/checkmk.deb + $STD omd --force -V ${RELEASE}.cre update --conflict=install monitoring + $STD omd start monitoring + $STD omd -f rm monitoringbackup + $STD omd cleanup rm -rf /opt/checkmk.deb msg_ok "Updated ${APP} to v${RELEASE}" else diff --git a/ct/cloudflared.sh b/ct/cloudflared.sh index 2b499f10b..1a3665009 100644 --- a/ct/cloudflared.sh +++ b/ct/cloudflared.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/cockpit.sh b/ct/cockpit.sh index ee0e03cb8..e3e61a7b1 100644 --- a/ct/cockpit.sh +++ b/ct/cockpit.sh @@ -36,48 +36,48 @@ function update_script() { if [ "$UPD" == "1" ]; then msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit fi if [ "$UPD" == "2" ]; then msg_info "Installing dependencies (patience)" - apt-get install -y attr &>/dev/null - apt-get install -y nfs-kernel-server &>/dev/null - apt-get install -y samba &>/dev/null - apt-get install -y samba-common-bin &>/dev/null - apt-get install -y winbind &>/dev/null - apt-get install -y gawk &>/dev/null + $STD apt-get install -y attr + $STD apt-get install -y nfs-kernel-server + $STD apt-get install -y samba + $STD apt-get install -y samba-common-bin + $STD apt-get install -y winbind + $STD apt-get install -y gawk msg_ok "Installed dependencies" msg_info "Installing Cockpit file sharing" wget -q $(curl -s https://api.github.com/repos/45Drives/cockpit-file-sharing/releases/latest | grep download | grep focal_all.deb | cut -d\" -f4) - dpkg -i cockpit-file-sharing_*focal_all.deb &>/dev/null + $STD dpkg -i cockpit-file-sharing_*focal_all.deb rm cockpit-file-sharing_*focal_all.deb msg_ok "Installed Cockpit file sharing" exit fi if [ "$UPD" == "3" ]; then msg_info "Installing dependencies (patience)" - apt-get install -y psmisc &>/dev/null - apt-get install -y samba &>/dev/null - apt-get install -y samba-common-bin &>/dev/null + $STD apt-get install -y psmisc + $STD apt-get install -y samba + $STD apt-get install -y samba-common-bin msg_ok "Installed dependencies" msg_info "Installing Cockpit identities" wget -q $(curl -s https://api.github.com/repos/45Drives/cockpit-identities/releases/latest | grep download | grep focal_all.deb | cut -d\" -f4) - dpkg -i cockpit-identities_*focal_all.deb &>/dev/null + $STD dpkg -i cockpit-identities_*focal_all.deb rm cockpit-identities_*focal_all.deb msg_ok "Installed Cockpit identities" exit fi if [ "$UPD" == "4" ]; then msg_info "Installing dependencies" - apt-get install -y rsync &>/dev/null - apt-get install -y zip &>/dev/null + $STD apt-get install -y rsync + $STD apt-get install -y zip msg_ok "Installed dependencies" msg_info "Installing Cockpit navigator" wget -q $(curl -s https://api.github.com/repos/45Drives/cockpit-navigator/releases/latest | grep download | grep focal_all.deb | cut -d\" -f4) - dpkg -i cockpit-navigator_*focal_all.deb &>/dev/null + $STD dpkg -i cockpit-navigator_*focal_all.deb rm cockpit-navigator_*focal_all.deb msg_ok "Installed Cockpit navigator" exit diff --git a/ct/create_lxc.sh b/ct/create_lxc.sh index 8f5722bf2..df493ed10 100644 --- a/ct/create_lxc.sh +++ b/ct/create_lxc.sh @@ -35,7 +35,7 @@ trap 'error_handler $LINENO "$BASH_COMMAND"' ERR # This function handles errors function error_handler() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local exit_code="$?" local line_number="$1" @@ -50,13 +50,13 @@ function spinner() { local frames=('β ‹' 'β ™' 'β Ή' 'β Έ' 'β Ό' 'β ΄' 'β ¦' 'β §' 'β ‡' '⠏') local spin_i=0 local interval=0.1 - printf "\e[?25l" + printf "\e[?25l" local color="${YWB}" while true; do printf "\r ${color}%s${CL}" "${frames[spin_i]}" - spin_i=$(( (spin_i + 1) % ${#frames[@]} )) + spin_i=$(((spin_i + 1) % ${#frames[@]})) sleep "$interval" done } @@ -69,9 +69,16 @@ function msg_info() { SPINNER_PID=$! } +function msg_warn() { + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi + printf "\e[?25h" + local msg="$1" + echo -e "${BFR}${INFO}${YWB}${msg}${CL}" +} + # This function displays a success message with a green color. function msg_ok() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local msg="$1" echo -e "${BFR}${CM}${GN}${msg}${CL}" @@ -79,7 +86,7 @@ function msg_ok() { # This function displays a error message with a red color. function msg_error() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local msg="$1" echo -e "${BFR}${CROSS}${RD}${msg}${CL}" @@ -112,9 +119,12 @@ function select_storage() { CONTENT='vztmpl' CONTENT_LABEL='Container template' ;; - *) false || { msg_error "Invalid storage class."; exit 201; }; + *) false || { + msg_error "Invalid storage class." + exit 201 + } ;; esac - + # This Queries all storage locations local -a MENU while read -r line; do @@ -128,34 +138,60 @@ function select_storage() { fi MENU+=("$TAG" "$ITEM" "OFF") done < <(pvesm status -content $CONTENT | awk 'NR>1') - + # Select storage location - if [ $((${#MENU[@]}/3)) -eq 1 ]; then + if [ $((${#MENU[@]} / 3)) -eq 1 ]; then printf ${MENU[0]} else local STORAGE while [ -z "${STORAGE:+x}" ]; do STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \ - "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \ - 16 $(($MSG_MAX_LENGTH + 23)) 6 \ - "${MENU[@]}" 3>&1 1>&2 2>&3) || { msg_error "Menu aborted."; exit 202; } + "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \ + 16 $(($MSG_MAX_LENGTH + 23)) 6 \ + "${MENU[@]}" 3>&1 1>&2 2>&3) || { + msg_error "Menu aborted." + exit 202 + } if [ $? -ne 0 ]; then echo -e "${CROSS}${RD} Menu aborted by user.${CL}" - exit 0 + exit 0 fi done printf "%s" "$STORAGE" fi } # Test if required variables are set -[[ "${CTID:-}" ]] || { msg_error "You need to set 'CTID' variable."; exit 203; } -[[ "${PCT_OSTYPE:-}" ]] || { msg_error "You need to set 'PCT_OSTYPE' variable."; exit 204; } +[[ "${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; } +[ "$CTID" -ge "100" ] || { + msg_error "ID cannot be less than 100." + exit 205 +} + +# Check for network connectivity (IPv4 & IPv6) +#function check_network() { +# local CHECK_URLS=("8.8.8.8" "1.1.1.1" "9.9.9.9" "2606:4700:4700::1111" "2001:4860:4860::8888" "2620:fe::fe") +# +# for url in "${CHECK_URLS[@]}"; do +# if ping -c 1 -W 2 "$url" &>/dev/null; then +# return 0 # Success: At least one connection works +# fi +# done +# +# msg_error "No network connection detected. Check your internet connection." +# exit 101 +#} # Test if ID is in use -if pct status $CTID &>/dev/null; then +if qm status "$CTID" &>/dev/null || 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." @@ -227,28 +263,38 @@ else msg_ok "Downloaded LXC Template" fi fi +msg_ok "LXC Template is ready to use." # Check and fix subuid/subgid -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 +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 # Combine all options PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}}) [[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}") -# Create container with template integrity check msg_info "Creating LXC Container" - if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then - [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH" - - msg_ok "Template integrity check completed" - 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 "Container creation failed. Checking if template is corrupted." + + if ! zstdcat "$TEMPLATE_PATH" | tar -tf - >/dev/null 2>&1; then + msg_error "Template appears to be corrupted. Removing and re-downloading." + rm -f "$TEMPLATE_PATH" + + if ! timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then + msg_error "Failed to re-download template." + exit 208 + fi + msg_ok "Re-downloaded LXC Template" + 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." + msg_error "Container creation failed after re-downloading template." exit 200 fi + else + msg_error "Container creation failed, but template is not corrupted." + exit 209 fi +fi msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created." diff --git a/ct/cronicle.sh b/ct/cronicle.sh index 54663ae9e..43584a199 100644 --- a/ct/cronicle.sh +++ b/ct/cronicle.sh @@ -36,12 +36,12 @@ function update_script() { if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then if ! command -v npm >/dev/null 2>&1; then echo "Installing NPM..." - apt-get install -y npm >/dev/null 2>&1 + $STD apt-get install -y npm echo "Installed NPM..." fi fi msg_info "Updating ${APP}" - /opt/cronicle/bin/control.sh upgrade &>/dev/null + $STD /opt/cronicle/bin/control.sh upgrade msg_ok "Updated ${APP}" exit fi @@ -49,7 +49,7 @@ function update_script() { if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then if ! command -v npm >/dev/null 2>&1; then echo "Installing NPM..." - apt-get install -y npm >/dev/null 2>&1 + $STD apt-get install -y npm echo "Installed NPM..." fi fi @@ -57,12 +57,12 @@ function update_script() { IP=$(hostname -I | awk '{print $1}') msg_info "Installing Dependencies" - apt-get install -y git &>/dev/null - apt-get install -y make &>/dev/null - apt-get install -y g++ &>/dev/null - apt-get install -y gcc &>/dev/null - apt-get install -y ca-certificates &>/dev/null - apt-get install -y gnupg &>/dev/null + $STD apt-get install -y git + $STD apt-get install -y make + $STD apt-get install -y g++ + $STD apt-get install -y gcc + $STD apt-get install -y ca-certificates + $STD apt-get install -y gnupg msg_ok "Installed Dependencies" msg_info "Setting up Node.js Repository" @@ -72,21 +72,21 @@ function update_script() { msg_ok "Set up Node.js Repository" msg_info "Installing Node.js" - apt-get update &>/dev/null - apt-get install -y nodejs &>/dev/null + $STD apt-get update + $STD apt-get install -y nodejs msg_ok "Installed Node.js" msg_info "Installing Cronicle Worker" mkdir -p /opt/cronicle cd /opt/cronicle - tar zxvf <(curl -fsSL https://github.com/jhuckaby/Cronicle/archive/${LATEST}.tar.gz) --strip-components 1 &>/dev/null - npm install &>/dev/null - node bin/build.js dist &>/dev/null + $STD tar zxvf <(curl -fsSL https://github.com/jhuckaby/Cronicle/archive/${LATEST}.tar.gz) --strip-components 1 + $STD npm install + $STD node bin/build.js dist sed -i "s/localhost:3012/${IP}:3012/g" /opt/cronicle/conf/config.json - /opt/cronicle/bin/control.sh start &>/dev/null - cp /opt/cronicle/bin/cronicled.init /etc/init.d/cronicled &>/dev/null + $STD /opt/cronicle/bin/control.sh start + $STD cp /opt/cronicle/bin/cronicled.init /etc/init.d/cronicled chmod 775 /etc/init.d/cronicled - update-rc.d cronicled defaults &>/dev/null + $STD update-rc.d cronicled defaults msg_ok "Installed Cronicle Worker" echo -e "\n Add Masters secret key to /opt/cronicle/conf/config.json \n" exit diff --git a/ct/cross-seed.sh b/ct/cross-seed.sh index 1cb34a39a..0a2337acf 100644 --- a/ct/cross-seed.sh +++ b/ct/cross-seed.sh @@ -29,7 +29,7 @@ function update_script() { latest_version=$(npm show cross-seed version) if [ "$current_version" != "$latest_version" ]; then msg_info "Updating ${APP} from version v${current_version} to v${latest_version}" - npm install -g cross-seed@latest &> /dev/null + $STD npm install -g cross-seed@latest systemctl restart cross-seed msg_ok "Updated Successfully" else diff --git a/ct/daemonsync.sh b/ct/daemonsync.sh index ae2fb6a2e..c65d08cdd 100644 --- a/ct/daemonsync.sh +++ b/ct/daemonsync.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/debian.sh b/ct/debian.sh index f4c3d6bff..0c12a60bc 100644 --- a/ct/debian.sh +++ b/ct/debian.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/deconz.sh b/ct/deconz.sh index 3d1d0dbec..57023b6a2 100644 --- a/ct/deconz.sh +++ b/ct/deconz.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/deluge.sh b/ct/deluge.sh index 038ed996d..effa41a91 100644 --- a/ct/deluge.sh +++ b/ct/deluge.sh @@ -28,7 +28,7 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null + $STD apt-get update pip3 install deluge[all] --upgrade msg_ok "Updated $APP LXC" exit diff --git a/ct/docker.sh b/ct/docker.sh index e21e9e0ff..8a49cadfe 100644 --- a/ct/docker.sh +++ b/ct/docker.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/docmost.sh b/ct/docmost.sh index 75e1f9363..443e7007e 100644 --- a/ct/docmost.sh +++ b/ct/docmost.sh @@ -34,6 +34,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" cp /opt/docmost/.env /opt/ + cp -r /opt/docmost/data /opt/ rm -rf /opt/docmost temp_file=$(mktemp) wget -q "https://github.com/docmost/docmost/archive/refs/tags/v${RELEASE}.tar.gz" -O "$temp_file" @@ -41,8 +42,9 @@ function update_script() { mv docmost-${RELEASE} /opt/docmost cd /opt/docmost mv /opt/.env /opt/docmost/.env - pnpm install --force &>/dev/null - pnpm build &>/dev/null + mv /opt/data /opt/docmost/data + $STD pnpm install --force + $STD pnpm build echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP}" diff --git a/ct/dotnetaspwebapi.sh b/ct/dotnetaspwebapi.sh index 667cb5b18..6345e87d5 100644 --- a/ct/dotnetaspwebapi.sh +++ b/ct/dotnetaspwebapi.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/elementsynapse.sh b/ct/elementsynapse.sh index d1b482be5..64057fa4d 100644 --- a/ct/elementsynapse.sh +++ b/ct/elementsynapse.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/emby.sh b/ct/emby.sh index eaa02bde7..0a9e9f575 100644 --- a/ct/emby.sh +++ b/ct/emby.sh @@ -33,8 +33,8 @@ function update_script() { msg_ok "Stopped ${APP}" msg_info "Updating ${APP}" - wget https://github.com/MediaBrowser/Emby.Releases/releases/download/${LATEST}/emby-server-deb_${LATEST}_amd64.deb &>/dev/null - dpkg -i emby-server-deb_${LATEST}_amd64.deb &>/dev/null + $STD wget https://github.com/MediaBrowser/Emby.Releases/releases/download/${LATEST}/emby-server-deb_${LATEST}_amd64.deb + $STD dpkg -i emby-server-deb_${LATEST}_amd64.deb rm emby-server-deb_${LATEST}_amd64.deb msg_ok "Updated ${APP}" diff --git a/ct/emqx.sh b/ct/emqx.sh index 08026b790..5f44b8325 100644 --- a/ct/emqx.sh +++ b/ct/emqx.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/esphome.sh b/ct/esphome.sh index 5c451f662..aaeca7e2b 100644 --- a/ct/esphome.sh +++ b/ct/esphome.sh @@ -33,9 +33,9 @@ function update_script() { msg_info "Updating ESPHome" if [[ -d /srv/esphome ]]; then - source /srv/esphome/bin/activate &>/dev/null + $STD source /srv/esphome/bin/activate fi - pip3 install -U esphome &>/dev/null + $STD pip3 install -U esphome msg_ok "Updated ESPHome" msg_info "Starting ESPHome" diff --git a/ct/evcc.sh b/ct/evcc.sh index df9ff5797..154555fd3 100644 --- a/ct/evcc.sh +++ b/ct/evcc.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating evcc LXC" - apt update &>/dev/null - apt --only-upgrade install -y evcc &>/dev/null + $STD apt update + $STD apt --only-upgrade install -y evcc msg_ok "Updated Successfully" exit } diff --git a/ct/excalidraw.sh b/ct/excalidraw.sh index d0ff3a27a..c1347b41c 100644 --- a/ct/excalidraw.sh +++ b/ct/excalidraw.sh @@ -43,7 +43,7 @@ function update_script() { rm -rf /opt/excalidraw mv excalidraw-${RELEASE} /opt/excalidraw cd /opt/excalidraw - yarn &> /dev/null + $STD yarn msg_ok "Updated $APP to v${RELEASE}" msg_info "Starting $APP" diff --git a/ct/fenrus.sh b/ct/fenrus.sh index a22e164ea..d9d4eec7b 100644 --- a/ct/fenrus.sh +++ b/ct/fenrus.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit msg_info "Updating ${APP}" systemctl stop ${APP} diff --git a/ct/fhem.sh b/ct/fhem.sh index aa87bb3dc..b3dd23968 100644 --- a/ct/fhem.sh +++ b/ct/fhem.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/firefly.sh b/ct/firefly.sh index efb5f8109..2f86e668c 100644 --- a/ct/firefly.sh +++ b/ct/firefly.sh @@ -37,21 +37,19 @@ check_container_resources msg_info "Updating ${APP} to v${RELEASE}" cp /opt/firefly/.env /opt/.env cp -r /opt/firefly/storage /opt/storage - rm -rf /opt/firefly/* cd /opt wget -q "https://github.com/firefly-iii/firefly-iii/releases/download/v${RELEASE}/FireflyIII-v${RELEASE}.tar.gz" tar -xzf FireflyIII-v${RELEASE}.tar.gz -C /opt/firefly --exclude='storage' + cp /opt/.env /opt/firefly/.env + cp -r /opt/storage /opt/firefly/storage cd /opt/firefly - composer install --no-dev --no-interaction &>/dev/null - php artisan migrate --seed --force &>/dev/null - php artisan firefly:decrypt-all &>/dev/null - php artisan cache:clear &>/dev/null - php artisan view:clear &>/dev/null - php artisan firefly:upgrade-database &>/dev/null - php artisan firefly:laravel-passport-keys &>/dev/null chown -R www-data:www-data /opt/firefly chmod -R 775 /opt/firefly/storage - + $STD php artisan migrate --seed --force + $STD php artisan cache:clear + $STD php artisan view:clear + $STD php artisan firefly-iii:upgrade-database + $STD php artisan firefly-iii:laravel-passport-keys echo "${RELEASE}" >"/opt/${APP}_version.txt" msg_ok "Updated ${APP} to v${RELEASE}" @@ -76,4 +74,4 @@ description msg_ok "Completed Successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Access it using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/ghost.sh b/ct/ghost.sh index 7a496b85f..8003ba206 100644 --- a/ct/ghost.sh +++ b/ct/ghost.sh @@ -30,7 +30,7 @@ function update_script() { latest_version=$(npm show ghost-cli version) if [ "$current_version" != "$latest_version" ]; then msg_info "Updating ${APP} from version v${current_version} to v${latest_version}" - npm install -g ghost-cli@latest &> /dev/null + $STD npm install -g ghost-cli@latest msg_ok "Updated Successfully" else msg_ok "${APP} is already at v${current_version}" diff --git a/ct/glpi.sh b/ct/glpi.sh index a25dba350..de03f7dd9 100644 --- a/ct/glpi.sh +++ b/ct/glpi.sh @@ -30,7 +30,7 @@ function update_script() { fi RELEASE=$(curl -s https://api.github.com/repos/glpi-project/glpi/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/') if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then - msg_error "Ther is currently no automatic update function for ${APP}." + msg_error "Currently we don't provide an update function for this ${APP}." else msg_ok "No update required. ${APP} is already at v${RELEASE}." fi diff --git a/ct/gokapi.sh b/ct/gokapi.sh index 868e9a36a..d3cab30f0 100644 --- a/ct/gokapi.sh +++ b/ct/gokapi.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/grafana.sh b/ct/grafana.sh index 0cdd0712a..37afd4496 100644 --- a/ct/grafana.sh +++ b/ct/grafana.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/graylog.sh b/ct/graylog.sh index ffed4bf22..5beed3753 100644 --- a/ct/graylog.sh +++ b/ct/graylog.sh @@ -34,8 +34,8 @@ function update_script() { msg_ok "Stopped $APP" msg_info "Updating $APP" - apt-get update &> /dev/null - apt-get upgrade -y &> /dev/null + $STD apt-get update + $STD apt-get upgrade -y msg_ok "Updated $APP" msg_info "Starting $APP" diff --git a/ct/grist.sh b/ct/grist.sh index f361552e4..217bcba78 100644 --- a/ct/grist.sh +++ b/ct/grist.sh @@ -53,15 +53,15 @@ function update_script() { cd grist msg_info "Installing Dependencies" - yarn install >/dev/null 2>&1 + $STD yarn install msg_ok "Installed Dependencies" msg_info "Building" - yarn run build:prod >/dev/null 2>&1 + $STD yarn run build:prod msg_ok "Done building" msg_info "Installing Python" - yarn run install:python >/dev/null 2>&1 + $STD yarn run install:python msg_ok "Installed Python" echo "${RELEASE}" >/opt/${APP}_version.txt diff --git a/ct/habitica.sh b/ct/habitica.sh new file mode 100644 index 000000000..a85a973ef --- /dev/null +++ b/ct/habitica.sh @@ -0,0 +1,74 @@ +#!/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/HabitRPG/habitica + +APP="Habitica" +var_tags="gaming" +var_cpu="2" +var_ram="4096" +var_disk="8" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d "/opt/habitica" ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/HabitRPG/habitica/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') + if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then + msg_info "Stopping $APP" + systemctl stop habitica-mongodb + systemctl stop habitica + systemctl stop habitica-client + msg_ok "Stopped $APP" + + msg_info "Updating $APP to ${RELEASE}" + temp_file=$(mktemp) + wget -q "https://github.com/HabitRPG/habitica/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file + tar zxf $temp_file + cp -rf habitica-${RELEASE}/* /opt/habitica + cd /opt/habitica + $STD npm i + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to ${RELEASE}" + + msg_info "Starting $APP" + systemctl start habitica-mongodb + systemctl start habitica + systemctl start habitica-client + msg_ok "Started $APP" + + msg_info "Cleaning Up" + rm -f $temp_file + rm -rf ~/habitica-${RELEASE} + msg_ok "Cleanup Completed" + + msg_ok "Update Successful" + 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}:8080${CL}" diff --git a/ct/headers/authelia b/ct/headers/authelia new file mode 100644 index 000000000..ed9aa67a7 --- /dev/null +++ b/ct/headers/authelia @@ -0,0 +1,6 @@ + ___ __ __ ___ + / | __ __/ /_/ /_ ___ / (_)___ _ + / /| |/ / / / __/ __ \/ _ \/ / / __ `/ + / ___ / /_/ / /_/ / / / __/ / / /_/ / +/_/ |_\__,_/\__/_/ /_/\___/_/_/\__,_/ + diff --git a/ct/headers/bytestash b/ct/headers/bytestash new file mode 100644 index 000000000..73089fe1c --- /dev/null +++ b/ct/headers/bytestash @@ -0,0 +1,6 @@ + ____ __ _____ __ __ + / __ )__ __/ /____ / ___// /_____ ______/ /_ + / __ / / / / __/ _ \\__ \/ __/ __ `/ ___/ __ \ + / /_/ / /_/ / /_/ __/__/ / /_/ /_/ (__ ) / / / +/_____/\__, /\__/\___/____/\__/\__,_/____/_/ /_/ + /____/ diff --git a/ct/headers/habitica b/ct/headers/habitica new file mode 100644 index 000000000..144591bb5 --- /dev/null +++ b/ct/headers/habitica @@ -0,0 +1,6 @@ + __ __ __ _ __ _ + / / / /___ _/ /_ (_) /_(_)________ _ + / /_/ / __ `/ __ \/ / __/ / ___/ __ `/ + / __ / /_/ / /_/ / / /_/ / /__/ /_/ / +/_/ /_/\__,_/_.___/_/\__/_/\___/\__,_/ + diff --git a/ct/headers/jupyternotebook b/ct/headers/jupyternotebook new file mode 100644 index 000000000..84965a56a --- /dev/null +++ b/ct/headers/jupyternotebook @@ -0,0 +1,6 @@ + __ __ _ __ __ __ __ + / /_ ______ __ __/ /____ _____ / | / /___ / /____ / /_ ____ ____ / /__ + __ / / / / / __ \/ / / / __/ _ \/ ___/ / |/ / __ \/ __/ _ \/ __ \/ __ \/ __ \/ //_/ +/ /_/ / /_/ / /_/ / /_/ / /_/ __/ / / /| / /_/ / /_/ __/ /_/ / /_/ / /_/ / ,< +\____/\__,_/ .___/\__, /\__/\___/_/ /_/ |_/\____/\__/\___/_.___/\____/\____/_/|_| + /_/ /____/ diff --git a/ct/headers/outline b/ct/headers/outline new file mode 100644 index 000000000..66e98f4d2 --- /dev/null +++ b/ct/headers/outline @@ -0,0 +1,6 @@ + ____ __ ___ + / __ \__ __/ /_/ (_)___ ___ + / / / / / / / __/ / / __ \/ _ \ +/ /_/ / /_/ / /_/ / / / / / __/ +\____/\__,_/\__/_/_/_/ /_/\___/ + diff --git a/ct/headers/pelican-panel b/ct/headers/pelican-panel new file mode 100644 index 000000000..e38095db6 --- /dev/null +++ b/ct/headers/pelican-panel @@ -0,0 +1,6 @@ + ____ ___ ____ __ + / __ \___ / (_)________ _____ / __ \____ _____ ___ / / + / /_/ / _ \/ / / ___/ __ `/ __ \______/ /_/ / __ `/ __ \/ _ \/ / + / ____/ __/ / / /__/ /_/ / / / /_____/ ____/ /_/ / / / / __/ / +/_/ \___/_/_/\___/\__,_/_/ /_/ /_/ \__,_/_/ /_/\___/_/ + diff --git a/ct/headers/pelican-wings b/ct/headers/pelican-wings new file mode 100644 index 000000000..888c4d388 --- /dev/null +++ b/ct/headers/pelican-wings @@ -0,0 +1,6 @@ + ____ ___ _ ___ + / __ \___ / (_)________ _____ | | / (_)___ ____ ______ + / /_/ / _ \/ / / ___/ __ `/ __ \_____| | /| / / / __ \/ __ `/ ___/ + / ____/ __/ / / /__/ /_/ / / / /_____/ |/ |/ / / / / / /_/ (__ ) +/_/ \___/_/_/\___/\__,_/_/ /_/ |__/|__/_/_/ /_/\__, /____/ + /____/ diff --git a/ct/headers/victoriametrics b/ct/headers/victoriametrics new file mode 100644 index 000000000..5e705603d --- /dev/null +++ b/ct/headers/victoriametrics @@ -0,0 +1,6 @@ + _ ___ __ _ __ ___ __ _ +| | / (_)____/ /_____ _____(_)___ _/ |/ /__ / /______(_)_________ +| | / / / ___/ __/ __ \/ ___/ / __ `/ /|_/ / _ \/ __/ ___/ / ___/ ___/ +| |/ / / /__/ /_/ /_/ / / / / /_/ / / / / __/ /_/ / / / /__(__ ) +|___/_/\___/\__/\____/_/ /_/\__,_/_/ /_/\___/\__/_/ /_/\___/____/ + diff --git a/ct/headers/web-check b/ct/headers/web-check new file mode 100644 index 000000000..371062cb9 --- /dev/null +++ b/ct/headers/web-check @@ -0,0 +1,6 @@ + __ __ __ + _ _____ / /_ _____/ /_ ___ _____/ /__ +| | /| / / _ \/ __ \______/ ___/ __ \/ _ \/ ___/ //_/ +| |/ |/ / __/ /_/ /_____/ /__/ / / / __/ /__/ ,< +|__/|__/\___/_.___/ \___/_/ /_/\___/\___/_/|_| + diff --git a/ct/headers/wger b/ct/headers/wger new file mode 100644 index 000000000..85e0a5dd3 --- /dev/null +++ b/ct/headers/wger @@ -0,0 +1,6 @@ + + _ ______ ____ _____ +| | /| / / __ `/ _ \/ ___/ +| |/ |/ / /_/ / __/ / +|__/|__/\__, /\___/_/ + /____/ diff --git a/ct/heimdall-dashboard.sh b/ct/heimdall-dashboard.sh index 7d03954a4..ba31c6bb4 100644 --- a/ct/heimdall-dashboard.sh +++ b/ct/heimdall-dashboard.sh @@ -44,8 +44,8 @@ function update_script() { VER=$(curl -s https://api.github.com/repos/linuxserver/Heimdall/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') cp -R Heimdall-${VER}/* /opt/Heimdall cd /opt/Heimdall - apt-get install -y composer &>/dev/null - COMPOSER_ALLOW_SUPERUSER=1 composer dump-autoload &>/dev/null + $STD apt-get install -y composer + $STD COMPOSER_ALLOW_SUPERUSER=1 composer dump-autoload echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated Heimdall Dashboard to ${RELEASE}" msg_info "Restoring Data" diff --git a/ct/hivemq.sh b/ct/hivemq.sh index 4a07b02bb..52ecea72b 100644 --- a/ct/hivemq.sh +++ b/ct/hivemq.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/hoarder.sh b/ct/hoarder.sh index 739bf59aa..cb69ec3b0 100644 --- a/ct/hoarder.sh +++ b/ct/hoarder.sh @@ -35,7 +35,7 @@ function update_script() { msg_ok "Stopped Services" msg_info "Updating ${APP} to v${RELEASE}" if [[ $(corepack -v) < "0.31.0" ]]; then - npm install -g corepack@0.31.0 &>/dev/null + $STD npm install -g corepack@0.31.0 fi cd /opt if [[ -f /opt/hoarder/.env ]] && [[ ! -f /etc/hoarder/hoarder.env ]]; then @@ -47,14 +47,14 @@ function update_script() { unzip -q v${RELEASE}.zip mv hoarder-${RELEASE} /opt/hoarder cd /opt/hoarder/apps/web - pnpm install --frozen-lockfile &>/dev/null - pnpm exec next build --experimental-build-mode compile &>/dev/null + $STD pnpm install --frozen-lockfile + $STD pnpm exec next build --experimental-build-mode compile cp -r /opt/hoarder/apps/web/.next/standalone/apps/web/server.js /opt/hoarder/apps/web cd /opt/hoarder/apps/workers - pnpm install --frozen-lockfile &>/dev/null + $STD pnpm install --frozen-lockfile export DATA_DIR=/opt/hoarder_data cd /opt/hoarder/packages/db - pnpm migrate &>/dev/null + $STD pnpm migrate sed -i "s/SERVER_VERSION=${PREV_RELEASE}/SERVER_VERSION=${RELEASE}/" /etc/hoarder/hoarder.env msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/homarr.sh b/ct/homarr.sh index fb6a3e8e9..ade524fff 100644 --- a/ct/homarr.sh +++ b/ct/homarr.sh @@ -38,14 +38,22 @@ fi if [[ ! -f /opt/run_homarr.sh ]]; then msg_info "Detected outdated and missing service files" msg_error "Warning - The port of homarr changed from 3000 to 7575" - apt-get install -y nginx gettext openssl gpg &>/dev/null + $STD apt-get install -y nginx gettext openssl gpg sed -i '/^NODE_ENV=/d' /opt/homarr/.env && echo "NODE_ENV='production'" >> /opt/homarr/.env sed -i '/^DB_DIALECT=/d' /opt/homarr/.env && echo "DB_DIALECT='sqlite'" >> /opt/homarr/.env cat <<'EOF' >/opt/run_homarr.sh #!/bin/bash +set -a +source /opt/homarr/.env +set +a export DB_DIALECT='sqlite' export AUTH_SECRET=$(openssl rand -base64 32) node /opt/homarr_db/migrations/$DB_DIALECT/migrate.cjs /opt/homarr_db/migrations/$DB_DIALECT +for dir in $(find /opt/homarr_db/migrations/migrations -mindepth 1 -maxdepth 1 -type d); do + dirname=$(basename "$dir") + mkdir -p "/opt/homarr_db/migrations/$dirname" + cp -r "$dir"/* "/opt/homarr_db/migrations/$dirname/" 2>/dev/null || true +done export HOSTNAME=$(ip route get 1.1.1.1 | grep -oP 'src \K[^ ]+') envsubst '${HOSTNAME}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf nginx -g 'daemon off;' & @@ -85,6 +93,30 @@ fi msg_ok "Backup Data" msg_info "Updating and rebuilding ${APP} to v${RELEASE} (Patience)" + rm /opt/run_homarr.sh + cat <<'EOF' >/opt/run_homarr.sh +#!/bin/bash +set -a +source /opt/homarr/.env +set +a +export DB_DIALECT='sqlite' +export AUTH_SECRET=$(openssl rand -base64 32) +node /opt/homarr_db/migrations/$DB_DIALECT/migrate.cjs /opt/homarr_db/migrations/$DB_DIALECT +for dir in $(find /opt/homarr_db/migrations/migrations -mindepth 1 -maxdepth 1 -type d); do + dirname=$(basename "$dir") + mkdir -p "/opt/homarr_db/migrations/$dirname" + cp -r "$dir"/* "/opt/homarr_db/migrations/$dirname/" 2>/dev/null || true +done +export HOSTNAME=$(ip route get 1.1.1.1 | grep -oP 'src \K[^ ]+') +envsubst '${HOSTNAME}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf +nginx -g 'daemon off;' & +redis-server /opt/homarr/packages/redis/redis.conf & +node apps/tasks/tasks.cjs & +node apps/websocket/wssServer.cjs & +node apps/nextjs/server.js & PID=$! +wait $PID +EOF + chmod +x /opt/run_homarr.sh wget -q "https://github.com/homarr-labs/homarr/archive/refs/tags/v${RELEASE}.zip" unzip -q v${RELEASE}.zip rm -rf v${RELEASE}.zip @@ -92,8 +124,8 @@ fi mv homarr-${RELEASE} /opt/homarr mv /opt/homarr-data-backup/.env /opt/homarr/.env cd /opt/homarr - pnpm install &>/dev/null - pnpm build &>/dev/null + $STD pnpm install + $STD pnpm build cp /opt/homarr/apps/nextjs/next.config.ts . cp /opt/homarr/apps/nextjs/package.json . cp -r /opt/homarr/packages/db/migrations /opt/homarr_db/migrations @@ -116,6 +148,7 @@ fi msg_info "Starting Services" systemctl start homarr + systemctl restart homarr msg_ok "Started Services" msg_ok "Updated Successfully" else diff --git a/ct/homeassistant-core.sh b/ct/homeassistant-core.sh index 78a8ac6f3..ccfd0859c 100644 --- a/ct/homeassistant-core.sh +++ b/ct/homeassistant-core.sh @@ -59,7 +59,7 @@ function update_script() { msg_info "Updating Home Assistant" source /srv/homeassistant/bin/activate - pip install ${BR}--upgrade homeassistant &>/dev/null + $STD pip install ${BR}--upgrade homeassistant msg_ok "Updated Home Assistant" msg_info "Starting Home Assistant" @@ -72,10 +72,10 @@ function update_script() { fi if [ "$UPD" == "2" ]; then msg_info "Installing Home Assistant Community Store (HACS)" - apt update &>/dev/null - apt install -y unzip &>/dev/null + $STD apt update + $STD apt install -y unzip cd .homeassistant - bash <(curl -fsSL https://get.hacs.xyz) &>/dev/null + $STD bash <(curl -fsSL https://get.hacs.xyz) msg_ok "Installed Home Assistant Community Store (HACS)" echo -e "\n Reboot Home Assistant and clear browser cache then Add HACS integration.\n" exit @@ -85,17 +85,17 @@ function update_script() { read -r -p "Would you like to use No Authentication? " prompt msg_info "Installing FileBrowser" RELEASE=$(curl -fsSL https://api.github.com/repos/filebrowser/filebrowser/releases/latest | grep -o '"tag_name": ".*"' | sed 's/"//g' | sed 's/tag_name: //g') - curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/$RELEASE/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null + $STD curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/$RELEASE/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then - filebrowser config init -a '0.0.0.0' &>/dev/null - filebrowser config set -a '0.0.0.0' &>/dev/null - filebrowser config set --auth.method=noauth &>/dev/null - filebrowser users add ID 1 --perm.admin &>/dev/null + $STD filebrowser config init -a '0.0.0.0' + $STD filebrowser config set -a '0.0.0.0' + $STD filebrowser config set --auth.method=noauth + $STD filebrowser users add ID 1 --perm.admin else - filebrowser config init -a '0.0.0.0' &>/dev/null - filebrowser config set -a '0.0.0.0' &>/dev/null - filebrowser users add admin helper-scripts.com --perm.admin &>/dev/null + $STD filebrowser config init -a '0.0.0.0' + $STD filebrowser config set -a '0.0.0.0' + $STD filebrowser users add admin helper-scripts.com --perm.admin fi msg_ok "Installed FileBrowser" diff --git a/ct/homeassistant.sh b/ct/homeassistant.sh index f9fbeecf5..07751f4fe 100644 --- a/ct/homeassistant.sh +++ b/ct/homeassistant.sh @@ -61,10 +61,10 @@ function update_script() { fi if [ "$UPD" == "3" ]; then msg_info "Installing Home Assistant Community Store (HACS)" - apt update &>/dev/null - apt install unzip &>/dev/null + $STD apt update + $STD apt install unzip cd /var/lib/docker/volumes/hass_config/_data - bash <(curl -fsSL https://get.hacs.xyz) &>/dev/null + $STD bash <(curl -fsSL https://get.hacs.xyz) msg_ok "Installed Home Assistant Community Store (HACS)" echo -e "\n Reboot Home Assistant and clear browser cache then Add HACS integration.\n" exit @@ -73,10 +73,10 @@ function update_script() { IP=$(hostname -I | awk '{print $1}') msg_info "Installing FileBrowser" RELEASE=$(curl -fsSL https://api.github.com/repos/filebrowser/filebrowser/releases/latest | grep -o '"tag_name": ".*"' | sed 's/"//g' | sed 's/tag_name: //g') - curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/v2.23.0/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin &>/dev/null - filebrowser config init -a '0.0.0.0' &>/dev/null - filebrowser config set -a '0.0.0.0' &>/dev/null - filebrowser users add admin helper-scripts.com --perm.admin &>/dev/null + $STD curl -fsSL https://github.com/filebrowser/filebrowser/releases/download/v2.23.0/linux-amd64-filebrowser.tar.gz | tar -xzv -C /usr/local/bin + $STD filebrowser config init -a '0.0.0.0' + $STD filebrowser config set -a '0.0.0.0' + $STD filebrowser users add admin helper-scripts.com --perm.admin msg_ok "Installed FileBrowser" msg_info "Creating Service" @@ -91,7 +91,7 @@ ExecStart=/usr/local/bin/filebrowser -r / [Install] WantedBy=default.target" >$service_path - systemctl enable --now filebrowser.service &>/dev/null + $STD systemctl enable --now filebrowser.service msg_ok "Created Service" msg_ok "Completed Successfully!\n" diff --git a/ct/homebridge.sh b/ct/homebridge.sh index abe603c81..b71758812 100644 --- a/ct/homebridge.sh +++ b/ct/homebridge.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get install -y homebridge &>/dev/null + $STD apt-get update + $STD apt-get install -y homebridge msg_ok "Updated Successfully" exit } diff --git a/ct/homepage.sh b/ct/homepage.sh index 6adce7d1a..05c9f2494 100644 --- a/ct/homepage.sh +++ b/ct/homepage.sh @@ -30,8 +30,8 @@ function update_script() { if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then if ! command -v npm >/dev/null 2>&1; then echo "Installing NPM..." - apt-get install -y npm >/dev/null 2>&1 - npm install -g pnpm >/dev/null 2>&1 + $STD apt-get install -y npm + $STD npm install -g pnpm echo "Installed NPM..." fi fi @@ -45,11 +45,11 @@ function update_script() { cp -r homepage-${RELEASE}/* /opt/homepage/ rm -rf homepage-${RELEASE} cd /opt/homepage - npx --yes update-browserslist-db@latest >/dev/null 2>&1 - pnpm install >/dev/null 2>&1 + $STD npx --yes update-browserslist-db@latest + $STD pnpm install export NEXT_PUBLIC_VERSION="v$RELEASE" export NEXT_PUBLIC_REVISION="source" - pnpm build >/dev/null 2>&1 + $STD pnpm build systemctl start homepage echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated Homepage to v${RELEASE}" diff --git a/ct/homer.sh b/ct/homer.sh index 09f9a931b..950c04cd1 100644 --- a/ct/homer.sh +++ b/ct/homer.sh @@ -41,7 +41,7 @@ function update_script() { rm -rf /opt/homer/* cd /opt/homer wget -q https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip - unzip homer.zip &>/dev/null + $STD unzip homer.zip msg_ok "Updated ${APP}" msg_info "Restoring assets directory" diff --git a/ct/hyperhdr.sh b/ct/hyperhdr.sh index 33c6216fe..f59a1f36f 100644 --- a/ct/hyperhdr.sh +++ b/ct/hyperhdr.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/hyperion.sh b/ct/hyperion.sh index 776e883bd..870690be9 100644 --- a/ct/hyperion.sh +++ b/ct/hyperion.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get install -y hyperion &>/dev/null + $STD apt-get update + $STD apt-get install -y hyperion msg_ok "Updated Successfully" exit } diff --git a/ct/influxdb.sh b/ct/influxdb.sh index c3c88dbfa..17646b650 100644 --- a/ct/influxdb.sh +++ b/ct/influxdb.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/inspircd.sh b/ct/inspircd.sh index c187d0f51..a5e057c79 100644 --- a/ct/inspircd.sh +++ b/ct/inspircd.sh @@ -36,7 +36,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" cd /opt wget -q https://github.com/inspircd/inspircd/releases/download/v${RELEASE}/inspircd_${RELEASE}.deb12u1_amd64.deb - apt-get install "./inspircd_${RELEASE}.deb12u1_amd64.deb" -y &>/dev/nul + $STD apt-get install "./inspircd_${RELEASE}.deb12u1_amd64.deb" -y echo "${RELEASE}" >"/opt/${APP}_version.txt" msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/iobroker.sh b/ct/iobroker.sh index 5951b0b19..73d25ee5b 100644 --- a/ct/iobroker.sh +++ b/ct/iobroker.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/iventoy.sh b/ct/iventoy.sh index 2895e4cc6..dc6bd05dd 100644 --- a/ct/iventoy.sh +++ b/ct/iventoy.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/jellyfin.sh b/ct/jellyfin.sh index 2d789cb3f..8433d0cb9 100644 --- a/ct/jellyfin.sh +++ b/ct/jellyfin.sh @@ -28,9 +28,9 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null - apt-get -y --with-new-pkgs upgrade jellyfin jellyfin-server &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade + $STD apt-get -y --with-new-pkgs upgrade jellyfin jellyfin-server msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/jellyseerr.sh b/ct/jellyseerr.sh index 396f2bfb3..cfae7a323 100644 --- a/ct/jellyseerr.sh +++ b/ct/jellyseerr.sh @@ -35,8 +35,8 @@ function update_script() { msg_ok "Updating Node.js Repository" msg_info "Updating Packages" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updating Packages" msg_info "Cleaning up" @@ -53,10 +53,10 @@ function update_script() { if [ -z "$pnpm_current" ]; then msg_error "pnpm not found. Installing version $pnpm_desired..." - npm install -g pnpm@"$pnpm_desired" &>/dev/null + $STD npm install -g pnpm@"$pnpm_desired" elif ! node -e "const semver = require('semver'); process.exit(semver.satisfies('$pnpm_current', '$pnpm_desired') ? 0 : 1)" ; then msg_error "Updating pnpm from version $pnpm_current to $pnpm_desired..." - npm install -g pnpm@"$pnpm_desired" &>/dev/null + $STD npm install -g pnpm@"$pnpm_desired" else msg_ok "pnpm is already installed and satisfies version $pnpm_desired." fi @@ -70,9 +70,9 @@ function update_script() { systemctl stop jellyseerr rm -rf dist .next node_modules export CYPRESS_INSTALL_BINARY=0 - pnpm install --frozen-lockfile &>/dev/null + $STD pnpm install --frozen-lockfile export NODE_OPTIONS="--max-old-space-size=3072" - pnpm build &>/dev/null + $STD pnpm build cat </etc/systemd/system/jellyseerr.service [Unit] diff --git a/ct/jenkins.sh b/ct/jenkins.sh index 391b70619..6d57346ec 100644 --- a/ct/jenkins.sh +++ b/ct/jenkins.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/jupyternotebook.sh b/ct/jupyternotebook.sh new file mode 100644 index 000000000..a40f3ac21 --- /dev/null +++ b/ct/jupyternotebook.sh @@ -0,0 +1,42 @@ +#!/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: Dave-code-creater (Tan Dat, Ta) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://jupyter.org/ + +APP="Jupyter Notebook" +var_tags="ai;dev-tools" +var_cpu="2" +var_ram="2048" +var_disk="4" +var_os="ubuntu" +var_version="24.04" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + msg_info "Updating ${APP} LXC" + $STD apt-get update + $STD apt-get install -y upgrade + $STD pip3 install jupyter --upgrade + msg_ok "Updated Successfully" + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8888${CL}" diff --git a/ct/kavita.sh b/ct/kavita.sh index 866f722d2..00ce169bf 100644 --- a/ct/kavita.sh +++ b/ct/kavita.sh @@ -30,7 +30,7 @@ function update_script() { msg_info "Updating $APP LXC" systemctl stop kavita RELEASE=$(curl -s https://api.github.com/repos/Kareadita/Kavita/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') - tar -xvzf <(curl -fsSL https://github.com/Kareadita/Kavita/releases/download/$RELEASE/kavita-linux-x64.tar.gz) --no-same-owner &>/dev/null + $STD tar -xvzf <(curl -fsSL https://github.com/Kareadita/Kavita/releases/download/$RELEASE/kavita-linux-x64.tar.gz) --no-same-owner rm -rf Kavita/config cp -r Kavita/* /opt/Kavita rm -rf Kavita diff --git a/ct/keycloak.sh b/ct/keycloak.sh index 09a44e49a..7a492c1ca 100644 --- a/ct/keycloak.sh +++ b/ct/keycloak.sh @@ -30,8 +30,8 @@ function update_script() { msg_info "Updating ${APP} LXC" msg_info "Updating packages" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade RELEASE=$(curl -s https://api.github.com/repos/keycloak/keycloak/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') msg_info "Updating Keycloak to v$RELEASE" diff --git a/ct/kimai.sh b/ct/kimai.sh index 06313043b..396257b07 100644 --- a/ct/kimai.sh +++ b/ct/kimai.sh @@ -35,19 +35,22 @@ function update_script() { msg_info "Updating ${APP} to ${RELEASE}" cp /opt/kimai/.env /opt/.env + [ -f /opt/kimai/config/packages/local.yaml ] && cp /opt/kimai/config/packages/local.yaml /opt/local.yaml rm -rf /opt/kimai wget -q "https://github.com/kimai/kimai/archive/refs/tags/${RELEASE}.zip" unzip -q ${RELEASE}.zip mv kimai-${RELEASE} /opt/kimai mv /opt/.env /opt/kimai/.env + [ -f /opt/local.yaml ] && mv /opt/local.yaml /opt/kimai/config/packages/local.yaml cd /opt/kimai - composer install --no-dev --optimize-autoloader &>/dev/null - bin/console kimai:update &>/dev/null + $STD composer install --no-dev --optimize-autoloader + $STD bin/console kimai:update chown -R :www-data . chmod -R g+r . chmod -R g+rw var/ - sudo chown -R www-data:www-data /opt/kimai - sudo chmod -R 755 /opt/kimai + chmod -R 777 /opt/kimai/var/ + chown -R www-data:www-data /opt/kimai + chmod -R 755 /opt/kimai echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to ${RELEASE}" @@ -72,4 +75,4 @@ description msg_ok "Completed Successfully!\n" echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" echo -e "${INFO}${YW} Access it using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/ct/koillection.sh b/ct/koillection.sh index 64dfde90d..31af04542 100644 --- a/ct/koillection.sh +++ b/ct/koillection.sh @@ -43,12 +43,12 @@ function update_script() { cp -r /opt/koillection-backup/.env.local /opt/koillection cp -r /opt/koillection-backup/public/uploads/. /opt/koillection/public/uploads/ export COMPOSER_ALLOW_SUPERUSER=1 - composer install --no-dev -o --no-interaction --classmap-authoritative &>/dev/null - php bin/console doctrine:migrations:migrate --no-interaction &>/dev/null - php bin/console app:translations:dump &>/dev/null + $STD composer install --no-dev -o --no-interaction --classmap-authoritative + $STD php bin/console doctrine:migrations:migrate --no-interaction + $STD php bin/console app:translations:dump cd assets/ - yarn install &>/dev/null - yarn build &>/dev/null + $STD yarn install + $STD yarn build chown -R www-data:www-data /opt/koillection/public/uploads echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" diff --git a/ct/kometa.sh b/ct/kometa.sh index 76d4adba3..757ad69db 100644 --- a/ct/kometa.sh +++ b/ct/kometa.sh @@ -46,7 +46,7 @@ function update_script() { mv Kometa-${RELEASE} /opt/kometa cd /opt/kometa rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED - pip install -r requirements.txt --ignore-installed &> /dev/null + $STD pip install -r requirements.txt --ignore-installed mkdir -p config/assets cp /opt/config.yml config/config.yml echo "${RELEASE}" >/opt/kometa_version.txt diff --git a/ct/komodo.sh b/ct/komodo.sh index d2069a282..2b59b6117 100644 --- a/ct/komodo.sh +++ b/ct/komodo.sh @@ -54,7 +54,7 @@ function update_script() { exit 1 } - docker compose -p komodo -f "/opt/komodo/$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d &>/dev/null + $STD docker compose -p komodo -f "/opt/komodo/$COMPOSE_FILE" --env-file /opt/komodo/compose.env up -d msg_ok "Updated ${APP}" } diff --git a/ct/kubo.sh b/ct/kubo.sh index 2d387becd..0a3bac10a 100644 --- a/ct/kubo.sh +++ b/ct/kubo.sh @@ -30,8 +30,8 @@ function update_script() { RELEASE=$(wget -q https://github.com/ipfs/kubo/releases/latest -O - | grep "title>Release" | cut -d " " -f 4) if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade wget -q "https://github.com/ipfs/kubo/releases/download/${RELEASE}/kubo_${RELEASE}_linux-amd64.tar.gz" tar -xzf "kubo_${RELEASE}_linux-amd64.tar.gz" -C /usr/local systemctl restart ipfs.service diff --git a/ct/lazylibrarian.sh b/ct/lazylibrarian.sh index 030831d4e..f648b2748 100644 --- a/ct/lazylibrarian.sh +++ b/ct/lazylibrarian.sh @@ -32,7 +32,7 @@ function update_script() { msg_ok "LazyLibrarian Stopped" msg_info "Updating $APP LXC" - git -C /opt/LazyLibrarian pull origin master &>/dev/null + $STD git -C /opt/LazyLibrarian pull origin master msg_ok "Updated $APP LXC" msg_info "Starting LazyLibrarian" diff --git a/ct/lidarr.sh b/ct/lidarr.sh index da0a39214..f0878246b 100644 --- a/ct/lidarr.sh +++ b/ct/lidarr.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/linkwarden.sh b/ct/linkwarden.sh index 3c862bb5a..d8ae54934 100644 --- a/ct/linkwarden.sh +++ b/ct/linkwarden.sh @@ -32,6 +32,15 @@ function update_script() { systemctl stop linkwarden msg_ok "Stopped ${APP}" + msg_info "Updating Rust" + $STD apt-get install -y build-essential + $STD curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source $HOME/.cargo/env + echo 'export PATH=/usr/local/cargo/bin:$PATH' >> /etc/profile + source /etc/profile + $STD cargo install monolith + msg_ok "Updated Rust" + msg_info "Updating ${APP} to ${RELEASE}" cd /opt mv /opt/linkwarden/.env /opt/.env @@ -41,12 +50,12 @@ function update_script() { unzip -q ${RELEASE}.zip mv linkwarden-${RELEASE:1} /opt/linkwarden cd /opt/linkwarden - yarn &>/dev/null - npx playwright install-deps &>/dev/null - yarn playwright install &>/dev/null + $STD yarn + $STD npx playwright install-deps + $STD yarn playwright install cp /opt/.env /opt/linkwarden/.env - yarn build &>/dev/null - yarn prisma migrate deploy &>/dev/null + $STD yarn build + $STD yarn prisma migrate deploy echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to ${RELEASE}" diff --git a/ct/listmonk.sh b/ct/listmonk.sh index 9a1c0c156..e95f7e3f8 100644 --- a/ct/listmonk.sh +++ b/ct/listmonk.sh @@ -42,7 +42,7 @@ function update_script() { tar -xzf "listmonk_${RELEASE}_linux_amd64.tar.gz" -C /opt/listmonk mv /opt/listmonk-backup/config.toml /opt/listmonk/config.toml mv /opt/listmonk-backup/uploads /opt/listmonk/uploads - /opt/listmonk/listmonk --upgrade --yes --config /opt/listmonk/config.toml &>/dev/null + $STD /opt/listmonk/listmonk --upgrade --yes --config /opt/listmonk/config.toml echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" diff --git a/ct/magicmirror.sh b/ct/magicmirror.sh index 3cbe6bf05..67ec9b0ce 100644 --- a/ct/magicmirror.sh +++ b/ct/magicmirror.sh @@ -50,7 +50,7 @@ function update_script() { rm -rf /opt/magicmirror mv MagicMirror-${RELEASE} /opt/magicmirror cd /opt/magicmirror - npm run install-mm &> /dev/null + $STD npm run install-mm cp /opt/magicmirror-backup/config.js /opt/magicmirror/config/ if [[ -f /opt/magicmirror-backup/custom.css ]]; then cp /opt/magicmirror-backup/custom.css /opt/magicmirror/css/ diff --git a/ct/mariadb.sh b/ct/mariadb.sh index d1db6d030..76be07d9c 100644 --- a/ct/mariadb.sh +++ b/ct/mariadb.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/mattermost.sh b/ct/mattermost.sh index 485962870..910d00bd2 100644 --- a/ct/mattermost.sh +++ b/ct/mattermost.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/mediamtx.sh b/ct/mediamtx.sh index 05d3bfebb..f6022fc41 100644 --- a/ct/mediamtx.sh +++ b/ct/mediamtx.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/memos.sh b/ct/memos.sh index ef854296e..e10c300e3 100644 --- a/ct/memos.sh +++ b/ct/memos.sh @@ -37,13 +37,13 @@ function update_script() { fi systemctl stop memos cd /opt/memos/web - pnpm i --frozen-lockfile &>/dev/null - pnpm build &>/dev/null + $STD pnpm i --frozen-lockfile + $STD pnpm build cd /opt/memos mkdir -p /opt/memos/server/dist cp -r web/dist/* /opt/memos/server/dist/ cp -r web/dist/* /opt/memos/server/router/frontend/dist/ - go build -o /opt/memos/memos -tags=embed bin/memos/main.go &>/dev/null + $STD go build -o /opt/memos/memos -tags=embed bin/memos/main.go systemctl start memos msg_ok "Updated $APP" exit diff --git a/ct/meshcentral.sh b/ct/meshcentral.sh index 77b6fb0d9..d945c021e 100644 --- a/ct/meshcentral.sh +++ b/ct/meshcentral.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/metube.sh b/ct/metube.sh index 45c9666f9..c6b838e92 100644 --- a/ct/metube.sh +++ b/ct/metube.sh @@ -37,14 +37,14 @@ function update_script() { rm -rf metube_bak fi mv metube metube_bak - git clone https://github.com/alexta69/metube /opt/metube >/dev/null 2>&1 + $STD git clone https://github.com/alexta69/metube /opt/metube cd /opt/metube/ui - npm install >/dev/null 2>&1 - node_modules/.bin/ng build >/dev/null 2>&1 + $STD npm install + $STD node_modules/.bin/ng build cd /opt/metube cp /opt/metube_bak/.env /opt/metube/ - pip3 install pipenv >/dev/null 2>&1 - pipenv install >/dev/null 2>&1 + $STD pip3 install pipenv + $STD pipenv install if [ -d "/opt/metube_bak" ]; then rm -rf /opt/metube_bak diff --git a/ct/mongodb.sh b/ct/mongodb.sh index 5a3bbe3e3..8dbffca86 100644 --- a/ct/mongodb.sh +++ b/ct/mongodb.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/monica.sh b/ct/monica.sh index 3a43f7e1a..7c84f2197 100644 --- a/ct/monica.sh +++ b/ct/monica.sh @@ -42,10 +42,10 @@ function update_script() { cd /opt/monica/ cp -r /opt/monica-backup/.env /opt/monica cp -r /opt/monica-backup/storage/* /opt/monica/storage/ - composer install --no-interaction --no-dev &>/dev/null - yarn install &>/dev/null - yarn run production &>/dev/null - php artisan monica:update --force &>/dev/null + $STD composer install --no-interaction --no-dev + $STD yarn install + $STD yarn run production + $STD php artisan monica:update --force chown -R www-data:www-data /opt/monica chmod -R 775 /opt/monica/storage echo "${RELEASE}" >/opt/${APP}_version.txt diff --git a/ct/motioneye.sh b/ct/motioneye.sh index 2b114a1d2..43fc6e242 100644 --- a/ct/motioneye.sh +++ b/ct/motioneye.sh @@ -28,7 +28,7 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - pip install motioneye --upgrade &>/dev/null + $STD pip install motioneye --upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/mqtt.sh b/ct/mqtt.sh index 302fea243..327f3da04 100644 --- a/ct/mqtt.sh +++ b/ct/mqtt.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/myspeed.sh b/ct/myspeed.sh index 80fb0e01e..371389c63 100644 --- a/ct/myspeed.sh +++ b/ct/myspeed.sh @@ -41,7 +41,7 @@ function update_script() { wget -q https://github.com/gnmyt/myspeed/releases/download/v$RELEASE/MySpeed-$RELEASE.zip unzip -q MySpeed-$RELEASE.zip -d myspeed cd myspeed - npm install >/dev/null 2>&1 + $STD npm install echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to ${RELEASE}" diff --git a/ct/mysql.sh b/ct/mysql.sh index a0e063c64..193144ed3 100644 --- a/ct/mysql.sh +++ b/ct/mysql.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/n8n.sh b/ct/n8n.sh index 9a75b2a2b..9182dc4f1 100644 --- a/ct/n8n.sh +++ b/ct/n8n.sh @@ -30,12 +30,12 @@ function update_script() { if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then if ! command -v npm >/dev/null 2>&1; then echo "Installing NPM..." - apt-get install -y npm >/dev/null 2>&1 + $STD apt-get install -y npm echo "Installed NPM..." fi fi msg_info "Updating ${APP} LXC" - npm update -g n8n &>/dev/null + $STD npm update -g n8n systemctl restart n8n msg_ok "Updated Successfully" exit diff --git a/ct/navidrome.sh b/ct/navidrome.sh index a3577541a..e5099be4b 100644 --- a/ct/navidrome.sh +++ b/ct/navidrome.sh @@ -35,7 +35,7 @@ function update_script() { msg_info "Updating to v${RELEASE}" cd /opt wget -q https://github.com/navidrome/navidrome/releases/download/v${RELEASE}/navidrome_${RELEASE}_linux_amd64.tar.gz -O Navidrome.tar.gz - tar -xvzf Navidrome.tar.gz -C /opt/navidrome/ &>/dev/null + $STD tar -xvzf Navidrome.tar.gz -C /opt/navidrome/ chmod +x /opt/navidrome/navidrome msg_ok "Updated ${APP}" rm -rf /opt/Navidrome.tar.gz diff --git a/ct/neo4j.sh b/ct/neo4j.sh index 80164322d..9ef98ecea 100644 --- a/ct/neo4j.sh +++ b/ct/neo4j.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/netbox.sh b/ct/netbox.sh index 240657fb6..f5ca61120 100644 --- a/ct/netbox.sh +++ b/ct/netbox.sh @@ -56,7 +56,7 @@ function update_script() { cp -r /opt/netbox-backup/netbox/netbox/ldap_config.py /opt/netbox/netbox/netbox/ fi - /opt/netbox/upgrade.sh &>/dev/null + $STD /opt/netbox/upgrade.sh echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" diff --git a/ct/nextcloudpi.sh b/ct/nextcloudpi.sh index f2bd834d0..69d5fa070 100644 --- a/ct/nextcloudpi.sh +++ b/ct/nextcloudpi.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/nextpvr.sh b/ct/nextpvr.sh index 99b5656c3..36b38b27b 100644 --- a/ct/nextpvr.sh +++ b/ct/nextpvr.sh @@ -32,14 +32,14 @@ function update_script() { msg_ok "Stopped ${APP}" msg_info "Updating LXC packages" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated LXC packages" msg_info "Updating ${APP}" cd /opt wget -q https://nextpvr.com/nextpvr-helper.deb - dpkg -i nextpvr-helper.deb &>/dev/null + $STD dpkg -i nextpvr-helper.deb msg_ok "Updated ${APP}" msg_info "Starting ${APP}" diff --git a/ct/nginxproxymanager.sh b/ct/nginxproxymanager.sh index 717a4d95e..a01e7ac75 100644 --- a/ct/nginxproxymanager.sh +++ b/ct/nginxproxymanager.sh @@ -30,7 +30,7 @@ function update_script() { if ! command -v pnpm &> /dev/null; then msg_info "Installing pnpm" #export NODE_OPTIONS=--openssl-legacy-provider - npm install -g pnpm@8.15 &>/dev/null + $STD npm install -g pnpm@8.15 msg_ok "Installed pnpm" fi RELEASE=$(curl -s https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest | @@ -47,11 +47,11 @@ function update_script() { /etc/nginx \ /var/log/nginx \ /var/lib/nginx \ - /var/cache/nginx &>/dev/null + $STD /var/cache/nginx msg_ok "Cleaned Old Files" msg_info "Downloading NPM v${RELEASE}" - wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz &>/dev/null + $STD wget -q https://codeload.github.com/NginxProxyManager/nginx-proxy-manager/tar.gz/v${RELEASE} -O - | tar -xz cd nginx-proxy-manager-${RELEASE} msg_ok "Downloaded NPM v${RELEASE}" @@ -96,25 +96,25 @@ function update_script() { chown root /tmp/nginx echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" >/etc/nginx/conf.d/include/resolvers.conf if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]; then - openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem &>/dev/null + $STD openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost" -keyout /data/nginx/dummykey.pem -out /data/nginx/dummycert.pem fi mkdir -p /app/global /app/frontend/images cp -r backend/* /app cp -r global/* /app/global - python3 -m pip install --no-cache-dir certbot-dns-cloudflare &>/dev/null + $STD python3 -m pip install --no-cache-dir certbot-dns-cloudflare msg_ok "Setup Enviroment" msg_info "Building Frontend" cd ./frontend - pnpm install &>/dev/null - pnpm upgrade &>/dev/null - pnpm run build &>/dev/null + $STD pnpm install + $STD pnpm upgrade + $STD pnpm run build cp -r dist/* /app/frontend cp -r app-images/* /app/frontend/images msg_ok "Built Frontend" msg_info "Initializing Backend" - rm -rf /app/config/default.json &>/dev/null + $STD rm -rf /app/config/default.json if [ ! -f /app/config/production.json ]; then cat <<'EOF' >/app/config/production.json { @@ -131,7 +131,7 @@ function update_script() { EOF fi cd /app - pnpm install &>/dev/null + $STD pnpm install msg_ok "Initialized Backend" msg_info "Starting Services" diff --git a/ct/node-red.sh b/ct/node-red.sh index 0bde53d89..dcb1ab380 100644 --- a/ct/node-red.sh +++ b/ct/node-red.sh @@ -35,7 +35,7 @@ function update_script() { if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then if ! command -v npm >/dev/null 2>&1; then msg_info "Installing NPM" - apt-get install -y npm >/dev/null 2>&1 + $STD apt-get install -y npm msg_ok "Installed NPM" fi fi @@ -44,7 +44,7 @@ function update_script() { msg_ok "Stopped ${APP}" msg_info "Updating ${APP}" - npm install -g --unsafe-perm node-red &>/dev/null + $STD npm install -g --unsafe-perm node-red msg_ok "Updated ${APP}" msg_info "Starting ${APP}" @@ -84,7 +84,7 @@ function update_script() { msg_info "Installing ${THEME} Theme" cd /root/.node-red sed -i 's|// theme: ".*",|theme: "",|g' /root/.node-red/settings.js - npm install @node-red-contrib-themes/theme-collection &>/dev/null + $STD npm install @node-red-contrib-themes/theme-collection sed -i "{s/theme: ".*"/theme: '${THEME}',/g}" /root/.node-red/settings.js systemctl restart nodered msg_ok "Installed ${THEME} Theme" diff --git a/ct/nodebb.sh b/ct/nodebb.sh index 7317abe7f..4b79273a8 100644 --- a/ct/nodebb.sh +++ b/ct/nodebb.sh @@ -39,7 +39,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" cd /opt/nodebb - ./nodebb upgrade >/dev/null 2>&1 + $STD ./nodebb upgrade echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/notifiarr.sh b/ct/notifiarr.sh index de9f241f2..64e037b57 100644 --- a/ct/notifiarr.sh +++ b/ct/notifiarr.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP" exit } diff --git a/ct/ntfy.sh b/ct/ntfy.sh index 324fcc2ac..f66dbe96a 100644 --- a/ct/ntfy.sh +++ b/ct/ntfy.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/nxwitness.sh b/ct/nxwitness.sh index 35fb307a8..ebcbe69cd 100644 --- a/ct/nxwitness.sh +++ b/ct/nxwitness.sh @@ -41,7 +41,7 @@ function update_script() { wget -q "$DOWNLOAD_URL" -O "nxwitness-server-$RELEASE-linux_x64.deb" export DEBIAN_FRONTEND=noninteractive export DEBCONF_NOWARNINGS=yes - dpkg -i nxwitness-server-$RELEASE-linux_x64.deb >/dev/null 2>&1 + $STD dpkg -i nxwitness-server-$RELEASE-linux_x64.deb echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP}" diff --git a/ct/nzbget.sh b/ct/nzbget.sh index 2413dd34c..c6beadcba 100644 --- a/ct/nzbget.sh +++ b/ct/nzbget.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/octoprint.sh b/ct/octoprint.sh index 2a453c070..43363f594 100644 --- a/ct/octoprint.sh +++ b/ct/octoprint.sh @@ -33,7 +33,7 @@ function update_script() { msg_info "Updating OctoPrint" source /opt/octoprint/bin/activate - pip3 install octoprint --upgrade &>/dev/null + $STD pip3 install octoprint --upgrade msg_ok "Updated OctoPrint" msg_info "Starting OctoPrint" diff --git a/ct/ollama.sh b/ct/ollama.sh index 03de9be5d..d591edbde 100644 --- a/ct/ollama.sh +++ b/ct/ollama.sh @@ -27,8 +27,8 @@ function update_script() { exit fi msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/omada.sh b/ct/omada.sh index 29268da20..b539c9374 100644 --- a/ct/omada.sh +++ b/ct/omada.sh @@ -27,18 +27,33 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi + + msg_info "Updating MongoDB" + MONGODB_VERSION="7.0" + if ! lscpu | grep -q 'avx'; then + MONGODB_VERSION="4.4" + msg_error "No AVX detected: TP-Link Canceled Support for Old MongoDB for Debian 12\n https://www.tp-link.com/baltic/support/faq/4160/" + exit 1 + fi + + wget -qO- https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc | gpg --dearmor >/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg + echo "deb [signed-by=/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg] http://repo.mongodb.org/apt/debian $(grep '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)/mongodb-org/${MONGODB_VERSION} main" >/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}.list + $STD apt-get update + $STD apt-get install -y --only-upgrade mongodb-org + msg_ok "Updated MongoDB to $MONGODB_VERSION" + + msg_info "Updating Omada Controller" latest_url=$(curl -s "https://support.omadanetworks.com/en/product/omada-software-controller/?resourceType=download" | grep -o 'https://static\.tp-link\.com/upload/software/[^"]*linux_x64[^"]*\.deb' | head -n 1) latest_version=$(basename "$latest_url") if [ -z "${latest_version}" ]; then msg_error "It seems that the server (tp-link.com) might be down. Please try again at a later time." exit fi - echo -e "Updating Omada Controller" + wget -qL ${latest_url} dpkg -i ${latest_version} rm -rf ${latest_version} - echo -e "Updated Omada Controller" - exit + msg_ok "Updated Omada Controller" } start diff --git a/ct/omv.sh b/ct/omv.sh index b8636f69b..1df48a1d5 100644 --- a/ct/omv.sh +++ b/ct/omv.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/onedev.sh b/ct/onedev.sh index 4b095a8c2..1b6289575 100644 --- a/ct/onedev.sh +++ b/ct/onedev.sh @@ -37,7 +37,7 @@ function update_script() { cd /opt wget -q https://code.onedev.io/onedev/server/~site/onedev-latest.tar.gz tar -xzf onedev-latest.tar.gz - /opt/onedev-latest/bin/upgrade.sh /opt/onedev >/dev/null + $STD /opt/onedev-latest/bin/upgrade.sh /opt/onedev RELEASE=$(cat /opt/onedev/release.properties | grep "version" | cut -d'=' -f2) echo "${RELEASE}" >"/opt/${APP}_version.txt" msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/opengist.sh b/ct/opengist.sh index 56d130f77..d49ffda65 100644 --- a/ct/opengist.sh +++ b/ct/opengist.sh @@ -34,8 +34,8 @@ function update_script() { msg_ok "Stopped Service" msg_info "Updating ${APP} to v${RELEASE}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade cd /opt mv /opt/opengist /opt/opengist-backup wget -q "https://github.com/thomiceli/opengist/releases/download/v${RELEASE}/opengist${RELEASE}-linux-arm64.tar.gz" @@ -52,8 +52,8 @@ function update_script() { msg_info "Cleaning up" rm -rf /opt/opengist${RELEASE}-linux-amd64.tar.gz rm -rf /opt/opengist-backup - apt-get -y autoremove &>/dev/null - apt-get -y autoclean &>/dev/null + $STD apt-get -y autoremove + $STD apt-get -y autoclean msg_ok "Cleaned" msg_ok "Updated Successfully" else diff --git a/ct/openhab.sh b/ct/openhab.sh index 52335d7f8..827235bff 100644 --- a/ct/openhab.sh +++ b/ct/openhab.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/openwebui.sh b/ct/openwebui.sh index 96efd35d1..950b93ccd 100644 --- a/ct/openwebui.sh +++ b/ct/openwebui.sh @@ -35,11 +35,11 @@ function update_script() { exit fi systemctl stop open-webui.service - npm install &>/dev/null + $STD npm install export NODE_OPTIONS="--max-old-space-size=3584" - npm run build &>/dev/null + $STD npm run build cd ./backend - pip install -r requirements.txt -U &>/dev/null + $STD pip install -r requirements.txt -U systemctl start open-webui.service msg_ok "Updated Successfully" exit diff --git a/ct/outline.sh b/ct/outline.sh new file mode 100644 index 000000000..a303be7e9 --- /dev/null +++ b/ct/outline.sh @@ -0,0 +1,71 @@ +#!/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/outline/outline + +APP="Outline" +var_tags="documentation" +var_disk="8" +var_cpu="2" +var_ram="4096" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/outline ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/outline/outline/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 outline + msg_ok "Services Stopped" + + msg_info "Updating ${APP} to ${RELEASE}" + temp_file=$(mktemp) + rm -rf /opt/outline/node_modules + wget -q "https://github.com/outline/outline/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file + tar zxf $temp_file + cp -rf outline-${RELEASE}/* /opt/outline + cd /opt/outline + export NODE_OPTIONS="--max-old-space-size=3584" + $STD yarn install --frozen-lockfile + $STD yarn build + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated ${APP}" + + msg_info "Starting Services" + systemctl start outline + msg_ok "Started Services" + + msg_info "Cleaning Up" + rm -rf $temp_file + rm -rf $HOME/outline-${RELEASE} + msg_ok "Cleaned" + msg_ok "Updated Successfully" + 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}:3000${CL}" diff --git a/ct/overseerr.sh b/ct/overseerr.sh index 74f9dd523..ee30d7553 100644 --- a/ct/overseerr.sh +++ b/ct/overseerr.sh @@ -31,14 +31,14 @@ function update_script() { systemctl stop overseerr cd /opt/overseerr output=$(git pull) - git pull &>/dev/null + $STD git pull if echo "$output" | grep -q "Already up to date."; then msg_ok " $APP is already up to date." systemctl start overseerr exit fi - yarn install &>/dev/null - yarn build &>/dev/null + $STD yarn install + $STD yarn build systemctl start overseerr msg_ok "Updated $APP" exit diff --git a/ct/owncast.sh b/ct/owncast.sh index 7ac45b0c9..6bca61e23 100644 --- a/ct/owncast.sh +++ b/ct/owncast.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/paperless-ai.sh b/ct/paperless-ai.sh index c4e02d1d5..60cd99faf 100644 --- a/ct/paperless-ai.sh +++ b/ct/paperless-ai.sh @@ -42,7 +42,7 @@ function update_script() { mkdir -p /opt/paperless-ai/data cp -a /opt/paperless-ai_bak/data/. /opt/paperless-ai/data/ cd /opt/paperless-ai - npm install &>/dev/null + $STD npm install echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" diff --git a/ct/paperless-ngx.sh b/ct/paperless-ngx.sh index 7bde9b7e5..429cfa0a6 100644 --- a/ct/paperless-ngx.sh +++ b/ct/paperless-ngx.sh @@ -41,9 +41,9 @@ function update_script() { wget -q https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10040/ghostscript-10.04.0.tar.gz tar -xzf ghostscript-10.04.0.tar.gz cd ghostscript-10.04.0 - ./configure &>/dev/null - make &>/dev/null - sudo make install &>/dev/null + $STD ./configure + $STD make + $STD sudo make install rm -rf /tmp/ghostscript* msg_ok "Ghostscript updated to 10.04.0" fi @@ -58,9 +58,9 @@ function update_script() { cp -r /opt/paperless/paperless.conf paperless-ngx/ cp -r paperless-ngx/* /opt/paperless/ cd /opt/paperless - pip install -r requirements.txt &>/dev/null + $STD pip install -r requirements.txt cd /opt/paperless/src - /usr/bin/python3 manage.py migrate &>/dev/null + $STD /usr/bin/python3 manage.py migrate echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated to ${RELEASE}" diff --git a/ct/part-db.sh b/ct/part-db.sh index 542642bb4..16fe9d720 100644 --- a/ct/part-db.sh +++ b/ct/part-db.sh @@ -46,11 +46,11 @@ function update_script() { cp -r "/opt/partdb-backup/config/banner.md" /opt/partdb/config/ export COMPOSER_ALLOW_SUPERUSER=1 - composer install --no-dev -o --no-interaction &>/dev/null - yarn install &>/dev/null - yarn build &>/dev/null - php bin/console cache:clear &>/dev/null - php bin/console doctrine:migrations:migrate -n &>/dev/null + $STD composer install --no-dev -o --no-interaction + $STD yarn install + $STD yarn build + $STD php bin/console cache:clear + $STD php bin/console doctrine:migrations:migrate -n chown -R www-data:www-data /opt/partdb echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to v${RELEASE}" diff --git a/ct/paymenter.sh b/ct/paymenter.sh index fbdf78466..9bab05f48 100644 --- a/ct/paymenter.sh +++ b/ct/paymenter.sh @@ -33,7 +33,7 @@ function update_script() { msg_info "Updating ${APP} to ${RELEASE}" echo "${RELEASE}" >/opt/${APP}_version.txt cd /opt/paymenter - php artisan p:upgrade --no-interaction &>/dev/null + $STD php artisan p:upgrade --no-interaction msg_ok "Updated Successfully" else msg_ok "No update required. ${APP} is already at ${RELEASE}." diff --git a/ct/peanut.sh b/ct/peanut.sh index eabec1d95..3d4a28c26 100644 --- a/ct/peanut.sh +++ b/ct/peanut.sh @@ -35,8 +35,8 @@ function update_script() { tar -xzf peanut.tar.gz -C /opt/peanut --strip-components 1 rm peanut.tar.gz cd /opt/peanut - pnpm i &>/dev/null - pnpm run build &>/dev/null + $STD pnpm i + $STD pnpm run build cp -r .next/static .next/standalone/.next/ mkdir -p /opt/peanut/.next/standalone/config ln -sf /etc/peanut/settings.yml /opt/peanut/.next/standalone/config/settings.yml diff --git a/ct/pelican-panel.sh b/ct/pelican-panel.sh new file mode 100644 index 000000000..bb7467511 --- /dev/null +++ b/ct/pelican-panel.sh @@ -0,0 +1,76 @@ +#!/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: bvdberg01 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/pelican-dev/panel + +APP="Pelican-Panel" +var_tags="Gaming" +var_cpu="2" +var_ram="1024" +var_disk="4" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/pelican-panel ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/pelican-dev/panel/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 Service" + cd /opt/pelican-panel + $STD php artisan down + msg_ok "Stopped Service" + + msg_info "Updating ${APP} to v${RELEASE}" + cp -r /opt/pelican-panel/.env /opt/ + rm -rf * .* + wget -q "https://github.com/pelican-dev/panel/releases/download/v${RELEASE}/panel.tar.gz" + tar -xzf "panel.tar.gz" + mv /opt/.env /opt/pelican-panel/ + $STD composer install --no-dev --optimize-autoloader --no-interaction + $STD php artisan p:environment:setup + $STD php artisan view:clear + $STD php artisan config:clear + $STD php artisan filament:optimize + $STD php artisan migrate --seed --force + chown -R www-data:www-data /opt/pelican-panel + chmod -R 755 /opt/pelican-panel/storage /opt/pelican-panel/bootstrap/cache/ + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Starting Service" + $STD php artisan queue:restart + $STD php artisan up + msg_ok "Started Service" + + msg_info "Cleaning up" + rm -rf "/opt/pelican-panel/panel.tar.gz" + 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}/installer${CL}" diff --git a/ct/pelican-wings.sh b/ct/pelican-wings.sh new file mode 100644 index 000000000..ff871626a --- /dev/null +++ b/ct/pelican-wings.sh @@ -0,0 +1,58 @@ +#!/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: bvdberg01 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/pelican-dev/wings + +APP="Pelican-Wings" +var_tags="Gaming" +var_cpu="2" +var_ram="4096" +var_disk="8" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -f /usr/local/bin/wings ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/pelican-dev/wings/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 Service" + systemctl stop wings + msg_ok "Stopped Service" + + msg_info "Updating ${APP} to v${RELEASE}" + rm /usr/local/bin/wings + wget -q -O /usr/local/bin/wings "https://github.com/pelican-dev/wings/releases/download/v${RELEASE}/wings_linux_amd64" + chmod u+x /usr/local/bin/wings + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Starting Service" + systemctl start wings + msg_ok "Started Service" + 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}" \ No newline at end of file diff --git a/ct/pf2etools.sh b/ct/pf2etools.sh index c5d1ab3ae..937e4d767 100644 --- a/ct/pf2etools.sh +++ b/ct/pf2etools.sh @@ -32,8 +32,8 @@ function update_script() { RELEASE=$(curl -s https://api.github.com/repos/Pf2eToolsOrg/Pf2eTools/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 msg_info "Updating System" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated System" msg_info "Updating ${APP}" @@ -43,8 +43,8 @@ function update_script() { rm -rf "/opt/${APP}" mv ${APP}-${RELEASE:1} /opt/${APP} cd /opt/Pf2eTools - npm install &>/dev/null - npm run build &>/dev/null + $STD npm install + $STD npm run build chown -R www-data: "/opt/${APP}" chmod -R 755 "/opt/${APP}" echo "${RELEASE}" >"/opt/${APP}_version.txt" diff --git a/ct/photoprism.sh b/ct/photoprism.sh index d9631d65d..1d3e2ba2d 100644 --- a/ct/photoprism.sh +++ b/ct/photoprism.sh @@ -32,7 +32,7 @@ function update_script() { msg_ok "Stopped PhotoPrism" msg_info "Updating PhotoPrism" - apt-get install -y libvips42 &>/dev/null + $STD apt-get install -y libvips42 wget -q -cO - https://dl.photoprism.app/pkg/linux/amd64.tar.gz | tar -xzf - -C /opt/photoprism --strip-components=1 msg_ok "Updated PhotoPrism" diff --git a/ct/pingvin.sh b/ct/pingvin.sh index 6b1487a11..dbc7937a4 100644 --- a/ct/pingvin.sh +++ b/ct/pingvin.sh @@ -42,11 +42,11 @@ function update_script() { cp -rf pingvin-share-${RELEASE}/* /opt/pingvin-share cd /opt/pingvin-share cd backend - npm install &>/dev/null - npm run build &>/dev/null + $STD npm install + $STD npm run build cd ../frontend - npm install &>/dev/null - npm run build &>/dev/null + $STD npm install + $STD npm run build echo "${RELEASE}" >"/opt/pingvin_version.txt" rm -rf /opt/v${RELEASE}.zip rm -rf /opt/pingvin-share-${RELEASE} diff --git a/ct/plex.sh b/ct/plex.sh index 7f6fbaee3..4e2a5cce1 100644 --- a/ct/plex.sh +++ b/ct/plex.sh @@ -33,8 +33,8 @@ function update_script() { 3>&1 1>&2 2>&3) if [ "$UPD" == "1" ]; then msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit fi diff --git a/ct/podman-homeassistant.sh b/ct/podman-homeassistant.sh index f09fa6cd0..0354924c1 100644 --- a/ct/podman-homeassistant.sh +++ b/ct/podman-homeassistant.sh @@ -33,8 +33,8 @@ check_container_resources if [ "$UPD" == "1" ]; then msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" msg_info "Updating All Containers\n" @@ -54,10 +54,10 @@ if [ "$UPD" == "1" ]; then fi if [ "$UPD" == "2" ]; then msg_info "Installing Home Assistant Community Store (HACS)" - apt update &>/dev/null - apt install unzip &>/dev/null + $STD apt update + $STD apt install unzip cd /var/lib/containers/storage/volumes/hass_config/_data - bash <(curl -fsSL https://get.hacs.xyz) &>/dev/null + $STD bash <(curl -fsSL https://get.hacs.xyz) msg_ok "Installed Home Assistant Community Store (HACS)" echo -e "\n Reboot Home Assistant and clear browser cache then Add HACS integration.\n" exit @@ -65,10 +65,10 @@ fi if [ "$UPD" == "3" ]; then IP=$(hostname -I | awk '{print $1}') msg_info "Installing FileBrowser" - curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash &>/dev/null - filebrowser config init -a '0.0.0.0' &>/dev/null - filebrowser config set -a '0.0.0.0' &>/dev/null - filebrowser users add admin helper-scripts.com --perm.admin &>/dev/null + $STD curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash + $STD filebrowser config init -a '0.0.0.0' + $STD filebrowser config set -a '0.0.0.0' + $STD filebrowser users add admin helper-scripts.com --perm.admin msg_ok "Installed FileBrowser" msg_info "Creating Service" @@ -83,7 +83,7 @@ if [ "$UPD" == "3" ]; then [Install] WantedBy=default.target" >$service_path - systemctl enable --now filebrowser.service &>/dev/null + $STD systemctl enable --now filebrowser.service msg_ok "Created Service" msg_ok "Completed Successfully!\n" diff --git a/ct/podman.sh b/ct/podman.sh index 5d4fce123..1f98b13fd 100644 --- a/ct/podman.sh +++ b/ct/podman.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/postgresql.sh b/ct/postgresql.sh index d07f34751..cc9c63541 100644 --- a/ct/postgresql.sh +++ b/ct/postgresql.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/prometheus-pve-exporter.sh b/ct/prometheus-pve-exporter.sh index 69b10a582..4987f816a 100644 --- a/ct/prometheus-pve-exporter.sh +++ b/ct/prometheus-pve-exporter.sh @@ -32,7 +32,7 @@ function update_script() { msg_ok "Stopped ${APP}" msg_info "Updating ${APP}" - pip install prometheus-pve-exporter --default-timeout=300 --upgrade --root-user-action=ignore &>/dev/null + $STD pip install prometheus-pve-exporter --default-timeout=300 --upgrade --root-user-action=ignore msg_ok "Updated ${APP}" msg_info "Starting ${APP}" diff --git a/ct/prowlarr.sh b/ct/prowlarr.sh index c8719c92f..85d371574 100644 --- a/ct/prowlarr.sh +++ b/ct/prowlarr.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/proxmox-backup-server.sh b/ct/proxmox-backup-server.sh index fc4199d87..f81185acc 100644 --- a/ct/proxmox-backup-server.sh +++ b/ct/proxmox-backup-server.sh @@ -25,8 +25,8 @@ function update_script() { check_container_resources if [[ ! -e /usr/sbin/proxmox-backup-manager ]]; then msg_error "No ${APP} Installation Found!"; exit; fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/proxmox-datacenter-manager.sh b/ct/proxmox-datacenter-manager.sh index 4d2cab0fc..4ae89d055 100644 --- a/ct/proxmox-datacenter-manager.sh +++ b/ct/proxmox-datacenter-manager.sh @@ -25,8 +25,8 @@ function update_script() { check_container_resources if [[ ! -e /usr/sbin/proxmox-datacenter-manager-admin ]]; then msg_error "No ${APP} Installation Found!"; exit; fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/proxmox-mail-gateway.sh b/ct/proxmox-mail-gateway.sh index 654bbc4b1..30b1656a3 100644 --- a/ct/proxmox-mail-gateway.sh +++ b/ct/proxmox-mail-gateway.sh @@ -25,8 +25,8 @@ function update_script() { check_container_resources if [[ ! -e /usr/bin/pmgproxy ]]; then msg_error "No ${APP} Installation Found!"; exit; fi msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP}" exit } diff --git a/ct/ps5-mqtt.sh b/ct/ps5-mqtt.sh index 2cf6bf5a9..c963e5b98 100644 --- a/ct/ps5-mqtt.sh +++ b/ct/ps5-mqtt.sh @@ -47,8 +47,8 @@ function update_script() { msg_info "Building new PS5-MQTT version" cd /opt/ps5-mqtt/ps5-mqtt/ - npm install &>/dev/null - npm run build &>/dev/null + $STD npm install + $STD npm run build msg_ok "Built new PS5-MQTT version" msg_info "Starting service" diff --git a/ct/qbittorrent.sh b/ct/qbittorrent.sh index 94a4f645f..3d59d6010 100644 --- a/ct/qbittorrent.sh +++ b/ct/qbittorrent.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/rabbitmq.sh b/ct/rabbitmq.sh index 8b6fb156f..a9fa9d71f 100644 --- a/ct/rabbitmq.sh +++ b/ct/rabbitmq.sh @@ -32,7 +32,7 @@ function update_script() { msg_ok "Stopped ${APP} Service" msg_info "Updating..." - apt install --only-upgrade rabbitmq-server &>/dev/null + $STD apt install --only-upgrade rabbitmq-server msg_ok "Update Successfully" msg_info "Starting ${APP}" diff --git a/ct/radarr.sh b/ct/radarr.sh index 6920406f3..b76b21e9d 100644 --- a/ct/radarr.sh +++ b/ct/radarr.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/rdtclient.sh b/ct/rdtclient.sh index ecb83e633..d7806ae2f 100755 --- a/ct/rdtclient.sh +++ b/ct/rdtclient.sh @@ -33,8 +33,8 @@ function update_script() { msg_info "Updating ${APP}" if dpkg-query -W dotnet-sdk-8.0 >/dev/null 2>&1; then - apt-get remove --purge -y dotnet-sdk-8.0 &>/dev/null - apt-get install -y dotnet-sdk-9.0 &>/dev/null + $STD apt-get remove --purge -y dotnet-sdk-8.0 + $STD apt-get install -y dotnet-sdk-9.0 fi mkdir -p rdtc-backup cp -R /opt/rdtc/appsettings.json rdtc-backup/ diff --git a/ct/readarr.sh b/ct/readarr.sh index 6a5adf414..4225ac9d4 100644 --- a/ct/readarr.sh +++ b/ct/readarr.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/redis.sh b/ct/redis.sh index a9eb8e4c9..3fe232b4e 100644 --- a/ct/redis.sh +++ b/ct/redis.sh @@ -27,7 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/rtsptoweb.sh b/ct/rtsptoweb.sh index 791a64934..8d2a3fdec 100644 --- a/ct/rtsptoweb.sh +++ b/ct/rtsptoweb.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/rustdeskserver.sh b/ct/rustdeskserver.sh index b98543283..16e306126 100644 --- a/ct/rustdeskserver.sh +++ b/ct/rustdeskserver.sh @@ -40,7 +40,7 @@ function update_script() { wget -q "https://github.com/rustdesk/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-hbbr_${RELEASE}_amd64.deb" -P $TEMPDIR wget -q "https://github.com/rustdesk/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-hbbs_${RELEASE}_amd64.deb" -P $TEMPDIR wget -q "https://github.com/rustdesk/rustdesk-server/releases/download/${RELEASE}/rustdesk-server-utils_${RELEASE}_amd64.deb" -P $TEMPDIR - dpkg -i $TEMPDIR/*.deb &> /dev/null + $STD dpkg -i $TEMPDIR/*.deb msg_ok "Updated $APP to v${RELEASE}" msg_info "Cleaning Up" diff --git a/ct/sabnzbd.sh b/ct/sabnzbd.sh index fbc789a98..ff884bbaa 100644 --- a/ct/sabnzbd.sh +++ b/ct/sabnzbd.sh @@ -31,16 +31,16 @@ function update_script() { if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then msg_info "Updating $APP to ${RELEASE}" systemctl stop sabnzbd.service - tar zxvf <(curl -fsSL https://github.com/sabnzbd/sabnzbd/releases/download/$RELEASE/SABnzbd-${RELEASE}-src.tar.gz) &>/dev/null - \cp -r SABnzbd-${RELEASE}/* /opt/sabnzbd &>/dev/null + tar zxvf <(curl -fsSL https://github.com/sabnzbd/sabnzbd/releases/download/$RELEASE/SABnzbd-${RELEASE}-src.tar.gz) + cp -rf SABnzbd-${RELEASE}/* /opt/sabnzbd rm -rf SABnzbd-${RELEASE} cd /opt/sabnzbd - python3 -m pip install -r requirements.txt &>/dev/null + $STD python3 -m pip install -r requirements.txt echo "${RELEASE}" >/opt/${APP}_version.txt systemctl start sabnzbd.service msg_ok "Updated ${APP} to ${RELEASE}" else - msg_info "No update required. ${APP} is already at ${RELEASE}" + msg_ok "No update required. ${APP} is already at ${RELEASE}" fi exit } diff --git a/ct/seelf.sh b/ct/seelf.sh index 481d6287f..40d0a47a0 100644 --- a/ct/seelf.sh +++ b/ct/seelf.sh @@ -44,7 +44,7 @@ function update_script() { tar -xzf v${RELEASE}.tar.gz cp -r seelf-${RELEASE}/ /opt/seelf cd /opt/seelf - make build &> /dev/null + $STD make build msg_ok "Updated $APP to v${RELEASE}" msg_info "Starting $APP" diff --git a/ct/semaphore.sh b/ct/semaphore.sh index 75d9ead1c..1524f4d82 100644 --- a/ct/semaphore.sh +++ b/ct/semaphore.sh @@ -37,7 +37,7 @@ function update_script() { msg_info "Updating ${APP} to v${RELEASE}" cd /opt wget -q https://github.com/semaphoreui/semaphore/releases/download/v${RELEASE}/semaphore_${RELEASE}_linux_amd64.deb - dpkg -i semaphore_${RELEASE}_linux_amd64.deb &>/dev/null + $STD dpkg -i semaphore_${RELEASE}_linux_amd64.deb echo "${RELEASE}" >"/opt/${APP}_version.txt" msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/sftpgo.sh b/ct/sftpgo.sh index a4417a21f..6dc2ccc13 100644 --- a/ct/sftpgo.sh +++ b/ct/sftpgo.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/smokeping.sh b/ct/smokeping.sh index 9527c9f95..ee53f0a35 100644 --- a/ct/smokeping.sh +++ b/ct/smokeping.sh @@ -29,8 +29,8 @@ function update_script() { fi msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/snipeit.sh b/ct/snipeit.sh index dd37443de..d6d74eba3 100644 --- a/ct/snipeit.sh +++ b/ct/snipeit.sh @@ -30,11 +30,11 @@ function update_script() { RELEASE=$(curl -s https://api.github.com/repos/snipe/snipe-it/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 "Updating ${APP} to v${RELEASE}" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade mv /opt/snipe-it /opt/snipe-it-backup cd /opt - wget -q "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" &>/dev/null + $STD wget -q "https://github.com/snipe/snipe-it/archive/refs/tags/v${RELEASE}.zip" unzip -q v${RELEASE}.zip mv snipe-it-${RELEASE} /opt/snipe-it cp /opt/snipe-it-backup/.env /opt/snipe-it/.env @@ -42,13 +42,13 @@ function update_script() { cp -r /opt/snipe-it-backup/storage/private_uploads /opt/snipe-it/storage/private_uploads cd /opt/snipe-it/ export COMPOSER_ALLOW_SUPERUSER=1 - composer install --no-dev --prefer-source &>/dev/null - composer dump-autoload &>/dev/null - php artisan migrate --force &>/dev/null - php artisan config:clear &>/dev/null - php artisan route:clear &>/dev/null - php artisan cache:clear &>/dev/null - php artisan view:clear &>/dev/null + $STD composer install --no-dev --prefer-source + $STD composer dump-autoload + $STD php artisan migrate --force + $STD php artisan config:clear + $STD php artisan route:clear + $STD php artisan cache:clear + $STD php artisan view:clear chown -R www-data: /opt/snipe-it chmod -R 755 /opt/snipe-it rm -rf /opt/v${RELEASE}.zip diff --git a/ct/spoolman.sh b/ct/spoolman.sh index e82fee712..5527ce9a9 100644 --- a/ct/spoolman.sh +++ b/ct/spoolman.sh @@ -41,7 +41,7 @@ function update_script() { wget -q https://github.com/Donkie/Spoolman/releases/download/${RELEASE}/spoolman.zip unzip -q spoolman.zip -d spoolman cd spoolman - pip3 install -r requirements.txt >/dev/null 2>&1 + $STD pip3 install -r requirements.txt wget -q https://raw.githubusercontent.com/Donkie/Spoolman/master/.env.example -O .env echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to ${RELEASE}" diff --git a/ct/sqlserver2022.sh b/ct/sqlserver2022.sh index e5cd23c6f..bf5d2c74d 100644 --- a/ct/sqlserver2022.sh +++ b/ct/sqlserver2022.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/stirling-pdf.sh b/ct/stirling-pdf.sh index d4ee45fc1..ea9429f9d 100644 --- a/ct/stirling-pdf.sh +++ b/ct/stirling-pdf.sh @@ -30,15 +30,15 @@ function update_script() { msg_info "Updating ${APP}" systemctl stop stirlingpdf if [[ -n $(dpkg -l | grep -w ocrmypdf) ]] && [[ -z $(dpkg -l | grep -w qpdf) ]]; then - apt-get remove -y ocrmypdf &>/dev/null - apt-get install -y qpdf &>/dev/null + $STD apt-get remove -y ocrmypdf + $STD apt-get install -y qpdf fi RELEASE=$(curl -s https://api.github.com/repos/Stirling-Tools/Stirling-PDF/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') wget -q https://github.com/Stirling-Tools/Stirling-PDF/archive/refs/tags/v$RELEASE.tar.gz tar -xzf v$RELEASE.tar.gz cd Stirling-PDF-$RELEASE chmod +x ./gradlew - ./gradlew build &>/dev/null + $STD ./gradlew build cp -r ./build/libs/Stirling-PDF-*.jar /opt/Stirling-PDF/ cp -r scripts /opt/Stirling-PDF/ cd ~ diff --git a/ct/syncthing.sh b/ct/syncthing.sh index 8b9bb075f..900e92729 100644 --- a/ct/syncthing.sh +++ b/ct/syncthing.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/tandoor.sh b/ct/tandoor.sh index d271c01d2..68fa4459a 100644 --- a/ct/tandoor.sh +++ b/ct/tandoor.sh @@ -33,15 +33,15 @@ function update_script() { msg_info "Updating ${APP} (Patience)" export $(cat /opt/tandoor/.env | grep "^[^#]" | xargs) cd /opt/tandoor/ - pip3 install -r requirements.txt >/dev/null 2>&1 - /usr/bin/python3 /opt/tandoor/manage.py migrate >/dev/null 2>&1 - /usr/bin/python3 /opt/tandoor/manage.py collectstatic --no-input >/dev/null 2>&1 - /usr/bin/python3 /opt/tandoor/manage.py collectstatic_js_reverse >/dev/null 2>&1 + $STD pip3 install -r requirements.txt + $STD /usr/bin/python3 /opt/tandoor/manage.py migrate + $STD /usr/bin/python3 /opt/tandoor/manage.py collectstatic --no-input + $STD /usr/bin/python3 /opt/tandoor/manage.py collectstatic_js_reverse cd /opt/tandoor/vue - yarn install >/dev/null 2>&1 - yarn build >/dev/null 2>&1 + $STD yarn install + $STD yarn build cd /opt/tandoor - python3 version.py &>/dev/null + $STD python3 version.py systemctl restart gunicorn_tandoor msg_ok "Updated ${APP}" fi diff --git a/ct/tasmoadmin.sh b/ct/tasmoadmin.sh index e351bd8c6..23bd7eb5c 100644 --- a/ct/tasmoadmin.sh +++ b/ct/tasmoadmin.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/tasmocompiler.sh b/ct/tasmocompiler.sh index 275b31fa0..6bbc0b498 100644 --- a/ct/tasmocompiler.sh +++ b/ct/tasmocompiler.sh @@ -40,10 +40,10 @@ function update_script() { tar xzf v${RELEASE}.tar.gz mv tasmocompiler-${RELEASE}/ /opt/tasmocompiler/ cd /opt/tasmocompiler - yarn install &> /dev/null + $STD yarn install export NODE_OPTIONS=--openssl-legacy-provider - npm i &> /dev/null - yarn build &> /dev/null + $STD npm i + $STD yarn build msg_ok "Updated $APP to v${RELEASE}" msg_info "Starting $APP" systemctl start tasmocompiler diff --git a/ct/tautulli.sh b/ct/tautulli.sh index 2d62bc91b..11c6c8f90 100644 --- a/ct/tautulli.sh +++ b/ct/tautulli.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/tdarr.sh b/ct/tdarr.sh index cdd894c3b..e0cf0c480 100644 --- a/ct/tdarr.sh +++ b/ct/tdarr.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/technitiumdns.sh b/ct/technitiumdns.sh index 52d2e9a05..5bdb26719 100644 --- a/ct/technitiumdns.sh +++ b/ct/technitiumdns.sh @@ -31,12 +31,12 @@ function update_script() { if ! dpkg -s aspnetcore-runtime-8.0 >/dev/null 2>&1; then wget -q https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb - dpkg -i packages-microsoft-prod.deb &>/dev/null - apt-get update &>/dev/null - apt-get install -y aspnetcore-runtime-8.0 &>/dev/null + $STD dpkg -i packages-microsoft-prod.deb + $STD apt-get update + $STD apt-get install -y aspnetcore-runtime-8.0 rm packages-microsoft-prod.deb fi - bash <(curl -fsSL https://download.technitium.com/dns/install.sh) &>/dev/null + $STD bash <(curl -fsSL https://download.technitium.com/dns/install.sh) msg_ok "Updated Successfully" exit } diff --git a/ct/the-lounge.sh b/ct/the-lounge.sh index 23cc28820..6ec2eab9e 100644 --- a/ct/the-lounge.sh +++ b/ct/the-lounge.sh @@ -34,7 +34,7 @@ function update_script() { msg_ok "Stopped Service" msg_info "Updating ${APP} to v${RELEASE}" - apt-get install --only-upgrade nodejs &>/dev/null + $STD apt-get install --only-upgrade nodejs cd /opt wget -q https://github.com/thelounge/thelounge-deb/releases/download/v${RELEASE}/thelounge_${RELEASE}_all.deb dpkg -i ./thelounge_${RELEASE}_all.deb diff --git a/ct/tianji.sh b/ct/tianji.sh index fc5a443b2..628bd47e0 100644 --- a/ct/tianji.sh +++ b/ct/tianji.sh @@ -41,15 +41,15 @@ function update_script() { mv tianji-${RELEASE} /opt/tianji cd tianji export NODE_OPTIONS="--max_old_space_size=4096" - pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile >/dev/null 2>&1 - pnpm build:static >/dev/null 2>&1 - pnpm install --filter @tianji/server... --config.dedupe-peer-dependents=false >/dev/null 2>&1 - mkdir -p ./src/server/public >/dev/null 2>&1 - cp -r ./geo ./src/server/public >/dev/null 2>&1 - pnpm build:server >/dev/null 2>&1 + $STD pnpm install --filter @tianji/client... --config.dedupe-peer-dependents=false --frozen-lockfile + $STD pnpm build:static + $STD pnpm install --filter @tianji/server... --config.dedupe-peer-dependents=false + mkdir -p ./src/server/public + cp -r ./geo ./src/server/public + $STD pnpm build:server mv /opt/.env /opt/tianji/src/server/.env cd src/server - pnpm db:migrate:apply >/dev/null 2>&1 + $STD pnpm db:migrate:apply echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP} to v${RELEASE}" diff --git a/ct/traccar.sh b/ct/traccar.sh index b7aae151a..ad7db8c4b 100644 --- a/ct/traccar.sh +++ b/ct/traccar.sh @@ -27,8 +27,7 @@ function update_script() { msg_error "No ${APP} Installation Found!" exit fi - msg_error "There is currently no update path available." - exit + msg_error "Currently we don't provide an update function for this ${APP}." exit } diff --git a/ct/transmission.sh b/ct/transmission.sh index 4cbc6398f..bc0376c85 100644 --- a/ct/transmission.sh +++ b/ct/transmission.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/typesense.sh b/ct/typesense.sh index f17dbce9e..8aed10a67 100644 --- a/ct/typesense.sh +++ b/ct/typesense.sh @@ -30,8 +30,8 @@ function update_script() { RELEASE=$(curl -s https://api.github.com/repos/typesense/typesense/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 "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" else msg_ok "No update required. ${APP} is already at ${RELEASE}" diff --git a/ct/ubuntu.sh b/ct/ubuntu.sh index 6be9d3acf..3e089012e 100644 --- a/ct/ubuntu.sh +++ b/ct/ubuntu.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/umbrel.sh b/ct/umbrel.sh index 49a6527fd..2b5758d73 100644 --- a/ct/umbrel.sh +++ b/ct/umbrel.sh @@ -24,8 +24,8 @@ function update_script() { check_container_storage check_container_resources msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/unbound.sh b/ct/unbound.sh index 27e684ee8..448dbb2c2 100644 --- a/ct/unbound.sh +++ b/ct/unbound.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/unifi.sh b/ct/unifi.sh index 9895c0428..985e352d0 100644 --- a/ct/unifi.sh +++ b/ct/unifi.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP}" - apt-get update --allow-releaseinfo-change &>/dev/null - apt-get install -y unifi &>/dev/null + $STD apt-get update --allow-releaseinfo-change + $STD apt-get install -y unifi msg_ok "Updated Successfully" exit } diff --git a/ct/unmanic.sh b/ct/unmanic.sh index 9050225e1..c488a39c9 100644 --- a/ct/unmanic.sh +++ b/ct/unmanic.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - pip3 install -U unmanic &>/dev/null - apt-get -y upgrade &>/dev/null + $STD pip3 install -U unmanic + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/uptimekuma.sh b/ct/uptimekuma.sh index 5c8669555..c1660497a 100644 --- a/ct/uptimekuma.sh +++ b/ct/uptimekuma.sh @@ -30,29 +30,29 @@ function update_script() { if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then if ! command -v npm >/dev/null 2>&1; then echo "Installing NPM..." - apt-get install -y npm >/dev/null 2>&1 + $STD apt-get install -y npm echo "Installed NPM..." fi fi LATEST=$(curl -sL https://api.github.com/repos/louislam/uptime-kuma/releases/latest | grep '"tag_name":' | cut -d'"' -f4) msg_info "Stopping ${APP}" - sudo systemctl stop uptime-kuma &>/dev/null + $STD sudo systemctl stop uptime-kuma msg_ok "Stopped ${APP}" cd /opt/uptime-kuma msg_info "Pulling ${APP} ${LATEST}" - git fetch --all &>/dev/null - git checkout $LATEST --force &>/dev/null + $STD git fetch --all + $STD git checkout $LATEST --force msg_ok "Pulled ${APP} ${LATEST}" msg_info "Updating ${APP} to ${LATEST}" - npm install --production &>/dev/null - npm run download-dist &>/dev/null + $STD npm install --production + $STD npm run download-dist msg_ok "Updated ${APP}" msg_info "Starting ${APP}" - sudo systemctl start uptime-kuma &>/dev/null + $STD sudo systemctl start uptime-kuma msg_ok "Started ${APP}" msg_ok "Updated Successfully" exit diff --git a/ct/urbackupserver.sh b/ct/urbackupserver.sh index 5383002b3..d60372faf 100644 --- a/ct/urbackupserver.sh +++ b/ct/urbackupserver.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated Successfully" exit } diff --git a/ct/vaultwarden.sh b/ct/vaultwarden.sh index 9e317c7ae..4cb7565eb 100644 --- a/ct/vaultwarden.sh +++ b/ct/vaultwarden.sh @@ -48,9 +48,9 @@ function update_script() { msg_info "Updating VaultWarden to $VAULT (Patience)" cd ~ && rm -rf vaultwarden - git clone https://github.com/dani-garcia/vaultwarden &>/dev/null + $STD git clone https://github.com/dani-garcia/vaultwarden cd vaultwarden - cargo build --features "sqlite,mysql,postgresql" --release &>/dev/null + $STD cargo build --features "sqlite,mysql,postgresql" --release DIR=/usr/bin/vaultwarden if [ -d "$DIR" ]; then cp target/release/vaultwarden /usr/bin/ @@ -76,8 +76,8 @@ function update_script() { msg_ok "Stopped Vaultwarden" msg_info "Updating Web-Vault to $WVRELEASE" - curl -fsSLO https://github.com/dani-garcia/bw_web_builds/releases/download/$WVRELEASE/bw_web_$WVRELEASE.tar.gz &>/dev/null - tar -zxf bw_web_$WVRELEASE.tar.gz -C /opt/vaultwarden/ &>/dev/null + $STD curl -fsSLO https://github.com/dani-garcia/bw_web_builds/releases/download/$WVRELEASE/bw_web_$WVRELEASE.tar.gz + $STD tar -zxf bw_web_$WVRELEASE.tar.gz -C /opt/vaultwarden/ msg_ok "Updated Web-Vault" msg_info "Cleaning up" @@ -93,7 +93,7 @@ function update_script() { if [ "$UPD" == "3" ]; then if NEWTOKEN=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "Set the ADMIN_TOKEN" 10 58 3>&1 1>&2 2>&3); then if [[ -z "$NEWTOKEN" ]]; then exit; fi - if ! command -v argon2 >/dev/null 2>&1; then apt-get install -y argon2 &>/dev/null; fi + if ! command -v argon2 >/dev/null 2>&1; then $STD apt-get install -y argon2; fi TOKEN=$(echo -n ${NEWTOKEN} | argon2 "$(openssl rand -base64 32)" -t 2 -m 16 -p 4 -l 64 -e) sed -i "s|ADMIN_TOKEN=.*|ADMIN_TOKEN='${TOKEN}'|" /opt/vaultwarden/.env if [[ -f /opt/vaultwarden/data/config.json ]]; then diff --git a/ct/victoriametrics.sh b/ct/victoriametrics.sh new file mode 100644 index 000000000..10ef77c40 --- /dev/null +++ b/ct/victoriametrics.sh @@ -0,0 +1,69 @@ +#!/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/VictoriaMetrics/VictoriaMetrics + +APP="VictoriaMetrics" +var_tags="database" +var_cpu="2" +var_ram="2048" +var_disk="16" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/victoriametrics ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/VictoriaMetrics/VictoriaMetrics/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 $APP" + systemctl stop victoriametrics + msg_ok "Stopped $APP" + + msg_info "Updating ${APP} to v${RELEASE}" + temp_dir=$(mktemp -d) + cd $temp_dir + wget -q https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v${RELEASE}/victoria-metrics-linux-amd64-v${RELEASE}.tar.gz + wget -q https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v${RELEASE}/vmutils-linux-amd64-v${RELEASE}.tar.gz + find /opt/victoriametrics -maxdepth 1 -type f -executable -delete + tar -xf victoria-metrics-linux-amd64-v${RELEASE}.tar.gz -C /opt/victoriametrics + tar -xf vmutils-linux-amd64-v${RELEASE}.tar.gz -C /opt/victoriametrics + chmod +x /opt/victoriametrics/* + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Starting $APP" + systemctl start victoriametrics + msg_ok "Started $APP" + + msg_info "Cleaning Up" + rm -rf $temp_dir + msg_ok "Cleaned" + msg_ok "Updated Successfully" + 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}:8428/vmui${CL}" diff --git a/ct/vikunja.sh b/ct/vikunja.sh index 62da510c8..b7aaac3b0 100644 --- a/ct/vikunja.sh +++ b/ct/vikunja.sh @@ -37,7 +37,8 @@ function update_script() { cd /opt rm -rf /opt/vikunja/vikunja wget -q "https://dl.vikunja.io/vikunja/$RELEASE/vikunja-$RELEASE-amd64.deb" - DEBIAN_FRONTEND=noninteractive dpkg -i vikunja-$RELEASE-amd64.deb &>/dev/null + export DEBIAN_FRONTEND=noninteractive + $STD dpkg -i vikunja-$RELEASE-amd64.deb echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP}" diff --git a/ct/wallos.sh b/ct/wallos.sh index 59e5be581..5407cd6ef 100644 --- a/ct/wallos.sh +++ b/ct/wallos.sh @@ -44,7 +44,7 @@ function update_script() { chown -R www-data:www-data /opt/wallos chmod -R 755 /opt/wallos mkdir -p /var/log/cron - curl http://localhost/endpoints/db/migrate.php &>/dev/null + $STD curl http://localhost/endpoints/db/migrate.php echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP}" diff --git a/ct/watcharr.sh b/ct/watcharr.sh index dd0f7835a..73daf7fc3 100644 --- a/ct/watcharr.sh +++ b/ct/watcharr.sh @@ -45,8 +45,8 @@ function update_script() { cp -rf ${temp_folder}/Watcharr-${RELEASE}/* /opt/watcharr cd /opt/watcharr export GOOS=linux - npm i &> /dev/null - npm run build &> /dev/null + $STD npm i + $STD npm run build mv ./build ./server/ui cd server go mod download diff --git a/ct/web-check.sh b/ct/web-check.sh new file mode 100644 index 000000000..fe4428fd4 --- /dev/null +++ b/ct/web-check.sh @@ -0,0 +1,41 @@ +#!/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: CrazyWolf13 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/Lissy93/web-check + +APP="web-check" +TAGS="network;analysis" +var_cpu="2" +var_ram="2048" +var_disk="12" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/web-check ]]; 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}:3000${CL}" diff --git a/ct/wger.sh b/ct/wger.sh new file mode 100644 index 000000000..3b017dd76 --- /dev/null +++ b/ct/wger.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +source <(curl -s https://raw.githubusercontent.com/tremor021/ProxmoxVE/refs/heads/wger/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/wger-project/wger + +APP="wger" +var_tags="management;fitness" +var_cpu="1" +var_ram="1024" +var_disk="6" +var_os="debian" +var_version="12" +var_unprivileged="1" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /home/wger ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + RELEASE=$(curl -s https://api.github.com/repos/wger-project/wger/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 + msg_info "Stopping $APP" + systemctl stop wger + msg_ok "Stopped $APP" + + msg_info "Updating $APP to v${RELEASE}" + temp_file=$(mktemp) + cd $temp_file + wget -q "https://github.com/wger-project/wger/archive/refs/tags/$RELEASE.tar.gz" -O $temp_file + tar xzf $temp_file + cp -rf wger-$RELEASE/* /home/wger/src + cd /home/wger/src + python3 manage.py migrate &>/dev/null + yarn install &>/dev/null + yarn build:css:sass &>/dev/null + python3 manage.py collectstatic --noinput &>/dev/null + echo "${RELEASE}" >/opt/${APP}_version.txt + msg_ok "Updated $APP to v${RELEASE}" + + msg_info "Starting $APP" + systemctl start wger + msg_ok "Started $APP" + + msg_info "Cleaning Up" + rm -rf $temp_file + msg_ok "Cleanup Completed" + + msg_ok "Update Successful" + 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}:3000${CL}" diff --git a/ct/whisparr.sh b/ct/whisparr.sh index aa6e02349..e128d3d5b 100644 --- a/ct/whisparr.sh +++ b/ct/whisparr.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/whoogle.sh b/ct/whoogle.sh index e7071043f..2b21b8dcf 100644 --- a/ct/whoogle.sh +++ b/ct/whoogle.sh @@ -28,7 +28,7 @@ function update_script() { exit fi msg_info "Updating ${APP} LXC" - pip3 install whoogle-search --upgrade &>/dev/null + $STD pip3 install whoogle-search --upgrade systemctl restart whoogle.service msg_ok "Updated Successfully" exit diff --git a/ct/wikijs.sh b/ct/wikijs.sh index 4fab17d2e..ee65e4c86 100644 --- a/ct/wikijs.sh +++ b/ct/wikijs.sh @@ -46,7 +46,7 @@ function update_script() { msg_info "Restoring Data" cp -R ~/data-backup/* /opt/wikijs rm -rf ~/data-backup - npm rebuild sqlite3 &>/dev/null + $STD npm rebuild sqlite3 msg_ok "Restored Data" msg_info "Starting ${APP}" diff --git a/ct/wireguard.sh b/ct/wireguard.sh index 9016b96d5..36c75a9e7 100644 --- a/ct/wireguard.sh +++ b/ct/wireguard.sh @@ -32,6 +32,7 @@ function update_script() { sleep 2 cd /etc/wgdashboard/src ./wgd.sh update + ./wgd.sh start exit } @@ -42,4 +43,4 @@ 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}" \ No newline at end of file +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:10086${CL}" diff --git a/ct/yunohost.sh b/ct/yunohost.sh index 7a31e4d5f..ad7d7583d 100644 --- a/ct/yunohost.sh +++ b/ct/yunohost.sh @@ -28,8 +28,8 @@ function update_script() { exit fi msg_info "Updating $APP LXC" - apt-get update &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-get -y upgrade msg_ok "Updated $APP LXC" exit } diff --git a/ct/zabbix.sh b/ct/zabbix.sh index f4770a919..bac537bd2 100644 --- a/ct/zabbix.sh +++ b/ct/zabbix.sh @@ -40,9 +40,9 @@ function update_script() { rm -Rf /etc/apt/sources.list.d/zabbix.list cd /tmp wget -q https://repo.zabbix.com/zabbix/7.2/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian12_all.deb - dpkg -i zabbix-release_latest+debian12_all.deb &>/dev/null - apt-get update &>/dev/null - apt-get install --only-upgrade zabbix-server-pgsql zabbix-frontend-php zabbix-agent2 zabbix-agent2-plugin-* &>/dev/null + $STD dpkg -i zabbix-release_latest+debian12_all.deb + $STD apt-get update + $STD apt-get install --only-upgrade zabbix-server-pgsql zabbix-frontend-php zabbix-agent2 zabbix-agent2-plugin-* msg_info "Starting ${APP} Services" systemctl start zabbix-server zabbix-agent2 diff --git a/ct/zammad.sh b/ct/zammad.sh index a28662a4b..3e3e355b4 100644 --- a/ct/zammad.sh +++ b/ct/zammad.sh @@ -28,15 +28,15 @@ function update_script() { exit fi msg_info "Stopping Service" - systemctl stop zammad &>/dev/null + $STD systemctl stop zammad msg_info "Updating ${APP}" - apt-get update &>/dev/null - apt-mark hold zammad &>/dev/null - apt-get -y upgrade &>/dev/null - apt-mark unhold zammad &>/dev/null - apt-get -y upgrade &>/dev/null + $STD apt-get update + $STD apt-mark hold zammad + $STD apt-get -y upgrade + $STD apt-mark unhold zammad + $STD apt-get -y upgrade msg_info "Starting Service" - systemctl start zammad &>/dev/null + $STD systemctl start zammad msg_ok "Updated ${APP} LXC" exit } diff --git a/ct/zerotier-one.sh b/ct/zerotier-one.sh index f8a94787d..ecbd8ac0e 100644 --- a/ct/zerotier-one.sh +++ b/ct/zerotier-one.sh @@ -33,7 +33,7 @@ function update_script() { systemctl stop zerotier-one msg_ok "Stopping Service" msg_info "Updating ${APP}" - apt-get update &>/dev/null + $STD apt-get update apt-get -y upgrade msg_ok "Updated ${APP}" diff --git a/ct/zigbee2mqtt.sh b/ct/zigbee2mqtt.sh index 8af3d1719..b45f34eee 100644 --- a/ct/zigbee2mqtt.sh +++ b/ct/zigbee2mqtt.sh @@ -33,10 +33,14 @@ function update_script() { systemctl stop zigbee2mqtt msg_ok "Stopped Service" + msg_info "Updating pnpm" + $STD npm install -g pnpm@10.4.1 + msg_ok "Updated pnpm" + msg_info "Creating Backup" rm -rf /opt/${APP}_backup*.tar.gz mkdir -p /opt/z2m_backup - tar -czf /opt/z2m_backup/${APP}_backup_$(date +%Y%m%d%H%M%S).tar.gz -C /opt zigbee2mqtt &>/dev/null + $STD tar -czf /opt/z2m_backup/${APP}_backup_$(date +%Y%m%d%H%M%S).tar.gz -C /opt zigbee2mqtt mv /opt/zigbee2mqtt/data /opt/z2m_backup msg_ok "Backup Created" @@ -49,8 +53,8 @@ function update_script() { rm -rf /opt/zigbee2mqtt/data mv /opt/z2m_backup/data /opt/zigbee2mqtt cd /opt/zigbee2mqtt - pnpm install --frozen-lockfile &>/dev/null - pnpm build &>/dev/null + $STD pnpm install --frozen-lockfile + $STD pnpm build msg_ok "Updated Zigbee2MQTT" msg_info "Starting Service" diff --git a/ct/zipline.sh b/ct/zipline.sh index fce9027db..11a86a390 100644 --- a/ct/zipline.sh +++ b/ct/zipline.sh @@ -29,7 +29,7 @@ function update_script() { if ! command -v pnpm &>/dev/null; then msg_info "Installing pnpm" #export NODE_OPTIONS=--openssl-legacy-provider - npm install -g pnpm@latest &>/dev/null + $STD npm install -g pnpm@latest msg_ok "Installed pnpm" fi RELEASE=$(curl -s https://api.github.com/repos/diced/zipline/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') @@ -46,8 +46,8 @@ function update_script() { mv zipline-${RELEASE} /opt/zipline cd /opt/zipline mv /opt/.env /opt/zipline/.env - pnpm install &>/dev/null - pnpm build &>/dev/null + $STD pnpm install + $STD pnpm build echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated ${APP}" diff --git a/ct/zitadel.sh b/ct/zitadel.sh index ce97e205a..f3f99c361 100644 --- a/ct/zitadel.sh +++ b/ct/zitadel.sh @@ -37,7 +37,7 @@ function update_script() { cd /tmp wget -qc https://github.com/zitadel/zitadel/releases/download/$RELEASE/zitadel-linux-amd64.tar.gz -O - | tar -xz mv zitadel-linux-amd64/zitadel /usr/local/bin - zitadel setup --masterkeyFile /opt/zitadel/.masterkey --config /opt/zitadel/config.yaml --init-projections=true &>/dev/null + $STD zitadel setup --masterkeyFile /opt/zitadel/.masterkey --config /opt/zitadel/config.yaml --init-projections=true echo "${RELEASE}" >/opt/${APP}_version.txt msg_ok "Updated $APP to ${RELEASE}" diff --git a/frontend/src/app/data/page.tsx b/frontend/src/app/data/page.tsx index e78b4a675..b75246484 100644 --- a/frontend/src/app/data/page.tsx +++ b/frontend/src/app/data/page.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React, { JSX, useEffect, useState } from "react"; import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; import ApplicationChart from "../../components/ApplicationChart"; @@ -21,28 +21,45 @@ interface DataModel { status: string; error: string; type: string; + [key: string]: any; } +interface SummaryData { + total_entries: number; + status_count: Record; + nsapp_count: Record; +} const DataFetcher: React.FC = () => { const [data, setData] = useState([]); + const [summary, setSummary] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [searchQuery, setSearchQuery] = useState(''); - const [startDate, setStartDate] = useState(null); - const [endDate, setEndDate] = useState(null); - const [sortConfig, setSortConfig] = useState<{ key: keyof DataModel | null, direction: 'ascending' | 'descending' }>({ key: 'id', direction: 'descending' }); - const [itemsPerPage, setItemsPerPage] = useState(25); const [currentPage, setCurrentPage] = useState(1); - - const [showErrorRow, setShowErrorRow] = useState(null); - + const [itemsPerPage, setItemsPerPage] = useState(25); + const [sortConfig, setSortConfig] = useState<{ key: string; direction: 'ascending' | 'descending' } | null>(null); useEffect(() => { - const fetchData = async () => { + const fetchSummary = async () => { try { - const response = await fetch("https://api.htl-braunau.at/data/json"); - if (!response.ok) throw new Error("Failed to fetch data: ${response.statusText}"); + const response = await fetch("https://api.htl-braunau.at/data/summary"); + if (!response.ok) throw new Error(`Failed to fetch summary: ${response.statusText}`); + const result: SummaryData = await response.json(); + setSummary(result); + } catch (err) { + setError((err as Error).message); + } + }; + + fetchSummary(); + }, []); + + useEffect(() => { + const fetchPaginatedData = async () => { + setLoading(true); + try { + const response = await fetch(`https://api.htl-braunau.at/data/paginated?page=${currentPage}&limit=${itemsPerPage === 0 ? '' : itemsPerPage}`); + if (!response.ok) throw new Error(`Failed to fetch data: ${response.statusText}`); const result: DataModel[] = await response.json(); setData(result); } catch (err) { @@ -52,52 +69,34 @@ const DataFetcher: React.FC = () => { } }; - fetchData(); - }, []); - - - const filteredData = data.filter(item => { - const matchesSearchQuery = Object.values(item).some(value => - value.toString().toLowerCase().includes(searchQuery.toLowerCase()) - ); - const itemDate = new Date(item.created_at); - const matchesDateRange = (!startDate || itemDate >= startDate) && (!endDate || itemDate <= endDate); - return matchesSearchQuery && matchesDateRange; - }); + fetchPaginatedData(); + }, [currentPage, itemsPerPage]); const sortedData = React.useMemo(() => { - let sortableData = [...filteredData]; - if (sortConfig.key !== null) { - sortableData.sort((a, b) => { - if (sortConfig.key !== null && a[sortConfig.key] < b[sortConfig.key]) { - return sortConfig.direction === 'ascending' ? -1 : 1; - } - if (sortConfig.key !== null && a[sortConfig.key] > b[sortConfig.key]) { - return sortConfig.direction === 'ascending' ? 1 : -1; - } - return 0; - }); - } - return sortableData; - }, [filteredData, sortConfig]); + if (!sortConfig) return data; + const sorted = [...data].sort((a, b) => { + if (a[sortConfig.key] < b[sortConfig.key]) { + return sortConfig.direction === 'ascending' ? -1 : 1; + } + if (a[sortConfig.key] > b[sortConfig.key]) { + return sortConfig.direction === 'ascending' ? 1 : -1; + } + return 0; + }); + return sorted; + }, [data, sortConfig]); - const requestSort = (key: keyof DataModel | null) => { + if (loading) return

Loading...

; + if (error) return

Error: {error}

; + + const requestSort = (key: string) => { let direction: 'ascending' | 'descending' = 'ascending'; - if (sortConfig.key === key && sortConfig.direction === 'ascending') { - direction = 'descending'; - } else if (sortConfig.key === key && sortConfig.direction === 'descending') { - direction = 'ascending'; - } else { + if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); }; - interface SortConfig { - key: keyof DataModel | null; - direction: 'ascending' | 'descending'; - } - const formatDate = (dateString: string): string => { const date = new Date(dateString); const year = date.getFullYear(); @@ -109,86 +108,15 @@ const DataFetcher: React.FC = () => { return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`; }; - const handleItemsPerPageChange = (event: React.ChangeEvent) => { - setItemsPerPage(Number(event.target.value)); - setCurrentPage(1); - }; - - const paginatedData = sortedData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); - - - if (loading) return

Loading...

; - if (error) return

Error: {error}

; - - var installingCounts: number = 0; - var failedCounts: number = 0; - var doneCounts: number = 0 - var unknownCounts: number = 0; - data.forEach((item) => { - if (item.status === "installing") { - installingCounts += 1; - } else if (item.status === "failed") { - failedCounts += 1; - } - else if (item.status === "done") { - doneCounts += 1; - } - else { - unknownCounts += 1; - } - }); - return (

Created LXCs

-
-
- setSearchQuery(e.target.value)} - className="p-2 border" - /> - -
-
- setStartDate(date)} - selectsStart - startDate={startDate} - endDate={endDate} - placeholderText="Start date" - className="p-2 border" - /> - -
- -
- setEndDate(date)} - selectsEnd - startDate={startDate} - endDate={endDate} - placeholderText="End date" - className="p-2 border" - /> - -
-
- + +

-

{filteredData.length} results found

-

Status Legend: πŸ”„ installing {installingCounts} | βœ”οΈ completetd {doneCounts} | ❌ failed {failedCounts} | ❓ unknown {unknownCounts}

- -
+

{summary?.total_entries} results found

+

Status Legend: πŸ”„ installing {summary?.status_count["installing"] ?? 0} | βœ”οΈ completed {summary?.status_count["done"] ?? 0} | ❌ failed {summary?.status_count["failed"] ?? 0} | ❓ unknown

+
@@ -209,7 +137,7 @@ const DataFetcher: React.FC = () => { - {paginatedData.map((item, index) => ( + {sortedData.map((item, index) => ( - + ))} @@ -259,26 +174,25 @@ const DataFetcher: React.FC = () => {
- + Page {currentPage} - +
); }; - - export default DataFetcher; diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index ef6ac54b5..657f23721 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -116,19 +116,15 @@ export default function Page() { Make managing your Homelab a breeze
-

- This project aims to take the community-made Proxmox Helper Scripts, originally started by tteck, and port it to arm64. -
-
- Originally created by{" "} - - tteck - - , these scripts automate and streamline -
- the process of creating and configuring Linux containers (LXC) and - virtual machines (VMs) on Proxmox VE. -

+

+ We are a community-driven initiative that simplifies the setup + of Proxmox Virtual Environment (VE). +

+

+ With 300+ scripts to help you manage your{" "} + Proxmox VE environment. Whether you're a seasoned + user or a newcomer, we've got you covered. +

diff --git a/frontend/src/app/scripts/_components/ScriptItem.tsx b/frontend/src/app/scripts/_components/ScriptItem.tsx index 1dd416c40..6b1a73c47 100644 --- a/frontend/src/app/scripts/_components/ScriptItem.tsx +++ b/frontend/src/app/scripts/_components/ScriptItem.tsx @@ -28,6 +28,10 @@ function ScriptItem({ setSelectedScript(null); }; + const defaultInstallMethod = item.install_methods?.[0]; + const os = defaultInstallMethod?.resources?.os || "Proxmox Node"; + const version = defaultInstallMethod?.resources?.version || ""; + return (
@@ -60,6 +64,9 @@ function ScriptItem({

Date added: {extractDate(item.date_created)}

+

+ Default OS: {os} {version} +

diff --git a/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx b/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx index 94964fb6d..127ccf330 100644 --- a/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx +++ b/frontend/src/app/scripts/_components/ScriptItems/Buttons.tsx @@ -1,14 +1,23 @@ import { Button } from "@/components/ui/button"; import { basePath } from "@/config/siteConfig"; import { Script } from "@/lib/types"; -import { BookOpenText, Code, Globe } from "lucide-react"; +import { BookOpenText, Code, Globe, RefreshCcw } from "lucide-react"; import Link from "next/link"; +const generateInstallSourceUrl = (slug: string) => { + const baseUrl = `https://raw.githubusercontent.com/asykynexo/${basePath}/main`; + return `${baseUrl}/install/${slug}-install.sh`; +}; + const generateSourceUrl = (slug: string, type: string) => { const baseUrl = `https://raw.githubusercontent.com/asylumexp/${basePath}/main`; - return type === "ct" - ? `${baseUrl}/install/${slug}-install.sh` - : `${baseUrl}/${type}/${slug}.sh`; + return type === "vm" ? `${baseUrl}/vm/${slug}.sh` : `${baseUrl}/misc/${slug}.sh`; + return `${baseUrl}/misc/${slug}.sh`; +}; + +const generateUpdateUrl = (slug: string) => { + const baseUrl = `https://raw.githubusercontent.com/asylumexp/${basePath}/main`; + return `${baseUrl}/ct/${slug}.sh`; }; interface ButtonLinkProps { @@ -29,20 +38,35 @@ const ButtonLink = ({ href, icon, text }: ButtonLinkProps) => ( ); export default function Buttons({ item }: { item: Script }) { + const isCtOrDefault = ["ct"].includes(item.type); + const installSourceUrl = isCtOrDefault ? generateInstallSourceUrl(item.slug) : null; + const updateSourceUrl = isCtOrDefault ? generateUpdateUrl(item.slug) : null; + const sourceUrl = !isCtOrDefault ? generateSourceUrl(item.slug, item.type) : null; + const buttons = [ item.website && { href: item.website, - icon: , + icon: , text: "Website", }, item.documentation && { href: item.documentation, - icon: , + icon: , text: "Documentation", }, - { - href: generateSourceUrl(item.slug, item.type), - icon: , + installSourceUrl && { + href: installSourceUrl, + icon: , + text: "Install-Source", + }, + updateSourceUrl && { + href: updateSourceUrl, + icon: , + text: "Update-Source", + }, + sourceUrl && { + href: sourceUrl, + icon: , text: "Source Code", }, ].filter(Boolean) as ButtonLinkProps[]; diff --git a/frontend/src/components/ApplicationChart.tsx b/frontend/src/components/ApplicationChart.tsx index e62c10961..f70fa7098 100644 --- a/frontend/src/components/ApplicationChart.tsx +++ b/frontend/src/components/ApplicationChart.tsx @@ -25,12 +25,16 @@ import { Chart as ChartJS, ArcElement, Tooltip as ChartTooltip, Legend } from "c import ChartDataLabels from "chartjs-plugin-datalabels"; import { BarChart3, PieChart } from "lucide-react"; import React, { useState } from "react"; -import { Pie } from "react-chartjs-2"; +import { Pie, Bar } from "react-chartjs-2"; ChartJS.register(ArcElement, ChartTooltip, Legend, ChartDataLabels); +interface SummaryData { + nsapp_count: Record; +} + interface ApplicationChartProps { - data: { nsapp: string }[]; + data: SummaryData | null; } const ITEMS_PER_PAGE = 20; @@ -57,13 +61,9 @@ export default function ApplicationChart({ data }: ApplicationChartProps) { const [chartStartIndex, setChartStartIndex] = useState(0); const [tableLimit, setTableLimit] = useState(ITEMS_PER_PAGE); - // Calculate application counts - const appCounts = data.reduce((acc, item) => { - acc[item.nsapp] = (acc[item.nsapp] || 0) + 1; - return acc; - }, {} as Record); + if (!data) return null; - const sortedApps = Object.entries(appCounts) + const sortedApps = Object.entries(data.nsapp_count) .sort(([, a], [, b]) => b - a); const chartApps = sortedApps.slice( diff --git a/frontend/src/components/ui/code-copy-button.tsx b/frontend/src/components/ui/code-copy-button.tsx index 6c79ce793..edcf0d0e4 100644 --- a/frontend/src/components/ui/code-copy-button.tsx +++ b/frontend/src/components/ui/code-copy-button.tsx @@ -37,10 +37,6 @@ export default function CodeCopyButton({ ); }, 500); } - - // toast.success(`copied ${type} to clipboard`, { - // icon: , - // }); }; return ( @@ -49,17 +45,17 @@ export default function CodeCopyButton({
{!isMobile && children ? children : "Copy install command"}
-
handleCopy("install command", children)} + className={cn("bg-muted px-3 py-4")} + title="Copy" > {hasCopied ? ( ) : ( )} - Copy -
+
); diff --git a/install/actualbudget-install.sh b/install/actualbudget-install.sh index 0aab11297..142e91c21 100644 --- a/install/actualbudget-install.sh +++ b/install/actualbudget-install.sh @@ -40,9 +40,9 @@ msg_ok "Installed Node.js" msg_info "Installing Actual Budget" cd /opt RELEASE=$(curl -s https://api.github.com/repos/actualbudget/actual/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') -wget -q https://github.com/actualbudget/actual-server/archive/refs/tags/v${RELEASE}.tar.gz +wget -q https://github.com/actualbudget/actual/archive/refs/tags/v${RELEASE}.tar.gz tar -xzf v${RELEASE}.tar.gz -mv *ctual-server-* /opt/actualbudget +mv actual-${RELEASE} /opt/actualbudget mkdir -p /opt/actualbudget-data/{server-files,upload,migrate,user-files,migrations,config} chown -R root:root /opt/actualbudget-data @@ -59,7 +59,7 @@ ACTUAL_HTTPS_KEY=/opt/actualbudget/selfhost.key ACTUAL_HTTPS_CERT=/opt/actualbudget/selfhost.crt EOF cd /opt/actualbudget -$STD yarn install +$STD yarn workspaces focus @actual-app/sync-server --production $STD openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout selfhost.key -out selfhost.crt </etc/authelia/users.yml +users: + authelia: + disabled: false + displayname: "Authelia Admin" + password: "\$argon2id\$v=19\$m=65536,t=3,p=4\$ZBopMzXrzhHXPEZxRDVT2w\$SxWm96DwhOsZyn34DLocwQEIb4kCDsk632PuiMdZnig" + groups: [] +EOF + +cat </etc/authelia/configuration.yml +authentication_backend: + file: + path: /etc/authelia/users.yml +access_control: + default_policy: one_factor +session: + secret: "${SESSION_SECRET}" + name: 'authelia_session' + same_site: 'lax' + inactivity: '5m' + expiration: '1h' + remember_me: '1M' + cookies: + - domain: "${DOMAIN}" + authelia_url: "https://auth.${DOMAIN}" +storage: + encryption_key: "${STORAGE_KEY}" + local: + path: /etc/authelia/db.sqlite +identity_validation: + reset_password: + jwt_secret: "${JWT_SECRET}" + jwt_lifespan: '5 minutes' + jwt_algorithm: 'HS256' +notifier: + filesystem: + filename: /etc/authelia/emails.txt +EOF +systemctl enable -q --now authelia +msg_ok "Authelia Setup completed" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -f "authelia_${RELEASE}_amd64.deb" +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/bytestash-install.sh b/install/bytestash-install.sh new file mode 100644 index 000000000..8d4d01b81 --- /dev/null +++ b/install/bytestash-install.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash + +# 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/jordan-dalby/ByteStash + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + sudo \ + curl \ + mc \ + gnupg +msg_ok "Installed Dependencies" + +msg_info "Setting up Node.js Repository" +mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list +msg_ok "Set up Node.js Repository" + +msg_info "Installing Node.js" +$STD apt-get update +$STD apt-get install -y nodejs +msg_ok "Installed Node.js" + +msg_info "Installing ByteStash" +temp_file=$(mktemp) +RELEASE=$(curl -s https://api.github.com/repos/jordan-dalby/ByteStash/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') +wget -q "https://github.com/jordan-dalby/ByteStash/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file +tar zxf $temp_file +mv ByteStash-${RELEASE} /opt/bytestash +cd /opt/bytestash/server +$STD npm install +cd /opt/bytestash/client +$STD npm install +echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" +msg_ok "Installed ByteStash" + +msg_info "Creating Service" +cat </etc/systemd/system/bytestash-backend.service +[Unit] +Description=ByteStash Backend Service +After=network.target + +[Service] +WorkingDirectory=/opt/bytestash/server +ExecStart=/usr/bin/node src/app.js +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +cat </etc/systemd/system/bytestash-frontend.service +[Unit] +Description=ByteStash Frontend Service +After=network.target bytestash-backend.service + +[Service] +WorkingDirectory=/opt/bytestash/client +ExecStart=/usr/bin/npx vite --host +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now bytestash-backend +systemctl enable -q --now bytestash-frontend +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -f $temp_file +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/docmost-install.sh b/install/docmost-install.sh index 3007b0140..298dba62e 100644 --- a/install/docmost-install.sh +++ b/install/docmost-install.sh @@ -61,8 +61,11 @@ tar -xzf "$temp_file" mv docmost-${RELEASE} /opt/docmost cd /opt/docmost mv .env.example .env -sed -i "s|APP_SECRET=.*|APP_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)|" /opt/docmost/.env -sed -i "s|DATABASE_URL=.*|DATABASE_URL=postgres://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME|" /opt/docmost/.env +mkdir data +sed -i -e "s|APP_SECRET=.*|APP_SECRET=$(openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | cut -c1-32)|" \ + -e "s|DATABASE_URL=.*|DATABASE_URL=postgres://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME|" \ + -e "s|FILE_UPLOAD_SIZE_LIMIT=.*|FILE_UPLOAD_SIZE_LIMIT=50mb|" \ + /opt/docmost/.env export NODE_OPTIONS="--max-old-space-size=2048" $STD pnpm install $STD pnpm build diff --git a/install/firefly-install.sh b/install/firefly-install.sh index 703d979e0..5ae7cb8ab 100644 --- a/install/firefly-install.sh +++ b/install/firefly-install.sh @@ -86,6 +86,7 @@ cat </etc/apache2/sites-available/firefly.conf EOF +chown www-data:www-data /opt/firefly/storage/oauth-*.key $STD a2enmod php8.4 $STD a2enmod rewrite $STD a2ensite firefly.conf diff --git a/install/habitica-install.sh b/install/habitica-install.sh new file mode 100644 index 000000000..9aaf92939 --- /dev/null +++ b/install/habitica-install.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash + +# 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/HabitRPG/habitica + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + curl \ + sudo \ + mc \ + libkrb5-dev \ + gnupg \ + build-essential \ + git +wget -q http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb +$STD dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb +msg_ok "Installed Dependencies" + +msg_info "Setting up Node.js Repository" +mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" >/etc/apt/sources.list.d/nodesource.list +msg_ok "Set up Node.js Repository" + +msg_info "Setup Node.js" +$STD apt-get update +$STD apt-get install -y nodejs +msg_ok "Setup Node.js" + +msg_info "Setup ${APPLICATION}" +temp_file=$(mktemp) +RELEASE=$(curl -s https://api.github.com/repos/HabitRPG/habitica/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') +wget -q "https://github.com/HabitRPG/habitica/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file +tar zxf $temp_file +mv habitica-${RELEASE}/ /opt/habitica +cd /opt/habitica +$STD npm i +cp config.json.example config.json +echo "${RELEASE}" >/opt/${APPLICATION}_version.txt +msg_ok "Setup ${APPLICATION}" + +msg_info "Creating Service" +cat </etc/systemd/system/habitica-mongodb.service +[Unit] +Description=Habitica MongoDB Service +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/habitica +ExecStart=/usr/bin/npm run mongo:dev +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +cat </etc/systemd/system/habitica.service +[Unit] +Description=Habitica Service +After=habitica-mongodb.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/habitica +ExecStart=/usr/bin/npm start +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +cat </etc/systemd/system/habitica-client.service +[Unit] +Description=Habitica Client Service +After=habitica.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/habitica +ExecStart=/usr/bin/npm run client:dev +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now habitica-mongodb +systemctl enable -q --now habitica +systemctl enable -q --now habitica-client +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -f $temp_file +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/homarr-install.sh b/install/homarr-install.sh index da2c07fe3..0a1c3cf09 100644 --- a/install/homarr-install.sh +++ b/install/homarr-install.sh @@ -88,9 +88,17 @@ msg_ok "Finished copying" msg_info "Creating Services" cat <<'EOF' >/opt/run_homarr.sh #!/bin/bash +set -a +source /opt/homarr/.env +set +a export DB_DIALECT='sqlite' export AUTH_SECRET=$(openssl rand -base64 32) node /opt/homarr_db/migrations/$DB_DIALECT/migrate.cjs /opt/homarr_db/migrations/$DB_DIALECT +for dir in $(find /opt/homarr_db/migrations/migrations -mindepth 1 -maxdepth 1 -type d); do + dirname=$(basename "$dir") + mkdir -p "/opt/homarr_db/migrations/$dirname" + cp -r "$dir"/* "/opt/homarr_db/migrations/$dirname/" 2>/dev/null || true +done export HOSTNAME=$(ip route get 1.1.1.1 | grep -oP 'src \K[^ ]+') envsubst '${HOSTNAME}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf nginx -g 'daemon off;' & diff --git a/install/jupyternotebook-install.sh b/install/jupyternotebook-install.sh new file mode 100644 index 000000000..3be8e1ee5 --- /dev/null +++ b/install/jupyternotebook-install.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: [Dave-code-creater (Tan Dat, Ta)] +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: [https://jupyter.org/] + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + curl \ + sudo \ + mc \ + python3 \ + python3-pip +msg_ok "Installed Dependencies" + +msg_info "Setting up Jupyter Notebook" +$STD pip3 install jupyter +msg_ok "Setup Jupyter Notebook" + +msg_info "Creating Service" +cat </etc/systemd/system/jupyternotebook.service +[Unit] +Description=Jupyter Notebook Server +After=network.target + +[Service] +Type=simple +ExecStart=jupyter notebook --ip=0.0.0.0 --port=8888 --allow-root +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now jupyternotebook + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/keycloak-install.sh b/install/keycloak-install.sh index fc24183aa..39d070c7f 100644 --- a/install/keycloak-install.sh +++ b/install/keycloak-install.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash -# Copyright (c) 2021-2024 tteck -# Author: tteck (tteckster) -# License: MIT -# https://github.com/tteck/Proxmox/raw/main/LICENSE +# Copyright (c) 2021-2025 community-scripts ORG +# Author: tteck (tteckster) | Co-Author: SlaviΕ‘a AreΕΎina (tremor021) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/keycloak/keycloak -source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" color verb_ip6 catch_errors @@ -13,42 +13,53 @@ setting_up_container network_check update_os -msg_info "Installing Dependencies (Patience)" -$STD apt-get install -y curl -$STD apt-get install -y sudo -$STD apt-get install -y mc -$STD apt-get install -y ca-certificates-java -$STD apt-get install -y openjdk-17-jre-headless -$STD apt-get install -y wget -$STD apt-get install -y openssh-server +msg_info "Installing Dependencies" +$STD apt-get install -y \ +curl \ +sudo \ +mc \ +gnupg \ +wget \ +openssh-server msg_ok "Installed Dependencies" +msg_info "Installing OpenJDK" +wget -qO- https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor >/etc/apt/trusted.gpg.d/adoptium.gpg +echo 'deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/adoptium.gpg] https://packages.adoptium.net/artifactory/deb bookworm main' >/etc/apt/sources.list.d/adoptium.list +$STD apt-get update +$STD apt-get install -y temurin-21-jre +msg_ok "Installed OpenJDK" + +msg_info "Installing Keycloak" +temp_file=$(mktemp) RELEASE=$(curl -s https://api.github.com/repos/keycloak/keycloak/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }') -msg_info "Installing Keycloak v$RELEASE" -cd /opt -wget -q https://github.com/keycloak/keycloak/releases/download/$RELEASE/keycloak-$RELEASE.tar.gz -$STD tar -xvf keycloak-$RELEASE.tar.gz -mv keycloak-$RELEASE keycloak +wget -q https://github.com/keycloak/keycloak/releases/download/$RELEASE/keycloak-$RELEASE.tar.gz -O $temp_file +tar xzf $temp_file +mv keycloak-$RELEASE /opt/keycloak msg_ok "Installed Keycloak" msg_info "Creating Service" -service_path="/etc/systemd/system/keycloak.service" -echo "[Unit] -Description=Keycloak -After=network-online.target +cat </etc/systemd/system/keycloak.service +[Unit] +Description=Keycloak Service +After=network.target + [Service] User=root WorkingDirectory=/opt/keycloak ExecStart=/opt/keycloak/bin/kc.sh start-dev + [Install] -WantedBy=multi-user.target" >$service_path -$STD systemctl enable --now keycloak.service +WantedBy=multi-user.target +EOF +systemctl enable -q --now keycloak msg_ok "Created Service" motd_ssh customize msg_info "Cleaning up" +rm -f $temp_file $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/kimai-install.sh b/install/kimai-install.sh index 2a31aa06f..f7d9b49d1 100644 --- a/install/kimai-install.sh +++ b/install/kimai-install.sh @@ -76,8 +76,9 @@ $STD bin/console kimai:install -n chown -R :www-data /opt/* chmod -R g+r /opt/* chmod -R g+rw /opt/* -sudo chown -R www-data:www-data /opt/* -sudo chmod -R 755 /opt/* +chown -R www-data:www-data /opt/* +chmod -R 755 /opt/* +chmod -R 777 /opt/kimai/var/ $STD expect </opt/kimai/config/packages/local.yaml +kimai: + timesheet: + rounding: + default: + begin: 15 + end: 15 + +admin_lte: + options: + default_avatar: build/apple-touch-icon.png +EOF + echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" msg_ok "Installed Kimai" diff --git a/install/linkwarden-install.sh b/install/linkwarden-install.sh index 3d4c515cf..b83e6c0e1 100644 --- a/install/linkwarden-install.sh +++ b/install/linkwarden-install.sh @@ -20,7 +20,9 @@ $STD apt-get install -y \ sudo \ mc \ make \ + git \ postgresql \ + build-essential \ cargo \ gnupg \ wget \ @@ -39,10 +41,13 @@ $STD apt-get install -y nodejs $STD npm install -g yarn msg_ok "Installed Node.js/Yarn" -msg_info "Installing Monolith" +msg_info "Installing Rust" +$STD curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +source $HOME/.cargo/env +echo 'export PATH=/usr/local/cargo/bin:$PATH' >> /etc/profile +source /etc/profile $STD cargo install monolith -export PATH=~/.cargo/bin:$PATH -msg_ok "Installed Monolith" +msg_ok "Installed Rust" msg_info "Setting up PostgreSQL DB" DB_NAME=linkwardendb diff --git a/install/minio-install.sh b/install/minio-install.sh index 6dd7b947c..f06b1b3b8 100644 --- a/install/minio-install.sh +++ b/install/minio-install.sh @@ -57,7 +57,7 @@ After=network-online.target User=minio-user Group=minio-user EnvironmentFile=-/etc/default/minio -ExecStart=/usr/local/bin/minio server /data +ExecStart=/usr/local/bin/minio server --console-address ":9001" /data Restart=always RestartSec=5 LimitNOFILE=65536 @@ -74,4 +74,4 @@ customize msg_info "Cleaning up" $STD apt-get -y autoremove $STD apt-get -y autoclean -msg_ok "Cleaned" \ No newline at end of file +msg_ok "Cleaned" diff --git a/install/nzbget-install.sh b/install/nzbget-install.sh index 8ccc90716..af1d25562 100644 --- a/install/nzbget-install.sh +++ b/install/nzbget-install.sh @@ -33,7 +33,7 @@ msg_ok "Installed Dependencies" msg_info "Installing NZBGet" mkdir -p /etc/apt/keyrings curl -fsSL https://nzbgetcom.github.io/nzbgetcom.asc | gpg --dearmor -o /etc/apt/keyrings/nzbgetcom.gpg -echo "deb [signed-by=/etc/apt/keyrings/nzbgetcom.gpg] https://nzbgetcom.github.io/deb stable main" >/etc/apt/sources.list.d/nzbgetcom.list +echo "deb [arch=all signed-by=/etc/apt/keyrings/nzbgetcom.gpg] https://nzbgetcom.github.io/deb stable main" >/etc/apt/sources.list.d/nzbgetcom.list $STD apt-get update $STD apt-get install -y nzbget msg_ok "Installed NZBGet" diff --git a/install/omada-install.sh b/install/omada-install.sh index 84f906d10..3a50e0714 100644 --- a/install/omada-install.sh +++ b/install/omada-install.sh @@ -14,34 +14,50 @@ network_check update_os msg_info "Installing Dependencies" -$STD apt-get install -y curl -$STD apt-get install -y sudo -$STD apt-get install -y mc -$STD apt-get install -y gnupg -$STD apt-get install -y jsvc -$STD apt-get install -y wget -$STD apt-get install -y openssh-server +$STD apt-get install -y curl sudo mc gnupg jsvc wget openssh-server msg_ok "Installed Dependencies" -msg_info "Installing Azul Zulu" +msg_info "Checking CPU Features" +if lscpu | grep -q 'avx'; then + USE_AVX=true + MONGODB_VERSION="7.0" + msg_ok "AVX detected: Using MongoDB 7.0" +else + USE_AVX=false + MONGODB_VERSION="4.4" + msg_error "No AVX detected: TP-Link Canceled Support for Old MongoDB for Debian 12\n https://www.tp-link.com/baltic/support/faq/4160/" + exit 1 +fi + +msg_info "Installing Azul Zulu Java" wget -qO /etc/apt/trusted.gpg.d/zulu-repo.asc "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xB1998361219BD9C9" wget -q https://cdn.azul.com/zulu/bin/zulu-repo_1.0.0-3_all.deb $STD dpkg -i zulu-repo_1.0.0-3_all.deb $STD apt-get update $STD apt-get -y install zulu8-jdk -msg_ok "Installed Azul Zulu" +msg_ok "Installed Azul Zulu Java" -msg_info "Installing MongoDB" -wget -qL http://ports.ubuntu.com/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_arm64.deb -$STD dpkg -i libssl1.1_1.1.1f-1ubuntu2_arm64.deb -wget -qL https://repo.mongodb.org/apt/ubuntu/dists/focal/mongodb-org/4.4/multiverse/binary-arm64/mongodb-org-server_4.4.29_arm64.deb -$STD dpkg -i mongodb-org-server_4.4.29_arm64.deb -msg_ok "Installed MongoDB" +msg_info "Installing libssl (if needed)" +if ! dpkg -l | grep -q 'libssl1.1'; then + wget -qO /tmp/libssl.deb "https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.1_1.1.1w-0+deb11u2_arm64.deb" + $STD dpkg -i /tmp/libssl.deb + rm -f /tmp/libssl.deb + msg_ok "Installed libssl1.1" +else + msg_ok "libssl1.1 already installed" +fi -latest_url=$(curl -fsSL "https://www.tp-link.com/en/support/download/omada-software-controller/" | grep -o 'https://.*x64.deb' | head -n1) -latest_version=$(basename "$latest_url") +msg_info "Installing MongoDB $MONGODB_VERSION" +wget -qO- https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc | gpg --dearmor >/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg +echo "deb [signed-by=/usr/share/keyrings/mongodb-server-${MONGODB_VERSION}.gpg] http://repo.mongodb.org/apt/debian $(grep '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)/mongodb-org/${MONGODB_VERSION} main" >/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}.list +$STD apt-get update +$STD apt-get install -y mongodb-org +msg_ok "Installed MongoDB $MONGODB_VERSION" msg_info "Installing Omada Controller" +latest_url=$(curl -s "https://support.omadanetworks.com/en/product/omada-software-controller/?resourceType=download" | grep -o 'https://static\.tp-link\.com/upload/software/[^"]*linux_x64[^"]*\.deb' | head -n 1) +latest_version=$(basename "$latest_url") + wget -qL ${latest_url} $STD dpkg -i --ignore-depends=jsvc,mongodb-server ${latest_version} msg_ok "Installed Omada Controller" @@ -50,7 +66,7 @@ motd_ssh customize msg_info "Cleaning up" -rm -rf ${latest_version} mongodb-org-server_4.4.29_arm64.deb zulu-repo_1.0.0-3_all.deb libssl1.1_1.1.1f-1ubuntu2_arm64.deb +rm -rf ${latest_version} zulu-repo_1.0.0-3_all.deb $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/outline-install.sh b/install/outline-install.sh new file mode 100644 index 000000000..436f4aadf --- /dev/null +++ b/install/outline-install.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash + +# 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/outline/outline + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ +curl \ +sudo \ +mc \ +gnupg \ +mkcert \ +git \ +redis +msg_ok "Installed Dependencies" + +msg_info "Setting up Node.js Repository" +mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" >/etc/apt/sources.list.d/nodesource.list +msg_ok "Set up Node.js Repository" + +msg_info "Setting up PostgreSQL Repository" +curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg +echo "deb https://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" >/etc/apt/sources.list.d/pgdg.list +msg_ok "Set up PostgreSQL Repository" + +msg_info "Installing Node.js" +$STD apt-get update +$STD apt-get install -y nodejs +$STD npm install -g yarn +msg_ok "Installed Node.js" + +msg_info "Install/Set up PostgreSQL Database" +$STD apt-get install -y postgresql-16 +DB_NAME="outline" +DB_USER="outline" +DB_PASS="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)" +SECRET_KEY="$(openssl rand -hex 32)" +$STD sudo -u postgres psql -c "CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';" +$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET client_encoding TO 'utf8';" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET default_transaction_isolation TO 'read committed';" +$STD sudo -u postgres psql -c "ALTER ROLE $DB_USER SET timezone TO 'UTC';" +msg_ok "Set up PostgreSQL" + +msg_info "Setup Outline (Patience)" +temp_file=$(mktemp) +LOCAL_IP="$(hostname -I | awk '{print $1}')" +RELEASE=$(curl -s https://api.github.com/repos/outline/outline/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') +wget -q "https://github.com/outline/outline/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file +tar zxf $temp_file +mv outline-${RELEASE} /opt/outline +cd /opt/outline +cp .env.sample .env +sed -i 's/NODE_ENV=production/NODE_ENV=development/g' /opt/outline/.env +sed -i "s/generate_a_new_key/${SECRET_KEY}/g" /opt/outline/.env +sed -i "s/user:pass@postgres/${DB_USER}:${DB_PASS}@localhost/g" /opt/outline/.env +sed -i 's/redis:6379/localhost:6379/g' /opt/outline/.env +sed -i "32s#URL=#URL=http://${LOCAL_IP}#g" /opt/outline/.env +sed -i 's/FORCE_HTTPS=true/FORCE_HTTPS=false/g' /opt/outline/.env +$STD yarn install --frozen-lockfile +export NODE_OPTIONS="--max-old-space-size=3584" +$STD yarn build +sed -i 's/NODE_ENV=development/NODE_ENV=production/g' /opt/outline/.env +echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt" +msg_ok "Setup Outline" + +msg_info "Creating Service" +cat </etc/systemd/system/outline.service +[Unit] +Description=Outline Service +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/outline +ExecStart=/usr/bin/node ./build/server/index.js +Restart=always +EnvironmentFile=/opt/outline/.env + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now outline +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -rf $temp_file +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" \ No newline at end of file diff --git a/install/pelican-panel-install.sh b/install/pelican-panel-install.sh new file mode 100644 index 000000000..a64aa9446 --- /dev/null +++ b/install/pelican-panel-install.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: bvdberg01 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE + +source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + curl \ + sudo \ + mc \ + lsb-release \ + mariadb-server \ + mariadb-client \ + apache2 \ + composer +msg_ok "Installed Dependencies" + +msg_info "Adding PHP8.3 Repository" +$STD curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb +$STD dpkg -i /tmp/debsuryorg-archive-keyring.deb +$STD sh -c '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 +msg_ok "Added PHP8.3 Repository" + +msg_info "Installing PHP" +$STD apt-get remove -y php8.2* +$STD apt-get install -y \ + php8.3 \ + php8.3-{gd,mysql,mbstring,bcmath,xml,curl,zip,intl,sqlite3,fpm} \ + libapache2-mod-php8.3 +msg_info "Installed PHP" + +msg_info "Setting up MariaDB" +DB_NAME=panel +DB_USER=pelican +DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13) +$STD mysql -u root -e "CREATE DATABASE $DB_NAME;" +$STD mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED WITH mysql_native_password AS PASSWORD('$DB_PASS');" +$STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;" +{ + echo "Pelican Panel-Credentials" + echo "Pelican Panel Database User: $DB_USER" + echo "Pelican Panel Database Password: $DB_PASS" + echo "Pelican Panel Database Name: $DB_NAME" +} >> ~/pelican-panel.creds +msg_ok "Set up MariaDB" + +msg_info "Installing Pelican Panel" +RELEASE=$(curl -s https://api.github.com/repos/pelican-dev/panel/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') +mkdir /opt/pelican-panel +cd /opt/pelican-panel +wget -q "https://github.com/pelican-dev/panel/releases/download/v${RELEASE}/panel.tar.gz" +tar -xzf "panel.tar.gz" +$STD composer install --no-dev --optimize-autoloader --no-interaction +$STD php artisan p:environment:setup +$STD php artisan p:environment:queue-service --no-interaction +echo "* * * * * php /opt/pelican-panel/artisan schedule:run >> /dev/null 2>&1" | crontab -u www-data - +chown -R www-data:www-data /opt/pelican-panel +chmod -R 755 /opt/pelican-panel/storage /opt/pelican-panel/bootstrap/cache/ +echo "${RELEASE}" >/opt/${APPLICATION}_version.txt +msg_ok "Installed Pelican Panel" + +msg_info "Creating Service" +cat </etc/apache2/sites-available/pelican.conf + + ServerName pelican + DocumentRoot /opt/pelican-panel/public + AllowEncodedSlashes On + php_value upload_max_filesize 100M + php_value post_max_size 100M + + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + + + ErrorLog /var/log/apache2/pelican_error.log + CustomLog /var/log/apache2/pelican_access.log combined + +EOF +$STD a2ensite pelican +$STD a2enmod rewrite +$STD a2dissite 000-default.conf +$STD systemctl reload apache2 +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -rf "/opt/pelican-panel/panel.tar.gz" +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/pelican-wings-install.sh b/install/pelican-wings-install.sh new file mode 100644 index 000000000..1a1e938e3 --- /dev/null +++ b/install/pelican-wings-install.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: bvdberg01 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE + +source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + curl \ + sudo \ + mc +msg_ok "Installed Dependencies" + +msg_info "Installing Docker" +DOCKER_CONFIG_PATH='/etc/docker/daemon.json' +mkdir -p $(dirname $DOCKER_CONFIG_PATH) +echo -e '{\n "log-driver": "journald"\n}' >/etc/docker/daemon.json +$STD sh <(curl -sSL https://get.docker.com) +systemctl enable -q --now docker +msg_ok "Installed Docker" + +msg_info "Installing Pelican Wings" +RELEASE=$(curl -s https://api.github.com/repos/pelican-dev/wings/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') +wget -q -O /usr/local/bin/wings "https://github.com/pelican-dev/wings/releases/download/v${RELEASE}/wings_linux_amd64" +chmod u+x /usr/local/bin/wings +mkdir -p /etc/pelican /var/run/wings +echo "${RELEASE}" >/opt/${APPLICATION}_version.txt +msg_ok "Installed Pelican Wings" + +msg_info "Creating Service" +cat </etc/systemd/system/wings.service +[Unit] +Description=Wings Daemon +After=docker.service +Requires=docker.service +PartOf=docker.service + +[Service] +User=root +WorkingDirectory=/etc/pelican +LimitNOFILE=4096 +PIDFile=/var/run/wings/daemon.pid +ExecStart=/usr/local/bin/wings +Restart=on-failure +StartLimitInterval=180 +StartLimitBurst=30 +RestartSec=5s + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now wings +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/pihole-install.sh b/install/pihole-install.sh index fcde213f8..d3c64e58f 100644 --- a/install/pihole-install.sh +++ b/install/pihole-install.sh @@ -143,7 +143,7 @@ server=8.8.8.8 server=8.8.4.4 EOF - sed -i -E "s|^(upstreams =).*|\1 [\"127.0.0.1#5335\", \"8.8.4.4\"]|" /etc/pihole/pihole.toml + sed -i -E '/^\s*upstreams\s*=\s*\[/,/^\s*\]/c\ upstreams = [\n "127.0.0.1#5335",\n "8.8.4.4"\n ]' /etc/pihole/pihole.toml systemctl enable -q --now unbound systemctl restart pihole-FTL.service msg_ok "Installed Unbound" diff --git a/install/sftpgo-install.sh b/install/sftpgo-install.sh index 2a513d0f5..93e17cf5a 100644 --- a/install/sftpgo-install.sh +++ b/install/sftpgo-install.sh @@ -41,7 +41,6 @@ motd_ssh customize msg_info "Cleaning up" -rm -rf $RELEASE $STD apt-get -y autoremove $STD apt-get -y autoclean msg_ok "Cleaned" diff --git a/install/unbound-install.sh b/install/unbound-install.sh index 387e57e75..4506a4111 100644 --- a/install/unbound-install.sh +++ b/install/unbound-install.sh @@ -63,7 +63,7 @@ EOF touch /var/log/unbound.log chown unbound:unbound /var/log/unbound.log - +sleep 5 systemctl restart unbound msg_ok "Installed Unbound" diff --git a/install/victoriametrics-install.sh b/install/victoriametrics-install.sh new file mode 100644 index 000000000..4ba74fb8d --- /dev/null +++ b/install/victoriametrics-install.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# 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/VictoriaMetrics/VictoriaMetrics + +source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + sudo \ + curl \ + mc +msg_ok "Installed Dependencies" + +msg_info "Setup VictoriaMetrics" +temp_dir=$(mktemp -d) +cd $temp_dir +mkdir -p /opt/victoriametrics/data +RELEASE=$(curl -s https://api.github.com/repos/VictoriaMetrics/VictoriaMetrics/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }') +wget -q https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v${RELEASE}/victoria-metrics-linux-amd64-v${RELEASE}.tar.gz +wget -q https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v${RELEASE}/vmutils-linux-amd64-v${RELEASE}.tar.gz +tar -xf victoria-metrics-linux-amd64-v${RELEASE}.tar.gz -C /opt/victoriametrics +tar -xf vmutils-linux-amd64-v${RELEASE}.tar.gz -C /opt/victoriametrics +chmod +x /opt/victoriametrics/* +msg_ok "Setup VictoriaMetrics" + +msg_info "Creating Service" +cat </etc/systemd/system/victoriametrics.service +[Unit] +Description=VictoriaMetrics Service + +[Service] +Type=simple +Restart=always +User=root +WorkingDirectory=/opt/victoriametrics +ExecStart=/opt/victoriametrics/victoria-metrics-prod --storageDataPath="/opt/victoriametrics/data" + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now victoriametrics +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -rf $temp_dir +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" diff --git a/install/web-check-install.sh b/install/web-check-install.sh new file mode 100644 index 000000000..0333aa89a --- /dev/null +++ b/install/web-check-install.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: CrazyWolf13 +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/lissy93/web-check +source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" + +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +export DEBIAN_FRONTEND=noninteractive +$STD apt-get -y install --no-install-recommends \ + curl \ + sudo \ + mc \ + git \ + gnupg \ + traceroute \ + make \ + g++ \ + traceroute \ + xvfb \ + dbus \ + xorg \ + xvfb \ + gtk2-engines-pixbuf \ + dbus-x11 \ + xfonts-base \ + xfonts-100dpi \ + xfonts-75dpi \ + xfonts-scalable \ + imagemagick \ + x11-apps +msg_ok "Installed Dependencies" + +msg_info "Setting up Node.js Repository" +mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list +msg_ok "Set up Node.js Repository" + +msg_info "Setup Python3" +$STD apt-get install -y python3 +rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED +msg_ok "Setup Python3" + +msg_info "Installing Chromium" +curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /etc/apt/trusted.gpg.d/google-archive.gpg +echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >/etc/apt/sources.list.d/google.list +$STD apt-get update +$STD apt-get -y install \ + chromium \ + libxss1 \ + lsb-release +msg_ok "Installed Chromium" + +msg_info "Installing Node.js" +$STD apt-get update +$STD apt-get install -y nodejs +$STD npm install -g yarn +msg_ok "Installed Node.js" + +msg_info "Setting up Chromium" +/usr/bin/chromium --no-sandbox --version > /etc/chromium-version +chmod 755 /usr/bin/chromium +msg_ok "Setup Chromium" + +msg_info "Installing Web-Check (Patience)" +temp_file=$(mktemp) +RELEASE="patch-1" +wget -q "https://github.com/CrazyWolf13/web-check/archive/refs/heads/${RELEASE}.tar.gz" -O $temp_file +tar xzf $temp_file +mv web-check-${RELEASE} /opt/web-check +cd /opt/web-check +cat <<'EOF' > /opt/web-check/.env +CHROME_PATH=/usr/bin/chromium +PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium +HEADLESS=true +GOOGLE_CLOUD_API_KEY='' +REACT_APP_SHODAN_API_KEY='' +REACT_APP_WHO_API_KEY='' +SECURITY_TRAILS_API_KEY='' +CLOUDMERSIVE_API_KEY='' +TRANCO_USERNAME='' +TRANCO_API_KEY='' +URL_SCAN_API_KEY='' +BUILT_WITH_API_KEY='' +TORRENT_IP_API_KEY='' +PORT='3000' +DISABLE_GUI='false' +API_TIMEOUT_LIMIT='10000' +API_CORS_ORIGIN='*' +API_ENABLE_RATE_LIMIT='false' +REACT_APP_API_ENDPOINT='/api' +ENABLE_ANALYTICS='false' +EOF +$STD yarn install --frozen-lockfile --network-timeout 100000 +echo "${RELEASE}" >/opt/${APPLICATION}_version.txt +msg_ok "Installed Web-Check" + +msg_info "Building Web-Check" +$STD yarn build --production +msg_ok "Built Web-Check" + +msg_info "Creating Service" +cat <<'EOF' > /opt/run_web-check.sh +#!/bin/bash +SCREEN_RESOLUTION="1280x1024x24" +if ! systemctl is-active --quiet dbus; then + echo "Warning: dbus service is not running. Some features may not work properly." +fi +[[ -z "${DISPLAY}" ]] && export DISPLAY=":99" +Xvfb "${DISPLAY}" -screen 0 "${SCREEN_RESOLUTION}" & +XVFB_PID=$! +sleep 2 +cd /opt/web-check +exec yarn start +EOF +chmod +x /opt/run_web-check.sh +cat <<'EOF' > /etc/systemd/system/web-check.service +[Unit] +Description=Web Check Service +After=network.target + +[Service] +Type=simple +User=root +Group=root +WorkingDirectory=/opt/web-check +EnvironmentFile=/opt/web-check/.env +ExecStartPre=/bin/bash -c "service dbus start || true" +ExecStartPre=/bin/bash -c "if ! pgrep -f 'Xvfb.*:99' > /dev/null; then Xvfb :99 -screen 0 1280x1024x24 & fi" +ExecStart=/opt/run_web-check.sh +Restart=on-failure +Environment=DISPLAY=:99 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now web-check +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -rf $temp_file +rm -rf /var/lib/apt/lists/* /app/node_modules/.cache +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" + +motd_ssh +customize diff --git a/install/wger-install.sh b/install/wger-install.sh new file mode 100644 index 000000000..7ffcdfbca --- /dev/null +++ b/install/wger-install.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash + +# 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/wger-project/wger + +source /dev/stdin <<< "$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt-get install -y \ + curl \ + sudo \ + mc \ + git \ + gnupg \ + apache2 \ + libapache2-mod-wsgi-py3 +msg_ok "Installed Dependencies" + +msg_info "Installing Python" +$STD apt-get install -y python3-pip +rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED +msg_ok "Installed Python" + +msg_info "Setting up Node.js Repository" +mkdir -p /etc/apt/keyrings +curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg +echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list +msg_ok "Set up Node.js Repository" + +msg_info "Installing Node.js" +$STD apt-get update +$STD apt-get install -y nodejs +$STD npm install -g yarn sass +msg_ok "Installed Node.js" + +msg_info "Setting up wger" +$STD adduser wger --disabled-password --gecos "" +mkdir /home/wger/db +touch /home/wger/db/database.sqlite +chown :www-data -R /home/wger/db +chmod g+w /home/wger/db /home/wger/db/database.sqlite +mkdir /home/wger/{static,media} +chmod o+w /home/wger/media +temp_dir=$(mktemp -d) +cd $temp_dir +RELEASE=$(curl -s https://api.github.com/repos/wger-project/wger/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3)}') +wget -q "https://github.com/wger-project/wger/archive/refs/tags/$RELEASE.tar.gz" +tar xzf $RELEASE.tar.gz +mv wger-$RELEASE /home/wger/src +cd /home/wger/src +$STD pip install -r requirements_prod.txt +$STD pip install -e . +$STD wger create-settings --database-path /home/wger/db/database.sqlite +sed -i "s#home/wger/src/media#home/wger/media#g" /home/wger/src/settings.py +sed -i "/MEDIA_ROOT = '\/home\/wger\/media'/a STATIC_ROOT = '/home/wger/static'" /home/wger/src/settings.py +$STD wger bootstrap +$STD python3 manage.py collectstatic +echo "${RELEASE}" >/opt/wger_version.txt +msg_ok "Finished setting up wger" + +msg_info "Creating Service" +cat </etc/apache2/sites-available/wger.conf + + + Require all granted + + + + + WSGIApplicationGroup %{GLOBAL} + WSGIDaemonProcess wger python-path=/home/wger/src python-home=/home/wger + WSGIProcessGroup wger + WSGIScriptAlias / /home/wger/src/wger/wsgi.py + WSGIPassAuthorization On + + Alias /static/ /home/wger/static/ + + Require all granted + + + Alias /media/ /home/wger/media/ + + Require all granted + + + ErrorLog /var/log/apache2/wger-error.log + CustomLog /var/log/apache2/wger-access.log combined + +EOF +$STD a2dissite 000-default.conf +$STD a2ensite wger +systemctl restart apache2 +cat </etc/systemd/system/wger.service +[Unit] +Description=wger Service +After=network.target + +[Service] +Type=simple +User=root +ExecStart=/usr/local/bin/wger start -a 0.0.0.0 -p 3000 +Restart=always + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now wger +msg_ok "Created Service" + +motd_ssh +customize + +msg_info "Cleaning up" +rm -rf $temp_dir +$STD apt-get -y autoremove +$STD apt-get -y autoclean +msg_ok "Cleaned" + +motd_ssh +customize diff --git a/install/zigbee2mqtt-install.sh b/install/zigbee2mqtt-install.sh index 8dc8cedb6..839d0fb0e 100644 --- a/install/zigbee2mqtt-install.sh +++ b/install/zigbee2mqtt-install.sh @@ -52,7 +52,7 @@ mv zigbee2mqtt-${RELEASE} /opt/zigbee2mqtt cd /opt/zigbee2mqtt/data mv configuration.example.yaml configuration.yaml cd /opt/zigbee2mqtt -$STD pnpm install --frozen-lockfile +$STD pnpm install --no-frozen-lockfile $STD pnpm build msg_ok "Installed Zigbee2MQTT" diff --git a/install/zitadel-install.sh b/install/zitadel-install.sh index 6ee097ca4..340ec3a42 100644 --- a/install/zitadel-install.sh +++ b/install/zitadel-install.sh @@ -46,7 +46,6 @@ msg_info "Installing Zitadel" RELEASE=$(curl -si https://github.com/zitadel/zitadel/releases/latest | grep location: | cut -d '/' -f 8 | tr -d '\r') wget -qc https://github.com/zitadel/zitadel/releases/download/$RELEASE/zitadel-linux-amd64.tar.gz -O - | tar -xz mv zitadel-linux-amd64/zitadel /usr/local/bin -echo "${RELEASE}" >"/opt/zitadel_version.txt" msg_ok "Installed Zitadel" msg_info "Setting up Zitadel Environments" @@ -126,7 +125,7 @@ zitadel start-from-init --masterkeyFile /opt/zitadel/.masterkey --config /opt/zi sleep 60 kill $(lsof -i | awk '/zitadel/ {print $2}' | head -n1) useradd zitadel -echo -e "$(zitadel -v | grep -oP 'v\d+\.\d+\.\d+')" > /opt/Zitadel_version.txt +echo "${RELEASE}" >/opt/${APPLICATION}_version.txt msg_ok "Zitadel initialized" msg_info "Set ExternalDomain to current IP and restart Zitadel" diff --git a/json/add-tailscale-lxc.json b/json/add-tailscale-lxc.json index d95295da4..3a6099cb3 100644 --- a/json/add-tailscale-lxc.json +++ b/json/add-tailscale-lxc.json @@ -31,6 +31,10 @@ "password": null }, "notes": [ + { + "text": "Only supported on Debian 12 LXCs", + "type": "warning" + }, { "text": "After the script finishes, reboot the LXC then run `tailscale up` in the LXC console", "type": "info" @@ -41,4 +45,4 @@ } ], "status": "βœ…" -} \ No newline at end of file +} diff --git a/json/authelia.json b/json/authelia.json new file mode 100644 index 000000000..95ed5dbff --- /dev/null +++ b/json/authelia.json @@ -0,0 +1,39 @@ +{ + "name": "Authelia", + "slug": "authelia", + "categories": [ + 6 + ], + "date_created": "2025-02-24", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 9091, + "documentation": "https://www.authelia.com/integration/deployment/bare-metal/", + "website": "https://www.authelia.com/", + "logo": "https://www.authelia.com/images/branding/logo.png", + "description": "Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies.", + "install_methods": [ + { + "type": "default", + "script": "ct/authelia.sh", + "resources": { + "cpu": 1, + "ram": 512, + "hdd": 2, + "os": "Debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": "authelia", + "password": "authelia" + }, + "notes": [ + { + "text": "During installation, you will have to input your domain (ex. domain.com). Authelia will use auth.domain.com", + "type": "info" + } + ] +} diff --git a/json/bytestash.json b/json/bytestash.json new file mode 100644 index 000000000..a88f04914 --- /dev/null +++ b/json/bytestash.json @@ -0,0 +1,34 @@ +{ + "name": "ByteStash", + "slug": "bytestash", + "categories": [ + 20 + ], + "date_created": "2025-02-27", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3000, + "documentation": "https://github.com/jordan-dalby/ByteStash/wiki", + "website": "https://github.com/jordan-dalby/ByteStash", + "logo": "https://raw.githubusercontent.com/jordan-dalby/ByteStash/refs/heads/main/client/public/logo192.png", + "description": "ByteStash is a self-hosted web application designed to store, organise, and manage your code snippets efficiently. With support for creating, editing, and filtering snippets, ByteStash helps you keep track of your code in one secure place.", + "install_methods": [ + { + "type": "default", + "script": "ct/bytestash.sh", + "resources": { + "cpu": 1, + "ram": 1024, + "hdd": 4, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/json/graylog.json b/json/graylog.json index 66cb9c13d..7258b2d15 100644 --- a/json/graylog.json +++ b/json/graylog.json @@ -12,7 +12,7 @@ "documentation": "https://go2docs.graylog.org/current/home.htm", "website": "https://graylog.org/", "logo": "https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/svg/graylog.svg", - "description": "Graylog is a free and open log management platform.", + "description": "Graylog is an open-source log management and analysis platform that centralizes and processes log data from various sources, enabling real-time search, analysis, and alerting for IT infrastructure monitoring and troubleshooting.", "install_methods": [ { "type": "default", diff --git a/json/habitica.json b/json/habitica.json new file mode 100644 index 000000000..0b8b0521c --- /dev/null +++ b/json/habitica.json @@ -0,0 +1,43 @@ +{ + "name": "Habitica", + "slug": "habitica", + "categories": [ + 24 + ], + "date_created": "2025-03-03", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8080, + "documentation": "https://github.com/HabitRPG/habitica/wiki", + "website": "https://habitica.com/", + "logo": "https://github.com/HabitRPG/habitica/raw/refs/heads/develop/website/client/src/assets/svg/logo.svg", + "description": "Habitica is an open-source habit-building program that treats your life like a role-playing game. Level up as you succeed, lose HP as you fail, and earn Gold to buy weapons and armor!", + "install_methods": [ + { + "type": "default", + "script": "ct/habitica.sh", + "resources": { + "cpu": 2, + "ram": 4096, + "hdd": 8, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "It takes a minute or two after installation for web UI to start, please be patient.", + "type": "info" + }, + { + "text": "Config file is at `/opt/habitica/config.json`", + "type": "info" + } + ] +} diff --git a/json/jupyternotebook.json b/json/jupyternotebook.json new file mode 100644 index 000000000..0ebf71f46 --- /dev/null +++ b/json/jupyternotebook.json @@ -0,0 +1,39 @@ +{ + "name": "Jupyter Notebook", + "slug": "jupyter-notebook", + "categories": [ + 20 + ], + "date_created": "2025-02-24", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8888, + "documentation": "https://jupyter-notebook.readthedocs.io/en/stable/", + "website": "https://jupyter.org/", + "logo": "https://upload.wikimedia.org/wikipedia/commons/thumb/3/38/Jupyter_logo.svg/800px-Jupyter_logo.svg.png", + "description": "The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, data visualization, machine learning, and much more.", + "install_methods": [ + { + "type": "default", + "script": "ct/jupyternotebook.sh", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 4, + "os": "ubuntu", + "version": "24.04" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "To get the token to access the Jupyter Notebook, run the following command: jupyter notebook list.", + "type": "info" + } + ] +} diff --git a/json/linkwarden.json b/json/linkwarden.json index 3ec555040..93d305e0e 100644 --- a/json/linkwarden.json +++ b/json/linkwarden.json @@ -31,10 +31,7 @@ "password": null }, "notes": [ - { - "text": "Linkwarden > 2.8.2 needs Monolith, More info: `https://github.com/community-scripts/ProxmoxVE/discussions/305`", - "type": "info" - } + {} ], "status": "βœ…" -} \ No newline at end of file +} diff --git a/json/minio.json b/json/minio.json index 5d307bb32..dc8075a9c 100644 --- a/json/minio.json +++ b/json/minio.json @@ -8,7 +8,7 @@ "type": "ct", "updateable": true, "privileged": false, - "interface_port": 9000, + "interface_port": 9001, "documentation": "https://min.io/docs/minio/linux/index.html", "website": "https://min.io/", "logo": "https://raw.githubusercontent.com/minio/minio/refs/heads/master/.github/logo.svg", diff --git a/json/outline.json b/json/outline.json new file mode 100644 index 000000000..b167040b7 --- /dev/null +++ b/json/outline.json @@ -0,0 +1,43 @@ +{ + "name": "Outline", + "slug": "outline", + "categories": [ + 12 + ], + "date_created": "2025-02-26", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3000, + "documentation": "https://docs.getoutline.com/s/hosting/", + "website": "https://www.getoutline.com", + "logo": "https://www.getoutline.com/images/logo.svg", + "description": "The fastest knowledge base for growing teams. Beautiful, realtime collaborative, feature packed, and markdown compatible. It’s time to get your team’s knowledge organized.", + "install_methods": [ + { + "type": "default", + "script": "ct/outline.sh", + "resources": { + "cpu": 2, + "ram": 4096, + "hdd": 8, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "After installation finishes, application will do a database migration so web UI might be unavailable for a minute or two. Also you need to manually add authentication and/or enable HTTPS.", + "type": "info" + }, + { + "text": "Configuration file is at: `/opt/outline/.env`. Modify to suit your environment.", + "type": "info" + } + ] +} \ No newline at end of file diff --git a/json/pelican-panel.json b/json/pelican-panel.json new file mode 100644 index 000000000..510626c14 --- /dev/null +++ b/json/pelican-panel.json @@ -0,0 +1,43 @@ +{ + "name": "Pelican Panel", + "slug": "pelican-panel", + "categories": [ + 24 + ], + "date_created": "2025-02-27", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 80, + "documentation": "https://pelican.dev/docs/panel/getting-started", + "website": "https://pelican.dev/", + "logo": "https://pelican.dev/img/logo.png", + "description": "Pelican Panel is a web-based control panel for managing game and application servers. It provides an intuitive interface to start, stop, configure, and monitor servers easily. It works alongside Pelican Wings, a lightweight daemon that handles server deployments and resource management.", + "install_methods": [ + { + "type": "default", + "script": "ct/pelican-panel.sh", + "resources": { + "cpu": 2, + "ram": 1024, + "hdd": 4, + "os": "Debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "Database credentials: `cat ~/pelican-panel.creds`", + "type": "info" + }, + { + "text": "Step 5 of the Panel installer can be skipped because it has already been set up by the script.", + "type": "info" + } + ] +} diff --git a/json/pelican-wings.json b/json/pelican-wings.json new file mode 100644 index 000000000..b587ef304 --- /dev/null +++ b/json/pelican-wings.json @@ -0,0 +1,39 @@ +{ + "name": "Pelican Wings", + "slug": "pelican-wings", + "categories": [ + 24 + ], + "date_created": "2025-02-27", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": null, + "documentation": "https://pelican.dev/docs/wings/install", + "website": "https://pelican.dev/", + "logo": "https://pelican.dev/img/logo.png", + "description": "Pelican Wings is Pelican's server control plane, built for the rapidly changing gaming industry and designed to be highly performant and secure. Wings provides an HTTP API allowing you to interface directly with running server instances, fetch server logs, generate backups, and control all aspects of the server lifecycle.", + "install_methods": [ + { + "type": "default", + "script": "ct/pelican-wings.sh", + "resources": { + "cpu": 2, + "ram": 4096, + "hdd": 8, + "os": "Debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "After installation, you need to use the Auto Deploy command generated by Pelican Panel and, after running the command, restart the Wings service with `systemctl restart wings.service`", + "type": "info" + } + ] +} diff --git a/json/pihole.json b/json/pihole.json index 19124d1ed..17fc88530 100644 --- a/json/pihole.json +++ b/json/pihole.json @@ -32,7 +32,7 @@ }, "notes": [ { - "text": "To set your password, log in to the container, and type the following: `pihole -a -p`", + "text": "To set your password, log in to the container, and type the following: `pihole setpassword`", "type": "info" }, { diff --git a/json/pocketid.json b/json/pocketid.json index 58fd59067..465b09ecd 100644 --- a/json/pocketid.json +++ b/json/pocketid.json @@ -9,8 +9,8 @@ "updateable": true, "privileged": false, "interface_port": 80, - "documentation": "https://stonith404.github.io/pocket-id/introduction", - "website": "https://github.com/stonith404/pocket-id", + "documentation": "https://pocket-id.org/docs/", + "website": "https://github.com/pocket-id/pocket-id", "logo": "https://raw.githubusercontent.com/pocket-id/pocket-id/refs/heads/main/backend/resources/images/logoDark.svg", "description": "Pocket ID is a simple OIDC provider that allows users to authenticate with their passkeys to your services.", "install_methods": [ diff --git a/json/victoriametrics.json b/json/victoriametrics.json new file mode 100644 index 000000000..43955e6ca --- /dev/null +++ b/json/victoriametrics.json @@ -0,0 +1,34 @@ +{ + "name": "VictoriaMetrics", + "slug": "victoria", + "categories": [ + 8 + ], + "date_created": "2025-02-24", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 8428, + "documentation": "https://docs.victoriametrics.com/", + "website": "https://victoriametrics.com/", + "logo": "https://marketplace-assets.digitalocean.com/logos/victoriametrics-victoriametricss.png", + "description": "VictoriaMetrics is a fast, cost-saving, and scalable solution for monitoring and managing time series data. It delivers high performance and reliability, making it an ideal choice for businesses of all sizes.", + "install_methods": [ + { + "type": "default", + "script": "ct/victoriametrics.sh", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 16, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/json/web-check.json b/json/web-check.json new file mode 100644 index 000000000..53cda3439 --- /dev/null +++ b/json/web-check.json @@ -0,0 +1,34 @@ +{ + "name": "Web-Check", + "slug": "web-check", + "categories": [ + 4 + ], + "date_created": "2025-02-27", + "type": "ct", + "updateable": false, + "privileged": false, + "interface_port": 3000, + "documentation": "https://github.com/Lissy93/web-check/blob/master/.github/README.md", + "website": "https://github.com/lissy93/web-check", + "logo": "https://raw.githubusercontent.com/Lissy93/web-check/refs/heads/master/.github/web-check-logo.png", + "description": "Get an insight into the inner-workings of a given website: uncover potential attack vectors, analyse server architecture, view security configurations, and learn what technologies a site is using.", + "install_methods": [ + { + "type": "default", + "script": "ct/web-check.sh", + "resources": { + "cpu": 2, + "ram": 2048, + "hdd": 12, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/json/wger.json b/json/wger.json new file mode 100644 index 000000000..c3282dfa4 --- /dev/null +++ b/json/wger.json @@ -0,0 +1,39 @@ +{ + "name": "wger", + "slug": "wger", + "categories": [ + 24 + ], + "date_created": "2025-02-24", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3000, + "documentation": "https://wger.readthedocs.io/en/latest/index.html#", + "website": "https://wger.de", + "logo": "https://avatars.githubusercontent.com/u/17430347?s=48&v=4", + "description": "wger (ˈvɛɑɐ) Workout Manager is a free, open source web application that helps you manage your personal workouts, weight and diet plans and can also be used as a simple gym management utility. It offers a REST API as well, for easy integration with other projects and tools.", + "install_methods": [ + { + "type": "default", + "script": "ct/wger.sh", + "resources": { + "cpu": 1, + "ram": 1024, + "hdd": 6, + "os": "debian", + "version": "12" + } + } + ], + "default_credentials": { + "username": "admin", + "password": "adminadmin" + }, + "notes": [ + { + "text": "Enable proxy support by uncommenting this line in `/home/wger/src/settings.py` and pointing it to your URL: `# CSRF_TRUSTED_ORIGINS = ['http://127.0.0.1', 'https://my.domain.example.com']`, then restart the service `systemctl restart wger`.", + "type": "info" + } + ] +} \ No newline at end of file diff --git a/json/zigbee2mqtt.json b/json/zigbee2mqtt.json index 30b2bdf68..2379a4a7d 100644 --- a/json/zigbee2mqtt.json +++ b/json/zigbee2mqtt.json @@ -43,7 +43,7 @@ }, "notes": [ { - "text": "You can find the post-install guide here: https://github.com/community-scripts/ProxmoxVE/discussions/410", + "text": "You can find the post-install guide here: `https://github.com/community-scripts/ProxmoxVE/discussions/410`", "type": "info" } ], diff --git a/misc/add-tailscale-lxc.sh b/misc/add-tailscale-lxc.sh index 36d148e40..93f37b9cd 100644 --- a/misc/add-tailscale-lxc.sh +++ b/misc/add-tailscale-lxc.sh @@ -67,6 +67,9 @@ echo "deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https:// apt-get update &>/dev/null apt-get install -y tailscale &>/dev/null ' || exit +TAGS=$(awk -F': ' '/^tags:/ {print $2}' /etc/pve/lxc/${CTID}.conf) +TAGS="${TAGS:+$TAGS; }tailscale" +pct set "$CTID" -tags "${TAGS}" msg "\e[1;32m βœ” Installed Tailscale\e[0m" msg "\e[1;31m Reboot ${CTID} LXC to apply the changes, then run tailscale up in the LXC console\e[0m" diff --git a/misc/alpine-install.func b/misc/alpine-install.func index b727b8eca..c00474a66 100644 --- a/misc/alpine-install.func +++ b/misc/alpine-install.func @@ -17,7 +17,7 @@ color() { BFR="\\r\\033[K" BOLD=$(echo "\033[1m") TAB=" " - + # System RETRY_NUM=10 RETRY_EVERY=3 @@ -35,12 +35,24 @@ color() { DEFAULT="${TAB}βš™οΈ${TAB}${CL}" } -# This function enables IPv6 if it's not disabled and sets verbose mode if the global variable is set to "yes" -verb_ip6() { +# Function to set STD mode based on verbosity +set_std_mode() { if [ "$VERBOSE" = "yes" ]; then STD="" - else STD="silent"; fi - silent() { "$@" >/dev/null 2>&1; } + else + STD="silent" + fi +} + +# Silent execution function +silent() { + "$@" >/dev/null 2>&1 +} + +# This function enables IPv6 if it's not disabled and sets verbose mode +verb_ip6() { + set_std_mode # Set STD mode based on VERBOSE + if [ "$DISABLEIPV6" == "yes" ]; then $STD sysctl -w net.ipv6.conf.all.disable_ipv6=1 echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf @@ -106,15 +118,15 @@ setting_up_container() { network_check() { set +e trap - ERR - if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then - msg_ok "Internet Connected"; + if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then + msg_ok "Internet Connected" else msg_error "Internet NOT Connected" read -r -p "Would you like to continue anyway? " prompt if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then echo -e "${INFO}${RD}Expect Issues Without Internet${CL}" else - echo -e "${NETWORK}Check Network Settings" + echo -e "${NETWORK}Check Network Settings" exit 1 fi fi @@ -147,13 +159,13 @@ motd_ssh() { fi PROFILE_FILE="/etc/profile.d/00_lxc-details.sh" - echo "echo -e \"\"" > "$PROFILE_FILE" - echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts & pimox-scripts ${YW}| GitHub: ${GN}https://github.com/asylumexp/Proxmox${CL}\"" >> "$PROFILE_FILE" - echo "echo \"\"" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(ip -4 addr show eth0 | awk '/inet / {print \$2}' | cut -d/ -f1 | head -n 1)${CL}\"" >> "$PROFILE_FILE" + echo "echo -e \"\"" >"$PROFILE_FILE" + echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts & pimox-scripts ${YW}| GitHub: ${GN}https://github.com/asylumexp/ProxmoxVE${CL}\"" >>"$PROFILE_FILE" + echo "echo \"\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(ip -4 addr show eth0 | awk '/inet / {print \$2}' | cut -d/ -f1 | head -n 1)${CL}\"" >>"$PROFILE_FILE" # Configure SSH if enabled if [[ "${SSH_ROOT}" == "yes" ]]; then @@ -169,8 +181,8 @@ motd_ssh() { # This function customizes the container and enables passwordless login for the root user customize() { if [[ "$PASSWORD" == "" ]]; then - msg_info "Customizing Container" - bash -c "passwd -d root" >/dev/null 2>&1 - msg_ok "Customized Container" + msg_info "Customizing Container" + bash -c "passwd -d root" >/dev/null 2>&1 + msg_ok "Customized Container" fi } diff --git a/misc/build.func b/misc/build.func index 9cba9936d..cd244f53c 100644 --- a/misc/build.func +++ b/misc/build.func @@ -4,16 +4,16 @@ # https://github.com/asylumexp/Proxmox/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. - INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern. - PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase - DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call. - METHOD="default" # sets the METHOD variable to "default", used for the API call. + 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. + INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern. + PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase + DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call. + METHOD="default" # sets the METHOD variable to "default", used for the API call. RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUID variable. } -source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) +source <(curl -s https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/api.func) # This function sets various color variables using ANSI escape codes for formatting text in the terminal. color() { @@ -68,55 +68,86 @@ catch_errors() { # This function is called when an error occurs. It receives the exit code, line number, and command that caused the error, and displays an error message. error_handler() { - source /dev/stdin <<< $(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + source /dev/stdin <<<$(wget -qLO - https://raw.githubusercontent.com/asylumexp/Proxmox/main/misc/api.func) + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local exit_code="$?" local line_number="$1" local command="$2" local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}" - post_update_to_api "failed" "${command}" + post_update_to_api "failed" "${command}" echo -e "\n$error_message\n" } -# This function displays a spinner. -spinner() { +# This function displays an informational message with logging support. +start_spinner() { + local msg="$1" local frames=('β ‹' 'β ™' 'β Ή' 'β Έ' 'β Ό' 'β ΄' 'β ¦' 'β §' 'β ‡' '⠏') local spin_i=0 local interval=0.1 - printf "\e[?25l" + local term_width=$(tput cols) - local color="${YWB}" + { + while [ "${SPINNER_ACTIVE:-1}" -eq 1 ]; do + printf "\r\e[2K${frames[spin_i]} ${YW}%b${CL}" "$msg" >&2 + spin_i=$(((spin_i + 1) % ${#frames[@]})) + sleep "$interval" + done + } & - while true; do - printf "\r ${color}%s${CL}" "${frames[spin_i]}" - spin_i=$(( (spin_i + 1) % ${#frames[@]} )) - sleep "$interval" - done -} - -# This function displays an informational message with a yellow color. -msg_info() { - local msg="$1" - echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}" - spinner & SPINNER_PID=$! } -# This function displays a success message with a green color. -msg_ok() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi - printf "\e[?25h" +msg_info() { local msg="$1" - echo -e "${BFR}${CM}${GN}${msg}${CL}" + if [ "${SPINNER_ACTIVE:-0}" -eq 1 ]; then + return + fi + + SPINNER_ACTIVE=1 + start_spinner "$msg" } -# This function displays a error message with a red color. -msg_error() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi - printf "\e[?25h" +msg_ok() { + if [ -n "${SPINNER_PID:-}" ] && ps -p "$SPINNER_PID" >/dev/null 2>&1; then + kill "$SPINNER_PID" >/dev/null 2>&1 + wait "$SPINNER_PID" 2>/dev/null || true + fi + local msg="$1" - echo -e "${BFR}${CROSS}${RD}${msg}${CL}" + printf "\r\e[2K${CM}${GN}%b${CL}\n" "$msg" >&2 + unset SPINNER_PID + SPINNER_ACTIVE=0 + + log_message "OK" "$msg" +} + +msg_error() { + if [ -n "${SPINNER_PID:-}" ] && ps -p "$SPINNER_PID" >/dev/null 2>&1; then + kill "$SPINNER_PID" >/dev/null 2>&1 + wait "$SPINNER_PID" 2>/dev/null || true + fi + + local msg="$1" + printf "\r\e[2K${CROSS}${RD}%b${CL}\n" "$msg" >&2 + unset SPINNER_PID + SPINNER_ACTIVE=0 + log_message "ERROR" "$msg" +} + +log_message() { + local level="$1" + local message="$2" + local timestamp + local logdate + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + logdate=$(date '+%Y-%m-%d') + + LOGDIR="/usr/local/community-scripts/logs" + mkdir -p "$LOGDIR" + + LOGFILE="${LOGDIR}/${logdate}_${NSAPP}.log" + echo "$timestamp - $level: $message" >>"$LOGFILE" } # Check if the shell is using bash @@ -235,14 +266,14 @@ update_motd_ip() { IP=$(get_current_ip) # Add the new IP address - echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >> "$MOTD_FILE" + echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >>"$MOTD_FILE" fi } # Function to download & save header files get_header() { - local app_name=$(echo ${APP,,} | tr -d ' ') - local header_url="https://github.com/community-scripts/ProxmoxVE/raw/main/ct/headers/${app_name}" + local app_name=$(echo ${APP,,} | tr -d ' ') + local header_url="https://github.com/asylumexp/Proxmox/raw/main/ct/headers/${app_name}" local local_header_path="/usr/local/community-scripts/headers/${app_name}" mkdir -p "/usr/local/community-scripts/headers" @@ -260,7 +291,7 @@ get_header() { # This function sets the APP-Name into an ASCII Header in Slant, figlet needed on proxmox main node. header_info() { - local app_name=$(echo ${APP,,} | tr -d ' ') + local app_name=$(echo ${APP,,} | tr -d ' ') local header_content # Download & save Header-File locally @@ -794,14 +825,14 @@ advanced_settings() { fi } -diagnostics_check(){ +diagnostics_check() { if ! [ -d "/usr/local/community-scripts" ]; then - mkdir -p /usr/local/community-scripts - fi + mkdir -p /usr/local/community-scripts + fi - if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then - if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then - cat </usr/local/community-scripts/diagnostics + if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then + if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then + cat </usr/local/community-scripts/diagnostics DIAGNOSTICS=yes #This file is used to store the diagnostics settings for the Community-Scripts API. @@ -918,23 +949,24 @@ install_script() { advanced_settings break ;; - 4) - if [[ $DIAGNOSTICS == "yes" ]]; then - if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ - --yes-button "No" --no-button "Back" ; then - DIAGNOSTICS="no" - sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics - whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 - fi - else - if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ - --yes-button "Yes" --no-button "Back" ; then - DIAGNOSTICS="yes" - sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics - whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 - fi - fi - ;; + 4) + if [[ $DIAGNOSTICS == "yes" ]]; then + if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ + --yes-button "No" --no-button "Back"; then + DIAGNOSTICS="no" + sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics + whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 + fi + else + if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \ + --yes-button "Yes" --no-button "Back"; then + DIAGNOSTICS="yes" + sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics + whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58 + fi + fi + + ;; 5) echo -e "${CROSS}${RD}Exiting.${CL}" exit 0 @@ -971,8 +1003,8 @@ check_container_storage() { # Check if the /boot partition is more than 80% full total_size=$(df /boot --output=size | tail -n 1) local used_size=$(df /boot --output=used | tail -n 1) - usage=$(( 100 * used_size / total_size )) - if (( usage > 80 )); then + usage=$((100 * used_size / total_size)) + if ((usage > 80)); then # Prompt the user for confirmation to continue echo -e "${INFO}${HOLD} ${YWB}Warning: Storage is dangerously low (${usage}%).${CL}" echo -ne "Continue anyway? " @@ -986,6 +1018,9 @@ check_container_storage() { } start() { + LOGDIR="/usr/local/community-scripts/logs" + mkdir -p "$LOGDIR" + if command -v pveversion >/dev/null 2>&1; then if ! (whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} LXC" --yesno "This will create a New ${APP} LXC. Proceed?" 10 58); then clear @@ -1002,11 +1037,32 @@ start() { elif [ -f /etc/alpine-release ]; then apk add --no-cache whiptail &>/dev/null fi - if ! (whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} LXC UPDATE" --yesno "Support/Update functions for ${APP} LXC. Proceed?" 10 58); then + CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "${APP} LXC Update/Setting" --menu \ + "Support/Update functions for ${APP} LXC. Choose an option:" \ + 12 60 3 \ + "1" "YES (Silent Mode)" \ + "2" "YES (Verbose Mode)" \ + "3" "NO (Cancel Update)" --nocancel --default-item "1" 3>&1 1>&2 2>&3) + + case "$CHOICE" in + 1) + VERB="no" + set_std_mode + log_message "INFO" "Update started (Silent Mode)" + ;; + 2) + VERB="yes" + set_std_mode + log_message "INFO" "Update started (Verbose Mode)" + ;; + 3) clear + log_message "INFO" "Update aborted." exit_script exit - fi + ;; + esac + SPINNER_PID="" update_script fi @@ -1138,7 +1194,7 @@ description() { cat < - Logo + Logo

${APP} LXC

@@ -1171,36 +1227,52 @@ EOF if [[ -f /etc/systemd/system/ping-instances.service ]]; then systemctl start ping-instances.service fi - + post_update_to_api "done" "none" } +set_std_mode() { + if [ "$VERB" = "yes" ]; then + STD="" + else + STD="silent" + fi +} + +# Silent execution function +silent() { + if [ "$VERB" = "no" ]; then + "$@" >>"$LOGFILE" 2>&1 + else + "$@" 2>&1 | tee -a "$LOGFILE" + fi +} exit_script() { - exit_code=$? # Capture the exit status of the last executed command + exit_code=$? # Capture the exit status of the last executed command #200 exit codes indicate error in create_lxc.sh #100 exit codes indicate error in install.func -if [ $exit_code -ne 0 ]; then # Check if exit code is nonzero + if [ $exit_code -ne 0 ]; then case $exit_code in - 200) post_update_to_api "failed" "create_lxc.sh: Error during LXC creation" ;; - 201) post_update_to_api "failed" "create_lxc.sh Invalid Storage class" ;; - 202) post_update_to_api "failed" "create_lxc.sh Invalid Menu aborted" ;; - 203) post_update_to_api "failed" "create_lxc.sh CTID was unset" ;; - 204) post_update_to_api "failed" "create_lxc.sh PCT_OSTYPE was unset" ;; - 205) post_update_to_api "failed" "create_lxc.sh ID cannot be less than 100" ;; - 206) post_update_to_api "failed" "create_lxc.sh ID already in use" ;; - 207) post_update_to_api "failed" "create_lxc.sh Template not found" ;; - 208) post_update_to_api "failed" "create_lxc.sh Error downloading template" ;; - 101) post_update_to_api "failed" "create_lxc.sh No Network connection" ;; - *) post_update_to_api "failed" "Unknown error, exit code: $exit_code" ;; + 100) post_update_to_api "failed" "100: Unexpected error in create_lxc.sh" ;; + 101) post_update_to_api "failed" "101: No network connection detected in create_lxc.sh" ;; + 200) post_update_to_api "failed" "200: LXC creation failed in create_lxc.sh" ;; + 201) post_update_to_api "failed" "201: Invalid Storage class in create_lxc.sh" ;; + 202) post_update_to_api "failed" "202: User aborted menu in create_lxc.sh" ;; + 203) post_update_to_api "failed" "203: CTID not set in create_lxc.sh" ;; + 204) post_update_to_api "failed" "204: PCT_OSTYPE not set in create_lxc.sh" ;; + 205) post_update_to_api "failed" "205: CTID cannot be less than 100 in create_lxc.sh" ;; + 206) post_update_to_api "failed" "206: CTID already in use in create_lxc.sh" ;; + 207) post_update_to_api "failed" "207: Template not found in create_lxc.sh" ;; + 208) post_update_to_api "failed" "208: Error downloading template in create_lxc.sh" ;; + 209) post_update_to_api "failed" "209: Container creation failed, but template is intact in create_lxc.sh" ;; + *) post_update_to_api "failed" "Unknown error, exit code: $exit_code in create_lxc.sh" ;; esac -fi + fi } - trap 'exit_script' EXIT trap 'post_update_to_api "failed" "$BASH_COMMAND"' ERR -trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT +trap 'post_update_to_api "failed" "INTERRUPTED"' SIGINT trap 'post_update_to_api "failed" "TERMINATED"' SIGTERM - diff --git a/misc/install.func b/misc/install.func index 4ee21fec4..ca20669bb 100644 --- a/misc/install.func +++ b/misc/install.func @@ -18,7 +18,7 @@ color() { BOLD=$(echo "\033[1m") HOLD=" " TAB=" " - + # System RETRY_NUM=10 RETRY_EVERY=3 @@ -35,12 +35,24 @@ color() { DEFAULT="${TAB}βš™οΈ${TAB}${CL}" } -# This function enables IPv6 if it's not disabled and sets verbose mode if the global variable is set to "yes" -verb_ip6() { +# Function to set STD mode based on verbosity +set_std_mode() { if [ "$VERBOSE" = "yes" ]; then STD="" - else STD="silent"; fi - silent() { "$@" >/dev/null 2>&1; } + else + STD="silent" + fi +} + +# Silent execution function +silent() { + "$@" >/dev/null 2>&1 +} + +# This function enables IPv6 if it's not disabled and sets verbose mode +verb_ip6() { + set_std_mode # Set STD mode based on VERBOSE + if [ "$DISABLEIPV6" == "yes" ]; then echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf $STD sysctl -p @@ -56,14 +68,14 @@ catch_errors() { # This function handles errors error_handler() { source <(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local exit_code="$?" local line_number="$1" local command="$2" local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}" echo -e "\n$error_message" - if [[ "$line_number" -eq 44 ]]; then + if [[ "$line_number" -eq 50 ]]; then echo -e "The silent function has suppressed the error, run the script with verbose mode enabled, which will provide more detailed output.\n" post_update_to_api "failed" "No error message, script ran in silent mode" else @@ -82,7 +94,7 @@ spinner() { while true; do printf "\r ${color}%s${CL}" "${frames[spin_i]}" - spin_i=$(( (spin_i + 1) % ${#frames[@]} )) + spin_i=$(((spin_i + 1) % ${#frames[@]})) sleep "$interval" done } @@ -97,7 +109,7 @@ msg_info() { # This function displays a success message with a green color. msg_ok() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local msg="$1" echo -e "${BFR}${CM}${GN}${msg}${CL}" @@ -105,7 +117,7 @@ msg_ok() { # This function displays a error message with a red color. msg_error() { - if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi + if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi printf "\e[?25h" local msg="$1" echo -e "${BFR}${CROSS}${RD}${msg}${CL}" @@ -146,23 +158,23 @@ network_check() { ipv4_connected=false ipv6_connected=false sleep 1 -# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers. - if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then - msg_ok "IPv4 Internet Connected"; + # Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers. + if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then + msg_ok "IPv4 Internet Connected" ipv4_connected=true else - msg_error "IPv4 Internet Not Connected"; + msg_error "IPv4 Internet Not Connected" fi -# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers. + # Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers. if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then - msg_ok "IPv6 Internet Connected"; + msg_ok "IPv6 Internet Connected" ipv6_connected=true else - msg_error "IPv6 Internet Not Connected"; + msg_error "IPv6 Internet Not Connected" fi -# If both IPv4 and IPv6 checks fail, prompt the user + # If both IPv4 and IPv6 checks fail, prompt the user if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then read -r -p "No Internet detected,would you like to continue anyway? " prompt if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then @@ -192,7 +204,7 @@ else echo -n "DIRECT" fi EOF - chmod +x /usr/local/bin/apt-proxy-detect.sh + chmod +x /usr/local/bin/apt-proxy-detect.sh fi $STD apt-get update $STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade @@ -203,7 +215,7 @@ EOF # This function modifies the message of the day (motd) and SSH settings motd_ssh() { # Set terminal to 256-color mode - grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >> /root/.bashrc + grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc # Get OS information (Debian / Ubuntu) if [ -f "/etc/os-release" ]; then @@ -215,13 +227,13 @@ motd_ssh() { fi PROFILE_FILE="/etc/profile.d/00_lxc-details.sh" - echo "echo -e \"\"" > "$PROFILE_FILE" - echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts & pimox-scripts ${YW}| GitHub: ${GN}https://github.com/asylumexp/Proxmox${CL}\"" >> "$PROFILE_FILE" - echo "echo \"\"" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >> "$PROFILE_FILE" - echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >> "$PROFILE_FILE" + echo "echo -e \"\"" >"$PROFILE_FILE" + echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts & pimox-scripts ${YW}| GitHub: ${GN}https://github.com/asylumexp/ProxmoxVE${CL}\"" >>"$PROFILE_FILE" + echo "echo \"\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE" + echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE" # Disable default MOTD scripts chmod -x /etc/update-motd.d/* @@ -252,7 +264,7 @@ EOF if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then mkdir -p /root/.ssh - echo "${SSH_AUTHORIZED_KEY}" > /root/.ssh/authorized_keys + echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys chmod 700 /root/.ssh chmod 600 /root/.ssh/authorized_keys fi
{item.status === "done" ? ( @@ -237,20 +165,7 @@ const DataFetcher: React.FC = () => { {item.ram_size} {item.method} {item.pve_version} - {item.error && item.error !== "none" ? ( - showErrorRow === index ? ( - <> - {item.error} - - - ) : ( - - ) - ) : ( - "none" - )} - {item.error} {formatDate(item.created_at)}