mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 02:12:49 +00:00 
			
		
		
		
	Compare commits
	
		
			171 Commits
		
	
	
		
			2025-01-24
			...
			2025-02-03
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					bd5db081c1 | ||
| 
						 | 
					c5a69d6e8b | ||
| 
						 | 
					a75c0e1562 | ||
| 
						 | 
					a97d76f428 | ||
| 
						 | 
					0e0539af3f | ||
| 
						 | 
					8d46f7266e | ||
| 
						 | 
					7f5ee39b25 | ||
| 
						 | 
					85333212b0 | ||
| 
						 | 
					577a415f10 | ||
| 
						 | 
					db24bf4d02 | ||
| 
						 | 
					21e0e0df98 | ||
| 
						 | 
					83015c8cff | ||
| 
						 | 
					7ca1ed019c | ||
| 
						 | 
					fb8f911c49 | ||
| 
						 | 
					b4a0b74bfd | ||
| 
						 | 
					99556bdbd2 | ||
| 
						 | 
					ec3b70e8fd | ||
| 
						 | 
					50ffcd4734 | ||
| 
						 | 
					55c1f2f3dc | ||
| 
						 | 
					99e04e1ded | ||
| 
						 | 
					884428e113 | ||
| 
						 | 
					00f58d71d6 | ||
| 
						 | 
					fa4ab5c8a3 | ||
| 
						 | 
					1528c46f0b | ||
| 
						 | 
					c5b9e4db64 | ||
| 
						 | 
					36f2fb3e52 | ||
| 
						 | 
					e379db8baf | ||
| 
						 | 
					91ba5cd412 | ||
| 
						 | 
					745d1f9444 | ||
| 
						 | 
					76f12fc596 | ||
| 
						 | 
					995906f299 | ||
| 
						 | 
					05ec444e2d | ||
| 
						 | 
					19911f5b81 | ||
| 
						 | 
					57b37b1e16 | ||
| 
						 | 
					91a3fd10e0 | ||
| 
						 | 
					6f0ebac209 | ||
| 
						 | 
					f40e6e5453 | ||
| 
						 | 
					8a07124457 | ||
| 
						 | 
					41c32af0d6 | ||
| 
						 | 
					3cb4196fee | ||
| 
						 | 
					a33108cd4f | ||
| 
						 | 
					a0d7c5db0e | ||
| 
						 | 
					baef2a0cb9 | ||
| 
						 | 
					f9b84bf5ee | ||
| 
						 | 
					ccab9d1be5 | ||
| 
						 | 
					58a2ece7b7 | ||
| 
						 | 
					aa16f936c8 | ||
| 
						 | 
					c8829beddd | ||
| 
						 | 
					3adc22d837 | ||
| 
						 | 
					71b1288220 | ||
| 
						 | 
					3c58303a9f | ||
| 
						 | 
					b8edf0dd68 | ||
| 
						 | 
					2fa3116c9c | ||
| 
						 | 
					d416ff9cfa | ||
| 
						 | 
					2e2db6603e | ||
| 
						 | 
					72335f2c4e | ||
| 
						 | 
					a359ffc211 | ||
| 
						 | 
					cd4bcefa58 | ||
| 
						 | 
					a0eb173824 | ||
| 
						 | 
					3d42ecb152 | ||
| 
						 | 
					0642c7e2c8 | ||
| 
						 | 
					af04e933e3 | ||
| 
						 | 
					0dfc513a27 | ||
| 
						 | 
					26433efcd8 | ||
| 
						 | 
					343de50ef8 | ||
| 
						 | 
					a38e9070ef | ||
| 
						 | 
					e2b548a7c3 | ||
| 
						 | 
					737b18dea5 | ||
| 
						 | 
					6b777a03c0 | ||
| 
						 | 
					d9b4778360 | ||
| 
						 | 
					7299b77359 | ||
| 
						 | 
					d3882b6818 | ||
| 
						 | 
					2ef0cd0f89 | ||
| 
						 | 
					f2eb24d527 | ||
| 
						 | 
					f520607d85 | ||
| 
						 | 
					1270d87bf8 | ||
| 
						 | 
					7f2481ea12 | ||
| 
						 | 
					05f114ed64 | ||
| 
						 | 
					6924a6fea4 | ||
| 
						 | 
					bb553ae48c | ||
| 
						 | 
					cbb18668dd | ||
| 
						 | 
					c7418171b4 | ||
| 
						 | 
					ed2ead9ef2 | ||
| 
						 | 
					e51c121af2 | ||
| 
						 | 
					8c4e97d6cb | ||
| 
						 | 
					1093fef23c | ||
| 
						 | 
					6fa540f0da | ||
| 
						 | 
					ca7fb9b929 | ||
| 
						 | 
					139f84a934 | ||
| 
						 | 
					8bc50f4d71 | ||
| 
						 | 
					3fa4cf6e07 | ||
| 
						 | 
					63e3619b68 | ||
| 
						 | 
					054b569e33 | ||
| 
						 | 
					cd740e52f4 | ||
| 
						 | 
					37c7205978 | ||
| 
						 | 
					eb9633215c | ||
| 
						 | 
					85a6819760 | ||
| 
						 | 
					20d6162ac1 | ||
| 
						 | 
					0dff2b3363 | ||
| 
						 | 
					c799e67ea5 | ||
| 
						 | 
					645972077e | ||
| 
						 | 
					24dfa9590e | ||
| 
						 | 
					cecf179b34 | ||
| 
						 | 
					1f39208c1c | ||
| 
						 | 
					63061942b9 | ||
| 
						 | 
					87a987ba35 | ||
| 
						 | 
					0680fbfac7 | ||
| 
						 | 
					41a836f990 | ||
| 
						 | 
					ad14b1b1d6 | ||
| 
						 | 
					94d60a79d6 | ||
| 
						 | 
					f10e625e41 | ||
| 
						 | 
					dae705056c | ||
| 
						 | 
					b973ca9d8d | ||
| 
						 | 
					1cf8f80c71 | ||
| 
						 | 
					97002e7047 | ||
| 
						 | 
					d366d24dea | ||
| 
						 | 
					05e46a07cd | ||
| 
						 | 
					af166e3346 | ||
| 
						 | 
					8221614cab | ||
| 
						 | 
					b70cd00764 | ||
| 
						 | 
					31473b2170 | ||
| 
						 | 
					690d6d42d4 | ||
| 
						 | 
					3be6824844 | ||
| 
						 | 
					f903cfd97a | ||
| 
						 | 
					901db73d78 | ||
| 
						 | 
					67b80306a1 | ||
| 
						 | 
					7dc446c8ac | ||
| 
						 | 
					9435b9d046 | ||
| 
						 | 
					2b1b517f20 | ||
| 
						 | 
					7c297d3dac | ||
| 
						 | 
					dbb9b66355 | ||
| 
						 | 
					ff06d417b5 | ||
| 
						 | 
					84b982ffa8 | ||
| 
						 | 
					53c7ab19f8 | ||
| 
						 | 
					d13c1e5722 | ||
| 
						 | 
					be92f947cd | ||
| 
						 | 
					452012529c | ||
| 
						 | 
					661654987d | ||
| 
						 | 
					c3a21069d2 | ||
| 
						 | 
					4de8c1c358 | ||
| 
						 | 
					cd86921467 | ||
| 
						 | 
					38a540b87a | ||
| 
						 | 
					8cd3669edb | ||
| 
						 | 
					adfbff63bc | ||
| 
						 | 
					47bf8e6f86 | ||
| 
						 | 
					43f05b3aba | ||
| 
						 | 
					b17befec88 | ||
| 
						 | 
					719da560d1 | ||
| 
						 | 
					ac25b5a702 | ||
| 
						 | 
					ce1a38eb50 | ||
| 
						 | 
					030174f508 | ||
| 
						 | 
					7e1fb858d7 | ||
| 
						 | 
					5dc1a7d219 | ||
| 
						 | 
					14247ac5a9 | ||
| 
						 | 
					4911a7918a | ||
| 
						 | 
					b06ad8bde8 | ||
| 
						 | 
					8a6364902e | ||
| 
						 | 
					dfd56aebf2 | ||
| 
						 | 
					78e6e12c8a | ||
| 
						 | 
					88c3f56157 | ||
| 
						 | 
					92057c4ea7 | ||
| 
						 | 
					0af7a5adbf | ||
| 
						 | 
					ba6edcdcaf | ||
| 
						 | 
					de80e95d69 | ||
| 
						 | 
					796275d175 | ||
| 
						 | 
					9ff56caafd | ||
| 
						 | 
					d596f4a3e0 | ||
| 
						 | 
					b9cdfc26d0 | ||
| 
						 | 
					ae726129b1 | ||
| 
						 | 
					bd3f823b86 | ||
| 
						 | 
					eddacd786d | 
							
								
								
									
										2
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
								
							@@ -80,7 +80,7 @@ git switch -c your-feature-branch
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 4. Change paths in build.func install.func and AppName.sh
 | 
			
		||||
To be able to develop from your own branch you need to change `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main` to `https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/head/[BRANCH]`. You need to make this change atleast in misc/build.func misc/install.func and in your ct/AppName.sh. This change is only for testing. Before opening a Pull Request you should change this line change all this back to point to `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main`.
 | 
			
		||||
To be able to develop from your own branch you need to change `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main` to `https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/heads/[BRANCH]`. You need to make this change atleast in misc/build.func misc/install.func and in your ct/AppName.sh. This change is only for testing. Before opening a Pull Request you should change this line change all this back to point to `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main`.
 | 
			
		||||
 | 
			
		||||
### 4. Commit changes (without build.func and install.func!)
 | 
			
		||||
