mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 02:12:49 +00:00 
			
		
		
		
	Compare commits
	
		
			24 Commits
		
	
	
		
			2025-09-28
			...
			2025-09-29
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					efe1e1edb5 | ||
| 
						 | 
					4567505c55 | ||
| 
						 | 
					42c87ba0d4 | ||
| 
						 | 
					b52c252553 | ||
| 
						 | 
					be5ac7153e | ||
| 
						 | 
					07f2849722 | ||
| 
						 | 
					760299283a | ||
| 
						 | 
					0bd2dd7a65 | ||
| 
						 | 
					6591c30e66 | ||
| 
						 | 
					780e5c114c | ||
| 
						 | 
					ba10ec721b | ||
| 
						 | 
					f66dc834bd | ||
| 
						 | 
					be36fc6a94 | ||
| 
						 | 
					65ada6e6f3 | ||
| 
						 | 
					853eb40bba | ||
| 
						 | 
					ace6265895 | ||
| 
						 | 
					639d4f2d53 | ||
| 
						 | 
					d7e77e232c | ||
| 
						 | 
					b850d3f79e | ||
| 
						 | 
					72e5ac5c80 | ||
| 
						 | 
					587579b3a1 | ||
| 
						 | 
					9b4e996d93 | ||
| 
						 | 
					e6f317ede9 | ||
| 
						 | 
					3e4420e357 | 
							
								
								
									
										23
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -10,8 +10,31 @@
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
 | 
			
		||||
 | 
			
		||||
## 2025-09-30
 | 
			
		||||
 | 
			
		||||
## 2025-09-29
 | 
			
		||||
 | 
			
		||||