```bash
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								.github/CONTRIBUTOR_GUIDE/ct/AppName.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/CONTRIBUTOR_GUIDE/ct/AppName.md
									
									
									
									
										vendored
									
									
								
							@@ -40,8 +40,8 @@
 | 
			
		||||
- Import the build.func file.
 | 
			
		||||
- When developing your own script, change the URL to your own repository.
 | 
			
		||||
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
> Before opening a Pull Request, change the URL to point to the community-scripts repo.
 | 
			
		||||
> [!IMPORTANT] 
 | 
			
		||||
> You also need to change all apperances of this URL in `misc/build.func` and `misc/install.func`
 | 
			
		||||
 | 
			
		||||
Example for development:
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +55,9 @@ Final script:
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> [!CAUTION]
 | 
			
		||||
> Before opening a Pull Request, change the URLs to point to the community-scripts repo.
 | 
			
		||||
 | 
			
		||||
### 1.3 **Metadata**
 | 
			
		||||
 | 
			
		||||
- Add clear comments for script metadata, including author, copyright, and license information.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							@@ -1 +1,2 @@
 | 
			
		||||
ko_fi: community_scripts
 | 
			
		||||
github: community_scripts
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								.github/workflows/auto-update-app-headers.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/auto-update-app-headers.yml
									
									
									
									
										vendored
									
									
								
							@@ -45,28 +45,26 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      # Step 6: Check if there are any changes
 | 
			
		||||
      - name: Check if there are any changes
 | 
			
		||||
        id: verify-diff
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "Checking for changes..."
 | 
			
		||||
          git add -A  # Untracked Dateien aufnehmen
 | 
			
		||||
          git status
 | 
			
		||||
          if git diff --quiet; then
 | 
			
		||||
          if git diff --cached --quiet; then
 | 
			
		||||
            echo "No changes detected."
 | 
			
		||||
            echo "changed=false" >> $GITHUB_OUTPUT
 | 
			
		||||
            echo "changed=false" >> "$GITHUB_ENV"
 | 
			
		||||
          else
 | 
			
		||||
            echo "Changes detected:"
 | 
			
		||||
            git diff --stat
 | 
			
		||||
            echo "changed=true" >> $GITHUB_OUTPUT
 | 
			
		||||
            git diff --stat --cached
 | 
			
		||||
            echo "changed=true" >> "$GITHUB_ENV"
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      # Step 7: Commit changes (if any) and create a PR
 | 
			
		||||
      # Step 7: Commit and create PR if changes exist
 | 
			
		||||
      - name: Commit and create PR if changes exist
 | 
			
		||||
        if: steps.verify-diff.outputs.changed == 'true'
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        run: |
 | 
			
		||||
          git add -A
 | 
			
		||||
          git commit -m "Update .app files"
 | 
			
		||||
          git checkout -b pr-update-app-files
 | 
			
		||||
          git push origin pr-update-app-files --force
 | 
			
		||||
 | 
			
		||||
          gh pr create --title "[core] update .app files" \
 | 
			
		||||
                       --body "This PR is auto-generated by a GitHub Action to update the .app files." \
 | 
			
		||||
                       --head pr-update-app-files \
 | 
			
		||||
@@ -77,6 +75,5 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      # Step 8: Output success message when no changes
 | 
			
		||||
      - name: No changes detected
 | 
			
		||||
        if: steps.verify-diff.outputs.changed == 'false'
 | 
			
		||||
        if: env.changed == 'false'
 | 
			
		||||
        run: echo "No changes to commit. Workflow completed successfully."
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "files.associations": {
 | 
			
		||||
        "*.func": "shellscript"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										188
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										188
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -17,6 +17,194 @@ All LXC instances created using this repository come pre-installed with Midnight
 | 
			
		||||
Do not break established syntax in this file, as it is automatically updated by a Github Workflow
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 2025-02-03
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New Script: Element Synapse [@tremor021](https://github.com/tremor021) ([#1955](https://github.com/community-scripts/ProxmoxVE/pull/1955))
 | 
			
		||||
- New Script: Privatebin [@opastorello](https://github.com/opastorello) ([#1925](https://github.com/community-scripts/ProxmoxVE/pull/1925))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Fix: Monica Install with nodejs [@MickLesk](https://github.com/MickLesk) ([#1996](https://github.com/community-scripts/ProxmoxVE/pull/1996))
 | 
			
		||||
- Element Synapse sed fix [@tremor021](https://github.com/tremor021) ([#1994](https://github.com/community-scripts/ProxmoxVE/pull/1994))
 | 
			
		||||
- Fix Hoarder corepack install/update error [@vhsdream](https://github.com/vhsdream) ([#1957](https://github.com/community-scripts/ProxmoxVE/pull/1957))
 | 
			
		||||
- [Security & Maintenance] Update NodeJS Repo to 22 for new Installs [@MickLesk](https://github.com/MickLesk) ([#1984](https://github.com/community-scripts/ProxmoxVE/pull/1984))
 | 
			
		||||
- [Standardization]: Same Setup for GoLang on all LXC's & Clear Tarball [@MickLesk](https://github.com/MickLesk) ([#1977](https://github.com/community-scripts/ProxmoxVE/pull/1977))
 | 
			
		||||
- Feature: urbackupserver Include fuse&nesting features during install [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1968](https://github.com/community-scripts/ProxmoxVE/pull/1968))
 | 
			
		||||
- Fix: MSSQL-Server: Better gpg handling [@MickLesk](https://github.com/MickLesk) ([#1962](https://github.com/community-scripts/ProxmoxVE/pull/1962))
 | 
			
		||||
- Fix: Grist ran into a heap space during the update [@MickLesk](https://github.com/MickLesk) ([#1964](https://github.com/community-scripts/ProxmoxVE/pull/1964))
 | 
			
		||||
- Fix: FS-Trim Cancel / Error-Button [@MickLesk](https://github.com/MickLesk) ([#1965](https://github.com/community-scripts/ProxmoxVE/pull/1965))
 | 
			
		||||
- Fix: Increase HDD Space for Hoarder [@MickLesk](https://github.com/MickLesk) ([#1970](https://github.com/community-scripts/ProxmoxVE/pull/1970))
 | 
			
		||||
- Feature: Clean Orphan LVM without CEPH [@MickLesk](https://github.com/MickLesk) ([#1974](https://github.com/community-scripts/ProxmoxVE/pull/1974))
 | 
			
		||||
- [Standardization] Fix Spelling for "Setup Python3"  [@MickLesk](https://github.com/MickLesk) ([#1975](https://github.com/community-scripts/ProxmoxVE/pull/1975))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- [Website] update data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1969](https://github.com/community-scripts/ProxmoxVE/pull/1969))
 | 
			
		||||
- Prometheus Proxmox VE Exporter: Set correct website slug [@andygrunwald](https://github.com/andygrunwald) ([#1961](https://github.com/community-scripts/ProxmoxVE/pull/1961))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
- [API] Remove Hostname, Verbose, SSH and TAGS [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1967](https://github.com/community-scripts/ProxmoxVE/pull/1967))
 | 
			
		||||
 | 
			
		||||
## 2025-02-02
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Prometheus PVE Exporter: Add `--default-timeout=300` to pip install commands [@andygrunwald](https://github.com/andygrunwald) ([#1950](https://github.com/community-scripts/ProxmoxVE/pull/1950))
 | 
			
		||||
- fix z2m update function to 2.1.0 [@MickLesk](https://github.com/MickLesk) ([#1938](https://github.com/community-scripts/ProxmoxVE/pull/1938))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
- VSCode: Add Shellscript Syntax highlighting for *.func files [@andygrunwald](https://github.com/andygrunwald) ([#1948](https://github.com/community-scripts/ProxmoxVE/pull/1948))
 | 
			
		||||
 | 
			
		||||
## 2025-02-01
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### 💥 Breaking Changes
 | 
			
		||||
 | 
			
		||||
- [DCMA] Delete scripts 5etools and pf2etools - Copyright abuse [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1922](https://github.com/community-scripts/ProxmoxVE/pull/1922))
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New script: Baïkal [@bvdberg01](https://github.com/bvdberg01) ([#1913](https://github.com/community-scripts/ProxmoxVE/pull/1913))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Bug fix: Paymenter [@opastorello](https://github.com/opastorello) ([#1917](https://github.com/community-scripts/ProxmoxVE/pull/1917))
 | 
			
		||||
 | 
			
		||||
## 2025-01-31
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New Script: Paymenter [@opastorello](https://github.com/opastorello) ([#1827](https://github.com/community-scripts/ProxmoxVE/pull/1827))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- [Fix] Alpine-IT-Tools, add missing ssh package for root ssh access [@CrazyWolf13](https://github.com/CrazyWolf13) ([#1891](https://github.com/community-scripts/ProxmoxVE/pull/1891))
 | 
			
		||||
- [Fix] Change Download of Trilium after there change the tag/release logic [@MickLesk](https://github.com/MickLesk) ([#1892](https://github.com/community-scripts/ProxmoxVE/pull/1892))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- [Website] Enhance DataFetcher with better UI components and add reactive data fetching intervals [@BramSuurdje](https://github.com/BramSuurdje) ([#1902](https://github.com/community-scripts/ProxmoxVE/pull/1902))
 | 
			
		||||
- [Website] Update /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1900](https://github.com/community-scripts/ProxmoxVE/pull/1900))
 | 
			
		||||
 | 
			
		||||
## 2025-01-30
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New Script: IT-Tools [@nicedevil007](https://github.com/nicedevil007) ([#1862](https://github.com/community-scripts/ProxmoxVE/pull/1862))
 | 
			
		||||
- New Script: Mattermost [@Dracentis](https://github.com/Dracentis) ([#1856](https://github.com/community-scripts/ProxmoxVE/pull/1856))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Optimize PVE Manager Version-Check [@MickLesk](https://github.com/MickLesk) ([#1866](https://github.com/community-scripts/ProxmoxVE/pull/1866))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- [API] Update build.func to set the status message correct [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1878](https://github.com/community-scripts/ProxmoxVE/pull/1878))
 | 
			
		||||
- [Website] Update /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1876](https://github.com/community-scripts/ProxmoxVE/pull/1876))
 | 
			
		||||
- Fix IT-Tools Website Entry (Default | Alpine)  [@MickLesk](https://github.com/MickLesk) ([#1869](https://github.com/community-scripts/ProxmoxVE/pull/1869))
 | 
			
		||||
- fix: remove rounded styles from command primitive [@steveiliop56](https://github.com/steveiliop56) ([#1840](https://github.com/community-scripts/ProxmoxVE/pull/1840))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
- [API] Update build.func: add function to see if a script failed or not [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1874](https://github.com/community-scripts/ProxmoxVE/pull/1874))
 | 
			
		||||
 | 
			
		||||
## 2025-01-29
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New Script: Prometheus Proxmox VE Exporter [@andygrunwald](https://github.com/andygrunwald) ([#1805](https://github.com/community-scripts/ProxmoxVE/pull/1805))
 | 
			
		||||
- New Script: Clean Orphaned LVM [@MickLesk](https://github.com/MickLesk) ([#1838](https://github.com/community-scripts/ProxmoxVE/pull/1838))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- Patch http Url to https in build.func and /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1849](https://github.com/community-scripts/ProxmoxVE/pull/1849))
 | 
			
		||||
- [Frontend] Add /data to show API results [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1841](https://github.com/community-scripts/ProxmoxVE/pull/1841))
 | 
			
		||||
- Update clean-orphaned-lvm.json [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1843](https://github.com/community-scripts/ProxmoxVE/pull/1843))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
- Update build.func [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1851](https://github.com/community-scripts/ProxmoxVE/pull/1851))
 | 
			
		||||
- [Diagnostic] Introduced optional lxc install diagnostics via API call [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1801](https://github.com/community-scripts/ProxmoxVE/pull/1801))
 | 
			
		||||
 | 
			
		||||
## 2025-01-28
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### 💥 Breaking Changes
 | 
			
		||||
 | 
			
		||||
- Breaking Change: Homarr v1 (Read Guide) [@MickLesk](https://github.com/MickLesk) ([#1825](https://github.com/community-scripts/ProxmoxVE/pull/1825))
 | 
			
		||||
- Update PingVin: Fix problem with update und switch to new method of getting files. [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1819](https://github.com/community-scripts/ProxmoxVE/pull/1819))
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New script: Monica LXC [@bvdberg01](https://github.com/bvdberg01) ([#1813](https://github.com/community-scripts/ProxmoxVE/pull/1813))
 | 
			
		||||
- New Script: NodeBB [@MickLesk](https://github.com/MickLesk) ([#1811](https://github.com/community-scripts/ProxmoxVE/pull/1811))
 | 
			
		||||
- New Script: Pocket ID [@Snarkenfaugister](https://github.com/Snarkenfaugister) ([#1779](https://github.com/community-scripts/ProxmoxVE/pull/1779))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Update all Alpine LXC's to 3.21 (Docker, Grafana, Nextcloud, Vaultwarden, Zigbee2Mqtt, Alpine) [@MickLesk](https://github.com/MickLesk) ([#1803](https://github.com/community-scripts/ProxmoxVE/pull/1803))
 | 
			
		||||
- [Standardization] Fix Spelling for "Setup Python3" [@MickLesk](https://github.com/MickLesk) ([#1810](https://github.com/community-scripts/ProxmoxVE/pull/1810))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- Filter out duplicate scripts in LatestScripts component and sort by creation date [@BramSuurdje](https://github.com/BramSuurdje) ([#1828](https://github.com/community-scripts/ProxmoxVE/pull/1828))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
- [core]: Remove Figlet | Get Headers by Repo & Store Local [@MickLesk](https://github.com/MickLesk) ([#1802](https://github.com/community-scripts/ProxmoxVE/pull/1802))
 | 
			
		||||
- [docs] Update AppName.md: Make it clear where to change the URLs [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1809](https://github.com/community-scripts/ProxmoxVE/pull/1809))
 | 
			
		||||
 | 
			
		||||
## 2025-01-27
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New Script: Arch Linux VM [@MickLesk](https://github.com/MickLesk) ([#1780](https://github.com/community-scripts/ProxmoxVE/pull/1780))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Increase alpine-vaultwarden default var_disk size [@nayzm](https://github.com/nayzm) ([#1788](https://github.com/community-scripts/ProxmoxVE/pull/1788))
 | 
			
		||||
- Added change of the mobile GUI to disable nag request [@GarryG](https://github.com/GarryG) ([#1785](https://github.com/community-scripts/ProxmoxVE/pull/1785))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- Update frontend alpine-vaultwarden hdd size and OS version [@nayzm](https://github.com/nayzm) ([#1789](https://github.com/community-scripts/ProxmoxVE/pull/1789))
 | 
			
		||||
- Website: Add Description for Metadata Categories [@MickLesk](https://github.com/MickLesk) ([#1783](https://github.com/community-scripts/ProxmoxVE/pull/1783))
 | 
			
		||||
- [Fix] Double "VM" on website (Arch Linux) [@lasharor](https://github.com/lasharor) ([#1782](https://github.com/community-scripts/ProxmoxVE/pull/1782))
 | 
			
		||||
 | 
			
		||||
## 2025-01-26
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Fix jellyfin update command [@jcisio](https://github.com/jcisio) ([#1771](https://github.com/community-scripts/ProxmoxVE/pull/1771))
 | 
			
		||||
- openHAB - Use https and include doc url [@moodyblue](https://github.com/moodyblue) ([#1766](https://github.com/community-scripts/ProxmoxVE/pull/1766))
 | 
			
		||||
- Jellyfin: Fix default logging level [@tremor021](https://github.com/tremor021) ([#1768](https://github.com/community-scripts/ProxmoxVE/pull/1768))
 | 
			
		||||
- Calibre-Web: added installation of calibre binaries [@tremor021](https://github.com/tremor021) ([#1763](https://github.com/community-scripts/ProxmoxVE/pull/1763))
 | 
			
		||||
- Added environment variable to accept EULA for SQLServer2022 [@tremor021](https://github.com/tremor021) ([#1755](https://github.com/community-scripts/ProxmoxVE/pull/1755))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- The Lounge: Fix the command to create new users [@tremor021](https://github.com/tremor021) ([#1762](https://github.com/community-scripts/ProxmoxVE/pull/1762))
 | 
			
		||||
 | 
			
		||||
## 2025-01-24
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								ct/5etools.sh
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								ct/5etools.sh
									
									
									
									
									
								
							@@ -1,113 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: TheRealVira
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://5e.tools/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="5etools"
 | 
			
		||||
var_tags="wiki"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="13"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    # Check if installation is present | -f for file, -d for folder
 | 
			
		||||
    if [[ ! -d "/opt/${APP}" ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/5etools-mirror-3/5etools-src/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
    if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f "/opt/${APP}_version.txt" ]]; then
 | 
			
		||||
        # Crawling the new version and checking whether an update is required
 | 
			
		||||
        msg_info "Updating System"
 | 
			
		||||
        apt-get update &>/dev/null
 | 
			
		||||
        apt-get -y upgrade &>/dev/null
 | 
			
		||||
        msg_ok "Updated System"
 | 
			
		||||
 | 
			
		||||
        # Execute Update
 | 
			
		||||
        msg_info "Updating base 5etools"
 | 
			
		||||
        cd /opt
 | 
			
		||||
        wget -q "https://github.com/5etools-mirror-3/5etools-src/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
        unzip -q "${RELEASE}.zip"
 | 
			
		||||
        mv "/opt/${APP}/img" "/opt/img-backup"
 | 
			
		||||
        rm -rf "/opt/${APP}"
 | 
			
		||||
        mv "${APP}-src-${RELEASE:1}" "/opt/${APP}"
 | 
			
		||||
        mv "/opt/img-backup" "/opt/${APP}/img"
 | 
			
		||||
        cd /opt/5etools
 | 
			
		||||
        $STD npm install
 | 
			
		||||
        $STD npm run build
 | 
			
		||||
        cd ~
 | 
			
		||||
        echo "${RELEASE}" >"/opt/${APP}_version.txt"
 | 
			
		||||
        chown -R www-data: "/opt/${APP}"
 | 
			
		||||
        chmod -R 755 "/opt/${APP}"
 | 
			
		||||
        msg_ok "Updated base 5etools"
 | 
			
		||||
        # Cleaning up
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -rf /opt/${RELEASE}.zip
 | 
			
		||||
        $STD apt-get -y autoremove
 | 
			
		||||
        $STD apt-get -y autoclean
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. Base ${APP} is already at ${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    IMG_RELEASE=$(curl -s https://api.github.com/repos/5etools-mirror-2/5etools-img/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
    if [[ "${IMG_RELEASE}" != "$(cat /opt/${APP}_IMG_version.txt)" ]] || [[ ! -f "/opt/${APP}_IMG_version.txt" ]]; then
 | 
			
		||||
        # Crawling the new version and checking whether an update is required
 | 
			
		||||
        msg_info "Updating System"
 | 
			
		||||
        apt-get update &>/dev/null
 | 
			
		||||
        apt-get -y upgrade &>/dev/null
 | 
			
		||||
        msg_ok "Updated System"
 | 
			
		||||
 | 
			
		||||
        # Execute Update
 | 
			
		||||
        msg_info "Updating 5etools images"
 | 
			
		||||
        curl -sSL "https://github.com/5etools-mirror-2/5etools-img/archive/refs/tags/${IMG_RELEASE}.zip" > "${IMG_RELEASE}.zip"
 | 
			
		||||
        unzip -q "${IMG_RELEASE}.zip"
 | 
			
		||||
        rm -rf "/opt/${APP}/img"
 | 
			
		||||
        mv "${APP}-img-${IMG_RELEASE:1}" "/opt/${APP}/img"
 | 
			
		||||
        echo "${IMG_RELEASE}" >"/opt/${APP}_IMG_version.txt"
 | 
			
		||||
        chown -R www-data: "/opt/${APP}"
 | 
			
		||||
        chmod -R 755 "/opt/${APP}"
 | 
			
		||||
 | 
			
		||||
        msg_ok "Updating 5etools images"
 | 
			
		||||
 | 
			
		||||
        # Cleaning up
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -rf /opt/${RELEASE}.zip
 | 
			
		||||
        rm -rf ${IMG_RELEASE}.zip
 | 
			
		||||
        $STD apt-get -y autoremove
 | 
			
		||||
        $STD apt-get -y autoclean
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} images are already at ${IMG_RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
@@ -47,6 +47,7 @@ function update_script() {
 | 
			
		||||
        mkdir -p /opt/actualbudget/
 | 
			
		||||
        tar -xzf v${RELEASE}.tar.gz >/dev/null 2>&1
 | 
			
		||||
        mv *ctual-server-*/* /opt/actualbudget
 | 
			
		||||
        rm -rf /opt/actualbudget/.env
 | 
			
		||||
        mv /opt/actualbudget_bak/.env /opt/actualbudget
 | 
			
		||||
        mv /opt/actualbudget_bak/server-files /opt/actualbudget/server-files
 | 
			
		||||
        cd /opt/actualbudget
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="2"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ var_cpu="1"
 | 
			
		||||
var_ram="256"
 | 
			
		||||
var_disk="1"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								ct/alpine-it-tools.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								ct/alpine-it-tools.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
#!/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: nicedevil007 (NiceDevil)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine-IT-Tools"
 | 
			
		||||
var_tags="alpine;development"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="256"
 | 
			
		||||
var_disk="0.2"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    if [[ ! -d /usr/share/nginx/html ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    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)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
        DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
 | 
			
		||||
        msg_info "Updating ${APP} LXC"
 | 
			
		||||
        curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
 | 
			
		||||
        mkdir -p /usr/share/nginx/html
 | 
			
		||||
        rm -rf /usr/share/nginx/html/*
 | 
			
		||||
        unzip -q it-tools.zip -d /tmp/it-tools
 | 
			
		||||
        cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
 | 
			
		||||
        rm -rf /tmp/it-tools
 | 
			
		||||
        rm -f it-tools.zip
 | 
			
		||||
        msg_ok "Updated Successfully"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
@@ -11,7 +11,7 @@ var_cpu="2"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="2"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,9 @@ APP="Alpine-Vaultwarden"
 | 
			
		||||
var_tags="alpine;vault"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="256"
 | 
			
		||||
var_disk="0.3"
 | 
			
		||||
var_disk="0.5"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ var_disk="0.3"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="256"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="0"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="0.1"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								ct/baikal.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								ct/baikal.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
#!/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://sabre.io/baikal/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Baikal"
 | 
			
		||||
var_tags="Dav"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/baikal ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/sabre-io/Baikal/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
  if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
 | 
			
		||||
    msg_info "Stopping Service"
 | 
			
		||||
    systemctl stop apache2
 | 
			
		||||
    msg_ok "Stopped Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    cd /opt
 | 
			
		||||
    wget -q "https://github.com/sabre-io/baikal/releases/download/${RELEASE}/baikal-${RELEASE}.zip"
 | 
			
		||||
    mv /opt/baikal /opt/baikal-backup
 | 
			
		||||
    unzip -o -q "baikal-${RELEASE}.zip"
 | 
			
		||||
    cp -r /opt/baikal-backup/config/baikal.yaml /opt/baikal/config/
 | 
			
		||||
    cp -r /opt/baikal-backup/Specific/ /opt/baikal/
 | 
			
		||||
    chown -R www-data:www-data /opt/baikal/
 | 
			
		||||
    chmod -R 755 /opt/baikal/
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Service"
 | 
			
		||||
    systemctl start apache2
 | 
			
		||||
    msg_ok "Started Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning up"
 | 
			
		||||
    rm -rf "/opt/baikal-${RELEASE}.zip"
 | 
			
		||||
    rm -rf /opt/baikal-backup
 | 
			
		||||
    msg_ok "Cleaned"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
@@ -73,7 +73,7 @@ function update_script() {
 | 
			
		||||
    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
 | 
			
		||||
    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"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								ct/elementsynapse.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								ct/elementsynapse.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
#!/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: tremor021
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/element-hq/synapse
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Element Synapse"
 | 
			
		||||
var_tags="server"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core 
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /etc/matrix-synapse ]]; 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
 | 
			
		||||
    msg_ok "Updated $APP LXC"
 | 
			
		||||
    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}:8008${CL}"
 | 
			
		||||
@@ -5,9 +5,9 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Grist"
 | 
			
		||||
var_tags="database;spreadsheet"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="3072"
 | 
			
		||||
var_disk="6"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
    ______     __              __    
 | 
			
		||||
   / ____/__  / /_____  ____  / /____
 | 
			
		||||
  /___ \/ _ \/ __/ __ \/ __ \/ / ___/
 | 
			
		||||
 ____/ /  __/ /_/ /_/ / /_/ / (__  ) 
 | 
			
		||||
/_____/\___/\__/\____/\____/_/____/  
 | 
			
		||||
                                     
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/alpine-it-tools
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/alpine-it-tools
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ___    __      _                  __________  ______            __    
 | 
			
		||||
   /   |  / /___  (_)___  ___        /  _/_  __/ /_  __/___  ____  / /____
 | 
			
		||||
  / /| | / / __ \/ / __ \/ _ \______ / /  / /_____/ / / __ \/ __ \/ / ___/
 | 
			
		||||
 / ___ |/ / /_/ / / / / /  __/_____// /  / /_____/ / / /_/ / /_/ / (__  ) 
 | 
			
		||||
/_/  |_/_/ .___/_/_/ /_/\___/     /___/ /_/     /_/  \____/\____/_/____/  
 | 
			
		||||
        /_/                                                               
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/baikal
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/baikal
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ____        _ __         __
 | 
			
		||||
   / __ )____ _(_) /______ _/ /
 | 
			
		||||
  / __  / __ `/ / //_/ __ `/ / 
 | 
			
		||||
 / /_/ / /_/ / / ,< / /_/ / /  
 | 
			
		||||
/_____/\__,_/_/_/|_|\__,_/_/   
 | 
			
		||||
                               
 | 
			
		||||
							
								
								
									
										12
									
								
								ct/headers/elementsynapse
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								ct/headers/elementsynapse
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
    ________                          __ 
 | 
			
		||||
   / ____/ /__  ____ ___  ___  ____  / /_
 | 
			
		||||
  / __/ / / _ \/ __ `__ \/ _ \/ __ \/ __/
 | 
			
		||||
 / /___/ /  __/ / / / / /  __/ / / / /_  
 | 
			
		||||
/_____/_/\___/_/ /_/ /_/\___/_/ /_/\__/  
 | 
			
		||||
                                         
 | 
			
		||||
   _____                                 
 | 
			
		||||
  / ___/__  ______  ____ _____  ________ 
 | 
			
		||||
  \__ \/ / / / __ \/ __ `/ __ \/ ___/ _ \
 | 
			
		||||
 ___/ / /_/ / / / / /_/ / /_/ (__  )  __/
 | 
			
		||||
/____/\__, /_/ /_/\__,_/ .___/____/\___/ 
 | 
			
		||||
     /____/           /_/                
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/mattermost
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/mattermost
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    __  ___      __  __                                 __ 
 | 
			
		||||
   /  |/  /___ _/ /_/ /____  _________ ___  ____  _____/ /_
 | 
			
		||||
  / /|_/ / __ `/ __/ __/ _ \/ ___/ __ `__ \/ __ \/ ___/ __/
 | 
			
		||||
 / /  / / /_/ / /_/ /_/  __/ /  / / / / / / /_/ (__  ) /_  
 | 
			
		||||