### 🆕 New Scripts
 | 
			
		||||
 | 
			
		||||
  - Ghostfolio ([#7982](https://github.com/community-scripts/ProxmoxVE/pull/7982))
 | 
			
		||||
- Warracker ([#7977](https://github.com/community-scripts/ProxmoxVE/pull/7977))
 | 
			
		||||
- MyIP ([#7974](https://github.com/community-scripts/ProxmoxVE/pull/7974))
 | 
			
		||||
- Verdaccio ([#7967](https://github.com/community-scripts/ProxmoxVE/pull/7967))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - fix sidebar loading issues and navbar on mobile [@BramSuurdje](https://github.com/BramSuurdje) ([#7991](https://github.com/community-scripts/ProxmoxVE/pull/7991))
 | 
			
		||||
 | 
			
		||||
  - #### ✨ New Features
 | 
			
		||||
 | 
			
		||||
    - Improve mobile ui: added a hamburger navigation to the mobile view. [@BramSuurdje](https://github.com/BramSuurdje) ([#7987](https://github.com/community-scripts/ProxmoxVE/pull/7987))
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - Remove Frigate from Website [@MickLesk](https://github.com/MickLesk) ([#7972](https://github.com/community-scripts/ProxmoxVE/pull/7972))
 | 
			
		||||
 | 
			
		||||
## 2025-09-28
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								ct/ghostfolio.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								ct/ghostfolio.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: lucasfell
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://ghostfol.io/
 | 
			
		||||
 | 
			
		||||
APP="Ghostfolio"
 | 
			
		||||
var_tags="${var_tags:-finance;investment}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-4096}"
 | 
			
		||||
var_disk="${var_disk:-8}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-13}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    if [[ ! -f /opt/ghostfolio/dist/apps/api/main.js ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if check_for_gh_release "ghostfolio" "ghostfolio/ghostfolio"; then
 | 
			
		||||
      msg_info "Stopping Service"
 | 
			
		||||
      systemctl stop ghostfolio
 | 
			
		||||
      msg_ok "Stopped Service"
 | 
			
		||||
 | 
			
		||||
      msg_info "Creating Backup"
 | 
			
		||||
      tar -czf "/opt/ghostfolio_backup_$(date +%F).tar.gz" \
 | 
			
		||||
        -C /opt \
 | 
			
		||||
        --exclude="ghostfolio/node_modules" \
 | 
			
		||||
        --exclude="ghostfolio/dist" \
 | 
			
		||||
        ghostfolio
 | 
			
		||||
      mv /opt/ghostfolio/.env /opt/env.backup
 | 
			
		||||
      msg_ok "Backup Created"
 | 
			
		||||
 | 
			
		||||
      CLEAN_INSTALL=1 fetch_and_deploy_gh_release "ghostfolio" "ghostfolio/ghostfolio" "tarball" "latest" "/opt/ghostfolio"
 | 
			
		||||
 | 
			
		||||
      msg_info "Updating Ghostfolio"
 | 
			
		||||
      mv /opt/env.backup /opt/ghostfolio/.env
 | 
			
		||||
      cd /opt/ghostfolio
 | 
			
		||||
      $STD npm ci
 | 
			
		||||
      $STD npm run build:production
 | 
			
		||||
      $STD npx prisma migrate deploy
 | 
			
		||||
      msg_ok "Updated Ghostfolio"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Service"
 | 
			
		||||
    systemctl start ghostfolio
 | 
			
		||||
    msg_ok "Started Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning Up"
 | 
			
		||||
    $STD npm cache clean --force
 | 
			
		||||
    msg_ok "Cleanup Completed"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3333${CL}"
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/ghostfolio
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/ghostfolio
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
   ________               __  ____      ___     
 | 
			
		||||
  / ____/ /_  ____  _____/ /_/ __/___  / (_)___ 
 | 
			
		||||
 / / __/ __ \/ __ \/ ___/ __/ /_/ __ \/ / / __ \
 | 
			
		||||
/ /_/ / / / / /_/ (__  ) /_/ __/ /_/ / / / /_/ /
 | 
			
		||||
\____/_/ /_/\____/____/\__/_/  \____/_/_/\____/ 
 | 
			
		||||
                                                
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/myip
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/myip
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    __  ___      ________ 
 | 
			
		||||
   /  |/  /_  __/  _/ __ \
 | 
			
		||||
  / /|_/ / / / // // /_/ /
 | 
			
		||||
 / /  / / /_/ // // ____/ 
 | 
			
		||||
/_/  /_/\__, /___/_/      
 | 
			
		||||
       /____/             
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/verdaccio
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/verdaccio
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
 _    __              __                _     
 | 
			
		||||
| |  / /__  _________/ /___ ___________(_)___ 
 | 
			
		||||
| | / / _ \/ ___/ __  / __ `/ ___/ ___/ / __ \
 | 
			
		||||
| |/ /  __/ /  / /_/ / /_/ / /__/ /__/ / /_/ /
 | 
			
		||||
|___/\___/_/   \__,_/\__,_/\___/\___/_/\____/ 
 | 
			
		||||
                                              
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/warracker
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/warracker
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
 _       __                           __            
 | 
			
		||||
| |     / /___ _______________ ______/ /_____  _____
 | 
			
		||||
| | /| / / __ `/ ___/ ___/ __ `/ ___/ //_/ _ \/ ___/
 | 
			
		||||
| |/ |/ / /_/ / /  / /  / /_/ / /__/ ,< /  __/ /    
 | 
			
		||||
|__/|__/\__,_/_/  /_/   \__,_/\___/_/|_|\___/_/     
 | 
			
		||||
                                                    
 | 
			
		||||
							
								
								
									
										55
									
								
								ct/myip.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								ct/myip.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://ipcheck.ing/
 | 
			
		||||
 | 
			
		||||
APP="MyIP"
 | 
			
		||||
var_tags="${var_tags:-network}"
 | 
			
		||||
var_cpu="${var_cpu:-1}"
 | 
			
		||||
var_ram="${var_ram:-512}"
 | 
			
		||||
var_disk="${var_disk:-4}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-13}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /opt/myip ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if check_for_gh_release "myip" "jason5ng32/MyIP"; then
 | 
			
		||||
        msg_info "Stopping Services"
 | 
			
		||||
        systemctl stop myip
 | 
			
		||||
        msg_ok "Stopped Services"
 | 
			
		||||
 | 
			
		||||
        cp /opt/myip/.env /opt
 | 
			
		||||
        CLEAN_INSTALL=1 fetch_and_deploy_gh_release "myip" "jason5ng32/MyIP" "tarball"
 | 
			
		||||
        mv /opt/.env /opt/myip
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting Services"
 | 
			
		||||
        systemctl start myip
 | 
			
		||||
        msg_ok "Started Services"
 | 
			
		||||
        msg_ok "Updated Successfully"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:18966${CL}"
 | 
			
		||||
							
								
								
									
										49
									
								
								ct/verdaccio.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								ct/verdaccio.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: BrynnJKnight
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://verdaccio.org/
 | 
			
		||||
 | 
			
		||||
APP="Verdaccio"
 | 
			
		||||
var_tags="${var_tags:-dev-tools;npm;registry}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-2048}"
 | 
			
		||||
var_disk="${var_disk:-8}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-13}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -f /etc/systemd/system/verdaccio.service ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  msg_info "Updating LXC Container"
 | 
			
		||||
  $STD apt update
 | 
			
		||||
  $STD apt -y upgrade
 | 
			
		||||
  msg_ok "Updated LXC Container"
 | 
			
		||||
 | 
			
		||||
  NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs
 | 
			
		||||
  systemctl restart verdaccio
 | 
			
		||||
  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}:4873${CL}"
 | 
			
		||||
							
								
								
									
										63
									
								
								ct/warracker.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								ct/warracker.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: BvdBerg01
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/sassanix/Warracker/
 | 
			
		||||
 | 
			
		||||
APP="Warracker"
 | 
			
		||||
var_tags="${var_tags:-warranty}"
 | 
			
		||||
var_cpu="${var_cpu:-1}"
 | 
			
		||||
var_ram="${var_ram:-512}"
 | 
			
		||||
var_disk="${var_disk:-4}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-13}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /opt/warracker ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if check_for_gh_release "warracker" "sassanix/Warracker"; then
 | 
			
		||||
        msg_info "Stopping Services"
 | 
			
		||||
        systemctl stop warrackermigration
 | 
			
		||||
        systemctl stop warracker
 | 
			
		||||
        systemctl stop nginx
 | 
			
		||||
        msg_ok "Stopped Services"
 | 
			
		||||
 | 
			
		||||
        fetch_and_deploy_gh_release "warracker" "sassanix/Warracker" "tarball" "latest" "/opt/warracker"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating Warracker"
 | 
			
		||||
        cd /opt/warracker/backend
 | 
			
		||||
        $STD uv venv .venv
 | 
			
		||||
        $STD source .venv/bin/activate
 | 
			
		||||
        $STD uv pip install -r requirements.txt
 | 
			
		||||
        msg_ok "Updated Warracker"
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting Services"
 | 
			
		||||
        systemctl start warracker
 | 
			
		||||
        systemctl start nginx
 | 
			
		||||
        msg_ok "Started Services"
 | 
			
		||||
        msg_ok "Updated Successfully"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
							
								
								
									
										52
									
								
								frontend/public/json/ghostfolio.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								frontend/public/json/ghostfolio.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Ghostfolio",
 | 
			
		||||
  "slug": "ghostfolio",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    23
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-09-29",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 3333,
 | 
			
		||||
  "documentation": "https://github.com/ghostfolio/ghostfolio?tab=readme-ov-file#self-hosting",
 | 
			
		||||
  "website": "https://ghostfol.io/",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/ghostfolio.webp",
 | 
			
		||||
  "config_path": "/opt/ghostfolio/.env",
 | 
			
		||||
  "description": "Ghostfolio is an open source wealth management software built with web technology. The application empowers busy people to keep track of stocks, ETFs or cryptocurrencies and make solid, data-driven investment decisions.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/ghostfolio.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 4096,
 | 
			
		||||
        "hdd": 8,
 | 
			
		||||
        "os": "debian",
 | 
			
		||||
        "version": "13"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Create your first user account by visiting the web interface and clicking 'Get Started'. The first user will automatically get admin privileges.",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Database and Redis credentials: `cat ~/ghostfolio.creds`",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Optional: CoinGecko API keys can be added during installation or later in the .env file for enhanced cryptocurrency data.",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Build process requires 4GB RAM (runtime: ~2GB). A temporary swap file will be created automatically if insufficient memory is detected.",
 | 
			
		||||
      "type": "warning"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								frontend/public/json/myip.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								frontend/public/json/myip.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "MyIP",
 | 
			
		||||
  "slug": "myip",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    4
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-09-29",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "config_path": "/opt/myip/.env",
 | 
			
		||||
  "interface_port": 18966,
 | 
			
		||||
  "documentation": "https://github.com/jason5ng32/MyIP#-environment-variable",
 | 
			
		||||
  "website": "https://ipcheck.ing/",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/myip.webp",
 | 
			
		||||
  "description": "The best IP Toolbox. Easy to check what's your IPs, IP geolocation, check for DNS leaks, examine WebRTC connections, speed test, ping test, MTR test, check website availability, whois search and more!",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/myip.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 1,
 | 
			
		||||
        "ram": 512,
 | 
			
		||||
        "hdd": 2,
 | 
			
		||||
        "os": "Debian",
 | 
			
		||||
        "version": "13"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								frontend/public/json/verdaccio.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								frontend/public/json/verdaccio.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Verdaccio",
 | 
			
		||||
  "slug": "verdaccio",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    20
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-09-29",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 4873,
 | 
			
		||||
  "documentation": "https://verdaccio.org/docs/what-is-verdaccio",
 | 
			
		||||
  "website": "https://verdaccio.org/",
 | 
			
		||||
  "logo": "https://verdaccio.org/img/logo/symbol/png/verdaccio-tiny.png",
 | 
			
		||||
  "config_path": "/opt/verdaccio/config/config.yaml",
 | 
			
		||||
  "description": "Verdaccio is a lightweight private npm proxy registry built with Node.js. It allows you to host your own npm registry with minimal configuration, providing a private npm repository for your projects. Verdaccio supports npm, yarn, and pnpm, and can cache packages from the public npm registry, allowing for faster installs and protection against npm registry outages. It includes a web interface for browsing packages, authentication and authorization features, and can be easily integrated into your development workflow.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/verdaccio.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 2048,
 | 
			
		||||
        "hdd": 8,
 | 
			
		||||
        "os": "debian",
 | 
			
		||||
        "version": "13"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "To create the first user, run: npm adduser --registry http://<container-ip>:4873",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,144 @@
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "name": "goauthentik/authentik",
 | 
			
		||||
    "version": "version/2025.8.4",
 | 
			
		||||
    "date": "2025-09-29T22:01:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "verdaccio/verdaccio",
 | 
			
		||||
    "version": "v6.2.0",
 | 
			
		||||
    "date": "2025-09-29T20:59:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "gristlabs/grist-core",
 | 
			
		||||
    "version": "v1.7.4",
 | 
			
		||||
    "date": "2025-09-29T20:19:43Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "immich-app/immich",
 | 
			
		||||
    "version": "v1.144.1",
 | 
			
		||||
    "date": "2025-09-29T19:49:34Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/telegraf",
 | 
			
		||||
    "version": "v1.36.2",
 | 
			
		||||
    "date": "2025-09-29T19:16:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Cleanuparr/Cleanuparr",
 | 
			
		||||
    "version": "v2.3.3",
 | 
			
		||||
    "date": "2025-09-29T18:53:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "esphome/esphome",
 | 
			
		||||
    "version": "2025.9.2",
 | 
			
		||||
    "date": "2025-09-29T18:50:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pommee/goaway",
 | 
			
		||||
    "version": "v0.62.6",
 | 
			
		||||
    "date": "2025-09-29T18:50:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "emqx/emqx",
 | 
			
		||||
    "version": "e6.0.0-rc.1",
 | 
			
		||||
    "date": "2025-09-29T18:31:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/influxdb",
 | 
			
		||||
    "version": "v3.5.0",
 | 
			
		||||
    "date": "2025-09-29T17:33:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "sassanix/Warracker",
 | 
			
		||||
    "version": "0.10.1.13",
 | 
			
		||||
    "date": "2025-09-29T17:11:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jhuckaby/Cronicle",
 | 
			
		||||
    "version": "v0.9.93",
 | 
			
		||||
    "date": "2025-09-29T16:24:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "msgbyte/tianji",
 | 
			
		||||
    "version": "v1.27.2",
 | 
			
		||||
    "date": "2025-09-29T16:16:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "meilisearch/meilisearch",
 | 
			
		||||
    "version": "prototype-v1.22.1.personalization-00",
 | 
			
		||||
    "date": "2025-09-29T15:47:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "n8n-io/n8n",
 | 
			
		||||
    "version": "n8n@1.112.6",
 | 
			
		||||
    "date": "2025-09-26T10:56:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "AdguardTeam/AdGuardHome",
 | 
			
		||||
    "version": "v0.107.67",
 | 
			
		||||
    "date": "2025-09-29T14:45:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "NodeBB/NodeBB",
 | 
			
		||||
    "version": "v4.5.2",
 | 
			
		||||
    "date": "2025-09-29T14:04:09Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MDeLuise/plant-it",
 | 
			
		||||
    "version": "1.0.0",
 | 
			
		||||
    "date": "2025-09-29T13:53:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "documenso/documenso",
 | 
			
		||||
    "version": "v1.12.8",
 | 
			
		||||
    "date": "2025-09-29T13:22:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "theonedev/onedev",
 | 
			
		||||
    "version": "v13.0.6",
 | 
			
		||||
    "date": "2025-09-29T12:33:56Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Graylog2/graylog2-server",
 | 
			
		||||
    "version": "7.0.0-beta.2",
 | 
			
		||||
    "date": "2025-09-29T11:28:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jupyter/notebook",
 | 
			
		||||
    "version": "@jupyter-notebook/ui-components@7.5.0-beta.0",
 | 
			
		||||
    "date": "2025-09-29T09:16:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "open-webui/open-webui",
 | 
			
		||||
    "version": "v0.6.32",
 | 
			
		||||
    "date": "2025-09-29T06:13:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Jackett/Jackett",
 | 
			
		||||
    "version": "v0.23.87",
 | 
			
		||||
    "date": "2025-09-29T05:54:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "inventree/InvenTree",
 | 
			
		||||
    "version": "1.0.2",
 | 
			
		||||
    "date": "2025-09-29T04:02:44Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "firefly-iii/firefly-iii",
 | 
			
		||||
    "version": "v6.4.0",
 | 
			
		||||
    "date": "2025-09-13T16:38:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jeedom/core",
 | 
			
		||||
    "version": "4.4.20",
 | 
			
		||||
    "date": "2025-09-29T00:27:05Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "steveiliop56/tinyauth",
 | 
			
		||||
    "version": "v3.6.2",
 | 
			
		||||
    "date": "2025-07-17T12:08:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "autobrr/autobrr",
 | 
			
		||||
    "version": "v1.67.0",
 | 
			
		||||
@@ -14,16 +154,16 @@
 | 
			
		||||
    "version": "v5.25.0",
 | 
			
		||||
    "date": "2025-09-28T19:02:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "runtipi/runtipi",
 | 
			
		||||
    "version": "nightly",
 | 
			
		||||
    "date": "2025-09-28T18:26:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "lazy-media/Reactive-Resume",
 | 
			
		||||
    "version": "v1.2.6",
 | 
			
		||||
    "date": "2025-09-28T18:09:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "msgbyte/tianji",
 | 
			
		||||
    "version": "v1.27.1",
 | 
			
		||||
    "date": "2025-09-28T17:38:54Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jellyfin/jellyfin",
 | 
			
		||||
    "version": "v10.10.7",
 | 
			
		||||
@@ -54,16 +194,6 @@
 | 
			
		||||
    "version": "v1.5.3",
 | 
			
		||||
    "date": "2025-09-20T12:12:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Jackett/Jackett",
 | 
			
		||||
    "version": "v0.23.74",
 | 
			
		||||
    "date": "2025-09-28T05:54:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "theonedev/onedev",
 | 
			
		||||
    "version": "v13.0.4",
 | 
			
		||||
    "date": "2025-09-28T02:38:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mealie-recipes/mealie",
 | 
			
		||||
    "version": "v3.3.0",
 | 
			
		||||
@@ -74,16 +204,6 @@
 | 
			
		||||
    "version": "2.1.1",
 | 
			
		||||
    "date": "2025-06-14T17:45:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jeedom/core",
 | 
			
		||||
    "version": "4.4.20",
 | 
			
		||||
    "date": "2025-09-28T00:27:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "steveiliop56/tinyauth",
 | 
			
		||||
    "version": "v3.6.2",
 | 
			
		||||
    "date": "2025-07-17T12:08:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "moghtech/komodo",
 | 
			
		||||
    "version": "v1.19.5",
 | 
			
		||||
@@ -119,15 +239,10 @@
 | 
			
		||||
    "version": "0.208.1",
 | 
			
		||||
    "date": "2025-09-27T12:57:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pommee/goaway",
 | 
			
		||||
    "version": "v0.62.3",
 | 
			
		||||
    "date": "2025-09-27T12:37:26Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "javedh-dev/tracktor",
 | 
			
		||||
    "version": "0.3.18",
 | 
			
		||||
    "date": "2025-09-27T10:32:09Z"
 | 
			
		||||
    "version": "0.3.17",
 | 
			
		||||
    "date": "2025-09-27T07:00:36Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "fuma-nama/fumadocs",
 | 
			
		||||
@@ -139,11 +254,6 @@
 | 
			
		||||
    "version": "26.3.5",
 | 
			
		||||
    "date": "2025-09-25T06:23:28Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jupyter/notebook",
 | 
			
		||||
    "version": "v7.4.7",
 | 
			
		||||
    "date": "2025-09-27T08:00:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Kozea/Radicale",
 | 
			
		||||
    "version": "v3.5.7",
 | 
			
		||||
@@ -154,11 +264,6 @@
 | 
			
		||||
    "version": "2.1.5",
 | 
			
		||||
    "date": "2025-09-27T04:43:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "firefly-iii/firefly-iii",
 | 
			
		||||
    "version": "v6.4.0",
 | 
			
		||||
    "date": "2025-09-13T16:38:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ipfs/kubo",
 | 
			
		||||
    "version": "v0.37.0",
 | 
			
		||||
@@ -179,11 +284,6 @@
 | 
			
		||||
    "version": "v4.104.2",
 | 
			
		||||
    "date": "2025-09-26T22:34:32Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "runtipi/runtipi",
 | 
			
		||||
    "version": "v4.4.0",
 | 
			
		||||
    "date": "2025-09-02T19:26:18Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/core",
 | 
			
		||||
    "version": "2025.9.4",
 | 
			
		||||
@@ -204,21 +304,11 @@
 | 
			
		||||
    "version": "v1.39.0",
 | 
			
		||||
    "date": "2025-09-26T19:15:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/influxdb",
 | 
			
		||||
    "version": "v3.5.0-1.rc.1",
 | 
			
		||||
    "date": "2025-09-26T18:34:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "bunkerity/bunkerweb",
 | 
			
		||||
    "version": "v1.6.4",
 | 
			
		||||
    "date": "2025-08-18T20:22:07Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "n8n-io/n8n",
 | 
			
		||||
    "version": "n8n@1.112.6",
 | 
			
		||||
    "date": "2025-09-26T10:56:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "traefik/traefik",
 | 
			
		||||
    "version": "v3.5.3",
 | 
			
		||||
@@ -229,11 +319,6 @@
 | 
			
		||||
    "version": "v4.13.1",
 | 
			
		||||
    "date": "2025-09-25T15:43:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "emqx/emqx",
 | 
			
		||||
    "version": "e6.0.0-beta.1",
 | 
			
		||||
    "date": "2025-09-26T06:28:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "nzbgetcom/nzbget",
 | 
			
		||||
    "version": "v25.3",
 | 
			
		||||
@@ -244,11 +329,6 @@
 | 
			
		||||
    "version": "v0.12.3",
 | 
			
		||||
    "date": "2025-09-26T05:08:26Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "documenso/documenso",
 | 
			
		||||
    "version": "v1.12.7",
 | 
			
		||||
    "date": "2025-09-25T23:57:34Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "henrygd/beszel",
 | 
			
		||||
    "version": "v0.12.12",
 | 
			
		||||
@@ -259,11 +339,6 @@
 | 
			
		||||
    "version": "v1.3.4",
 | 
			
		||||
    "date": "2025-09-25T21:19:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "open-webui/open-webui",
 | 
			
		||||
    "version": "v0.6.31",
 | 
			
		||||
    "date": "2025-09-25T20:28:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "go-gitea/gitea",
 | 
			
		||||
    "version": "v1.26.0-dev",
 | 
			
		||||
@@ -309,11 +384,6 @@
 | 
			
		||||
    "version": "v0.96.1",
 | 
			
		||||
    "date": "2025-09-25T15:18:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "meilisearch/meilisearch",
 | 
			
		||||
    "version": "latest",
 | 
			
		||||
    "date": "2025-09-25T14:32:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "bluenviron/mediamtx",
 | 
			
		||||
    "version": "v1.15.1",
 | 
			
		||||
@@ -334,11 +404,6 @@
 | 
			
		||||
    "version": "v1.138.2",
 | 
			
		||||
    "date": "2025-09-24T12:45:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Cleanuparr/Cleanuparr",
 | 
			
		||||
    "version": "v2.3.2",
 | 
			
		||||
    "date": "2025-09-25T09:34:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "rabbitmq/rabbitmq-server",
 | 
			
		||||
    "version": "v4.1.4",
 | 
			
		||||
@@ -409,11 +474,6 @@
 | 
			
		||||
    "version": "v2.2.0",
 | 
			
		||||
    "date": "2025-09-23T21:46:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "immich-app/immich",
 | 
			
		||||
    "version": "v1.143.1",
 | 
			
		||||
    "date": "2025-09-23T19:00:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "getumbrel/umbrel",
 | 
			
		||||
    "version": "1.4.2",
 | 
			
		||||
@@ -459,11 +519,6 @@
 | 
			
		||||
    "version": "4.5.3",
 | 
			
		||||
    "date": "2025-08-25T13:59:56Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Graylog2/graylog2-server",
 | 
			
		||||
    "version": "7.0.0-beta.1",
 | 
			
		||||
    "date": "2025-09-22T11:53:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "itsmng/itsm-ng",
 | 
			
		||||
    "version": "v2.1.0",
 | 
			
		||||
@@ -524,11 +579,6 @@
 | 
			
		||||
    "version": "v6.10.0",
 | 
			
		||||
    "date": "2025-09-20T15:40:36Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "inventree/InvenTree",
 | 
			
		||||
    "version": "1.0.1",
 | 
			
		||||
    "date": "2025-09-19T22:28:31Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mmastrac/stylus",
 | 
			
		||||
    "version": "v0.17.0",
 | 
			
		||||
@@ -549,11 +599,6 @@
 | 
			
		||||
    "version": "v2.39.4",
 | 
			
		||||
    "date": "2025-09-19T08:49:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "esphome/esphome",
 | 
			
		||||
    "version": "2025.9.1",
 | 
			
		||||
    "date": "2025-09-19T08:47:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "saltstack/salt",
 | 
			
		||||
    "version": "v3007.8",
 | 
			
		||||
@@ -569,11 +614,6 @@
 | 
			
		||||
    "version": "2025.09.0",
 | 
			
		||||
    "date": "2025-09-18T15:07:01Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "sassanix/Warracker",
 | 
			
		||||
    "version": "0.10.1.12",
 | 
			
		||||
    "date": "2025-09-18T14:24:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "grokability/snipe-it",
 | 
			
		||||
    "version": "v8.3.2",
 | 
			
		||||
@@ -644,21 +684,11 @@
 | 
			
		||||
    "version": "2.510",
 | 
			
		||||
    "date": "2025-09-16T20:28:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "AdguardTeam/AdGuardHome",
 | 
			
		||||
    "version": "v0.107.66",
 | 
			
		||||
    "date": "2025-09-15T13:39:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "netbox-community/netbox",
 | 
			
		||||
    "version": "v4.4.1",
 | 
			
		||||
    "date": "2025-09-16T15:58:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "goauthentik/authentik",
 | 
			
		||||
    "version": "version/2025.8.3",
 | 
			
		||||
    "date": "2025-09-16T15:19:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "tobychui/zoraxy",
 | 
			
		||||
    "version": "v3.2.5r2",
 | 
			
		||||
@@ -709,11 +739,6 @@
 | 
			
		||||
    "version": "v5.15.0",
 | 
			
		||||
    "date": "2025-09-15T17:25:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jhuckaby/Cronicle",
 | 
			
		||||
    "version": "v0.9.92",
 | 
			
		||||
    "date": "2025-09-15T16:32:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "FlowiseAI/Flowise",
 | 
			
		||||
    "version": "flowise@3.0.7",
 | 
			
		||||
@@ -789,11 +814,6 @@
 | 
			
		||||
    "version": "1.11.3",
 | 
			
		||||
    "date": "2025-09-09T08:03:31Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/telegraf",
 | 
			
		||||
    "version": "v1.36.1",
 | 
			
		||||
    "date": "2025-09-09T06:44:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "gotson/komga",
 | 
			
		||||
    "version": "1.23.4",
 | 
			
		||||
@@ -859,11 +879,6 @@
 | 
			
		||||
    "version": "v1.0.0-beta17",
 | 
			
		||||
    "date": "2025-09-04T21:30:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "NodeBB/NodeBB",
 | 
			
		||||
    "version": "v4.5.1",
 | 
			
		||||
    "date": "2025-09-04T16:02:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "plankanban/planka",
 | 
			
		||||
    "version": "planka-1.0.4",
 | 
			
		||||
@@ -924,11 +939,6 @@
 | 
			
		||||
    "version": "1.7.0",
 | 
			
		||||
    "date": "2025-08-28T18:10:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "gristlabs/grist-core",
 | 
			
		||||
    "version": "v1.7.3",
 | 
			
		||||
    "date": "2025-08-28T16:50:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "BookStackApp/BookStack",
 | 
			
		||||
    "version": "v25.07.2",
 | 
			
		||||
@@ -1119,11 +1129,6 @@
 | 
			
		||||
    "version": "v2.19.0",
 | 
			
		||||
    "date": "2025-07-27T22:25:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "verdaccio/verdaccio",
 | 
			
		||||
    "version": "v6.1.6",
 | 
			
		||||
    "date": "2025-07-25T06:43:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "PCJones/UmlautAdaptarr",
 | 
			
		||||
    "version": "v0.7.3",
 | 
			
		||||
@@ -1469,11 +1474,6 @@
 | 
			
		||||
    "version": "v1.0.22",
 | 
			
		||||
    "date": "2024-12-13T12:22:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MDeLuise/plant-it",
 | 
			
		||||
    "version": "0.10.0",
 | 
			
		||||
    "date": "2024-12-10T09:35:26Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "phpipam/phpipam",
 | 
			
		||||
    "version": "v1.7.3",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								frontend/public/json/warracker.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								frontend/public/json/warracker.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Warracker",
 | 
			
		||||
  "slug": "warracker",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    12
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-09-29",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 80,
 | 
			
		||||
  "documentation": null,
 | 
			
		||||
  "config_path": "/opt/.env",
 | 
			
		||||
  "website": "https://warracker.com/",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/warracker.webp",
 | 
			
		||||
  "description": "Warracker is an open source, self-hostable warranty tracker to monitor expirations, store receipts, files. You own the data, your rules!",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/warracker.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 1,
 | 
			
		||||
        "ram": 512,
 | 
			
		||||
        "hdd": 4,
 | 
			
		||||
        "os": "Debian",
 | 
			
		||||
        "version": "13"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "The first user you register will be the admin user.",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -103,18 +103,22 @@ export default function RootLayout({
 | 
			
		||||
      <body className={inter.className}>
 | 
			
		||||
        <ThemeProvider attribute="class" defaultTheme="dark" enableSystem disableTransitionOnChange>
 | 
			
		||||
          <div className="flex w-full flex-col justify-center">
 | 
			
		||||
            <Navbar />
 | 
			
		||||
            <div className="flex min-h-screen flex-col justify-center">
 | 
			
		||||
              <div className="flex w-full justify-center">
 | 
			
		||||
                <div className="w-full max-w-[1440px] ">
 | 
			
		||||
                  <QueryProvider>
 | 
			
		||||
                    <NuqsAdapter>{children}</NuqsAdapter>
 | 
			
		||||
                  </QueryProvider>
 | 
			
		||||
                  <Toaster richColors />
 | 
			
		||||
            <NuqsAdapter>
 | 
			
		||||
              <QueryProvider>
 | 
			
		||||
 | 
			
		||||
                <Navbar />
 | 
			
		||||
                <div className="flex min-h-screen flex-col justify-center">
 | 
			
		||||
                  <div className="flex w-full justify-center">
 | 
			
		||||
                    <div className="w-full max-w-[1440px] ">
 | 
			
		||||
                      {children}
 | 
			
		||||
                      <Toaster richColors />
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <Footer />
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              <Footer />
 | 
			
		||||
            </div>
 | 
			
		||||
              </QueryProvider>
 | 
			
		||||
 | 
			
		||||
            </NuqsAdapter>
 | 
			
		||||
          </div>
 | 
			
		||||
        </ThemeProvider>
 | 
			
		||||
      </body>
 | 
			
		||||
 
 | 
			
		||||
@@ -27,12 +27,14 @@ export default function ScriptAccordion({
 | 
			
		||||
  setSelectedScript,
 | 
			
		||||
  selectedCategory,
 | 
			
		||||
  setSelectedCategory,
 | 
			
		||||
  onItemSelect,
 | 
			
		||||
}: {
 | 
			
		||||
  items: Category[];
 | 
			
		||||
  selectedScript: string | null;
 | 
			
		||||
  setSelectedScript: (script: string | null) => void;
 | 
			
		||||
  selectedCategory: string | null;
 | 
			
		||||
  setSelectedCategory: (category: string | null) => void;
 | 
			
		||||
  onItemSelect?: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
  const [expandedItem, setExpandedItem] = useState<string | undefined>(undefined);
 | 
			
		||||
  const linkRefs = useRef<{ [key: string]: HTMLAnchorElement | null }>({});
 | 
			
		||||
@@ -77,7 +79,7 @@ export default function ScriptAccordion({
 | 
			
		||||
      value={expandedItem}
 | 
			
		||||
      onValueChange={handleAccordionChange}
 | 
			
		||||
      collapsible
 | 
			
		||||
      className="overflow-y-scroll max-h-[calc(100vh-225px)] overflow-x-hidden p-2"
 | 
			
		||||
      className="overflow-y-scroll sm:max-h-[calc(100vh-209px)] overflow-x-hidden p-1"
 | 
			
		||||
    >
 | 
			
		||||
      {items.map(category => (
 | 
			
		||||
        <AccordionItem
 | 
			
		||||
@@ -125,6 +127,7 @@ export default function ScriptAccordion({
 | 
			
		||||
                    onClick={() => {
 | 
			
		||||
                      handleSelected(script.slug);
 | 
			
		||||
                      setSelectedCategory(category.name);
 | 
			
		||||
                      onItemSelect?.();
 | 
			
		||||
                    }}
 | 
			
		||||
                    ref={(el) => {
 | 
			
		||||
                      linkRefs.current[script.slug] = el;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,21 +2,29 @@
 | 
			
		||||
 | 
			
		||||
import type { Category, Script } from "@/lib/types";
 | 
			
		||||
 | 
			
		||||
import { cn } from "@/lib/utils";
 | 
			
		||||
 | 
			
		||||
import ScriptAccordion from "./script-accordion";
 | 
			
		||||
 | 
			
		||||
type SidebarProps = {
 | 
			
		||||
  items: Category[];
 | 
			
		||||
  selectedScript: string | null;
 | 
			
		||||
  setSelectedScript: (script: string | null) => void;
 | 
			
		||||
  selectedCategory: string | null;
 | 
			
		||||
  setSelectedCategory: (category: string | null) => void;
 | 
			
		||||
  onItemSelect?: () => void;
 | 
			
		||||
  className?: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function Sidebar({
 | 
			
		||||
  items,
 | 
			
		||||
  selectedScript,
 | 
			
		||||
  setSelectedScript,
 | 
			
		||||
  selectedCategory,
 | 
			
		||||
  setSelectedCategory,
 | 
			
		||||
}: {
 | 
			
		||||
  items: Category[];
 | 
			
		||||
  selectedScript: string | null;
 | 
			
		||||
  setSelectedScript: (script: string | null) => void;
 | 
			
		||||
  selectedCategory: string | null;
 | 
			
		||||
  setSelectedCategory: (category: string | null) => void;
 | 
			
		||||
}) {
 | 
			
		||||
  onItemSelect,
 | 
			
		||||
  className,
 | 
			
		||||
}: SidebarProps) {
 | 
			
		||||
  const uniqueScripts = items.reduce((acc, category) => {
 | 
			
		||||
    for (const script of category.scripts) {
 | 
			
		||||
      if (!acc.some(s => s.name === script.name)) {
 | 
			
		||||
@@ -27,7 +35,7 @@ function Sidebar({
 | 
			
		||||
  }, [] as Script[]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="flex min-w-[350px] flex-col sm:max-w-[350px]">
 | 
			
		||||
    <div className={cn("flex w-full flex-col sm:min-w-[350px] sm:max-w-[350px]", className)}>
 | 
			
		||||
      <div className="flex items-end justify-between pb-4">
 | 
			
		||||
        <h1 className="text-xl font-bold">Categories</h1>
 | 
			
		||||
        <p className="text-xs italic text-muted-foreground">
 | 
			
		||||
@@ -43,6 +51,7 @@ function Sidebar({
 | 
			
		||||
          setSelectedScript={setSelectedScript}
 | 
			
		||||
          selectedCategory={selectedCategory}
 | 
			
		||||
          setSelectedCategory={setSelectedCategory}
 | 
			
		||||
          onItemSelect={onItemSelect}
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
"use client";
 | 
			
		||||
import { useEffect, useState } from "react";
 | 
			
		||||
import { Suspense, useEffect, useState } from "react";
 | 
			
		||||
import Image from "next/image";
 | 
			
		||||
import Link from "next/link";
 | 
			
		||||
 | 
			
		||||
@@ -8,6 +8,7 @@ import { navbarLinks } from "@/config/site-config";
 | 
			
		||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
 | 
			
		||||
import { GitHubStarsButton } from "./animate-ui/components/buttons/github-stars";
 | 
			
		||||
import { Button } from "./animate-ui/components/buttons/button";
 | 
			
		||||
import MobileSidebar from "./navigation/mobile-sidebar";
 | 
			
		||||
import { ThemeToggle } from "./ui/theme-toggle";
 | 
			
		||||
import CommandMenu from "./command-menu";
 | 
			
		||||
 | 
			
		||||
@@ -30,39 +31,45 @@ function Navbar() {
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <div
 | 
			
		||||
        className={`fixed left-0 top-0 z-50 flex w-screen justify-center px-4 xl:px-0 ${
 | 
			
		||||
          isScrolled ? "glass border-b bg-background/50" : ""
 | 
			
		||||
        className={`fixed left-0 top-0 z-50 flex w-screen justify-center px-4 xl:px-0 ${isScrolled ? "glass border-b bg-background/50" : ""
 | 
			
		||||
        }`}
 | 
			
		||||
      >
 | 
			
		||||
        <div className="flex h-20 w-full max-w-[1440px] items-center justify-between sm:flex-row">
 | 
			
		||||
          <Link
 | 
			
		||||
            href="/"
 | 
			
		||||
            className="flex cursor-pointer w-full justify-center sm:justify-start flex-row-reverse items-center gap-2 font-semibold sm:flex-row"
 | 
			
		||||
            className="cursor-pointer w-full justify-center sm:justify-start flex-row-reverse hidden sm:flex items-center gap-2 font-semibold sm:flex-row"
 | 
			
		||||
          >
 | 
			
		||||
            <Image height={18} unoptimized width={18} alt="logo" src="/ProxmoxVE/logo.png" className="" />
 | 
			
		||||
            <span className="hidden md:block">Proxmox VE Helper-Scripts</span>
 | 
			
		||||
            <span className="">Proxmox VE Helper-Scripts</span>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <div className="flex gap-2">
 | 
			
		||||
            <CommandMenu />
 | 
			
		||||
            <GitHubStarsButton username="community-scripts" repo="ProxmoxVE" />
 | 
			
		||||
            {navbarLinks.map(({ href, event, icon, text, mobileHidden }) => (
 | 
			
		||||
              <TooltipProvider key={event}>
 | 
			
		||||
                <Tooltip delayDuration={100}>
 | 
			
		||||
                  <TooltipTrigger className={mobileHidden ? "hidden lg:block" : ""}>
 | 
			
		||||
                    <Button variant="ghost" size="icon" asChild>
 | 
			
		||||
                      <Link target="_blank" href={href} data-umami-event={event}>
 | 
			
		||||
                        {icon}
 | 
			
		||||
                        <span className="sr-only">{text}</span>
 | 
			
		||||
                      </Link>
 | 
			
		||||
                    </Button>
 | 
			
		||||
                  </TooltipTrigger>
 | 
			
		||||
                  <TooltipContent side="bottom" className="text-xs">
 | 
			
		||||
                    {text}
 | 
			
		||||
                  </TooltipContent>
 | 
			
		||||
                </Tooltip>
 | 
			
		||||
              </TooltipProvider>
 | 
			
		||||
            ))}
 | 
			
		||||
            <ThemeToggle />
 | 
			
		||||
          <div className="flex items-center justify-between gap-2 w-full">
 | 
			
		||||
            <div className="flex sm:hidden">
 | 
			
		||||
              <Suspense>
 | 
			
		||||
                <MobileSidebar />
 | 
			
		||||
              </Suspense>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="flex sm:gap-2">
 | 
			
		||||
              <CommandMenu />
 | 
			
		||||
              <GitHubStarsButton username="community-scripts" repo="ProxmoxVE" className="hidden md:flex" />
 | 
			
		||||
              {navbarLinks.map(({ href, event, icon, text, mobileHidden }) => (
 | 
			
		||||
                <TooltipProvider key={event}>
 | 
			
		||||
                  <Tooltip delayDuration={100}>
 | 
			
		||||
                    <TooltipTrigger className={mobileHidden ? "hidden lg:block" : ""}>
 | 
			
		||||
                      <Button variant="ghost" size="icon" asChild>
 | 
			
		||||
                        <Link target="_blank" href={href} data-umami-event={event}>
 | 
			
		||||
                          {icon}
 | 
			
		||||
                          <span className="sr-only">{text}</span>
 | 
			
		||||
                        </Link>
 | 
			
		||||
                      </Button>
 | 
			
		||||
                    </TooltipTrigger>
 | 
			
		||||
                    <TooltipContent side="bottom" className="text-xs">
 | 
			
		||||
                      {text}
 | 
			
		||||
                    </TooltipContent>
 | 
			
		||||
                  </Tooltip>
 | 
			
		||||
                </TooltipProvider>
 | 
			
		||||
              ))}
 | 
			
		||||
              <ThemeToggle />
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								frontend/src/components/navigation/mobile-sidebar.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								frontend/src/components/navigation/mobile-sidebar.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { useCallback, useEffect, useState } from "react";
 | 
			
		||||
import { usePathname } from "next/navigation";
 | 
			
		||||
import { useQueryState } from "nuqs";
 | 
			
		||||
import { Menu } from "lucide-react";
 | 
			
		||||
 | 
			
		||||
import type { Category, Script } from "@/lib/types";
 | 
			
		||||
 | 
			
		||||
import { ScriptItem } from "@/app/scripts/_components/script-item";
 | 
			
		||||
import Sidebar from "@/app/scripts/_components/sidebar";
 | 
			
		||||
import { fetchCategories } from "@/lib/data";
 | 
			
		||||
 | 
			
		||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "../ui/sheet";
 | 
			
		||||
import { Button } from "../ui/button";
 | 
			
		||||
 | 
			
		||||
function MobileSidebar() {
 | 
			
		||||
  const [isOpen, setIsOpen] = useState(false);
 | 
			
		||||
  const [isLoading, setIsLoading] = useState(false);
 | 
			
		||||
  const [categories, setCategories] = useState<Category[]>([]);
 | 
			
		||||
  const [lastViewedScript, setLastViewedScript] = useState<Script | undefined>(undefined);
 | 
			
		||||
  const pathname = usePathname();
 | 
			
		||||
 | 
			
		||||
  // Always call the hooks (React hooks can't be conditional)
 | 
			
		||||
  const [selectedScript, setSelectedScript] = useQueryState("id");
 | 
			
		||||
  const [selectedCategory, setSelectedCategory] = useQueryState("category");
 | 
			
		||||
 | 
			
		||||
  // For non-scripts pages, we'll manage state locally
 | 
			
		||||
  const [tempSelectedScript, setTempSelectedScript] = useState<string | null>(null);
 | 
			
		||||
  const [tempSelectedCategory, setTempSelectedCategory] = useState<string | null>(null);
 | 
			
		||||
 | 
			
		||||
  const isOnScriptsPage = pathname === "/scripts";
 | 
			
		||||
  const currentSelectedScript = isOnScriptsPage ? selectedScript : tempSelectedScript;
 | 
			
		||||
  const currentSelectedCategory = isOnScriptsPage ? selectedCategory : tempSelectedCategory;
 | 
			
		||||
 | 
			
		||||
  const loadCategories = useCallback(async () => {
 | 
			
		||||
    setIsLoading(true);
 | 
			
		||||
    try {
 | 
			
		||||
      const response = await fetchCategories();
 | 
			
		||||
      setCategories(response);
 | 
			
		||||
    }
 | 
			
		||||
    catch (error) {
 | 
			
		||||
      console.error(error);
 | 
			
		||||
    }
 | 
			
		||||
    finally {
 | 
			
		||||
      setIsLoading(false);
 | 
			
		||||
    }
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    void loadCategories();
 | 
			
		||||
  }, [loadCategories]);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (!currentSelectedScript || categories.length === 0) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const scriptMatch = categories
 | 
			
		||||
      .flatMap(category => category.scripts)
 | 
			
		||||
      .find(script => script.slug === currentSelectedScript);
 | 
			
		||||
 | 
			
		||||
    setLastViewedScript(scriptMatch);
 | 
			
		||||
  }, [currentSelectedScript, categories]);
 | 
			
		||||
 | 
			
		||||
  const handleOpenChange = (openState: boolean) => {
 | 
			
		||||
    setIsOpen(openState);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleItemSelect = () => {
 | 
			
		||||
    setIsOpen(false);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const hasLinks = categories.length > 0;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Sheet open={isOpen} onOpenChange={handleOpenChange}>
 | 
			
		||||
      <SheetTrigger asChild>
 | 
			
		||||
        <Button
 | 
			
		||||
          variant="ghost"
 | 
			
		||||
          size="icon"
 | 
			
		||||
          aria-label="Open navigation menu"
 | 
			
		||||
          tabIndex={0}
 | 
			
		||||
          onKeyDown={(event) => {
 | 
			
		||||
            if (event.key === "Enter" || event.key === " ") {
 | 
			
		||||
              setIsOpen(true);
 | 
			
		||||
            }
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          <Menu className="size-5" aria-hidden="true" />
 | 
			
		||||
        </Button>
 | 
			
		||||
      </SheetTrigger>
 | 
			
		||||
      <SheetHeader className="border-b border-border px-6 pb-4 pt-2 sr-only">
 | 
			
		||||
        <SheetTitle className="sr-only">Categories</SheetTitle>
 | 
			
		||||
      </SheetHeader>
 | 
			
		||||
      <SheetContent side="left" className="flex w-full max-w-xs flex-col gap-4 overflow-hidden px-0 pb-6">
 | 
			
		||||
        <div className="flex h-full flex-col gap-4 overflow-y-auto">
 | 
			
		||||
          {isLoading && !hasLinks
 | 
			
		||||
            ? (
 | 
			
		||||
                <div className="flex w-full flex-col items-center justify-center gap-2 px-6 py-4 text-sm text-muted-foreground">
 | 
			
		||||
                  Loading categories...
 | 
			
		||||
                </div>
 | 
			
		||||
              )
 | 
			
		||||
            : (
 | 
			
		||||
                <div className="flex flex-col gap-4 px-4">
 | 
			
		||||
                  <Sidebar
 | 
			
		||||
                    items={categories}
 | 
			
		||||
                    selectedScript={currentSelectedScript}
 | 
			
		||||
                    setSelectedScript={isOnScriptsPage ? setSelectedScript : setTempSelectedScript}
 | 
			
		||||
                    selectedCategory={currentSelectedCategory}
 | 
			
		||||
                    setSelectedCategory={isOnScriptsPage ? setSelectedCategory : setTempSelectedCategory}
 | 
			
		||||
                    onItemSelect={handleItemSelect}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
              )}
 | 
			
		||||
          {currentSelectedScript && lastViewedScript
 | 
			
		||||
            ? (
 | 
			
		||||
                <div className="flex flex-col gap-3 px-4">
 | 
			
		||||
                  <p className="text-sm font-medium">Last Viewed</p>
 | 
			
		||||
                  <ScriptItem
 | 
			
		||||
                    item={lastViewedScript}
 | 
			
		||||
                    setSelectedScript={isOnScriptsPage ? setSelectedScript : setTempSelectedScript}
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
              )
 | 
			
		||||
            : null}
 | 
			
		||||
        </div>
 | 
			
		||||
      </SheetContent>
 | 
			
		||||
    </Sheet>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default MobileSidebar;
 | 
			
		||||
@@ -6,7 +6,7 @@ import { Command as CommandPrimitive } from "cmdk";
 | 
			
		||||
import { Search } from "lucide-react";
 | 
			
		||||
import * as React from "react";
 | 
			
		||||
 | 
			
		||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
 | 
			
		||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
 | 
			
		||||
import { cn } from "@/lib/utils";
 | 
			
		||||
 | 
			
		||||
const Command = React.forwardRef<
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import type { Category } from "./types";
 | 
			
		||||
 | 
			
		||||
export async function fetchCategories() {
 | 
			
		||||
  const response = await fetch("api/categories");
 | 
			
		||||
  const response = await fetch(`/ProxmoxVE/api/categories`);
 | 
			
		||||
  if (!response.ok) {
 | 
			
		||||
    throw new Error(`Failed to fetch categories: ${response.statusText}`);
 | 
			
		||||
  }
 | 
			
		||||
@@ -10,7 +10,7 @@ export async function fetchCategories() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function fetchVersions() {
 | 
			
		||||
  const response = await fetch(`api/versions`);
 | 
			
		||||
  const response = await fetch(`/ProxmoxVE/api/versions`);
 | 
			
		||||
  if (!response.ok) {
 | 
			
		||||
    throw new Error(`Failed to fetch versions: ${response.statusText}`);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										131
									
								
								install/ghostfolio-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								install/ghostfolio-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: lucasfell
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://ghostfol.io/
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt install -y \
 | 
			
		||||
    build-essential \
 | 
			
		||||
    openssl \
 | 
			
		||||
    ca-certificates \
 | 
			
		||||
    redis-server
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
PG_VERSION="17" setup_postgresql
 | 
			
		||||
NODE_VERSION="24" setup_nodejs
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Database"
 | 
			
		||||
DB_NAME=ghostfolio
 | 
			
		||||
DB_USER=ghostfolio
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
REDIS_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
ACCESS_TOKEN_SALT=$(openssl rand -base64 32)
 | 
			
		||||
JWT_SECRET_KEY=$(openssl rand -base64 32)
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;"
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASS';"
 | 
			
		||||
$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -c "ALTER USER $DB_USER CREATEDB;"
 | 
			
		||||
$STD sudo -u postgres psql -d $DB_NAME -c "GRANT ALL ON SCHEMA public TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -d $DB_NAME -c "GRANT CREATE ON SCHEMA public TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -d $DB_NAME -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -d $DB_NAME -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO $DB_USER;"
 | 
			
		||||
{
 | 
			
		||||
    echo "Ghostfolio Credentials"
 | 
			
		||||
    echo "Database User: $DB_USER"
 | 
			
		||||
    echo "Database Password: $DB_PASS"
 | 
			
		||||
    echo "Database Name: $DB_NAME"
 | 
			
		||||
    echo "Redis Password: $REDIS_PASS"
 | 
			
		||||
    echo "Access Token Salt: $ACCESS_TOKEN_SALT"
 | 
			
		||||
    echo "JWT Secret Key: $JWT_SECRET_KEY"
 | 
			
		||||
} >>~/ghostfolio.creds
 | 
			
		||||
msg_ok "Set up Database"
 | 
			
		||||
 | 
			
		||||
fetch_and_deploy_gh_release "ghostfolio" "ghostfolio/ghostfolio" "tarball" "latest" "/opt/ghostfolio"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Ghostfolio"
 | 
			
		||||
sed -i "s/# requirepass foobared/requirepass $REDIS_PASS/" /etc/redis/redis.conf
 | 
			
		||||
systemctl restart redis-server
 | 
			
		||||
cd /opt/ghostfolio
 | 
			
		||||
$STD npm ci
 | 
			
		||||
$STD npm run build:production
 | 
			
		||||
msg_ok "Built Ghostfolio"
 | 
			
		||||
 | 
			
		||||
msg_ok "Optional CoinGecko API Configuration"
 | 
			
		||||
echo
 | 
			
		||||
echo -e "${YW}CoinGecko API keys are optional but provide better cryptocurrency data.${CL}"
 | 
			
		||||
echo -e "${YW}You can skip this and add them later by editing /opt/ghostfolio/.env${CL}"
 | 
			
		||||
echo
 | 
			
		||||
read -rp "${TAB3}CoinGecko Demo API key (press Enter to skip): " COINGECKO_DEMO_KEY
 | 
			
		||||
read -rp "${TAB3}CoinGecko Pro API key (press Enter to skip): " COINGECKO_PRO_KEY
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Environment"
 | 
			
		||||
cat <<EOF >/opt/ghostfolio/.env
 | 
			
		||||
DATABASE_URL=postgresql://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME?connect_timeout=300&sslmode=prefer
 | 
			
		||||
REDIS_HOST=localhost
 | 
			
		||||
REDIS_PORT=6379
 | 
			
		||||
REDIS_PASSWORD=$REDIS_PASS
 | 
			
		||||
ACCESS_TOKEN_SALT=$ACCESS_TOKEN_SALT
 | 
			
		||||
JWT_SECRET_KEY=$JWT_SECRET_KEY
 | 
			
		||||
NODE_ENV=production
 | 
			
		||||
PORT=3333
 | 
			
		||||
HOST=0.0.0.0
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
if [[ -n "${COINGECKO_DEMO_KEY:-}" ]]; then
 | 
			
		||||
    echo "API_KEY_COINGECKO_DEMO=$COINGECKO_DEMO_KEY" >>/opt/ghostfolio/.env
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [[ -n "${COINGECKO_PRO_KEY:-}" ]]; then
 | 
			
		||||
    echo "API_KEY_COINGECKO_PRO=$COINGECKO_PRO_KEY" >>/opt/ghostfolio/.env
 | 
			
		||||
fi
 | 
			
		||||
msg_ok "Set up Environment"
 | 
			
		||||
 | 
			
		||||
msg_info "Running Database Migrations"
 | 
			
		||||
cd /opt/ghostfolio
 | 
			
		||||
$STD npx prisma migrate deploy
 | 
			
		||||
$STD npx prisma db seed
 | 
			
		||||
msg_ok "Database Migrations Complete"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/ghostfolio.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Ghostfolio Investment Tracker
 | 
			
		||||
After=network.target postgresql.service redis-server.service
 | 
			
		||||
Wants=postgresql.service redis-server.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
User=root
 | 
			
		||||
WorkingDirectory=/opt/ghostfolio/dist/apps/api
 | 
			
		||||
Environment=NODE_ENV=production
 | 
			
		||||
EnvironmentFile=/opt/ghostfolio/.env
 | 
			
		||||
ExecStart=/usr/bin/node main.js
 | 
			
		||||
Restart=always
 | 
			
		||||
RestartSec=10
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
systemctl enable -q --now ghostfolio
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD npm cache clean --force
 | 
			
		||||
$STD apt -y autoremove
 | 
			
		||||
$STD apt -y autoclean
 | 
			
		||||
$STD apt -y clean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
							
								
								
									
										54
									
								
								install/myip-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								install/myip-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
#!/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://ipcheck.ing/
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
NODE_VERSION="22" setup_nodejs
 | 
			
		||||
fetch_and_deploy_gh_release "myip" "jason5ng32/MyIP" "tarball"
 | 
			
		||||
 | 
			
		||||
msg_info "Configuring MyIP"
 | 
			
		||||
cd /opt/myip
 | 
			
		||||
cp .env.example .env
 | 
			
		||||
$STD npm install
 | 
			
		||||
$STD npm run build
 | 
			
		||||
msg_ok "Configured MyIP"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/myip.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=MyIP Service
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
User=root
 | 
			
		||||
WorkingDirectory=/opt/myip
 | 
			
		||||
ExecStart=/usr/bin/npm start
 | 
			
		||||
EnvironmentFile=/opt/myip/.env
 | 
			
		||||
Restart=on-failure
 | 
			
		||||
RestartSec=5
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl enable -q --now myip
 | 
			
		||||
msg_ok "Service created"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD apt -y autoremove
 | 
			
		||||
$STD apt -y autoclean
 | 
			
		||||
$STD apt -y clean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
							
								
								
									
										96
									
								
								install/verdaccio-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								install/verdaccio-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: BrynnJKnight
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://verdaccio.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 \
 | 
			
		||||
  ca-certificates \
 | 
			
		||||
  build-essential
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
NODE_VERSION="22" NODE_MODULE="verdaccio" setup_nodejs
 | 
			
		||||
 | 
			
		||||
msg_info "Configuring Verdaccio"
 | 
			
		||||
mkdir -p /opt/verdaccio/config
 | 
			
		||||
mkdir -p /opt/verdaccio/storage
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/opt/verdaccio/config/config.yaml
 | 
			
		||||
# Verdaccio configuration
 | 
			
		||||
storage: /opt/verdaccio/storage
 | 
			
		||||
auth:
 | 
			
		||||
  htpasswd:
 | 
			
		||||
    file: /opt/verdaccio/storage/htpasswd
 | 
			
		||||
    max_users: 1000
 | 
			
		||||
uplinks:
 | 
			
		||||
  npmjs:
 | 
			
		||||
    url: https://registry.npmjs.org/
 | 
			
		||||
packages:
 | 
			
		||||
  '@*/*':
 | 
			
		||||
    access: \$all
 | 
			
		||||
    publish: \$authenticated
 | 
			
		||||
    proxy: npmjs
 | 
			
		||||
  '**':
 | 
			
		||||
    access: \$all
 | 
			
		||||
    publish: \$authenticated
 | 
			
		||||
    proxy: npmjs
 | 
			
		||||
middlewares:
 | 
			
		||||
  audit:
 | 
			
		||||
    enabled: true
 | 
			
		||||
logs:
 | 
			
		||||
  - {type: stdout, format: pretty, level: http}
 | 
			
		||||
listen:
 | 
			
		||||
  - 0.0.0.0:4873
 | 
			
		||||
web:
 | 
			
		||||
  enable: true
 | 
			
		||||
  title: Verdaccio
 | 
			
		||||
  gravatar: true
 | 
			
		||||
  sort_packages: asc
 | 
			
		||||
  login: true
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
chown -R root:root /opt/verdaccio
 | 
			
		||||
chmod -R 755 /opt/verdaccio
 | 
			
		||||
msg_ok "Configured Verdaccio"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/verdaccio.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Verdaccio lightweight private npm proxy registry
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=/usr/bin/verdaccio --config /opt/verdaccio/config/config.yaml
 | 
			
		||||
Restart=on-failure
 | 
			
		||||
StandardOutput=journal
 | 
			
		||||
StandardError=journal
 | 
			
		||||
SyslogIdentifier=verdaccio
 | 
			
		||||
KillMode=control-group
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
systemctl enable -q --now verdaccio
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD apt -y autoremove
 | 
			
		||||
$STD apt -y autoclean
 | 
			
		||||
$STD apt -y clean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
							
								
								
									
										119
									
								
								install/warracker-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								install/warracker-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
#!/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: https://github.com/sassanix/Warracker/
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt install -y \
 | 
			
		||||
    build-essential \
 | 
			
		||||
    libpq-dev \
 | 
			
		||||
    nginx
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
PYTHON_VERSION="3.12" setup_uv
 | 
			
		||||
PG_VERSION="17" setup_postgresql
 | 
			
		||||
 | 
			
		||||
msg_info "Setup PostgreSQL"
 | 
			
		||||
DB_NAME="warranty_db"
 | 
			
		||||
DB_USER="warranty_user"
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
 | 
			
		||||
DB_ADMIN_USER="warracker_admin"
 | 
			
		||||
DB_ADMIN_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';"
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE USER $DB_ADMIN_USER WITH PASSWORD '$DB_ADMIN_PASS' SUPERUSER;"
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME OWNER $DB_ADMIN_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -d "$DB_NAME" -c "GRANT USAGE ON SCHEMA public TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -d "$DB_NAME" -c "GRANT CREATE ON SCHEMA public TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -d "$DB_NAME" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO $DB_USER;"
 | 
			
		||||
{
 | 
			
		||||
    echo "Application Credentials"
 | 
			
		||||
    echo "DB_NAME: $DB_NAME"
 | 
			
		||||
    echo "DB_USER: $DB_USER"
 | 
			
		||||
    echo "DB_PASS: $DB_PASS"
 | 
			
		||||
    echo "DB_ADMIN_USER: $DB_ADMIN_USER"
 | 
			
		||||
    echo "DB_ADMIN_PASS: $DB_ADMIN_PASS"
 | 
			
		||||
} >>~/warracker.creds
 | 
			
		||||
msg_ok "Setup PostgreSQL"
 | 
			
		||||
 | 
			
		||||
fetch_and_deploy_gh_release "warracker" "sassanix/Warracker" "tarball" "latest" "/opt/warracker"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Warracker"
 | 
			
		||||
cd /opt/warracker/backend
 | 
			
		||||
$STD uv venv .venv
 | 
			
		||||
$STD source .venv/bin/activate
 | 
			
		||||
$STD uv pip install -r requirements.txt
 | 
			
		||||
mv /opt/warracker/env.example /opt/.env
 | 
			
		||||
sed -i \
 | 
			
		||||
    -e "s/your_secure_database_password/$DB_PASS/" \
 | 
			
		||||
    -e "s/your_secure_admin_password/$DB_ADMIN_PASS/" \
 | 
			
		||||
    -e "s|^# DB_PORT=5432$|DB_HOST=127.0.0.1|" \
 | 
			
		||||
    -e "s|your_very_secure_flask_secret_key_change_this_in_production|$(openssl rand -base64 32 | tr -d '\n')|" \
 | 
			
		||||
    /opt/.env
 | 
			
		||||
mkdir -p /data/uploads
 | 
			
		||||
msg_ok "Installed Warracker"
 | 
			
		||||
 | 
			
		||||
msg_info "Configuring Nginx"
 | 
			
		||||
mv /opt/warracker/nginx.conf /etc/nginx/sites-available/warracker.conf
 | 
			
		||||
sed -i \
 | 
			
		||||
    -e "s|alias /var/www/html/locales/;|alias /opt/warracker/locales/;|" \
 | 
			
		||||
    -e "s|/var/www/html|/opt/warracker/frontend|g" \
 | 
			
		||||
    -e "s/client_max_body_size __NGINX_MAX_BODY_SIZE_CONFIG_VALUE__/client_max_body_size 32M/" \
 | 
			
		||||
    /etc/nginx/sites-available/warracker.conf
 | 
			
		||||
ln -s /etc/nginx/sites-available/warracker.conf /etc/nginx/sites-enabled/warracker.conf
 | 
			
		||||
rm /etc/nginx/sites-enabled/default
 | 
			
		||||
systemctl restart nginx
 | 
			
		||||
 | 
			
		||||
msg_ok "Configured Nginx"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating systemd services"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/warrackermigration.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Warracker Migration Service
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=oneshot
 | 
			
		||||
WorkingDirectory=/opt/warracker/backend/migrations
 | 
			
		||||
EnvironmentFile=/opt/.env
 | 
			
		||||
ExecStart=/opt/warracker/backend/.venv/bin/python apply_migrations.py
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/etc/systemd/system/warracker.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Warracker Service
 | 
			
		||||
After=network.target warrackermigration.service
 | 
			
		||||
Requires=warrackermigration.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
WorkingDirectory=/opt/warracker
 | 
			
		||||
EnvironmentFile=/opt/.env
 | 
			
		||||
ExecStart=/opt/warracker/backend/.venv/bin/gunicorn --config /opt/warracker/backend/gunicorn_config.py backend:create_app() --bind 127.0.0.1:5000
 | 
			
		||||
Restart=always
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl enable -q --now warracker
 | 
			
		||||
msg_ok "Started Warracker Services"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD apt -y autoremove
 | 
			
		||||
$STD apt -y autoclean
 | 
			
		||||
$STD apt -y clean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
		Reference in New Issue
	
	Block a user