/_/  /_/\__,_/\__/\__/\___/_/  /_/ /_/ /_/\____/____/\__/  
 | 
			
		||||
                                                           
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/monica
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/monica
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    __  ___            _           
 | 
			
		||||
   /  |/  /___  ____  (_)________ _
 | 
			
		||||
  / /|_/ / __ \/ __ \/ / ___/ __ `/
 | 
			
		||||
 / /  / / /_/ / / / / / /__/ /_/ / 
 | 
			
		||||
/_/  /_/\____/_/ /_/_/\___/\__,_/  
 | 
			
		||||
                                   
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/nodebb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/nodebb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    _   __          __     ____  ____ 
 | 
			
		||||
   / | / /___  ____/ /__  / __ )/ __ )
 | 
			
		||||
  /  |/ / __ \/ __  / _ \/ __  / __  |
 | 
			
		||||
 / /|  / /_/ / /_/ /  __/ /_/ / /_/ / 
 | 
			
		||||
/_/ |_/\____/\__,_/\___/_____/_____/  
 | 
			
		||||
                                      
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/paymenter
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/paymenter
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ____                                   __           
 | 
			
		||||
   / __ \____ ___  ______ ___  ___  ____  / /____  _____
 | 
			
		||||
  / /_/ / __ `/ / / / __ `__ \/ _ \/ __ \/ __/ _ \/ ___/
 | 
			
		||||
 / ____/ /_/ / /_/ / / / / / /  __/ / / / /_/  __/ /    
 | 
			
		||||
/_/    \__,_/\__, /_/ /_/ /_/\___/_/ /_/\__/\___/_/     
 | 
			
		||||
            /____/                                      
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
    ____  _______      ______            __    
 | 
			
		||||
   / __ \/ __/__ \ ___/_  __/___  ____  / /____
 | 
			
		||||
  / /_/ / /_ __/ // _ \/ / / __ \/ __ \/ / ___/
 | 
			
		||||
 / ____/ __// __//  __/ / / /_/ / /_/ / (__  ) 
 | 
			
		||||
/_/   /_/  /____/\___/_/  \____/\____/_/____/  
 | 
			
		||||
                                               
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/pocketid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/pocketid
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ____             __        __  ________ 
 | 
			
		||||
   / __ \____  _____/ /_____  / /_/  _/ __ \
 | 
			
		||||
  / /_/ / __ \/ ___/ //_/ _ \/ __// // / / /
 | 
			
		||||
 / ____/ /_/ / /__/ ,< /  __/ /__/ // /_/ / 
 | 
			
		||||
/_/    \____/\___/_/|_|\___/\__/___/_____/  
 | 
			
		||||
                                            
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/privatebin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/privatebin
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ____       _             __       ____  _     
 | 
			
		||||
   / __ \_____(_)   ______ _/ /____  / __ )(_)___ 
 | 
			
		||||
  / /_/ / ___/ / | / / __ `/ __/ _ \/ __  / / __ \
 | 
			
		||||
 / ____/ /  / /| |/ / /_/ / /_/  __/ /_/ / / / / /
 | 
			
		||||
/_/   /_/  /_/ |___/\__,_/\__/\___/_____/_/_/ /_/ 
 | 
			
		||||
                                                  
 | 
			
		||||
							
								
								
									
										12
									
								
								ct/headers/prometheus-pve-exporter
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								ct/headers/prometheus-pve-exporter
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
    ____                            __  __                          ____ 
 | 
			
		||||
   / __ \_________  ____ ___  ___  / /_/ /_  ___  __  _______      / __ \
 | 
			
		||||
  / /_/ / ___/ __ \/ __ `__ \/ _ \/ __/ __ \/ _ \/ / / / ___/_____/ /_/ /
 | 
			
		||||
 / ____/ /  / /_/ / / / / / /  __/ /_/ / / /  __/ /_/ (__  )_____/ ____/ 
 | 
			
		||||
/_/   /_/   \____/_/ /_/ /_/\___/\__/_/ /_/\___/\__,_/____/     /_/      
 | 
			
		||||
                                                                         
 | 
			
		||||
 _    ________     ______                      __           
 | 
			
		||||
| |  / / ____/    / ____/  ______  ____  _____/ /____  _____
 | 
			
		||||
| | / / __/______/ __/ | |/_/ __ \/ __ \/ ___/ __/ _ \/ ___/
 | 
			
		||||
| |/ / /__/_____/ /____>  </ /_/ / /_/ / /  / /_/  __/ /    
 | 
			
		||||
|___/_____/    /_____/_/|_/ .___/\____/_/   \__/\___/_/     
 | 
			
		||||
                         /_/                                
 | 
			
		||||
@@ -10,7 +10,7 @@ APP="Hoarder"
 | 
			
		||||
var_tags="bookmark"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="4096"
 | 
			
		||||
var_disk="8"
 | 
			
		||||
var_disk="10"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
@@ -39,6 +39,9 @@ function update_script() {
 | 
			
		||||
    systemctl stop hoarder-web hoarder-workers hoarder-browser
 | 
			
		||||
    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
 | 
			
		||||
    fi
 | 
			
		||||
    cd /opt
 | 
			
		||||
    if [[ -f /opt/hoarder/.env ]] && [[ ! -f /etc/hoarder/hoarder.env ]]; then
 | 
			
		||||
      mkdir -p /etc/hoarder
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								ct/homarr.sh
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								ct/homarr.sh
									
									
									
									
									
								
							@@ -9,7 +9,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
APP="Homarr"
 | 
			
		||||
var_tags="arr;dashboard"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_ram="4096"
 | 
			
		||||
var_disk="8"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
@@ -32,46 +32,47 @@ function update_script() {
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/ajnart/homarr/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
if [[ -f /opt/homarr/database/db.sqlite ]]; then
 | 
			
		||||
    msg_error "Old Homarr detected due to existing database file (/opt/homarr/database/db.sqlite)."
 | 
			
		||||
    msg_error "Update not supported. Refer to:"
 | 
			
		||||
    msg_error " - https://github.com/community-scripts/ProxmoxVE/discussions/1551"
 | 
			
		||||
    msg_error " - https://homarr.dev/docs/getting-started/after-the-installation/#importing-a-zip-from-version-before-100"
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/homarr-labs/homarr/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 homarr
 | 
			
		||||
    msg_ok "Services Stopped"
 | 
			
		||||
 | 
			
		||||
    msg_info "Backing up Data"
 | 
			
		||||
    msg_info "Backup Data"
 | 
			
		||||
    mkdir -p /opt/homarr-data-backup
 | 
			
		||||
    cp /opt/homarr/.env /opt/homarr-data-backup/.env
 | 
			
		||||
    cp /opt/homarr/database/db.sqlite /opt/homarr-data-backup/db.sqlite
 | 
			
		||||
    cp -r /opt/homarr/data/configs /opt/homarr-data-backup/configs
 | 
			
		||||
    msg_ok "Backed up Data"
 | 
			
		||||
    msg_ok "Backup Data"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to ${RELEASE}"
 | 
			
		||||
    wget -q "https://github.com/ajnart/homarr/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    wget -q "https://github.com/homarr-labs/homarr/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
    unzip -q v${RELEASE}.zip
 | 
			
		||||
    rm -rf v${RELEASE}.zip
 | 
			
		||||
    rm -rf /opt/homarr
 | 
			
		||||
    mv homarr-${RELEASE} /opt/homarr
 | 
			
		||||
    mv /opt/homarr-data-backup/.env /opt/homarr/.env
 | 
			
		||||
    cd /opt/homarr
 | 
			
		||||
    yarn install &>/dev/null
 | 
			
		||||
    yarn build &>/dev/null
 | 
			
		||||
    pnpm install &>/dev/null
 | 
			
		||||
    pnpm run db:migration:sqlite:run &>/dev/null
 | 
			
		||||
    pnpm build &>/dev/null
 | 
			
		||||
    mkdir build
 | 
			
		||||
    cp ./node_modules/better-sqlite3/build/Release/better_sqlite3.node ./build/better_sqlite3.node
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Restoring Data"
 | 
			
		||||
    rm -rf /opt/homarr/data/configs
 | 
			
		||||
    mv /opt/homarr-data-backup/configs /opt/homarr/data/configs
 | 
			
		||||
    mv /opt/homarr-data-backup/db.sqlite /opt/homarr/database/db.sqlite
 | 
			
		||||
    yarn db:migrate &>/dev/null
 | 
			
		||||
    rm -rf /opt/homarr-data-backup
 | 
			
		||||
    msg_ok "Restored Data"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Services"
 | 
			
		||||
    systemctl start homarr
 | 
			
		||||
    msg_ok "Started Services"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
@@ -83,4 +84,4 @@ description
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ function update_script() {
 | 
			
		||||
     msg_info "Updating ${APP} LXC"
 | 
			
		||||
     apt-get update &>/dev/null
 | 
			
		||||
     apt-get -y upgrade &>/dev/null
 | 
			
		||||
     apt-get --with-new-pkgs upgrade jellyfin jellyfin-server &>/dev/null
 | 
			
		||||
     apt-get -y --with-new-pkgs upgrade jellyfin jellyfin-server &>/dev/null
 | 
			
		||||
     msg_ok "Updated ${APP} LXC"
 | 
			
		||||
     exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								ct/mattermost.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								ct/mattermost.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
#!/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: Kaedon Cleland-Host (dracentis)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://mattermost.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Mattermost"
 | 
			
		||||
var_tags="collaboration"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="8"
 | 
			
		||||
var_os="ubuntu"
 | 
			
		||||
var_version="24.04"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -f /etc/apt/sources.list.d/mattermost.list ]]; 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
 | 
			
		||||
    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}:8065${CL}"
 | 
			
		||||
							
								
								
									
										81
									
								
								ct/monica.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								ct/monica.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
#!/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://www.monicahq.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Monica"
 | 
			
		||||
var_tags="network"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="8"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/monica ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/monicahq/monica/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 apache2
 | 
			
		||||
    msg_ok "Stopped Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    cd /opt
 | 
			
		||||
    mv /opt/monica/ /opt/monica-backup
 | 
			
		||||
    wget -q "https://github.com/monicahq/monica/releases/download/v${RELEASE}/monica-v${RELEASE}.tar.bz2"
 | 
			
		||||
    tar -xjf "monica-v${RELEASE}.tar.bz2"
 | 
			
		||||
    mv "/opt/monica-v${RELEASE}" /opt/monica
 | 
			
		||||
    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
 | 
			
		||||
    chown -R www-data:www-data /opt/monica
 | 
			
		||||
    chmod -R 775 /opt/monica/storage
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Service"
 | 
			
		||||
    systemctl start apache2
 | 
			
		||||
    msg_ok "Started Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning up"
 | 
			
		||||
    rm -r "/opt/monica-v${RELEASE}.tar.bz2"
 | 
			
		||||
    rm -r /opt/monica-backup
 | 
			
		||||
    msg_ok "Cleaned"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
							
								
								
									
										63
									
								
								ct/nodebb.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								ct/nodebb.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: MickLesk (Canbiz)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="NodeBB"
 | 
			
		||||
var_tags="forum"
 | 
			
		||||
var_disk="10"
 | 
			
		||||
var_cpu="4"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_os="ubuntu"
 | 
			
		||||
var_version="24.04"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/nodebb ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/NodeBB/NodeBB/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 nodebb
 | 
			
		||||
    msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    cd /opt/nodebb
 | 
			
		||||
    ./nodebb upgrade >/dev/null 2>&1
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated ${APP} to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting ${APP}"
 | 
			
		||||
    systemctl start nodebb
 | 
			
		||||
    msg_ok "Started ${APP}"
 | 
			
		||||
    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}:4567${CL}"
 | 
			
		||||
@@ -45,5 +45,6 @@ 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} or ${TAB}${GATEWAY}${BGN}https://${IP}:8443${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using one of the following URLs:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8443${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								ct/paymenter.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								ct/paymenter.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
#!/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: Nícolas Pastorello (opastorello)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Paymenter"
 | 
			
		||||
var_tags="hosting;ecommerce;marketplace;"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="5"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
 | 
			
		||||
  if [[ ! -d /opt/paymenter ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/paymenter/paymenter/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_info "Updating ${APP} to ${RELEASE}"
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    cd /opt/paymenter
 | 
			
		||||
    php artisan p:upgrade --no-interaction &>/dev/null
 | 
			
		||||
    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}:80${CL}"
 | 
			
		||||
@@ -1,81 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: TheRealVira
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://pf2etools.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Pf2eTools"
 | 
			
		||||
var_tags="wiki"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="6"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    # Check if installation is present | -f for file, -d for folder
 | 
			
		||||
    if [[ ! -d "/opt/${APP}" ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/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
 | 
			
		||||
        # Crawling the new version and checking whether an update is required
 | 
			
		||||
        msg_info "Updating System"
 | 
			
		||||
        apt-get update &>/dev/null
 | 
			
		||||
        apt-get -y upgrade &>/dev/null
 | 
			
		||||
        msg_ok "Updated System"
 | 
			
		||||
 | 
			
		||||
        # Execute Update
 | 
			
		||||
        msg_info "Updating ${APP}"
 | 
			
		||||
        cd /opt
 | 
			
		||||
        wget -q "https://github.com/Pf2eToolsOrg/Pf2eTools/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
        unzip -q ${RELEASE}.zip
 | 
			
		||||
        rm -rf "/opt/${APP}"
 | 
			
		||||
        mv ${APP}-${RELEASE:1} /opt/${APP}
 | 
			
		||||
        cd /opt/Pf2eTools
 | 
			
		||||
        $STD npm install
 | 
			
		||||
        $STD npm run build
 | 
			
		||||
        echo "${RELEASE}" >"/opt/${APP}_version.txt"
 | 
			
		||||
        msg_ok "Updated ${APP}"
 | 
			
		||||
 | 
			
		||||
        chown -R www-data: "/opt/${APP}"
 | 
			
		||||
        chmod -R 755 "/opt/${APP}"
 | 
			
		||||
 | 
			
		||||
        # Cleaning up
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -rf /opt/${RELEASE}.zip
 | 
			
		||||
        $STD apt-get -y autoremove
 | 
			
		||||
        $STD apt-get -y autoclean
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${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}${CL}"
 | 
			
		||||
@@ -32,30 +32,42 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Stopping Pingvin Share"
 | 
			
		||||
    systemctl stop pm2-root.service
 | 
			
		||||
    msg_ok "Stopped Pingvin Share"
 | 
			
		||||
   
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/stonith404/pingvin-share/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
    if [[ ! -f /opt/$pingvin_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/pingvin_version.txt)" ]]; then
 | 
			
		||||
      
 | 
			
		||||
      msg_info "Stopping Pingvin Share"
 | 
			
		||||
      systemctl stop pm2-root.service
 | 
			
		||||
      msg_ok "Stopped Pingvin Share"
 | 
			
		||||
      
 | 
			
		||||
      msg_info "Updating Pingvin Share to v${RELEASE}"
 | 
			
		||||
      cd /opt
 | 
			
		||||
      wget -q "https://github.com/stonith404/pingvin-share/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
      unzip -q v${RELEASE}.zip
 | 
			
		||||
      mv pingvin-share-${RELEASE} /opt/pingvin-share  
 | 
			
		||||
      cd /opt/pingvin-share
 | 
			
		||||
      cd backend
 | 
			
		||||
      npm install &>/dev/null
 | 
			
		||||
      npm run build &>/dev/null
 | 
			
		||||
      cd ../frontend
 | 
			
		||||
      npm install &>/dev/null
 | 
			
		||||
      npm run build &>/dev/null
 | 
			
		||||
      echo "${RELEASE}" >"/opt/pingvin_version.txt"
 | 
			
		||||
      rm -rf /opt/v${RELEASE}.zip
 | 
			
		||||
      msg_ok "Updated Pingvin Share to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating Pingvin Share"
 | 
			
		||||
    cd /opt/pingvin-share
 | 
			
		||||
    git fetch --tags
 | 
			
		||||
    git checkout $(git describe --tags $(git rev-list --tags --max-count=1)) &>/dev/null
 | 
			
		||||
    cd backend
 | 
			
		||||
    npm install &>/dev/null
 | 
			
		||||
    npm run build &>/dev/null
 | 
			
		||||
    cd ../frontend
 | 
			
		||||
    npm install &>/dev/null
 | 
			
		||||
    npm run build &>/dev/null
 | 
			
		||||
    msg_ok "Updated Pingvin Share"
 | 
			
		||||
      msg_info "Starting Pingvin Share"
 | 
			
		||||
      systemctl start pm2-root.service
 | 
			
		||||
      msg_ok "Started Pingvin Share"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Pingvin Share"
 | 
			
		||||
    systemctl start pm2-root.service
 | 
			
		||||
    msg_ok "Started Pingvin Share"
 | 
			
		||||
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
    exit
 | 
			
		||||
      msg_ok "Updated Successfully"
 | 
			
		||||
      exit
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. Pingvin Share is already at v${RELEASE}."
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
@@ -63,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}:3000${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								ct/pocketid.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										95
									
								
								ct/pocketid.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
#!/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: Snarkenfaugister
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/stonith404/pocket-id
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="PocketID"
 | 
			
		||||
TAGS="identity-provider"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    if [[ ! -d /opt/pocket-id ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    RELEASE=$(curl -fsSL https://api.github.com/repos/stonith404/pocket-id/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 "Updating $APP"
 | 
			
		||||
 | 
			
		||||
        msg_info "Stopping $APP"
 | 
			
		||||
        systemctl stop pocketid-backend.service
 | 
			
		||||
        systemctl stop pocketid-frontend.service
 | 
			
		||||
        systemctl stop caddy.service
 | 
			
		||||
        msg_ok "Stopped $APP"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating $APP to v${RELEASE}"
 | 
			
		||||
        cd /opt
 | 
			
		||||
        cp -r /opt/pocket-id/backend/data /opt/data
 | 
			
		||||
        cp /opt/pocket-id/backend/.env /opt/backend.env
 | 
			
		||||
        cp /opt/pocket-id/frontend/.env /opt/frontend.env
 | 
			
		||||
        rm -r /opt/pocket-id
 | 
			
		||||
        wget -q "https://github.com/stonith404/pocket-id/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
        unzip -q v${RELEASE}.zip
 | 
			
		||||
        mv pocket-id-${RELEASE} /opt/pocket-id
 | 
			
		||||
        mv /opt/data /opt/pocket-id/backend/data
 | 
			
		||||
        mv /opt/backend.env /opt/pocket-id/backend/.env 
 | 
			
		||||
        mv /opt/frontend.env /opt/pocket-id/frontend/.env 
 | 
			
		||||
 | 
			
		||||
        cd /opt/pocket-id/backend/cmd
 | 
			
		||||
        go build -o ../pocket-id-backend
 | 
			
		||||
        cd ../../frontend
 | 
			
		||||
        npm install
 | 
			
		||||
        npm run build
 | 
			
		||||
        msg_ok "Updated $APP to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting $APP"
 | 
			
		||||
        systemctl start pocketid-backend.service
 | 
			
		||||
        systemctl start pocketid-frontend.service
 | 
			
		||||
        systemctl start caddy.service
 | 
			
		||||
        sleep 2
 | 
			
		||||
        msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
        # Cleaning up
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -f /opt/v${RELEASE}.zip
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
        echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
        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} Configure your reverse proxy to point to:${BGN} ${IP}:80${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}https://{PUBLIC_URL}/login/setup${CL}"
 | 
			
		||||
							
								
								
									
										64
									
								
								ct/privatebin.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								ct/privatebin.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
#!/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: Nícolas Pastorello (opastorello)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="PrivateBin"
 | 
			
		||||
var_tags="paste;secure"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/privatebin ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/PrivateBin/PrivateBin/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
  if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    cp -f /opt/privatebin/cfg/conf.php /tmp/privatebin_conf.bak
 | 
			
		||||
    wget -q "https://github.com/PrivateBin/PrivateBin/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
    unzip -q ${RELEASE}.zip
 | 
			
		||||
    rm -rf /opt/privatebin/*
 | 
			
		||||
    mv PrivateBin-${RELEASE}/* /opt/privatebin/
 | 
			
		||||
    mv /tmp/privatebin_conf.bak /opt/privatebin/cfg/conf.php
 | 
			
		||||
    chown -R www-data:www-data /opt/privatebin
 | 
			
		||||
    chmod -R 0755 /opt/privatebin/data
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    rm -rf ${RELEASE}.zip PrivateBin-${RELEASE}
 | 
			
		||||
    systemctl reload nginx php8.2-fpm
 | 
			
		||||
    msg_ok "Updated ${APP} to v${RELEASE}"
 | 
			
		||||
  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}https://${IP}${CL}"
 | 
			
		||||
							
								
								
									
										57
									
								
								ct/prometheus-pve-exporter.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								ct/prometheus-pve-exporter.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
#!/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: Andy Grunwald (andygrunwald)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/prometheus-pve/prometheus-pve-exporter
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Prometheus-PVE-Exporter"
 | 
			
		||||
var_tags="monitoring"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="2"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -f /etc/systemd/system/prometheus-pve-exporter.service ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Stopping ${APP}"
 | 
			
		||||
    systemctl stop prometheus-pve-exporter
 | 
			
		||||
    msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP}"
 | 
			
		||||
    pip install prometheus-pve-exporter --default-timeout=300 --upgrade --root-user-action=ignore &>/dev/null
 | 
			
		||||
    msg_ok "Updated ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting ${APP}"
 | 
			
		||||
    systemctl start prometheus-pve-exporter
 | 
			
		||||
    msg_ok "Started ${APP}"
 | 
			
		||||
    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}:9221${CL}"
 | 
			
		||||
@@ -35,22 +35,22 @@ function update_script() {
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/TriliumNext/Notes/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
 | 
			
		||||
    msg_info "Stopping ${APP}"
 | 
			
		||||
    systemctl stop trilium.service
 | 
			
		||||
    systemctl stop trilium
 | 
			
		||||
    sleep 1
 | 
			
		||||
    msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating to ${RELEASE}"
 | 
			
		||||
    wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
 | 
			
		||||
    tar -xf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
 | 
			
		||||
    wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
 | 
			
		||||
    tar -xf TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
 | 
			
		||||
    cp -r trilium-linux-x64-server/* /opt/trilium/
 | 
			
		||||
    msg_ok "Updated to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning up"
 | 
			
		||||
    rm -rf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz trilium-linux-x64-server
 | 
			
		||||
    rm -rf TriliumNextNotes-linux-x64-${RELEASE}.tar.xz trilium-linux-x64-server
 | 
			
		||||
    msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting ${APP}"
 | 
			
		||||
    systemctl start trilium.service
 | 
			
		||||
    systemctl start trilium
 | 
			
		||||
    sleep 1
 | 
			
		||||
    msg_ok "Started ${APP}"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
@@ -64,4 +64,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}:8080${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,9 @@ start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
pct set $CTID -features fuse=1,nesting=1
 | 
			
		||||
pct reboot $CTID
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
 | 
			
		||||
 
 | 
			
		||||
@@ -39,24 +39,33 @@ function update_script() {
 | 
			
		||||
    msg_ok "Stopped Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Creating Backup"
 | 
			
		||||
    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
 | 
			
		||||
    mv /opt/zigbee2mqtt/data /opt/z2m_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
 | 
			
		||||
      mv /opt/zigbee2mqtt/data /opt/z2m_backup
 | 
			
		||||
    msg_ok "Backup Created"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    cd /opt
 | 
			
		||||
    wget -q "https://github.com/Koenkk/zigbee2mqtt/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
    unzip -q ${RELEASE}.zip
 | 
			
		||||
    mv zigbee2mqtt-${RELEASE} /opt/zigbee2mqtt
 | 
			
		||||
    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
 | 
			
		||||
      cd /opt
 | 
			
		||||
      wget -q "https://github.com/Koenkk/zigbee2mqtt/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
      unzip -q ${RELEASE}.zip
 | 
			
		||||
      rm -rf /opt/zigbee2mqtt
 | 
			
		||||
      mv zigbee2mqtt-${RELEASE} /opt/zigbee2mqtt
 | 
			
		||||
      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
 | 
			
		||||
    msg_ok "Updated Zigbee2MQTT"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Service"
 | 
			
		||||
    systemctl start zigbee2mqtt
 | 
			
		||||
      systemctl start zigbee2mqtt
 | 
			
		||||
    msg_ok "Started Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning up"
 | 
			
		||||
      rm -rf /opt/z2m_backup
 | 
			
		||||
      rm -rf /opt/${RELEASE}.zip
 | 
			
		||||
    msg_ok "Cleaned up"
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at v${RELEASE}."
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										99
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										99
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -23,6 +23,8 @@
 | 
			
		||||
        "@radix-ui/react-tabs": "^1.1.0",
 | 
			
		||||
        "@radix-ui/react-tooltip": "^1.1.2",
 | 
			
		||||
        "@vercel/analytics": "^1.2.2",
 | 
			
		||||
        "chart.js": "^4.4.1",
 | 
			
		||||
        "chartjs-plugin-datalabels": "^2.2.0",
 | 
			
		||||
        "class-variance-authority": "^0.7.0",
 | 
			
		||||
        "clsx": "^2.1.1",
 | 
			
		||||
        "cmdk": "^1.0.0",
 | 
			
		||||
@@ -37,7 +39,9 @@
 | 
			
		||||
        "pocketbase": "^0.21.4",
 | 
			
		||||
        "prettier-plugin-organize-imports": "^4.1.0",
 | 
			
		||||
        "react": "19.0.0-rc-02c0e824-20241028",
 | 
			
		||||
        "react-chartjs-2": "^5.3.0",
 | 
			
		||||
        "react-code-blocks": "^0.1.6",
 | 
			
		||||
        "react-datepicker": "^7.6.0",
 | 
			
		||||
        "react-day-picker": "8.10.1",
 | 
			
		||||
        "react-dom": "19.0.0-rc-02c0e824-20241028",
 | 
			
		||||
        "react-icons": "^5.1.0",
 | 
			
		||||
@@ -1083,9 +1087,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@floating-ui/utils": {
 | 
			
		||||
      "version": "0.2.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
 | 
			
		||||
      "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
 | 
			
		||||
      "version": "0.2.9",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
 | 
			
		||||
      "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@humanfs/core": {
 | 
			
		||||
@@ -1572,6 +1576,12 @@
 | 
			
		||||
        "@jridgewell/sourcemap-codec": "^1.4.14"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@kurkle/color": {
 | 
			
		||||
      "version": "0.3.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
 | 
			
		||||
      "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@next/env": {
 | 
			
		||||
      "version": "15.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.3.tgz",
 | 
			
		||||
@@ -3194,7 +3204,7 @@
 | 
			
		||||
      "version": "19.0.0-rc.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/types-react/-/types-react-19.0.0-rc.1.tgz",
 | 
			
		||||
      "integrity": "sha512-RshndUfqTW6K3STLPis8BtAYCGOkMbtvYsi90gmVNDZBXUyUc5juf2PE9LfS/JmOlUIRO8cWTS/1MTnmhjDqyQ==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "csstype": "^3.0.2"
 | 
			
		||||
      }
 | 
			
		||||
@@ -3204,7 +3214,7 @@
 | 
			
		||||
      "version": "19.0.0-rc.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/types-react-dom/-/types-react-dom-19.0.0-rc.1.tgz",
 | 
			
		||||
      "integrity": "sha512-VSLZJl8VXCD0fAWp7DUTFUDCcZ8DVXOQmjhJMD03odgeFmu14ZQJHCXeETm3BEAhJqfgJaFkLnGkQv88sRx0fQ==",
 | 
			
		||||
      "devOptional": true,
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@types/react": "*"
 | 
			
		||||
      }
 | 
			
		||||
@@ -4152,6 +4162,27 @@
 | 
			
		||||
        "url": "https://github.com/sponsors/wooorm"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/chart.js": {
 | 
			
		||||
      "version": "4.4.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz",
 | 
			
		||||
      "integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@kurkle/color": "^0.3.0"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "pnpm": ">=8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/chartjs-plugin-datalabels": {
 | 
			
		||||
      "version": "2.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "chart.js": ">=3.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/check-error": {
 | 
			
		||||
      "version": "2.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
 | 
			
		||||
@@ -7774,6 +7805,7 @@
 | 
			
		||||
      "version": "3.3.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
 | 
			
		||||
      "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "prettier": "bin/prettier.cjs"
 | 
			
		||||
@@ -7999,6 +8031,16 @@
 | 
			
		||||
        "node": ">=0.10.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-chartjs-2": {
 | 
			
		||||
      "version": "5.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "chart.js": "^4.1.1",
 | 
			
		||||
        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-code-blocks": {
 | 
			
		||||
      "version": "0.1.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-code-blocks/-/react-code-blocks-0.1.6.tgz",
 | 
			
		||||
@@ -8017,6 +8059,46 @@
 | 
			
		||||
        "react": ">=16"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-datepicker": {
 | 
			
		||||
      "version": "7.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.6.0.tgz",
 | 
			
		||||
      "integrity": "sha512-9cQH6Z/qa4LrGhzdc3XoHbhrxNcMi9MKjZmYgF/1MNNaJwvdSjv3Xd+jjvrEEbKEf71ZgCA3n7fQbdwd70qCRw==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@floating-ui/react": "^0.27.0",
 | 
			
		||||
        "clsx": "^2.1.1",
 | 
			
		||||
        "date-fns": "^3.6.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
 | 
			
		||||
        "react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-datepicker/node_modules/@floating-ui/react": {
 | 
			
		||||
      "version": "0.27.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.3.tgz",
 | 
			
		||||
      "integrity": "sha512-CLHnes3ixIFFKVQDdICjel8muhFLOBdQH7fgtHNPY8UbCNqbeKZ262G7K66lGQOUQWWnYocf7ZbUsLJgGfsLHg==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@floating-ui/react-dom": "^2.1.2",
 | 
			
		||||
        "@floating-ui/utils": "^0.2.9",
 | 
			
		||||
        "tabbable": "^6.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": ">=17.0.0",
 | 
			
		||||
        "react-dom": ">=17.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-datepicker/node_modules/date-fns": {
 | 
			
		||||
      "version": "3.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
 | 
			
		||||
      "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
 | 
			
		||||
      "license": "MIT",
 | 
			
		||||
      "funding": {
 | 
			
		||||
        "type": "github",
 | 
			
		||||
        "url": "https://github.com/sponsors/kossnocorp"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-day-picker": {
 | 
			
		||||
      "version": "8.10.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
 | 
			
		||||
@@ -9055,6 +9137,12 @@
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tabbable": {
 | 
			
		||||
      "version": "6.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
 | 
			
		||||
      "license": "MIT"
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/tailwind-merge": {
 | 
			
		||||
      "version": "2.5.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
 | 
			
		||||
@@ -9420,6 +9508,7 @@
 | 
			
		||||
      "version": "5.6.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
 | 
			
		||||
      "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "license": "Apache-2.0",
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "tsc": "bin/tsc",
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,8 @@
 | 
			
		||||
    "@radix-ui/react-tabs": "^1.1.0",
 | 
			
		||||
    "@radix-ui/react-tooltip": "^1.1.2",
 | 
			
		||||
    "@vercel/analytics": "^1.2.2",
 | 
			
		||||
    "chart.js": "^4.4.1",
 | 
			
		||||
    "chartjs-plugin-datalabels": "^2.2.0",
 | 
			
		||||
    "class-variance-authority": "^0.7.0",
 | 
			
		||||
    "clsx": "^2.1.1",
 | 
			
		||||
    "cmdk": "^1.0.0",
 | 
			
		||||
@@ -48,7 +50,9 @@
 | 
			
		||||
    "pocketbase": "^0.21.4",
 | 
			
		||||
    "prettier-plugin-organize-imports": "^4.1.0",
 | 
			
		||||
    "react": "19.0.0-rc-02c0e824-20241028",
 | 
			
		||||
    "react-chartjs-2": "^5.3.0",
 | 
			
		||||
    "react-code-blocks": "^0.1.6",
 | 
			
		||||
    "react-datepicker": "^7.6.0",
 | 
			
		||||
    "react-day-picker": "8.10.1",
 | 
			
		||||
    "react-dom": "19.0.0-rc-02c0e824-20241028",
 | 
			
		||||
    "react-icons": "^5.1.0",
 | 
			
		||||
@@ -63,20 +67,20 @@
 | 
			
		||||
    "@testing-library/dom": "^10.4.0",
 | 
			
		||||
    "@testing-library/react": "^16.0.1",
 | 
			
		||||
    "@types/node": "^22",
 | 
			
		||||
    "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
 | 
			
		||||
    "@types/react": "npm:types-react@19.0.0-rc.1",
 | 
			
		||||
    "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^8.8.1",
 | 
			
		||||
    "@typescript-eslint/parser": "^8.8.1",
 | 
			
		||||
    "@vitejs/plugin-react": "^4.3.4",
 | 
			
		||||
    "eslint-config-next": "15.0.2",
 | 
			
		||||
    "eslint": "^9.13.0",
 | 
			
		||||
    "eslint-config-next": "15.0.2",
 | 
			
		||||
    "jsdom": "^25.0.1",
 | 
			
		||||
    "postcss": "^8",
 | 
			
		||||
    "prettier-plugin-tailwindcss": "^0.6.5",
 | 
			
		||||
    "prettier": "^3.2.5",
 | 
			
		||||
    "prettier-plugin-tailwindcss": "^0.6.5",
 | 
			
		||||
    "tailwindcss": "^3.4.9",
 | 
			
		||||
    "tailwindcss-animate": "^1.0.7",
 | 
			
		||||
    "tailwindcss-animated": "^1.1.2",
 | 
			
		||||
    "tailwindcss": "^3.4.9",
 | 
			
		||||
    "typescript": "^5",
 | 
			
		||||
    "vite-tsconfig-paths": "^5.1.3",
 | 
			
		||||
    "vitest": "^2.1.6"
 | 
			
		||||
 
 | 
			
		||||
@@ -4,15 +4,33 @@ import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { Card, CardContent } from "@/components/ui/card";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import { Badge } from "@/components/ui/badge";
 | 
			
		||||
import { ChevronLeft, ChevronRight } from "lucide-react";
 | 
			
		||||
import { Category } from "@/lib/types";
 | 
			
		||||
 | 
			
		||||
const defaultLogo = "/default-logo.png"; // Fallback logo path
 | 
			
		||||
 | 
			
		||||
const MAX_DESCRIPTION_LENGTH = 100; // Set max length for description
 | 
			
		||||
const MAX_LOGOS = 5; // Max logos to display at once
 | 
			
		||||
 | 
			
		||||
const formattedBadge = (type: string) => {
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case "vm":
 | 
			
		||||
      return <Badge className="text-blue-500/75 border-blue-500/75 badge">VM</Badge>;
 | 
			
		||||
    case "ct":
 | 
			
		||||
      return (
 | 
			
		||||
        <Badge className="text-yellow-500/75 border-yellow-500/75 badge">LXC</Badge>
 | 
			
		||||
      );
 | 
			
		||||
    case "misc":
 | 
			
		||||
      return <Badge className="text-green-500/75 border-green-500/75 badge">MISC</Badge>;
 | 
			
		||||
  }
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CategoryView = () => {
 | 
			
		||||
  const [categories, setCategories] = useState<Category[]>([]);
 | 
			
		||||
  const [selectedCategory, setSelectedCategory] = useState<Category | null>(null);
 | 
			
		||||
  const [selectedCategoryIndex, setSelectedCategoryIndex] = useState<number | null>(null);
 | 
			
		||||
  const [currentScripts, setCurrentScripts] = useState<any[]>([]);
 | 
			
		||||
  const [logoIndices, setLogoIndices] = useState<{ [key: string]: number }>({});
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
@@ -24,8 +42,14 @@ const CategoryView = () => {
 | 
			
		||||
          throw new Error("Failed to fetch categories");
 | 
			
		||||
        }
 | 
			
		||||
        const data = await response.json();
 | 
			
		||||
        console.log("Fetched categories:", data); // Debugging
 | 
			
		||||
        setCategories(data);
 | 
			
		||||
 | 
			
		||||
        // Initialize logo indices
 | 
			
		||||
        const initialLogoIndices: { [key: string]: number } = {};
 | 
			
		||||
        data.forEach((category: any) => {
 | 
			
		||||
          initialLogoIndices[category.name] = 0;
 | 
			
		||||
        });
 | 
			
		||||
        setLogoIndices(initialLogoIndices);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error("Error fetching categories:", error);
 | 
			
		||||
      }
 | 
			
		||||
@@ -34,91 +58,209 @@ const CategoryView = () => {
 | 
			
		||||
    fetchCategories();
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const handleCategoryClick = (category: Category) => {
 | 
			
		||||
    setSelectedCategory(category);
 | 
			
		||||
  const handleCategoryClick = (index: number) => {
 | 
			
		||||
    setSelectedCategoryIndex(index);
 | 
			
		||||
    setCurrentScripts(categories[index]?.scripts || []); // Update scripts for the selected category
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleBackClick = () => {
 | 
			
		||||
    setSelectedCategory(null);
 | 
			
		||||
    setSelectedCategoryIndex(null);
 | 
			
		||||
    setCurrentScripts([]); // Clear scripts when going back
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleScriptClick = (scriptSlug: string) => {
 | 
			
		||||
    router.push(`/scripts?id=${scriptSlug}`);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const navigateCategory = (direction: "prev" | "next") => {
 | 
			
		||||
    if (selectedCategoryIndex !== null) {
 | 
			
		||||
      const newIndex =
 | 
			
		||||
        direction === "prev"
 | 
			
		||||
          ? (selectedCategoryIndex - 1 + categories.length) % categories.length
 | 
			
		||||
          : (selectedCategoryIndex + 1) % categories.length;
 | 
			
		||||
      setSelectedCategoryIndex(newIndex);
 | 
			
		||||
      setCurrentScripts(categories[newIndex]?.scripts || []); // Update scripts for the new category
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const switchLogos = (categoryName: string, direction: "prev" | "next") => {
 | 
			
		||||
    setLogoIndices((prev) => {
 | 
			
		||||
      const currentIndex = prev[categoryName] || 0;
 | 
			
		||||
      const category = categories.find((cat) => cat.name === categoryName);
 | 
			
		||||
      if (!category || !category.scripts) return prev;
 | 
			
		||||
 | 
			
		||||
      const totalLogos = category.scripts.length;
 | 
			
		||||
      const newIndex =
 | 
			
		||||
        direction === "prev"
 | 
			
		||||
          ? (currentIndex - MAX_LOGOS + totalLogos) % totalLogos
 | 
			
		||||
          : (currentIndex + MAX_LOGOS) % totalLogos;
 | 
			
		||||
 | 
			
		||||
      return { ...prev, [categoryName]: newIndex };
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const truncateDescription = (text: string) => {
 | 
			
		||||
    return text.length > MAX_DESCRIPTION_LENGTH
 | 
			
		||||
      ? `${text.slice(0, MAX_DESCRIPTION_LENGTH)}...`
 | 
			
		||||
      : text;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const renderResources = (script: any) => {
 | 
			
		||||
    const cpu = script.install_methods[0]?.resources.cpu;
 | 
			
		||||
    const ram = script.install_methods[0]?.resources.ram;
 | 
			
		||||
    const hdd = script.install_methods[0]?.resources.hdd;
 | 
			
		||||
 | 
			
		||||
    const resourceParts = [];
 | 
			
		||||
    if (cpu) resourceParts.push(<span key="cpu"><b>CPU:</b> {cpu}vCPU</span>);
 | 
			
		||||
    if (ram) resourceParts.push(<span key="ram"><b>RAM:</b> {ram}MB</span>);
 | 
			
		||||
    if (hdd) resourceParts.push(<span key="hdd"><b>HDD:</b> {hdd}GB</span>);
 | 
			
		||||
 | 
			
		||||
    return resourceParts.length > 0 ? (
 | 
			
		||||
      <div className="text-sm text-gray-400">
 | 
			
		||||
        {resourceParts.map((part, index) => (
 | 
			
		||||
          <React.Fragment key={index}>
 | 
			
		||||
            {part}
 | 
			
		||||
            {index < resourceParts.length - 1 && " | "}
 | 
			
		||||
          </React.Fragment>
 | 
			
		||||
        ))}
 | 
			
		||||
      </div>
 | 
			
		||||
    ) : null;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="p-4 mt-20">
 | 
			
		||||
    <div className="p-6 mt-20">
 | 
			
		||||
      {categories.length === 0 && (
 | 
			
		||||
        <p className="text-center text-gray-500">No categories available. Please check the API endpoint.</p>
 | 
			
		||||
      )}
 | 
			
		||||
      {selectedCategory ? (
 | 
			
		||||
      {selectedCategoryIndex !== null ? (
 | 
			
		||||
        <div>
 | 
			
		||||
          <Button variant="default" onClick={handleBackClick} className="mb-4">
 | 
			
		||||
            Back to Categories
 | 
			
		||||
          </Button>
 | 
			
		||||
          <h2 className="text-xl font-semibold mb-4">{selectedCategory.name}</h2>
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
 | 
			
		||||
            {selectedCategory.scripts
 | 
			
		||||
          {/* Header with Navigation */}
 | 
			
		||||
          <div className="flex items-center justify-between mb-6">
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="ghost"
 | 
			
		||||
              onClick={() => navigateCategory("prev")}
 | 
			
		||||
              className="p-2 transition-transform duration-300 hover:scale-105"
 | 
			
		||||
            >
 | 
			
		||||
              <ChevronLeft className="h-6 w-6" />
 | 
			
		||||
            </Button>
 | 
			
		||||
            <h2 className="text-3xl font-semibold transition-opacity duration-300 hover:opacity-90">
 | 
			
		||||
              {categories[selectedCategoryIndex].name}
 | 
			
		||||
            </h2>
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="ghost"
 | 
			
		||||
              onClick={() => navigateCategory("next")}
 | 
			
		||||
              className="p-2 transition-transform duration-300 hover:scale-105"
 | 
			
		||||
            >
 | 
			
		||||
              <ChevronRight className="h-6 w-6" />
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          {/* Scripts Grid */}
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
 | 
			
		||||
            {currentScripts
 | 
			
		||||
              .sort((a, b) => a.name.localeCompare(b.name))
 | 
			
		||||
              .map((script) => (
 | 
			
		||||
                <Card key={script.name} className="p-4 cursor-pointer" onClick={() => handleScriptClick(script.slug)}>
 | 
			
		||||
                <Card
 | 
			
		||||
                  key={script.name}
 | 
			
		||||
                  className="p-4 cursor-pointer hover:shadow-md transition-shadow duration-300"
 | 
			
		||||
                  onClick={() => handleScriptClick(script.slug)}
 | 
			
		||||
                >
 | 
			
		||||
                  <CardContent className="flex flex-col gap-4">
 | 
			
		||||
                    <div className="flex items-center gap-4">
 | 
			
		||||
                      <img
 | 
			
		||||
                        src={script.logo || defaultLogo}
 | 
			
		||||
                        alt={script.name}
 | 
			
		||||
                        className="h-12 w-12 object-contain"
 | 
			
		||||
                      />
 | 
			
		||||
                      <div>
 | 
			
		||||
                        <h3 className="text-lg font-bold">{script.name}</h3>
 | 
			
		||||
                        <p className="text-sm text-gray-500"><b>Created at:</b> {script.date_created || "No date available"}</p>
 | 
			
		||||
                        <p className="text-sm text-gray-700">
 | 
			
		||||
                          {truncateDescription(script.description || "No description available.")}
 | 
			
		||||
                        </p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="text-sm text-gray-600">
 | 
			
		||||
                      <b>CPU:</b> {script.install_methods[0]?.resources.cpu || "N/A"}vCPU | <b>RAM:</b> {script.install_methods[0]?.resources.ram || "N/A"}MB | <b>HDD:</b> {script.install_methods[0]?.resources.hdd || "N/A"}GB
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <h3 className="text-lg font-bold script-text text-center hover:text-blue-600 transition-colors duration-300">
 | 
			
		||||
                      {script.name}
 | 
			
		||||
                    </h3>
 | 
			
		||||
                    <img
 | 
			
		||||
                      src={script.logo || defaultLogo}
 | 
			
		||||
                      alt={script.name || "Script logo"}
 | 
			
		||||
                      className="h-12 w-12 object-contain mx-auto"
 | 
			
		||||
                    />
 | 
			
		||||
                    <p className="text-sm text-gray-500 text-center">
 | 
			
		||||
                      <b>Created at:</b> {script.date_created || "No date available"}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p
 | 
			
		||||
                      className="text-sm text-gray-700 hover:text-gray-900 text-center transition-colors duration-300"
 | 
			
		||||
                      title={script.description || "No description available."}
 | 
			
		||||
                    >
 | 
			
		||||
                      {truncateDescription(script.description || "No description available.")}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    {renderResources(script)}
 | 
			
		||||
                  </CardContent>
 | 
			
		||||
                </Card>
 | 
			
		||||
              ))}
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          {/* Back to Categories Button */}
 | 
			
		||||
          <div className="mt-8 text-center">
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="default"
 | 
			
		||||
              onClick={handleBackClick}
 | 
			
		||||
              className="px-6 py-2 text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow-md transition-transform duration-300 hover:scale-105"
 | 
			
		||||
            >
 | 
			
		||||
              Back to Categories
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <div>
 | 
			
		||||
          <div className="flex justify-between items-center mb-6">
 | 
			
		||||
            <h1 className="text-2xl font-bold">Categories</h1>
 | 
			
		||||
          {/* Categories Grid */}
 | 
			
		||||
          <div className="flex justify-between items-center mb-8">
 | 
			
		||||
            <h1 className="text-3xl font-semibold mb-4">Categories</h1>
 | 
			
		||||
            <p className="text-sm text-gray-500">
 | 
			
		||||
              {categories.reduce((acc, cat) => acc + (cat.scripts?.length || 0), 0)} Total scripts
 | 
			
		||||
              {categories.reduce((total, category) => total + (category.scripts?.length || 0), 0)} Total scripts
 | 
			
		||||
            </p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
 | 
			
		||||
            {categories.map((category) => (
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8">
 | 
			
		||||
            {categories.map((category, index) => (
 | 
			
		||||
              <Card
 | 
			
		||||
                key={category.name}
 | 
			
		||||
                onClick={() => handleCategoryClick(category)}
 | 
			
		||||
                className="cursor-pointer hover:shadow-lg flex flex-col items-center justify-center"
 | 
			
		||||
                onClick={() => handleCategoryClick(index)}
 | 
			
		||||
                className="cursor-pointer hover:shadow-lg flex flex-col items-center justify-center py-6 transition-shadow duration-300"
 | 
			
		||||
              >
 | 
			
		||||
                <CardContent className="flex flex-col items-center">
 | 
			
		||||
                  <div className="flex flex-wrap justify-center gap-1 mb-2">
 | 
			
		||||
                    {category.scripts && category.scripts.slice(0, 4).map((script, index) => (
 | 
			
		||||
                      <img
 | 
			
		||||
                        key={index}
 | 
			
		||||
                        src={script.logo || defaultLogo}
 | 
			
		||||
                        alt={script.name || "Script logo"}
 | 
			
		||||
                        className="h-6 w-6 object-contain"
 | 
			
		||||
                      />
 | 
			
		||||
                    ))}
 | 
			
		||||
                  <h3 className="text-xl font-bold mb-4 category-title transition-colors duration-300 hover:text-blue-600">
 | 
			
		||||
                    {category.name}
 | 
			
		||||
                  </h3>
 | 
			
		||||
                  <div className="flex justify-center items-center gap-2 mb-4">
 | 
			
		||||
                    <Button
 | 
			
		||||
                      variant="ghost"
 | 
			
		||||
                      onClick={(e) => {
 | 
			
		||||
                        e.stopPropagation();
 | 
			
		||||
                        switchLogos(category.name, "prev");
 | 
			
		||||
                      }}
 | 
			
		||||
                      className="p-1 transition-transform duration-300 hover:scale-110"
 | 
			
		||||
                    >
 | 
			
		||||
                      <ChevronLeft className="h-4 w-4" />
 | 
			
		||||
                    </Button>
 | 
			
		||||
                    {category.scripts &&
 | 
			
		||||
                      category.scripts
 | 
			
		||||
                        .slice(logoIndices[category.name] || 0, (logoIndices[category.name] || 0) + MAX_LOGOS)
 | 
			
		||||
                        .map((script, i) => (
 | 
			
		||||
                          <div key={i} className="flex flex-col items-center">
 | 
			
		||||
                            <img
 | 
			
		||||
                              src={script.logo || defaultLogo}
 | 
			
		||||
                              alt={script.name || "Script logo"}
 | 
			
		||||
                              title={script.name}
 | 
			
		||||
                              className="h-8 w-8 object-contain cursor-pointer"
 | 
			
		||||
                              onClick={(e) => {
 | 
			
		||||
                                e.stopPropagation();
 | 
			
		||||
                                handleScriptClick(script.slug);
 | 
			
		||||
                              }}
 | 
			
		||||
                            />
 | 
			
		||||
                            {formattedBadge(script.type)}
 | 
			
		||||
                          </div>
 | 
			
		||||
                        ))}
 | 
			
		||||
                    <Button
 | 
			
		||||
                      variant="ghost"
 | 
			
		||||
                      onClick={(e) => {
 | 
			
		||||
                        e.stopPropagation();
 | 
			
		||||
                        switchLogos(category.name, "next");
 | 
			
		||||
                      }}
 | 
			
		||||
                      className="p-1 transition-transform duration-300 hover:scale-110"
 | 
			
		||||
                    >
 | 
			
		||||
                      <ChevronRight className="h-4 w-4" />
 | 
			
		||||
                    </Button>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <h3 className="text-lg font-bold mb-1">{category.name}</h3>
 | 
			
		||||
                  <p className="text-sm text-gray-500 text-center">
 | 
			
		||||
                  <p className="text-sm text-gray-400 text-center">
 | 
			
		||||
                    {(category as any).description || "No description available."}
 | 
			
		||||
                  </p>
 | 
			
		||||
                </CardContent>
 | 
			
		||||
@@ -131,4 +273,4 @@ const CategoryView = () => {
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default CategoryView;
 | 
			
		||||
export default CategoryView;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										308
									
								
								frontend/src/app/data/page.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										308
									
								
								frontend/src/app/data/page.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,308 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import DatePicker from 'react-datepicker';
 | 
			
		||||
import 'react-datepicker/dist/react-datepicker.css';
 | 
			
		||||
import ApplicationChart from "../../components/ApplicationChart";
 | 
			
		||||
 | 
			
		||||
interface DataModel {
 | 
			
		||||
  id: number;
 | 
			
		||||
  ct_type: number;
 | 
			
		||||
  disk_size: number;
 | 
			
		||||
  core_count: number;
 | 
			
		||||
  ram_size: number;
 | 
			
		||||
  verbose: string;
 | 
			
		||||
  os_type: string;
 | 
			
		||||
  os_version: string;
 | 
			
		||||
  hn: string;
 | 
			
		||||
  disableip6: string;
 | 
			
		||||
  ssh: string;
 | 
			
		||||
  tags: string;
 | 
			
		||||
  nsapp: string;
 | 
			
		||||
  created_at: string;
 | 
			
		||||
  method: string;
 | 
			
		||||
  pve_version: string;
 | 
			
		||||
  status: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const DataFetcher: React.FC = () => {
 | 
			
		||||
  const [data, setData] = useState<DataModel[]>([]);
 | 
			
		||||
  const [loading, setLoading] = useState<boolean>(true);
 | 
			
		||||
  const [error, setError] = useState<string | null>(null);
 | 
			
		||||
  const [searchQuery, setSearchQuery] = useState('');
 | 
			
		||||
  const [startDate, setStartDate] = useState<Date | null>(null);
 | 
			
		||||
  const [endDate, setEndDate] = useState<Date | null>(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 [interval, setIntervalTime] = useState<number>(10); // Default interval 10 seconds
 | 
			
		||||
  const [reloadInterval, setReloadInterval] = useState<NodeJS.Timeout | null>(null);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const fetchData = 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 result: DataModel[] = await response.json();
 | 
			
		||||
        setData(result);
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        setError((err as Error).message);
 | 
			
		||||
      } finally {
 | 
			
		||||
        setLoading(false);
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  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]);
 | 
			
		||||
 | 
			
		||||
  const requestSort = (key: keyof DataModel | null) => {
 | 
			
		||||
    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 {
 | 
			
		||||
      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();
 | 
			
		||||
    const month = date.getMonth() + 1;
 | 
			
		||||
    const day = date.getDate();
 | 
			
		||||
    const hours = String(date.getHours()).padStart(2, '0');
 | 
			
		||||
    const minutes = String(date.getMinutes()).padStart(2, '0');
 | 
			
		||||
    const timezoneOffset = dateString.slice(-6);
 | 
			
		||||
    return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleItemsPerPageChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
 | 
			
		||||
    setItemsPerPage(Number(event.target.value));
 | 
			
		||||
    setCurrentPage(1);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const paginatedData = sortedData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const storedInterval = localStorage.getItem('reloadInterval');
 | 
			
		||||
    if (storedInterval) {
 | 
			
		||||
      setIntervalTime(Number(storedInterval));
 | 
			
		||||
    }
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (interval <= 10) { 
 | 
			
		||||
      const newInterval = setInterval(() => {
 | 
			
		||||
        window.location.reload();
 | 
			
		||||
      }, 10000); 
 | 
			
		||||
 | 
			
		||||
     
 | 
			
		||||
      return () => clearInterval(newInterval);
 | 
			
		||||
    } else {
 | 
			
		||||
      const newInterval = setInterval(() => {
 | 
			
		||||
        window.location.reload();
 | 
			
		||||
      }, interval * 1000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }, [interval]); 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (interval > 0) {
 | 
			
		||||
      localStorage.setItem('reloadInterval', interval.toString());
 | 
			
		||||
    } else {
 | 
			
		||||
      localStorage.removeItem('reloadInterval');
 | 
			
		||||
    }
 | 
			
		||||
  }, [interval]);
 | 
			
		||||
 | 
			
		||||
  if (loading) return <p>Loading...</p>;
 | 
			
		||||
  if (error) return <p>Error: {error}</p>;
 | 
			
		||||
 | 
			
		||||
  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 (
 | 
			
		||||
    <div className="p-6 mt-20">
 | 
			
		||||
      <h1 className="text-2xl font-bold mb-4 text-center">Created LXCs</h1>
 | 
			
		||||
      <div className="mb-4 flex space-x-4">
 | 
			
		||||
        <div>
 | 
			
		||||
          <input
 | 
			
		||||
            type="text"
 | 
			
		||||
            placeholder="Search..."
 | 
			
		||||
            value={searchQuery}
 | 
			
		||||
            onChange={e => setSearchQuery(e.target.value)}
 | 
			
		||||
            className="p-2 border"
 | 
			
		||||
          />
 | 
			
		||||
          <label className="text-sm text-gray-600 mt-1 block">Search by keyword</label>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <DatePicker
 | 
			
		||||
            selected={startDate}
 | 
			
		||||
            onChange={date => setStartDate(date)}
 | 
			
		||||
            selectsStart
 | 
			
		||||
            startDate={startDate}
 | 
			
		||||
            endDate={endDate}
 | 
			
		||||
            placeholderText="Start date"
 | 
			
		||||
            className="p-2 border"
 | 
			
		||||
          />
 | 
			
		||||
          <label className="text-sm text-gray-600 mt-1 block">Set a start date</label>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div>
 | 
			
		||||
          <DatePicker
 | 
			
		||||
            selected={endDate}
 | 
			
		||||
            onChange={date => setEndDate(date)}
 | 
			
		||||
            selectsEnd
 | 
			
		||||
            startDate={startDate}
 | 
			
		||||
            endDate={endDate}
 | 
			
		||||
            placeholderText="End date"
 | 
			
		||||
            className="p-2 border"
 | 
			
		||||
          />
 | 
			
		||||
          <label className="text-sm text-gray-600 mt-1 block">Set a end date</label>
 | 
			
		||||
        </div>
 | 
			
		||||
     
 | 
			
		||||
      <div className="mb-4 flex space-x-4">
 | 
			
		||||
        <div>
 | 
			
		||||
          <input
 | 
			
		||||
            type="number"
 | 
			
		||||
            value={interval}
 | 
			
		||||
            onChange={e => setIntervalTime(Number(e.target.value))}
 | 
			
		||||
            className="p-2 border"
 | 
			
		||||
            placeholder="Interval (seconds)"
 | 
			
		||||
          />
 | 
			
		||||
          <label className="text-sm text-gray-600 mt-1 block">Set reload interval (0 for no reload)</label>
 | 
			
		||||
        </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <ApplicationChart data={filteredData} />
 | 
			
		||||
      <div className="mb-4 flex justify-between items-center">
 | 
			
		||||
        <p className="text-lg font-bold">{filteredData.length} results found</p>
 | 
			
		||||
        <p className="text-lg font">Status Legend: 🔄 installing {installingCounts} | ✔️ completetd {doneCounts} | ❌ failed {failedCounts} | ❓ unknown {unknownCounts}</p>
 | 
			
		||||
        <select value={itemsPerPage} onChange={handleItemsPerPageChange} className="p-2 border">
 | 
			
		||||
          <option value={25}>25</option>
 | 
			
		||||
          <option value={50}>50</option>
 | 
			
		||||
          <option value={100}>100</option>
 | 
			
		||||
          <option value={200}>200</option>
 | 
			
		||||
        </select>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="overflow-x-auto">
 | 
			
		||||
        <div className="overflow-y-auto lg:overflow-y-visible">
 | 
			
		||||
          <table className="min-w-full table-auto border-collapse">
 | 
			
		||||
            <thead>
 | 
			
		||||
              <tr>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('status')}>Status</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('nsapp')}>Application</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_type')}>OS</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_version')}>OS Version</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('disk_size')}>Disk Size</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('core_count')}>Core Count</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ram_size')}>RAM Size</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('method')}>Method</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('pve_version')}>PVE Version</th>
 | 
			
		||||
                <th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('created_at')}>Created At</th>
 | 
			
		||||
              </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
              {paginatedData.map((item, index) => (
 | 
			
		||||
                <tr key={index}>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">
 | 
			
		||||
                    {item.status === "done" ? (
 | 
			
		||||
                      "✔️"
 | 
			
		||||
                    ) : item.status === "failed" ? (
 | 
			
		||||
                      "❌"
 | 
			
		||||
                    ) : item.status === "installing" ? (
 | 
			
		||||
                      "🔄"  
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      item.status
 | 
			
		||||
                    )}
 | 
			
		||||
                  </td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.nsapp}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.os_type}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.os_version}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.disk_size}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.core_count}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.ram_size}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.method}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{item.pve_version}</td>
 | 
			
		||||
                  <td className="px-4 py-2 border-b">{formatDate(item.created_at)}</td>
 | 
			
		||||
                </tr>
 | 
			
		||||
              ))}
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="mt-4 flex justify-between items-center">
 | 
			
		||||
        <button
 | 
			
		||||
          onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
 | 
			
		||||
          disabled={currentPage === 1}
 | 
			
		||||
          className="p-2 border"
 | 
			
		||||
        >
 | 
			
		||||
          Previous
 | 
			
		||||
        </button>
 | 
			
		||||
        <span>Page {currentPage}</span>
 | 
			
		||||
        <button
 | 
			
		||||
          onClick={() => setCurrentPage(prev => (prev * itemsPerPage < sortedData.length ? prev + 1 : prev))}
 | 
			
		||||
          disabled={currentPage * itemsPerPage >= sortedData.length}
 | 
			
		||||
          className="p-2 border"
 | 
			
		||||
        >
 | 
			
		||||
          Next
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default DataFetcher;
 | 
			
		||||
@@ -35,8 +35,18 @@ export function LatestScripts({ items }: { items: Category[] }) {
 | 
			
		||||
 | 
			
		||||
  const latestScripts = useMemo(() => {
 | 
			
		||||
    if (!items) return [];
 | 
			
		||||
    
 | 
			
		||||
    const scripts = items.flatMap((category) => category.scripts || []);
 | 
			
		||||
    return scripts.sort(
 | 
			
		||||
 | 
			
		||||
    // Filter out duplicates by slug
 | 
			
		||||
    const uniqueScriptsMap = new Map<string, Script>();
 | 
			
		||||
    scripts.forEach((script) => {
 | 
			
		||||
      if (!uniqueScriptsMap.has(script.slug)) {
 | 
			
		||||
        uniqueScriptsMap.set(script.slug, script);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return Array.from(uniqueScriptsMap.values()).sort(
 | 
			
		||||
      (a, b) =>
 | 
			
		||||
        new Date(b.date_created).getTime() - new Date(a.date_created).getTime(),
 | 
			
		||||
    );
 | 
			
		||||
@@ -49,7 +59,7 @@ export function LatestScripts({ items }: { items: Category[] }) {
 | 
			
		||||
  const goToPreviousPage = () => {
 | 
			
		||||
    setPage((prevPage) => prevPage - 1);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  const startIndex = (page - 1) * ITEMS_PER_PAGE;
 | 
			
		||||
  const endIndex = page * ITEMS_PER_PAGE;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								frontend/src/components/ApplicationChart.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								frontend/src/components/ApplicationChart.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import {
 | 
			
		||||
  Dialog,
 | 
			
		||||
  DialogContent,
 | 
			
		||||
  DialogHeader,
 | 
			
		||||
  DialogTitle,
 | 
			
		||||
} from "@/components/ui/dialog";
 | 
			
		||||
import {
 | 
			
		||||
  Table,
 | 
			
		||||
  TableBody,
 | 
			
		||||
  TableCell,
 | 
			
		||||
  TableHead,
 | 
			
		||||
  TableHeader,
 | 
			
		||||
  TableRow,
 | 
			
		||||
} from "@/components/ui/table";
 | 
			
		||||
import {
 | 
			
		||||
  Tooltip,
 | 
			
		||||
  TooltipContent,
 | 
			
		||||
  TooltipProvider,
 | 
			
		||||
  TooltipTrigger,
 | 
			
		||||
} from "@/components/ui/tooltip";
 | 
			
		||||
import { Chart as ChartJS, ArcElement, Tooltip as ChartTooltip, Legend } from "chart.js";
 | 
			
		||||
import ChartDataLabels from "chartjs-plugin-datalabels";
 | 
			
		||||
import { BarChart3, PieChart } from "lucide-react";
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import { Pie } from "react-chartjs-2";
 | 
			
		||||
 | 
			
		||||
ChartJS.register(ArcElement, ChartTooltip, Legend, ChartDataLabels);
 | 
			
		||||
 | 
			
		||||
interface ApplicationChartProps {
 | 
			
		||||
  data: { nsapp: string }[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ITEMS_PER_PAGE = 20;
 | 
			
		||||
const CHART_COLORS = [
 | 
			
		||||
  "#ff6384",
 | 
			
		||||
  "#36a2eb",
 | 
			
		||||
  "#ffce56",
 | 
			
		||||
  "#4bc0c0",
 | 
			
		||||
  "#9966ff",
 | 
			
		||||
  "#ff9f40",
 | 
			
		||||
  "#4dc9f6",
 | 
			
		||||
  "#f67019",
 | 
			
		||||
  "#537bc4",
 | 
			
		||||
  "#acc236",
 | 
			
		||||
  "#166a8f",
 | 
			
		||||
  "#00a950",
 | 
			
		||||
  "#58595b",
 | 
			
		||||
  "#8549ba",
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default function ApplicationChart({ data }: ApplicationChartProps) {
 | 
			
		||||
  const [isChartOpen, setIsChartOpen] = useState(false);
 | 
			
		||||
  const [isTableOpen, setIsTableOpen] = useState(false);
 | 
			
		||||
  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<string, number>);
 | 
			
		||||
 | 
			
		||||
  const sortedApps = Object.entries(appCounts)
 | 
			
		||||
    .sort(([, a], [, b]) => b - a);
 | 
			
		||||
 | 
			
		||||
  const chartApps = sortedApps.slice(
 | 
			
		||||
    chartStartIndex,
 | 
			
		||||
    chartStartIndex + ITEMS_PER_PAGE
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const chartData = {
 | 
			
		||||
    labels: chartApps.map(([name]) => name),
 | 
			
		||||
    datasets: [
 | 
			
		||||
      {
 | 
			
		||||
        data: chartApps.map(([, count]) => count),
 | 
			
		||||
        backgroundColor: CHART_COLORS,
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const chartOptions = {
 | 
			
		||||
    plugins: {
 | 
			
		||||
      legend: { display: false },
 | 
			
		||||
      datalabels: {
 | 
			
		||||
        color: "white",
 | 
			
		||||
        font: { weight: "bold" as const },
 | 
			
		||||
        formatter: (value: number, context: any) => {
 | 
			
		||||
          const label = context.chart.data.labels?.[context.dataIndex];
 | 
			
		||||
          return `${label}\n(${value})`;
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    responsive: true,
 | 
			
		||||
    maintainAspectRatio: false,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="mt-6 flex justify-center gap-4">
 | 
			
		||||
      <TooltipProvider>
 | 
			
		||||
        <Tooltip>
 | 
			
		||||
          <TooltipTrigger asChild>
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              size="icon"
 | 
			
		||||
              onClick={() => setIsChartOpen(true)}
 | 
			
		||||
            >
 | 
			
		||||
              <PieChart className="h-5 w-5" />
 | 
			
		||||
            </Button>
 | 
			
		||||
          </TooltipTrigger>
 | 
			
		||||
          <TooltipContent>Open Chart View</TooltipContent>
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
 | 
			
		||||
        <Tooltip>
 | 
			
		||||
          <TooltipTrigger asChild>
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              size="icon"
 | 
			
		||||
              onClick={() => setIsTableOpen(true)}
 | 
			
		||||
            >
 | 
			
		||||
              <BarChart3 className="h-5 w-5" />
 | 
			
		||||
            </Button>
 | 
			
		||||
          </TooltipTrigger>
 | 
			
		||||
          <TooltipContent>Open Table View</TooltipContent>
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
      </TooltipProvider>
 | 
			
		||||
 | 
			
		||||
      <Dialog open={isChartOpen} onOpenChange={setIsChartOpen}>
 | 
			
		||||
        <DialogContent className="max-w-3xl">
 | 
			
		||||
          <DialogHeader>
 | 
			
		||||
            <DialogTitle>Applications Distribution</DialogTitle>
 | 
			
		||||
          </DialogHeader>
 | 
			
		||||
          <div className="h-[60vh] w-full">
 | 
			
		||||
            <Pie data={chartData} options={chartOptions} />
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="flex justify-center gap-4">
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              onClick={() => setChartStartIndex(Math.max(0, chartStartIndex - ITEMS_PER_PAGE))}
 | 
			
		||||
              disabled={chartStartIndex === 0}
 | 
			
		||||
            >
 | 
			
		||||
              Previous {ITEMS_PER_PAGE}
 | 
			
		||||
            </Button>
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              onClick={() => setChartStartIndex(chartStartIndex + ITEMS_PER_PAGE)}
 | 
			
		||||
              disabled={chartStartIndex + ITEMS_PER_PAGE >= sortedApps.length}
 | 
			
		||||
            >
 | 
			
		||||
              Next {ITEMS_PER_PAGE}
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </DialogContent>
 | 
			
		||||
      </Dialog>
 | 
			
		||||
 | 
			
		||||
      <Dialog open={isTableOpen} onOpenChange={setIsTableOpen}>
 | 
			
		||||
        <DialogContent className="max-w-2xl">
 | 
			
		||||
          <DialogHeader>
 | 
			
		||||
            <DialogTitle>Applications Count</DialogTitle>
 | 
			
		||||
          </DialogHeader>
 | 
			
		||||
          <div className="max-h-[60vh] overflow-y-auto">
 | 
			
		||||
            <Table>
 | 
			
		||||
              <TableHeader>
 | 
			
		||||
                <TableRow>
 | 
			
		||||
                  <TableHead>Application</TableHead>
 | 
			
		||||
                  <TableHead className="text-right">Count</TableHead>
 | 
			
		||||
                </TableRow>
 | 
			
		||||
              </TableHeader>
 | 
			
		||||
              <TableBody>
 | 
			
		||||
                {sortedApps.slice(0, tableLimit).map(([name, count]) => (
 | 
			
		||||
                  <TableRow key={name}>
 | 
			
		||||
                    <TableCell>{name}</TableCell>
 | 
			
		||||
                    <TableCell className="text-right">{count}</TableCell>
 | 
			
		||||
                  </TableRow>
 | 
			
		||||
                ))}
 | 
			
		||||
              </TableBody>
 | 
			
		||||
            </Table>
 | 
			
		||||
          </div>
 | 
			
		||||
          {tableLimit < sortedApps.length && (
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="outline"
 | 
			
		||||
              className="w-full"
 | 
			
		||||
              onClick={() => setTableLimit(prev => prev + ITEMS_PER_PAGE)}
 | 
			
		||||
            >
 | 
			
		||||
              Load More
 | 
			
		||||
            </Button>
 | 
			
		||||
          )}
 | 
			
		||||
        </DialogContent>
 | 
			
		||||
      </Dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								frontend/src/components/Modal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								frontend/src/components/Modal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
"use client";
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
interface ModalProps {
 | 
			
		||||
  isOpen: boolean;
 | 
			
		||||
  onClose: () => void;
 | 
			
		||||
  children: React.ReactNode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Modal: React.FC<ModalProps> = ({ isOpen, onClose, children }) => {
 | 
			
		||||
  if (!isOpen) return null;
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50">
 | 
			
		||||
      <div className="bg-white dark:bg-gray-900 p-6 rounded-lg shadow-lg w-11/12 max-w-4xl relative max-h-[90vh] overflow-y-auto">
 | 
			
		||||
        <button
 | 
			
		||||
          onClick={onClose}
 | 
			
		||||
          className="absolute top-2 right-2 bg-red-500 text-white p-1 rounded"
 | 
			
		||||
        >
 | 
			
		||||
          ✖
 | 
			
		||||
        </button>
 | 
			
		||||
        {children}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Modal;
 | 
			
		||||
@@ -15,7 +15,7 @@ const Command = React.forwardRef<
 | 
			
		||||
  <CommandPrimitive
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn(
 | 
			
		||||
      "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
 | 
			
		||||
      "flex h-full w-full flex-col overflow-hidden bg-popover text-popover-foreground",
 | 
			
		||||
      className,
 | 
			
		||||
    )}
 | 
			
		||||
    {...props}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										120
									
								
								frontend/src/components/ui/table.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								frontend/src/components/ui/table.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
import * as React from "react"
 | 
			
		||||
 | 
			
		||||
import { cn } from "@/lib/utils"
 | 
			
		||||
 | 
			
		||||
const Table = React.forwardRef<
 | 
			
		||||
  HTMLTableElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLTableElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <div className="relative w-full overflow-auto">
 | 
			
		||||
    <table
 | 
			
		||||
      ref={ref}
 | 
			
		||||
      className={cn("w-full caption-bottom text-sm", className)}
 | 
			
		||||
      {...props}
 | 
			
		||||
    />
 | 
			
		||||
  </div>
 | 
			
		||||
))
 | 
			
		||||
Table.displayName = "Table"
 | 
			
		||||
 | 
			
		||||
const TableHeader = React.forwardRef<
 | 
			
		||||
  HTMLTableSectionElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLTableSectionElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
 | 
			
		||||
))
 | 
			
		||||
TableHeader.displayName = "TableHeader"
 | 
			
		||||
 | 
			
		||||
const TableBody = React.forwardRef<
 | 
			
		||||
  HTMLTableSectionElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLTableSectionElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <tbody
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn("[&_tr:last-child]:border-0", className)}
 | 
			
		||||
    {...props}
 | 
			
		||||
  />
 | 
			
		||||
))
 | 
			
		||||
TableBody.displayName = "TableBody"
 | 
			
		||||
 | 
			
		||||
const TableFooter = React.forwardRef<
 | 
			
		||||
  HTMLTableSectionElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLTableSectionElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <tfoot
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn(
 | 
			
		||||
      "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
 | 
			
		||||
      className
 | 
			
		||||
    )}
 | 
			
		||||
    {...props}
 | 
			
		||||
  />
 | 
			
		||||
))
 | 
			
		||||
TableFooter.displayName = "TableFooter"
 | 
			
		||||
 | 
			
		||||
const TableRow = React.forwardRef<
 | 
			
		||||
  HTMLTableRowElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLTableRowElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <tr
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn(
 | 
			
		||||
      "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
 | 
			
		||||
      className
 | 
			
		||||
    )}
 | 
			
		||||
    {...props}
 | 
			
		||||
  />
 | 
			
		||||
))
 | 
			
		||||
TableRow.displayName = "TableRow"
 | 
			
		||||
 | 
			
		||||
const TableHead = React.forwardRef<
 | 
			
		||||
  HTMLTableCellElement,
 | 
			
		||||
  React.ThHTMLAttributes<HTMLTableCellElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <th
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn(
 | 
			
		||||
      "h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
 | 
			
		||||
      className
 | 
			
		||||
    )}
 | 
			
		||||
    {...props}
 | 
			
		||||
  />
 | 
			
		||||
))
 | 
			
		||||
TableHead.displayName = "TableHead"
 | 
			
		||||
 | 
			
		||||
const TableCell = React.forwardRef<
 | 
			
		||||
  HTMLTableCellElement,
 | 
			
		||||
  React.TdHTMLAttributes<HTMLTableCellElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <td
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn(
 | 
			
		||||
      "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
 | 
			
		||||
      className
 | 
			
		||||
    )}
 | 
			
		||||
    {...props}
 | 
			
		||||
  />
 | 
			
		||||
))
 | 
			
		||||
TableCell.displayName = "TableCell"
 | 
			
		||||
 | 
			
		||||
const TableCaption = React.forwardRef<
 | 
			
		||||
  HTMLTableCaptionElement,
 | 
			
		||||
  React.HTMLAttributes<HTMLTableCaptionElement>
 | 
			
		||||
>(({ className, ...props }, ref) => (
 | 
			
		||||
  <caption
 | 
			
		||||
    ref={ref}
 | 
			
		||||
    className={cn("mt-4 text-sm text-muted-foreground", className)}
 | 
			
		||||
    {...props}
 | 
			
		||||
  />
 | 
			
		||||
))
 | 
			
		||||
TableCaption.displayName = "TableCaption"
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  Table,
 | 
			
		||||
  TableHeader,
 | 
			
		||||
  TableBody,
 | 
			
		||||
  TableFooter,
 | 
			
		||||
  TableHead,
 | 
			
		||||
  TableRow,
 | 
			
		||||
  TableCell,
 | 
			
		||||
  TableCaption,
 | 
			
		||||
}
 | 
			
		||||
@@ -1,83 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: TheRealVira
 | 
			
		||||
# License: MIT
 | 
			
		||||
# Source: https://5e.tools/
 | 
			
		||||
 | 
			
		||||
# Import Functions und Setup
 | 
			
		||||
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 \
 | 
			
		||||
  mc \
 | 
			
		||||
  sudo \
 | 
			
		||||
  git \
 | 
			
		||||
  gpg \
 | 
			
		||||
  ca-certificates \
 | 
			
		||||
  apache2
 | 
			
		||||
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 "Installing Node.js"
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
msg_ok "Installed Node.js"
 | 
			
		||||
 | 
			
		||||
# Setup App
 | 
			
		||||
msg_info "Set up 5etools Base"
 | 
			
		||||
cd /opt
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/5etools-mirror-3/5etools-src/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
wget -q "https://github.com/5etools-mirror-3/5etools-src/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
unzip -q "${RELEASE}.zip"
 | 
			
		||||
mv "5etools-src-${RELEASE:1}" /opt/5etools
 | 
			
		||||
cd /opt/5etools
 | 
			
		||||
$STD npm install
 | 
			
		||||
$STD npm run build
 | 
			
		||||
echo "${RELEASE}" >"/opt/5etools_version.txt"
 | 
			
		||||
msg_ok "Set up 5etools Base"
 | 
			
		||||
 | 
			
		||||
msg_info "Set up 5etools Image"
 | 
			
		||||
cd /opt
 | 
			
		||||
IMG_RELEASE=$(curl -s https://api.github.com/repos/5etools-mirror-2/5etools-img/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
curl -sSL "https://github.com/5etools-mirror-2/5etools-img/archive/refs/tags/${IMG_RELEASE}.zip" > "${IMG_RELEASE}.zip"
 | 
			
		||||
unzip -q "${IMG_RELEASE}.zip"
 | 
			
		||||
mv "5etools-img-${IMG_RELEASE:1}" /opt/5etools/img
 | 
			
		||||
echo "${IMG_RELEASE}" >"/opt/5etools_IMG_version.txt"
 | 
			
		||||
msg_ok "Set up 5etools Image"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >> /etc/apache2/apache2.conf
 | 
			
		||||
<Location /server-status>
 | 
			
		||||
    SetHandler server-status
 | 
			
		||||
    Order deny,allow
 | 
			
		||||
    Allow from all
 | 
			
		||||
</Location>
 | 
			
		||||
EOF
 | 
			
		||||
rm -rf /var/www/html
 | 
			
		||||
ln -s "/opt/5etools" /var/www/html
 | 
			
		||||
chown -R www-data: "/opt/5etools"
 | 
			
		||||
chmod -R 755 "/opt/5etools"
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -rf /opt/${IMG_RELEASE}.zip
 | 
			
		||||
rm -rf /opt/${RELEASE}.zip
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
@@ -31,7 +31,7 @@ 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
 | 
			
		||||
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 "Setting up PostgreSQL Repository"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								install/alpine-it-tools-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								install/alpine-it-tools-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: nicedevil007 (NiceDevil)
 | 
			
		||||
# 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 apk add \
 | 
			
		||||
  curl \
 | 
			
		||||
  mc \
 | 
			
		||||
  openssh \
 | 
			
		||||
  nginx \
 | 
			
		||||
  unzip
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing IT-Tools"
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4)
 | 
			
		||||
DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
 | 
			
		||||
 | 
			
		||||
curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
 | 
			
		||||
mkdir -p /usr/share/nginx/html
 | 
			
		||||
unzip -q it-tools.zip -d /tmp/it-tools
 | 
			
		||||
cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
 | 
			
		||||
cat <<'EOF' > /etc/nginx/http.d/default.conf
 | 
			
		||||
server {
 | 
			
		||||
  listen 80;
 | 
			
		||||
  server_name localhost;
 | 
			
		||||
  root /usr/share/nginx/html;
 | 
			
		||||
  index index.html;
 | 
			
		||||
  
 | 
			
		||||
  location / {
 | 
			
		||||
      try_files $uri $uri/ /index.html;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
EOF
 | 
			
		||||
$STD rc-update add nginx default
 | 
			
		||||
$STD rc-service nginx start
 | 
			
		||||
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
 | 
			
		||||
msg_ok "Installed IT-Tools"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -rf /tmp/it-tools
 | 
			
		||||
rm -f it-tools.zip
 | 
			
		||||
$STD apk cache clean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -39,7 +39,7 @@ msg_ok "Installed Python 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -81,12 +81,13 @@ $STD apt-get install -y nodejs
 | 
			
		||||
msg_ok "Installed Node.js"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Golang"
 | 
			
		||||
cd /tmp
 | 
			
		||||
set +o pipefail
 | 
			
		||||
GO_RELEASE=$(curl -s https://go.dev/dl/ | grep -o -m 1 "go.*\linux-amd64.tar.gz")
 | 
			
		||||
wget -q https://golang.org/dl/${GO_RELEASE}
 | 
			
		||||
tar -xzf ${GO_RELEASE} -C /usr/local
 | 
			
		||||
ln -s /usr/local/go/bin/go /usr/bin/go
 | 
			
		||||
temp_file=$(mktemp)
 | 
			
		||||
golang_tarball=$(curl -s https://go.dev/dl/ | grep -oP 'go[\d\.]+\.linux-amd64\.tar\.gz' | head -n 1)
 | 
			
		||||
wget -q https://golang.org/dl/"$golang_tarball" -O "$temp_file"
 | 
			
		||||
tar -C /usr/local -xzf "$temp_file"
 | 
			
		||||
ln -sf /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
rm -f "$temp_file"
 | 
			
		||||
set -o pipefail
 | 
			
		||||
msg_ok "Installed Golang"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										97
									
								
								install/baikal-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								install/baikal-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
			
		||||
#!/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 \
 | 
			
		||||
  postgresql \
 | 
			
		||||
  apache2 \
 | 
			
		||||
  libapache2-mod-php \
 | 
			
		||||
  php-{pgsql,dom}
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up PostgreSQL"
 | 
			
		||||
DB_NAME=baikal
 | 
			
		||||
DB_USER=baikal
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)
 | 
			
		||||
$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 TEMPLATE template0;"
 | 
			
		||||
{
 | 
			
		||||
echo "Baikal Credentials"
 | 
			
		||||
echo "Baikal Database User: $DB_USER"
 | 
			
		||||
echo "Baikal Database Password: $DB_PASS"
 | 
			
		||||
echo "Baikal Database Name: $DB_NAME"
 | 
			
		||||
} >> ~/baikal.creds
 | 
			
		||||
msg_ok "Set up PostgreSQL"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Baikal"
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/sabre-io/Baikal/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
cd /opt
 | 
			
		||||
wget -q "https://github.com/sabre-io/baikal/releases/download/${RELEASE}/baikal-${RELEASE}.zip"
 | 
			
		||||
unzip -q "baikal-${RELEASE}.zip"
 | 
			
		||||
cat <<EOF >/opt/baikal/config/baikal.yaml
 | 
			
		||||
database:
 | 
			
		||||
    backend: pgsql
 | 
			
		||||
    pgsql_host: localhost
 | 
			
		||||
    pgsql_dbname: $DB_NAME
 | 
			
		||||
    pgsql_username: $DB_USER
 | 
			
		||||
    pgsql_password: $DB_PASS
 | 
			
		||||
EOF
 | 
			
		||||
chown -R www-data:www-data /opt/baikal/
 | 
			
		||||
chmod -R 755 /opt/baikal/
 | 
			
		||||
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
 | 
			
		||||
msg_ok "Installed Baikal"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF > /etc/apache2/sites-available/baikal.conf
 | 
			
		||||
<VirtualHost *:80>
 | 
			
		||||
    ServerName baikal
 | 
			
		||||
    DocumentRoot /opt/baikal/html
 | 
			
		||||
 | 
			
		||||
    RewriteEngine on
 | 
			
		||||
    RewriteRule /.well-known/carddav /dav.php [R=308,L]
 | 
			
		||||
    RewriteRule /.well-known/caldav  /dav.php [R=308,L]
 | 
			
		||||
    RewriteCond %{REQUEST_URI} ^/dav.php$ [NC]
 | 
			
		||||
    RewriteRule ^(.*)$ /dav.php/ [R=301,L]
 | 
			
		||||
        
 | 
			
		||||
    <Directory /opt/baikal/html>
 | 
			
		||||
        Options FollowSymLinks
 | 
			
		||||
        AllowOverride All
 | 
			
		||||
        Require all granted
 | 
			
		||||
    </Directory>
 | 
			
		||||
 | 
			
		||||
    <IfModule mod_expires.c>
 | 
			
		||||
        ExpiresActive Off
 | 
			
		||||
    </IfModule>
 | 
			
		||||
 | 
			
		||||
    ErrorLog /var/log/apache2/baikal_error.log
 | 
			
		||||
    CustomLog /var/log/apache2/baikal_access.log combined
 | 
			
		||||
</VirtualHost>
 | 
			
		||||
EOF
 | 
			
		||||
$STD a2ensite baikal
 | 
			
		||||
$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/baikal-${RELEASE}.zip"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -19,13 +19,13 @@ $STD apt-get install -y sudo
 | 
			
		||||
$STD apt-get install -y mc
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Bazarr"
 | 
			
		||||
mkdir -p /var/lib/bazarr/
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
# Author: tteck (tteckster) | Co-Author: MickLesk (CanbiZ)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
 | 
			
		||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,16 +33,16 @@ msg_ok "Installed Caddy"
 | 
			
		||||
read -r -p "Would you like to install xCaddy Addon? <y/N> " prompt
 | 
			
		||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
 | 
			
		||||
  msg_info "Installing Golang"
 | 
			
		||||
  cd /opt
 | 
			
		||||
  set +o pipefail
 | 
			
		||||
  GOLANG=$(curl -s https://go.dev/dl/ | grep -o "go.*\linux-amd64.tar.gz" | head -n 1)
 | 
			
		||||
  wget -q https://golang.org/dl/$GOLANG
 | 
			
		||||
  tar -xzf $GOLANG -C /usr/local
 | 
			
		||||
  ln -s /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
  temp_file=$(mktemp)
 | 
			
		||||
  golang_tarball=$(curl -s https://go.dev/dl/ | grep -oP 'go[\d\.]+\.linux-amd64\.tar\.gz' | head -n 1)
 | 
			
		||||
  wget -q https://golang.org/dl/"$golang_tarball" -O "$temp_file"
 | 
			
		||||
  tar -C /usr/local -xzf "$temp_file"
 | 
			
		||||
  ln -sf /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
  rm -f "$temp_file"
 | 
			
		||||
  set -o pipefail
 | 
			
		||||
  rm -rf /opt/go*
 | 
			
		||||
  msg_ok "Installed Golang"
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
  msg_info "Setup xCaddy"
 | 
			
		||||
  cd /opt
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/caddyserver/xcaddy/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@ msg_ok "Installed Kepubify"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Calibre-Web"
 | 
			
		||||
mkdir -p /opt/calibre-web
 | 
			
		||||
$STD apt-get install -y calibre
 | 
			
		||||
$STD wget https://github.com/janeczku/calibre-web/raw/master/library/metadata.db -P /opt/calibre-web
 | 
			
		||||
$STD pip install calibreweb
 | 
			
		||||
$STD pip install jsonschema
 | 
			
		||||
 
 | 
			
		||||
@@ -47,18 +47,18 @@ $STD apt-get install -y \
 | 
			
		||||
  gnupg
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -20,13 +20,13 @@ $STD apt-get install -y mc
 | 
			
		||||
$STD apt-get install -y python3-libtorrent
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Deluge"
 | 
			
		||||
$STD pip install deluge[all]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								install/elementsynapse-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								install/elementsynapse-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: tremor021
 | 
			
		||||
# 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 \
 | 
			
		||||
  sudo \
 | 
			
		||||
  curl \
 | 
			
		||||
  mc \
 | 
			
		||||
  lsb-release \
 | 
			
		||||
  wget \
 | 
			
		||||
  apt-transport-https \
 | 
			
		||||
  debconf-utils
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Element Synapse"
 | 
			
		||||
wget -O /usr/share/keyrings/matrix-org-archive-keyring.gpg https://packages.matrix.org/debian/matrix-org-archive-keyring.gpg
 | 
			
		||||
echo "deb [signed-by=/usr/share/keyrings/matrix-org-archive-keyring.gpg] https://packages.matrix.org/debian/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/matrix-org.list
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
echo "matrix-synapse-py3 matrix-synapse/server-name string matrix" | debconf-set-selections
 | 
			
		||||
echo "matrix-synapse-py3 matrix-synapse/report-stats boolean false" | debconf-set-selections
 | 
			
		||||
$STD apt-get install matrix-synapse-py3 -y
 | 
			
		||||
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/matrix-synapse/homeserver.yaml
 | 
			
		||||
sed -i 's/'\''::1'\'', //g' /etc/matrix-synapse/homeserver.yaml
 | 
			
		||||
systemctl enable -q --now matrix-synapse
 | 
			
		||||
msg_ok "Installed Element Synapse"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -20,14 +20,14 @@ $STD apt-get install -y mc
 | 
			
		||||
$STD apt-get install -y git
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip \
 | 
			
		||||
  python3-venv
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing ESPHome"
 | 
			
		||||
mkdir /root/config
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ msg_ok "Installed Dependencies"
 | 
			
		||||
msg_info "Installing Node.js"
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
msg_ok "Installed Node.js"
 | 
			
		||||
 
 | 
			
		||||
@@ -18,15 +18,15 @@ msg_info "Installing Dependencies (Patience)"
 | 
			
		||||
$STD apt-get install -y {curl,sudo,mc,git,gpg,ca-certificates,automake,build-essential,xz-utils,libtool,ccache,pkg-config,libgtk-3-dev,libavcodec-dev,libavformat-dev,libswscale-dev,libv4l-dev,libxvidcore-dev,libx264-dev,libjpeg-dev,libpng-dev,libtiff-dev,gfortran,openexr,libatlas-base-dev,libssl-dev,libtbb2,libtbb-dev,libdc1394-22-dev,libopenexr-dev,libgstreamer-plugins-base1.0-dev,libgstreamer1.0-dev,gcc,gfortran,libopenblas-dev,liblapack-dev,libusb-1.0-0-dev,jq,moreutils}
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Python3 Dependencies"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y {python3,python3-dev,python3-setuptools,python3-distutils,python3-pip}
 | 
			
		||||
$STD pip install --upgrade pip
 | 
			
		||||
msg_ok "Installed Python3 Dependencies"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Node.js"
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
msg_ok "Installed Node.js"
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ msg_ok "Configured MySQL"
 | 
			
		||||
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
 | 
			
		||||
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 Node.js"
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ msg_ok "Installed Dependencies"
 | 
			
		||||
msg_info "Installing Node.js"
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
$STD npm install -g yarn
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,7 @@ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dea
 | 
			
		||||
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
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
$STD npm install -g corepack@0.31.0
 | 
			
		||||
msg_ok "Installed Node.js"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Hoarder"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# Co-Author: MickLesk (Canbiz)
 | 
			
		||||
# License: MIT
 | 
			
		||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: MickLesk (Canbiz)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/ajnart/homarr
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
 | 
			
		||||
@@ -20,6 +18,7 @@ $STD apt-get install -y \
 | 
			
		||||
  sudo \
 | 
			
		||||
  mc \
 | 
			
		||||
  curl \
 | 
			
		||||
  redis-server \
 | 
			
		||||
  ca-certificates \
 | 
			
		||||
  gnupg \
 | 
			
		||||
  make \
 | 
			
		||||
@@ -30,32 +29,40 @@ 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
 | 
			
		||||
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/Yarn"
 | 
			
		||||
msg_info "Installing Node.js/pnpm"
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
$STD npm install -g yarn
 | 
			
		||||
msg_ok "Installed Node.js/Yarn"
 | 
			
		||||
$STD npm install -g pnpm@latest
 | 
			
		||||
msg_ok "Installed Node.js/pnpm"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Homarr (Patience)"
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/ajnart/homarr/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
wget -q "https://github.com/ajnart/homarr/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
cd /opt
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/homarr-labs/homarr/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
wget -q "https://github.com/homarr-labs/homarr/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
unzip -q v${RELEASE}.zip
 | 
			
		||||
rm -rf v${RELEASE}.zip
 | 
			
		||||
mv homarr-${RELEASE} /opt/homarr
 | 
			
		||||
mkdir -p /opt/homarr_db
 | 
			
		||||
touch /opt/homarr_db/db.sqlite
 | 
			
		||||
AUTH_SECRET="$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | cut -c1-13)"
 | 
			
		||||
SECRET_ENCRYPTION_KEY="$(openssl rand -hex 32)"
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/opt/homarr/.env
 | 
			
		||||
DATABASE_URL="file:./database/db.sqlite"
 | 
			
		||||
NEXTAUTH_URL="http://localhost:3000"
 | 
			
		||||
NEXTAUTH_SECRET="$(openssl rand -base64 32)"
 | 
			
		||||
NEXT_PUBLIC_DISABLE_ANALYTICS="true"
 | 
			
		||||
DEFAULT_COLOR_SCHEME="dark"
 | 
			
		||||
AUTH_SECRET='${AUTH_SECRET}'
 | 
			
		||||
DB_DRIVER='better-sqlite3'
 | 
			
		||||
SECRET_ENCRYPTION_KEY='${SECRET_ENCRYPTION_KEY}'
 | 
			
		||||
DB_URL='/opt/homarr_db/db.sqlite'
 | 
			
		||||
TURBO_TELEMETRY_DISABLED=1
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
cd /opt/homarr
 | 
			
		||||
$STD yarn install
 | 
			
		||||
$STD yarn build
 | 
			
		||||
$STD yarn db:migrate
 | 
			
		||||
$STD pnpm install
 | 
			
		||||
$STD pnpm run db:migration:sqlite:run
 | 
			
		||||
$STD pnpm build
 | 
			
		||||
mkdir build
 | 
			
		||||
cp ./node_modules/better-sqlite3/build/Release/better_sqlite3.node ./build/better_sqlite3.node
 | 
			
		||||
echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"
 | 
			
		||||
msg_ok "Installed Homarr"
 | 
			
		||||
 | 
			
		||||
@@ -69,18 +76,19 @@ After=network.target
 | 
			
		||||
Type=exec
 | 
			
		||||
WorkingDirectory=/opt/homarr
 | 
			
		||||
EnvironmentFile=-/opt/homarr/.env
 | 
			
		||||
ExecStart=/usr/bin/yarn start
 | 
			
		||||
ExecStart=/usr/bin/pnpm start
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl enable -q --now homarr.service
 | 
			
		||||
systemctl enable -q --now homarr
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -rf /opt/v${RELEASE}.zip
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ $STD apt-get install -y \
 | 
			
		||||
  pkg-config
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Python3/pip"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
$STD apt-get remove --purge -y python3.12 python3.12-dev python3.12-venv
 | 
			
		||||
 
 | 
			
		||||
@@ -19,14 +19,14 @@ $STD apt-get install -y sudo
 | 
			
		||||
$STD apt-get install -y mc
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip \
 | 
			
		||||
  python3-venv
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing runlike"
 | 
			
		||||
$STD pip install runlike
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,7 @@ EOF
 | 
			
		||||
# Install Jellyfin using the metapackage (which will fetch jellyfin-server, jellyfin-web, and jellyfin-ffmpeg5)
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y jellyfin
 | 
			
		||||
sed -i 's/"MinimumLevel": "Information"/"MinimumLevel": "Error"/g' /etc/jellyfin/logging.json
 | 
			
		||||
chown -R jellyfin:adm /etc/jellyfin
 | 
			
		||||
sleep 10
 | 
			
		||||
systemctl restart jellyfin
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ $STD apt-get install -y \
 | 
			
		||||
    imagemagick
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Python3 Dependencies"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
    pip \
 | 
			
		||||
    python3-irc
 | 
			
		||||
@@ -34,7 +34,7 @@ $STD pip install jaraco.stream
 | 
			
		||||
$STD pip install python-Levenshtein
 | 
			
		||||
$STD pip install soupsieve
 | 
			
		||||
$STD pip install pypdf
 | 
			
		||||
msg_ok "Installed Python3 Dependencies"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing LazyLibrarian"
 | 
			
		||||
$STD git clone https://gitlab.com/LazyLibrarian/LazyLibrarian /opt/LazyLibrarian
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ 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
 | 
			
		||||
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/Yarn"
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										60
									
								
								install/mattermost-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								install/mattermost-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Kaedon Cleland-Host (dracentis)
 | 
			
		||||
# 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 \
 | 
			
		||||
  gpg \
 | 
			
		||||
  postgresql 
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up PostgreSQL"
 | 
			
		||||
DB_NAME=mattermost
 | 
			
		||||
DB_USER=mmuser
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;"
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH 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 DATABASE $DB_NAME OWNER TO $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -c "GRANT USAGE, CREATE ON SCHEMA PUBLIC TO $DB_USER;"
 | 
			
		||||
{
 | 
			
		||||
    echo "Mattermost Credentials"
 | 
			
		||||
    echo "Database User: $DB_USER"
 | 
			
		||||
    echo "Database Password: $DB_PASS"
 | 
			
		||||
    echo "Database Name: $DB_NAME"
 | 
			
		||||
} >> ~/mattermost.creds
 | 
			
		||||
msg_ok "Set up PostgreSQL"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Mattermost"
 | 
			
		||||
IPADDRESS=$(hostname -I | awk '{print $1}')
 | 
			
		||||
curl -sL -o /usr/share/keyrings/mattermost-archive-keyring.gpg https://deb.packages.mattermost.com/pubkey.gpg
 | 
			
		||||
sh -c 'curl -sL https://deb.packages.mattermost.com/repo-setup.sh | sudo bash -s mattermost' >/dev/null
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y mattermost
 | 
			
		||||
$STD install -C -m 600 -o mattermost -g mattermost /opt/mattermost/config/config.defaults.json /opt/mattermost/config/config.json
 | 
			
		||||
sed -i -e "/DataSource/c\   \"DataSource\": \"postgres://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME?sslmode=disable&connect_timeout=10\"," \
 | 
			
		||||
       -e "/SiteURL/c\   \"SiteURL\": \"http://$IPADDRESS:8065\"," /opt/mattermost/config/config.json
 | 
			
		||||
systemctl enable -q --now mattermost.service
 | 
			
		||||
msg_ok "Installed Mattermost"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -28,7 +28,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
@@ -42,10 +42,12 @@ msg_ok "Installed pnpm"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Golang"
 | 
			
		||||
set +o pipefail
 | 
			
		||||
GOLANG=$(curl -s https://go.dev/dl/ | grep -o "go.*\linux-amd64.tar.gz" | head -n 1)
 | 
			
		||||
wget -q https://golang.org/dl/$GOLANG
 | 
			
		||||
tar -xzf $GOLANG -C /usr/local
 | 
			
		||||
ln -s /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
temp_file=$(mktemp)
 | 
			
		||||
golang_tarball=$(curl -s https://go.dev/dl/ | grep -oP 'go[\d\.]+\.linux-amd64\.tar\.gz' | head -n 1)
 | 
			
		||||
wget -q https://golang.org/dl/"$golang_tarball" -O "$temp_file"
 | 
			
		||||
tar -C /usr/local -xzf "$temp_file"
 | 
			
		||||
ln -sf /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
rm -f "$temp_file"
 | 
			
		||||
set -o pipefail
 | 
			
		||||
msg_ok "Installed Golang"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -33,18 +33,18 @@ $STD apt-get install -y --no-install-recommends \
 | 
			
		||||
  mc
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip \
 | 
			
		||||
  python3-venv
 | 
			
		||||
msg_ok "Installed Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										104
									
								
								install/monica-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								install/monica-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -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 \
 | 
			
		||||
  gnupg2\
 | 
			
		||||
  mariadb-server \
 | 
			
		||||
  apache2 \
 | 
			
		||||
  libapache2-mod-php \
 | 
			
		||||
  php-{bcmath,curl,dom,gd,gmp,iconv,intl,json,mbstring,mysqli,opcache,pdo-mysql,redis,tokenizer,xml,zip} \
 | 
			
		||||
  composer
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up MariaDB"
 | 
			
		||||
DB_NAME=monica
 | 
			
		||||
DB_USER=monica
 | 
			
		||||
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 "monica-Credentials"
 | 
			
		||||
    echo "monica Database User: $DB_USER"
 | 
			
		||||
    echo "monica Database Password: $DB_PASS"
 | 
			
		||||
    echo "monica Database Name: $DB_NAME"
 | 
			
		||||
} >> ~/monica.creds
 | 
			
		||||
msg_ok "Set up MariaDB"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Node.js/Yarn"
 | 
			
		||||
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
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
$STD npm install -g npm@latest
 | 
			
		||||
$STD npm install -g yarn
 | 
			
		||||
msg_ok "Installed Node.js/Yarn"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing monica"
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/monicahq/monica/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
cd /opt
 | 
			
		||||
wget -q "https://github.com/monicahq/monica/releases/download/v${RELEASE}/monica-v${RELEASE}.tar.bz2"
 | 
			
		||||
tar -xjf "monica-v${RELEASE}.tar.bz2"
 | 
			
		||||
mv "/opt/monica-v${RELEASE}" /opt/monica
 | 
			
		||||
cd /opt/monica
 | 
			
		||||
cp /opt/monica/.env.example /opt/monica/.env
 | 
			
		||||
HASH_SALT=$(openssl rand -base64 32)
 | 
			
		||||
sed -i -e "s|^DB_USERNAME=.*|DB_USERNAME=${DB_USER}|" \
 | 
			
		||||
       -e "s|^DB_PASSWORD=.*|DB_PASSWORD=${DB_PASS}|" \
 | 
			
		||||
       -e "s|^HASH_SALT=.*|HASH_SALT=${HASH_SALT}|" \
 | 
			
		||||
       /opt/monica/.env
 | 
			
		||||
$STD composer install --no-dev -o --no-interaction
 | 
			
		||||
$STD yarn install
 | 
			
		||||
$STD yarn run production
 | 
			
		||||
$STD php artisan key:generate
 | 
			
		||||
$STD php artisan setup:production --email=admin@helper-scripts.com --password=helper-scripts.com --force
 | 
			
		||||
chown -R www-data:www-data /opt/monica
 | 
			
		||||
chmod -R 775 /opt/monica/storage
 | 
			
		||||
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
 | 
			
		||||
msg_ok "Installed monica"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >/etc/apache2/sites-available/monica.conf
 | 
			
		||||
<VirtualHost *:80>
 | 
			
		||||
    ServerName monica
 | 
			
		||||
    DocumentRoot /opt/monica/public
 | 
			
		||||
    <Directory /opt/monica/public>
 | 
			
		||||
        Options Indexes FollowSymLinks
 | 
			
		||||
        AllowOverride All
 | 
			
		||||
        Require all granted
 | 
			
		||||
    </Directory>
 | 
			
		||||
 | 
			
		||||
    ErrorLog /var/log/apache2/monica_error.log
 | 
			
		||||
    CustomLog /var/log/apache2/monica_access.log combined
 | 
			
		||||
</VirtualHost>
 | 
			
		||||
EOF
 | 
			
		||||
$STD a2ensite monica
 | 
			
		||||
$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/monica-v${RELEASE}.tar.bz2"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -21,13 +21,13 @@ $STD apt-get install -y git
 | 
			
		||||
$STD apt-get install -y cifs-utils
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-pip
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Motion"
 | 
			
		||||
$STD apt-get install -y motion
 | 
			
		||||
 
 | 
			
		||||
@@ -26,11 +26,11 @@ $STD apt-get install -y unrar
 | 
			
		||||
rm /etc/apt/sources.list.d/non-free.list
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y python3-pip
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
$STD pip install -U --no-cache-dir pip
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing ${APPLICATION}"
 | 
			
		||||
mkdir -p /opt/mylar3
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ 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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										164
									
								
								install/nodebb-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								install/nodebb-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,164 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2024 tteck
 | 
			
		||||
# Author: MickLesk (Canbiz)
 | 
			
		||||
# License: MIT | https://github.com/tteck/Proxmox/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/NodeBB/NodeBB
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies (Patience)"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  build-essential \
 | 
			
		||||
  curl \
 | 
			
		||||
  sudo \
 | 
			
		||||
  make \
 | 
			
		||||
  redis-server \
 | 
			
		||||
  expect \
 | 
			
		||||
  gnupg \
 | 
			
		||||
  ca-certificates \
 | 
			
		||||
  mc
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Node.js & MongoDB 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
 | 
			
		||||
 | 
			
		||||
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | gpg --dearmor -o /etc/apt/keyrings/mongodb-server-8.0.gpg
 | 
			
		||||
echo "deb [arch=amd64,arm64 signed-by=/etc/apt/keyrings/mongodb-server-8.0.gpg] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" > /etc/apt/sources.list.d/mongodb-org-8.0.list
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
msg_ok "Set up Repositories"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Node.js"
 | 
			
		||||
$STD apt-get install -y nodejs
 | 
			
		||||
msg_ok "Installed Node.js"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing MongoDB"
 | 
			
		||||
$STD apt-get install -y mongodb-org
 | 
			
		||||
systemctl enable -q --now mongod
 | 
			
		||||
sleep 10 # MongoDB needs some secounds to start, if not sleep it collide with following mongosh
 | 
			
		||||
msg_ok "Installed MongoDB"   
 | 
			
		||||
 | 
			
		||||
msg_info "Configure MongoDB"
 | 
			
		||||
MONGO_ADMIN_USER="admin"
 | 
			
		||||
MONGO_ADMIN_PWD="$(openssl rand -base64 18 | cut -c1-13)"
 | 
			
		||||
NODEBB_USER="nodebb"
 | 
			
		||||
NODEBB_PWD="$(openssl rand -base64 18 | cut -c1-13)"
 | 
			
		||||
MONGO_CONNECTION_STRING="mongodb://${NODEBB_USER}:${NODEBB_PWD}@localhost:27017/nodebb"
 | 
			
		||||
NODEBB_SECRET=$(uuidgen)
 | 
			
		||||
{
 | 
			
		||||
    echo "NodeBB-Credentials"
 | 
			
		||||
    echo "Mongo Database User: $MONGO_ADMIN_USER"
 | 
			
		||||
    echo "Mongo Database Password: $MONGO_ADMIN_PWD"
 | 
			
		||||
    echo "NodeBB User: $NODEBB_USER"
 | 
			
		||||
	echo "NodeBB Password: $NODEBB_PWD"
 | 
			
		||||
	echo "NodeBB Secret: $NODEBB_SECRET"
 | 
			
		||||
} >> ~/nodebb.creds
 | 
			
		||||
 | 
			
		||||
$STD mongosh <<EOF
 | 
			
		||||
use admin
 | 
			
		||||
db.createUser({
 | 
			
		||||
  user: "$MONGO_ADMIN_USER",
 | 
			
		||||
  pwd: "$MONGO_ADMIN_PWD",
 | 
			
		||||
  roles: [{ role: "root", db: "admin" }]
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
use nodebb
 | 
			
		||||
db.createUser({
 | 
			
		||||
  user: "$NODEBB_USER",
 | 
			
		||||
  pwd: "$NODEBB_PWD",
 | 
			
		||||
  roles: [
 | 
			
		||||
    { role: "readWrite", db: "nodebb" },
 | 
			
		||||
    { role: "clusterMonitor", db: "admin" }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
quit()
 | 
			
		||||
EOF
 | 
			
		||||
sed -i 's/bindIp: 127.0.0.1/bindIp: 0.0.0.0/' /etc/mongod.conf
 | 
			
		||||
sed -i '/security:/d' /etc/mongod.conf
 | 
			
		||||
bash -c 'echo -e "\nsecurity:\n  authorization: enabled" >> /etc/mongod.conf'
 | 
			
		||||
systemctl restart mongod
 | 
			
		||||
msg_ok "MongoDB successfully configurated" 
 | 
			
		||||
 | 
			
		||||
msg_info "Install NodeBB" 
 | 
			
		||||
cd /opt
 | 
			
		||||
RELEASE=$(curl -s https://api.github.com/repos/NodeBB/NodeBB/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
wget -q "https://github.com/NodeBB/NodeBB/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
unzip -q v${RELEASE}.zip
 | 
			
		||||
mv NodeBB-${RELEASE} /opt/nodebb
 | 
			
		||||
cd /opt/nodebb
 | 
			
		||||
touch pidfile
 | 
			
		||||
expect <<EOF > /dev/null 2>&1
 | 
			
		||||
log_file /dev/null
 | 
			
		||||
set timeout -1
 | 
			
		||||
 | 
			
		||||
spawn ./nodebb setup
 | 
			
		||||
expect "URL used to access this NodeBB" {
 | 
			
		||||
    send "http://localhost:4567\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Please enter a NodeBB secret" {
 | 
			
		||||
    send "$NODEBB_SECRET\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Would you like to submit anonymous plugin usage to nbbpm? (yes)" {
 | 
			
		||||
    send "no\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Which database to use (mongo)" {
 | 
			
		||||
    send "mongo\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Format: mongodb://*" {
 | 
			
		||||
    send "$MONGO_CONNECTION_STRING\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Administrator username" {
 | 
			
		||||
    send "helper-scripts\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Administrator email address" {
 | 
			
		||||
    send "helper-scripts@local.com\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Password" {
 | 
			
		||||
    send "helper-scripts\r"
 | 
			
		||||
}
 | 
			
		||||
expect "Confirm Password" {
 | 
			
		||||
    send "helper-scripts\r"
 | 
			
		||||
}
 | 
			
		||||
expect eof
 | 
			
		||||
EOF
 | 
			
		||||
echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"
 | 
			
		||||
msg_ok "Installed NodeBB"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Services"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/nodebb.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=NodeBB
 | 
			
		||||
Documentation=https://docs.nodebb.org
 | 
			
		||||
After=system.slice multi-user.target mongod.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=forking
 | 
			
		||||
User=root
 | 
			
		||||
 | 
			
		||||
WorkingDirectory=/opt/nodebb
 | 
			
		||||
PIDFile=/opt/nodebb/pidfile
 | 
			
		||||
ExecStart=/usr/bin/node /opt/nodebb/loader.js
 | 
			
		||||
Restart=always
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl enable -q --now nodebb
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -R /opt/v${RELEASE}.zip
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -22,7 +22,7 @@ $STD apt-get install -y libyaml-dev
 | 
			
		||||
$STD apt-get install -y build-essential
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Updating Python3"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
@@ -31,7 +31,7 @@ $STD apt-get install -y \
 | 
			
		||||
 | 
			
		||||
$STD apt-get install -y python3-setuptools
 | 
			
		||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
msg_ok "Updated Python3"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating user octoprint"
 | 
			
		||||
useradd -m -s /bin/bash -p $(openssl passwd -1 octoprint) octoprint
 | 
			
		||||
 
 | 
			
		||||
@@ -26,10 +26,14 @@ $STD apt-get install -y cmake
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Golang"
 | 
			
		||||
$STD wget https://golang.org/dl/go1.23.2.linux-amd64.tar.gz
 | 
			
		||||
$STD tar -xzf go1.23.2.linux-amd64.tar.gz -C /usr/local
 | 
			
		||||
$STD ln -s /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
rm -rf go1.23.2.linux-amd64.tar.gz
 | 
			
		||||
set +o pipefail
 | 
			
		||||
temp_file=$(mktemp)
 | 
			
		||||
golang_tarball=$(curl -s https://go.dev/dl/ | grep -oP 'go[\d\.]+\.linux-amd64\.tar\.gz' | head -n 1)
 | 
			
		||||
wget -q https://golang.org/dl/"$golang_tarball" -O "$temp_file"
 | 
			
		||||
tar -C /usr/local -xzf "$temp_file"
 | 
			
		||||
ln -sf /usr/local/go/bin/go /usr/local/bin/go
 | 
			
		||||
rm -f "$temp_file"
 | 
			
		||||
set -o pipefail
 | 
			
		||||
msg_ok "Installed Golang"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Intel® Repositories"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,16 +24,16 @@ $STD apt-get install -y \
 | 
			
		||||
  ffmpeg
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Python3 Dependencies"
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y --no-install-recommends \
 | 
			
		||||
  python3 \
 | 
			
		||||
  python3-pip
 | 
			
		||||
msg_ok "Installed Python3 Dependencies"
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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"
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user