mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 02:12:49 +00:00 
			
		
		
		
	Compare commits
	
		
			811 Commits
		
	
	
		
			2025-01-28
			...
			2025-03-14
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					0a9eb5078a | ||
| 
						 | 
					46016dc3da | ||
| 
						 | 
					f9c7717719 | ||
| 
						 | 
					ea05730868 | ||
| 
						 | 
					077e49c5c9 | ||
| 
						 | 
					4cc1ab728c | ||
| 
						 | 
					66c4d0e03f | ||
| 
						 | 
					b95e6ec9cf | ||
| 
						 | 
					936a526de3 | ||
| 
						 | 
					72b35646bb | ||
| 
						 | 
					e10574e724 | ||
| 
						 | 
					57b5852f91 | ||
| 
						 | 
					b774ad37c1 | ||
| 
						 | 
					efd5f1944b | ||
| 
						 | 
					bad18f77cb | ||
| 
						 | 
					09cca74147 | ||
| 
						 | 
					c59c796774 | ||
| 
						 | 
					0dc526af08 | ||
| 
						 | 
					127390c917 | ||
| 
						 | 
					d1528d4ba7 | ||
| 
						 | 
					6953a7779b | ||
| 
						 | 
					7aebd12d87 | ||
| 
						 | 
					a426e80b83 | ||
| 
						 | 
					ed93923672 | ||
| 
						 | 
					41ee6adab2 | ||
| 
						 | 
					3dbce17fc3 | ||
| 
						 | 
					4646e10382 | ||
| 
						 | 
					c895fb7809 | ||
| 
						 | 
					540d80a21c | ||
| 
						 | 
					9ad4dcf8d0 | ||
| 
						 | 
					91bfe2442c | ||
| 
						 | 
					f4afe5be9e | ||
| 
						 | 
					fe956f650d | ||
| 
						 | 
					3dd67e46c2 | ||
| 
						 | 
					6de4a8107c | ||
| 
						 | 
					f6a6ca5e26 | ||
| 
						 | 
					7f796478f3 | ||
| 
						 | 
					d72d742fbb | ||
| 
						 | 
					d5f5f1e5de | ||
| 
						 | 
					31d80c3461 | ||
| 
						 | 
					68936f0edd | ||
| 
						 | 
					5ce76f0a3a | ||
| 
						 | 
					48c20bbd6d | ||
| 
						 | 
					05266b2849 | ||
| 
						 | 
					293a220719 | ||
| 
						 | 
					a0f7643838 | ||
| 
						 | 
					96c943a7de | ||
| 
						 | 
					57350a8324 | ||
| 
						 | 
					9953d8d662 | ||
| 
						 | 
					35efc4ed8a | ||
| 
						 | 
					de001f5022 | ||
| 
						 | 
					c737473f8b | ||
| 
						 | 
					a9db3283dd | ||
| 
						 | 
					77fbf68a43 | ||
| 
						 | 
					04a473b4a8 | ||
| 
						 | 
					49d7d4a106 | ||
| 
						 | 
					4b638e93be | ||
| 
						 | 
					e508fb101f | ||
| 
						 | 
					2c73cd7cf7 | ||
| 
						 | 
					da94a2c6bc | ||
| 
						 | 
					1de7e428cd | ||
| 
						 | 
					60994b6851 | ||
| 
						 | 
					30e14a157f | ||
| 
						 | 
					ff30e03e88 | ||
| 
						 | 
					88c952c1b4 | ||
| 
						 | 
					8441e65000 | ||
| 
						 | 
					d4ac4809c0 | ||
| 
						 | 
					824e091a67 | ||
| 
						 | 
					cc0ce1a756 | ||
| 
						 | 
					e5b39e6671 | ||
| 
						 | 
					6ad1ea004f | ||
| 
						 | 
					a640814ae0 | ||
| 
						 | 
					89962b01fa | ||
| 
						 | 
					b0a06bdc5f | ||
| 
						 | 
					54fc60b60e | ||
| 
						 | 
					830634517b | ||
| 
						 | 
					f99fd28fe6 | ||
| 
						 | 
					70f96e3bfd | ||
| 
						 | 
					a56bbba2bd | ||
| 
						 | 
					9f0945394f | ||
| 
						 | 
					c9dec5e3cd | ||
| 
						 | 
					6e8dd730ad | ||
| 
						 | 
					0fdab8c0b4 | ||
| 
						 | 
					24af87ae08 | ||
| 
						 | 
					175150d928 | ||
| 
						 | 
					50963e0fa1 | ||
| 
						 | 
					e0f65118a4 | ||
| 
						 | 
					c48111496c | ||
| 
						 | 
					2630c46c24 | ||
| 
						 | 
					4a41b24386 | ||
| 
						 | 
					f3d59531c1 | ||
| 
						 | 
					4a67ba0a88 | ||
| 
						 | 
					d19d535873 | ||
| 
						 | 
					2fd035582a | ||
| 
						 | 
					c057e14daf | ||
| 
						 | 
					06771873f3 | ||
| 
						 | 
					ee008c7db4 | ||
| 
						 | 
					b4874d9705 | ||
| 
						 | 
					06fc4209a7 | ||
| 
						 | 
					9d46a6d133 | ||
| 
						 | 
					bbbbd3cb5f | ||
| 
						 | 
					5db4a93697 | ||
| 
						 | 
					dc7529dc8e | ||
| 
						 | 
					301ea36264 | ||
| 
						 | 
					fc26badfdb | ||
| 
						 | 
					0ded79b785 | ||
| 
						 | 
					83a79dcb6d | ||
| 
						 | 
					c98e92b034 | ||
| 
						 | 
					c8dd6b1af1 | ||
| 
						 | 
					7ee0c9cc78 | ||
| 
						 | 
					648e452f8b | ||
| 
						 | 
					8e3177135f | ||
| 
						 | 
					7352cbc220 | ||
| 
						 | 
					3dd87d8989 | ||
| 
						 | 
					4a3192b704 | ||
| 
						 | 
					7cbb8947ff | ||
| 
						 | 
					482ad0444c | ||
| 
						 | 
					a3da545905 | ||
| 
						 | 
					043baf299a | ||
| 
						 | 
					cf2f7a9af5 | ||
| 
						 | 
					204219a477 | ||
| 
						 | 
					f7101c6aec | ||
| 
						 | 
					d8f104e765 | ||
| 
						 | 
					52e8568bdb | ||
| 
						 | 
					ab94ff3cdc | ||
| 
						 | 
					4bee83a981 | ||
| 
						 | 
					4359f23e63 | ||
| 
						 | 
					b7968becc3 | ||
| 
						 | 
					cc9075a14b | ||
| 
						 | 
					bc06ad4226 | ||
| 
						 | 
					183c829917 | ||
| 
						 | 
					266eee3029 | ||
| 
						 | 
					80631f5152 | ||
| 
						 | 
					3b965e7431 | ||
| 
						 | 
					a6c99568aa | ||
| 
						 | 
					c5639ca45b | ||
| 
						 | 
					46605615c0 | ||
| 
						 | 
					1950fba34b | ||
| 
						 | 
					02e694afc5 | ||
| 
						 | 
					18534b73be | ||
| 
						 | 
					430e2c27f2 | ||
| 
						 | 
					e623eb4197 | ||
| 
						 | 
					5f805ba414 | ||
| 
						 | 
					ba00f1d302 | ||
| 
						 | 
					367dc0d78f | ||
| 
						 | 
					48a824de07 | ||
| 
						 | 
					6c5200d0a1 | ||
| 
						 | 
					712ff6f5cc | ||
| 
						 | 
					f80bc3c09a | ||
| 
						 | 
					7c5efad1ca | ||
| 
						 | 
					d0edd224ca | ||
| 
						 | 
					6c5ef63375 | ||
| 
						 | 
					402420e159 | ||
| 
						 | 
					af302d62f3 | ||
| 
						 | 
					bedb908682 | ||
| 
						 | 
					9bf30de4cb | ||
| 
						 | 
					9302e2e27d | ||
| 
						 | 
					6ab8815b3b | ||
| 
						 | 
					4baae014ab | ||
| 
						 | 
					d000c35ff5 | ||
| 
						 | 
					9570c9199a | ||
| 
						 | 
					705ad208d7 | ||
| 
						 | 
					6e3367c4e7 | ||
| 
						 | 
					71d8da316a | ||
| 
						 | 
					ba990514c4 | ||
| 
						 | 
					0ae7f3b445 | ||
| 
						 | 
					307b49fee6 | ||
| 
						 | 
					6a940716f0 | ||
| 
						 | 
					53b30e5f15 | ||
| 
						 | 
					134741f681 | ||
| 
						 | 
					9ef77cfd3f | ||
| 
						 | 
					01e8f413ea | ||
| 
						 | 
					6aa2057202 | ||
| 
						 | 
					4583158cf5 | ||
| 
						 | 
					48b14f7347 | ||
| 
						 | 
					623e1896aa | ||
| 
						 | 
					e29652c8dd | ||
| 
						 | 
					6d0fe3e2ee | ||
| 
						 | 
					f25f13e789 | ||
| 
						 | 
					4101618556 | ||
| 
						 | 
					5f30084c6f | ||
| 
						 | 
					4c266aeb42 | ||
| 
						 | 
					00794c41e6 | ||
| 
						 | 
					f1cdfecaaf | ||
| 
						 | 
					c738615bf2 | ||
| 
						 | 
					8af885a0f3 | ||
| 
						 | 
					62cdb5c0c2 | ||
| 
						 | 
					843c4f8c1e | ||
| 
						 | 
					d82c9a24a7 | ||
| 
						 | 
					b24860c97b | ||
| 
						 | 
					e8e298581c | ||
| 
						 | 
					05769fdff1 | ||
| 
						 | 
					5c5c628954 | ||
| 
						 | 
					10f4172349 | ||
| 
						 | 
					d781c75dfe | ||
| 
						 | 
					0c0d1de317 | ||
| 
						 | 
					ab370762a4 | ||
| 
						 | 
					51bb4566e7 | ||
| 
						 | 
					0e00057477 | ||
| 
						 | 
					ccd70a835f | ||
| 
						 | 
					5bfde87159 | ||
| 
						 | 
					949dcd0b23 | ||
| 
						 | 
					4cad868175 | ||
| 
						 | 
					35f74cb3b6 | ||
| 
						 | 
					51a3361686 | ||
| 
						 | 
					0ac0cc263e | ||
| 
						 | 
					c730b5c009 | ||
| 
						 | 
					8c1cc56321 | ||
| 
						 | 
					c01abd559b | ||
| 
						 | 
					a5039cff58 | ||
| 
						 | 
					3bf4155fec | ||
| 
						 | 
					fb515bc057 | ||
| 
						 | 
					bd0c906c44 | ||
| 
						 | 
					0871b9c84c | ||
| 
						 | 
					0d4b4a1837 | ||
| 
						 | 
					474954afb6 | ||
| 
						 | 
					5041708810 | ||
| 
						 | 
					c630378701 | ||
| 
						 | 
					be5e6cc870 | ||
| 
						 | 
					87afc99489 | ||
| 
						 | 
					ff49b8fea8 | ||
| 
						 | 
					bb0bc65e27 | ||
| 
						 | 
					6a60704d8e | ||
| 
						 | 
					cd40beb1eb | ||
| 
						 | 
					e1df6b0a6f | ||
| 
						 | 
					b582b9f04d | ||
| 
						 | 
					407801d9ff | ||
| 
						 | 
					6bcbc0ae91 | ||
| 
						 | 
					62bd7d5eef | ||
| 
						 | 
					663962e873 | ||
| 
						 | 
					3e7458dfaa | ||
| 
						 | 
					db5cc430c7 | ||
| 
						 | 
					5b91a776f1 | ||
| 
						 | 
					0aa13fbea7 | ||
| 
						 | 
					2d20686131 | ||
| 
						 | 
					5f2163bff4 | ||
| 
						 | 
					9c59bdaea1 | ||
| 
						 | 
					7f4c116b2c | ||
| 
						 | 
					ba842a1e49 | ||
| 
						 | 
					41f4aebdc7 | ||
| 
						 | 
					c12470ff12 | ||
| 
						 | 
					6722e52c9b | ||
| 
						 | 
					e68355d880 | ||
| 
						 | 
					7d29d8a05a | ||
| 
						 | 
					e6792790cc | ||
| 
						 | 
					4354079c4e | ||
| 
						 | 
					a02a9d803e | ||
| 
						 | 
					46462a790c | ||
| 
						 | 
					a971cedde5 | ||
| 
						 | 
					fda9557811 | ||
| 
						 | 
					633dbe3e2b | ||
| 
						 | 
					981baed9d3 | ||
| 
						 | 
					90fc30a228 | ||
| 
						 | 
					0641ec1e2a | ||
| 
						 | 
					82d4ee01d2 | ||
| 
						 | 
					d564dc0ecb | ||
| 
						 | 
					cb462dcb39 | ||
| 
						 | 
					3401b76c44 | ||
| 
						 | 
					599a518cc3 | ||
| 
						 | 
					59223628af | ||
| 
						 | 
					029332fb51 | ||
| 
						 | 
					aba73bd0f8 | ||
| 
						 | 
					893bff1b59 | ||
| 
						 | 
					bef3ccd164 | ||
| 
						 | 
					02fb3ab9b4 | ||
| 
						 | 
					87c17fc16d | ||
| 
						 | 
					03424f0474 | ||
| 
						 | 
					bf9edf41d9 | ||
| 
						 | 
					377d11bf48 | ||
| 
						 | 
					42ad6832ea | ||
| 
						 | 
					e2b6296cdf | ||
| 
						 | 
					a3b1984d0a | ||
| 
						 | 
					f24286b717 | ||
| 
						 | 
					375275b9c0 | ||
| 
						 | 
					8c41fb692b | ||
| 
						 | 
					5de3075252 | ||
| 
						 | 
					c72e8d3da6 | ||
| 
						 | 
					40469c5de5 | ||
| 
						 | 
					6827056a1d | ||
| 
						 | 
					1172662095 | ||
| 
						 | 
					43dc12074d | ||
| 
						 | 
					6eb272ba4a | ||
| 
						 | 
					1bb6e4e899 | ||
| 
						 | 
					157657b298 | ||
| 
						 | 
					188712936f | ||
| 
						 | 
					0e5be846be | ||
| 
						 | 
					05364685af | ||
| 
						 | 
					03a2c41718 | ||
| 
						 | 
					de4f7c3166 | ||
| 
						 | 
					ba0153539d | ||
| 
						 | 
					8a64d345a4 | ||
| 
						 | 
					62939edc2e | ||
| 
						 | 
					56a7505f15 | ||
| 
						 | 
					01a02c41ff | ||
| 
						 | 
					a03a1034de | ||
| 
						 | 
					ece3ad2b13 | ||
| 
						 | 
					20cc7572a5 | ||
| 
						 | 
					7700b1a541 | ||
| 
						 | 
					fc9a7f2cd4 | ||
| 
						 | 
					a97a56bf88 | ||
| 
						 | 
					de2e785731 | ||
| 
						 | 
					eb3a2e41ed | ||
| 
						 | 
					acf5eda756 | ||
| 
						 | 
					df110695cd | ||
| 
						 | 
					ebf63f55e6 | ||
| 
						 | 
					0a1248861b | ||
| 
						 | 
					10d4ce4eef | ||
| 
						 | 
					35f635bdb4 | ||
| 
						 | 
					27c764afd3 | ||
| 
						 | 
					1f500d5aeb | ||
| 
						 | 
					4e13134774 | ||
| 
						 | 
					2dbd03b74c | ||
| 
						 | 
					0084169c02 | ||
| 
						 | 
					4aabbefcc8 | ||
| 
						 | 
					6daeb7e288 | ||
| 
						 | 
					81b367df07 | ||
| 
						 | 
					0f410e11eb | ||
| 
						 | 
					0a9dffb7a1 | ||
| 
						 | 
					67b90f5582 | ||
| 
						 | 
					eaceba3ed3 | ||
| 
						 | 
					d7dceede4b | ||
| 
						 | 
					9c867b467a | ||
| 
						 | 
					d35a01f5c4 | ||
| 
						 | 
					1e2f953a8f | ||
| 
						 | 
					2937516869 | ||
| 
						 | 
					92d2065f1d | ||
| 
						 | 
					13c2f50f19 | ||
| 
						 | 
					dccc45d492 | ||
| 
						 | 
					a9362e0b4a | ||
| 
						 | 
					10c46723fe | ||
| 
						 | 
					666e170f7d | ||
| 
						 | 
					109c48694e | ||
| 
						 | 
					d0cd58e923 | ||
| 
						 | 
					16b8bbfca6 | ||
| 
						 | 
					209aa220b0 | ||
| 
						 | 
					dd8db43dea | ||
| 
						 | 
					7d40e148e9 | ||
| 
						 | 
					ef6eeea608 | ||
| 
						 | 
					0c13b71466 | ||
| 
						 | 
					e1c25a3c8e | ||
| 
						 | 
					e5bfb8f8a3 | ||
| 
						 | 
					4dfcd32d92 | ||
| 
						 | 
					167deb5d7f | ||
| 
						 | 
					8cb3007d66 | ||
| 
						 | 
					49bcd30e77 | ||
| 
						 | 
					1e2954a993 | ||
| 
						 | 
					fe5711d9c4 | ||
| 
						 | 
					33f812179f | ||
| 
						 | 
					d7a2614819 | ||
| 
						 | 
					dc259847af | ||
| 
						 | 
					9bcd1cd237 | ||
| 
						 | 
					3a1ae8f7c0 | ||
| 
						 | 
					9cbe196913 | ||
| 
						 | 
					d0c8b1c15b | ||
| 
						 | 
					2efdea9a29 | ||
| 
						 | 
					978dc549f4 | ||
| 
						 | 
					d4d8943c9f | ||
| 
						 | 
					12a1f46703 | ||
| 
						 | 
					15d20a54b3 | ||
| 
						 | 
					bedfbd232d | ||
| 
						 | 
					3c289e7235 | ||
| 
						 | 
					450d2410d9 | ||
| 
						 | 
					e1ecc8d6cf | ||
| 
						 | 
					e9d9da3355 | ||
| 
						 | 
					6d3c442464 | ||
| 
						 | 
					1a8f5a4007 | ||
| 
						 | 
					20414d9659 | ||
| 
						 | 
					1fe8bc05b3 | ||
| 
						 | 
					049afa994b | ||
| 
						 | 
					ba41bcd561 | ||
| 
						 | 
					4aa84c265d | ||
| 
						 | 
					436945b711 | ||
| 
						 | 
					b749119a1c | ||
| 
						 | 
					87c61de11e | ||
| 
						 | 
					b293638c40 | ||
| 
						 | 
					d1e0c2d164 | ||
| 
						 | 
					7e6a7468df | ||
| 
						 | 
					1ffe6b1c3c | ||
| 
						 | 
					a76733df60 | ||
| 
						 | 
					70f5280fcc | ||
| 
						 | 
					4cbe90597e | ||
| 
						 | 
					0afe60e11a | ||
| 
						 | 
					6982d02489 | ||
| 
						 | 
					031aefe05a | ||
| 
						 | 
					fa01cfd840 | ||
| 
						 | 
					331bc0f5a6 | ||
| 
						 | 
					7e9eb2f98a | ||
| 
						 | 
					5a72b1e523 | ||
| 
						 | 
					2693fabac2 | ||
| 
						 | 
					ce16be6393 | ||
| 
						 | 
					b694c339cb | ||
| 
						 | 
					3957b46d98 | ||
| 
						 | 
					54929e4b0d | ||
| 
						 | 
					ca20d52ac1 | ||
| 
						 | 
					e22a6dad6f | ||
| 
						 | 
					ee84468498 | ||
| 
						 | 
					746f19b0b8 | ||
| 
						 | 
					a646a035d8 | ||
| 
						 | 
					505cb23467 | ||
| 
						 | 
					345e109d9f | ||
| 
						 | 
					bca944034a | ||
| 
						 | 
					be27905776 | ||
| 
						 | 
					53196c7603 | ||
| 
						 | 
					0777ddfbfc | ||
| 
						 | 
					18bd71da89 | ||
| 
						 | 
					ecd13dd5a4 | ||
| 
						 | 
					3ef1ac434a | ||
| 
						 | 
					60e32a05cd | ||
| 
						 | 
					b7df0ee936 | ||
| 
						 | 
					4cf24c54d7 | ||
| 
						 | 
					c4ed0738cf | ||
| 
						 | 
					88b20e5545 | ||
| 
						 | 
					7c5b072303 | ||
| 
						 | 
					347a23ad60 | ||
| 
						 | 
					29806c4525 | ||
| 
						 | 
					a045dc8012 | ||
| 
						 | 
					80e7e2f5b6 | ||
| 
						 | 
					1789d181aa | ||
| 
						 | 
					f0ca0c3379 | ||
| 
						 | 
					1711e44a4d | ||
| 
						 | 
					afe4af2ff6 | ||
| 
						 | 
					ec8c564e25 | ||
| 
						 | 
					fd9d64b342 | ||
| 
						 | 
					1d928f7ea8 | ||
| 
						 | 
					f3c9e8f013 | ||
| 
						 | 
					99813136fe | ||
| 
						 | 
					21a29d7212 | ||
| 
						 | 
					f679a4a1dc | ||
| 
						 | 
					d27f7f13e5 | ||
| 
						 | 
					80cfc3b8a5 | ||
| 
						 | 
					d159e47a62 | ||
| 
						 | 
					47fd890bcd | ||
| 
						 | 
					af01193bc2 | ||
| 
						 | 
					8373e26f1e | ||
| 
						 | 
					1cc2a90b08 | ||
| 
						 | 
					a8a729fcda | ||
| 
						 | 
					fe93224d77 | ||
| 
						 | 
					ddccd1dd3f | ||
| 
						 | 
					2b61b184f2 | ||
| 
						 | 
					01d761ce71 | ||
| 
						 | 
					cfa6b28131 | ||
| 
						 | 
					431fbd471f | ||
| 
						 | 
					ca5e4559df | ||
| 
						 | 
					928946cd4c | ||
| 
						 | 
					221bbdeff3 | ||
| 
						 | 
					879989b5b6 | ||
| 
						 | 
					1d42ce6282 | ||
| 
						 | 
					6f131933b7 | ||
| 
						 | 
					aaa6ae879b | ||
| 
						 | 
					da8c40dca8 | ||
| 
						 | 
					caa4b7d19e | ||
| 
						 | 
					b99adb5e1a | ||
| 
						 | 
					8b23cafed9 | ||
| 
						 | 
					3c82ae04d7 | ||
| 
						 | 
					504cecfe97 | ||
| 
						 | 
					880b6e0476 | ||
| 
						 | 
					4b430aac7c | ||
| 
						 | 
					819bda4573 | ||
| 
						 | 
					8b327552b2 | ||
| 
						 | 
					24a2bbdb65 | ||
| 
						 | 
					2692cbe5e0 | ||
| 
						 | 
					3b01e633a7 | ||
| 
						 | 
					8a720c328a | ||
| 
						 | 
					585bb697b5 | ||
| 
						 | 
					3b905f29ef | ||
| 
						 | 
					f2512b032f | ||
| 
						 | 
					29d3073539 | ||
| 
						 | 
					2a91a5d2e9 | ||
| 
						 | 
					2492497417 | ||
| 
						 | 
					dc3a0eca69 | ||
| 
						 | 
					d5714eb749 | ||
| 
						 | 
					bd90b30300 | ||
| 
						 | 
					5946079f47 | ||
| 
						 | 
					72b546e945 | ||
| 
						 | 
					65f8495a12 | ||
| 
						 | 
					ab64e7e013 | ||
| 
						 | 
					80053c1cc3 | ||
| 
						 | 
					067c962baf | ||
| 
						 | 
					e5c6953e98 | ||
| 
						 | 
					03d8d095cc | ||
| 
						 | 
					22f44d117a | ||
| 
						 | 
					417d4089d7 | ||
| 
						 | 
					c892401218 | ||
| 
						 | 
					3483ea7025 | ||
| 
						 | 
					9ec1b651cd | ||
| 
						 | 
					f06b37f180 | ||
| 
						 | 
					ca01015586 | ||
| 
						 | 
					362b5cd031 | ||
| 
						 | 
					64e9eac80f | ||
| 
						 | 
					e4c2485823 | ||
| 
						 | 
					a5f77f23e9 | ||
| 
						 | 
					0f7ff181df | ||
| 
						 | 
					1788551393 | ||
| 
						 | 
					1c9d23713d | ||
| 
						 | 
					3f779e14fa | ||
| 
						 | 
					58eff8c4cb | ||
| 
						 | 
					6c495bcafc | ||
| 
						 | 
					6de6b1542c | ||
| 
						 | 
					62425bc514 | ||
| 
						 | 
					8cf1c2969b | ||
| 
						 | 
					5d56822d1b | ||
| 
						 | 
					c014bc200e | ||
| 
						 | 
					56de05a392 | ||
| 
						 | 
					76ca5181ae | ||
| 
						 | 
					8181518c24 | ||
| 
						 | 
					ba636ed25d | ||
| 
						 | 
					e797cba504 | ||
| 
						 | 
					ecc294953b | ||
| 
						 | 
					e9d8b30de0 | ||
| 
						 | 
					4a42012906 | ||
| 
						 | 
					37016259e1 | ||
| 
						 | 
					bf5fc97e1a | ||
| 
						 | 
					1c89ef3f12 | ||
| 
						 | 
					b2d022edff | ||
| 
						 | 
					a5a143111c | ||
| 
						 | 
					9338fdeebf | ||
| 
						 | 
					6a486d4d73 | ||
| 
						 | 
					e55db3cb75 | ||
| 
						 | 
					b39078af7e | ||
| 
						 | 
					8e8e631d22 | ||
| 
						 | 
					a34da2459d | ||
| 
						 | 
					81a64c2cff | ||
| 
						 | 
					414a6617f8 | ||
| 
						 | 
					4af819f449 | ||
| 
						 | 
					229016ca10 | ||
| 
						 | 
					51f3f97967 | ||
| 
						 | 
					c548c3bd88 | ||
| 
						 | 
					0877e6a2f2 | ||
| 
						 | 
					133aa1a1f2 | ||
| 
						 | 
					c32e71cae3 | ||
| 
						 | 
					a71bdb6f06 | ||
| 
						 | 
					f6bc82e77a | ||
| 
						 | 
					5736b6aa5c | ||
| 
						 | 
					c30b080e44 | ||
| 
						 | 
					61567a66b0 | ||
| 
						 | 
					e23137eb63 | ||
| 
						 | 
					8acf81b937 | ||
| 
						 | 
					f1683ad39f | ||
| 
						 | 
					33ee969d91 | ||
| 
						 | 
					f03471133e | ||
| 
						 | 
					cdbabcac89 | ||
| 
						 | 
					0122e70b1d | ||
| 
						 | 
					a4037c151e | ||
| 
						 | 
					5d58d6d14f | ||
| 
						 | 
					8a1446ac4e | ||
| 
						 | 
					1ce3929d66 | ||
| 
						 | 
					dd62089b61 | ||
| 
						 | 
					8cda7e4dd8 | ||
| 
						 | 
					bc3abdfe91 | ||
| 
						 | 
					e793dfff3a | ||
| 
						 | 
					12ec0b46bc | ||
| 
						 | 
					55fa65e168 | ||
| 
						 | 
					6de6216bc6 | ||
| 
						 | 
					1bca424acf | ||
| 
						 | 
					a51e688388 | ||
| 
						 | 
					c40fc2b159 | ||
| 
						 | 
					d859646dac | ||
| 
						 | 
					a0e0f28c66 | ||
| 
						 | 
					8595675531 | ||
| 
						 | 
					70435b9e5a | ||
| 
						 | 
					1731f5274b | ||
| 
						 | 
					6a775f6026 | ||
| 
						 | 
					0b3e63bd3f | ||
| 
						 | 
					514ff1fbe7 | ||
| 
						 | 
					85bf9f319b | ||
| 
						 | 
					dff4e735f0 | ||
| 
						 | 
					b81b9c574b | ||
| 
						 | 
					f82eb87476 | ||
| 
						 | 
					d47bd677da | ||
| 
						 | 
					2c32b7fa94 | ||
| 
						 | 
					4d996c95e0 | ||
| 
						 | 
					90473b7b10 | ||
| 
						 | 
					e4f756ce73 | ||
| 
						 | 
					10159e934f | ||
| 
						 | 
					865e6fd3d7 | ||
| 
						 | 
					a1dd57ded6 | ||
| 
						 | 
					1c808b95a8 | ||
| 
						 | 
					0c024515f1 | ||
| 
						 | 
					4c7d82f4eb | ||
| 
						 | 
					e4ee00b403 | ||
| 
						 | 
					d380fdd0ea | ||
| 
						 | 
					9756ac639b | ||
| 
						 | 
					7105f67145 | ||
| 
						 | 
					35547c4316 | ||
| 
						 | 
					ccc71a7225 | ||
| 
						 | 
					c5101d3358 | ||
| 
						 | 
					5bbf197a8d | ||
| 
						 | 
					70b5c62c9f | ||
| 
						 | 
					33ef8aadbe | ||
| 
						 | 
					e989bbba29 | ||
| 
						 | 
					3f35900914 | ||
| 
						 | 
					e5f738b567 | ||
| 
						 | 
					6fc357ecd0 | ||
| 
						 | 
					758659a91e | ||
| 
						 | 
					b05858c6e9 | ||
| 
						 | 
					a481e89cad | ||
| 
						 | 
					b9094e306e | ||
| 
						 | 
					31c8617258 | ||
| 
						 | 
					f94d727af7 | ||
| 
						 | 
					054829c4d5 | ||
| 
						 | 
					d20c92bd4f | ||
| 
						 | 
					64b9fa090a | ||
| 
						 | 
					5abc84b776 | ||
| 
						 | 
					2b0666bcf8 | ||
| 
						 | 
					2ef6ac2fe4 | ||
| 
						 | 
					4bb887a390 | ||
| 
						 | 
					8fd8ca2c50 | ||
| 
						 | 
					f69d5b5831 | ||
| 
						 | 
					fead4b76f8 | ||
| 
						 | 
					800c1065b9 | ||
| 
						 | 
					782e0a8535 | ||
| 
						 | 
					5863d81571 | ||
| 
						 | 
					c15e34143f | ||
| 
						 | 
					57c3a42a6e | ||
| 
						 | 
					7c13a7bce0 | ||
| 
						 | 
					9c23b55bc0 | ||
| 
						 | 
					5c0811c5ba | ||
| 
						 | 
					6bc92a0feb | ||
| 
						 | 
					9f5f5f54a0 | ||
| 
						 | 
					047ef8e669 | ||
| 
						 | 
					be572755a9 | ||
| 
						 | 
					393e1c6481 | ||
| 
						 | 
					539696e84a | ||
| 
						 | 
					6ecfc10b8c | ||
| 
						 | 
					1c7bab33e6 | ||
| 
						 | 
					b0cdb308bd | ||
| 
						 | 
					9d61a37945 | ||
| 
						 | 
					c4bd38cb9e | ||
| 
						 | 
					2f37355d77 | ||
| 
						 | 
					59a132fd6b | ||
| 
						 | 
					9c3bd7dc20 | ||
| 
						 | 
					d73d312882 | ||
| 
						 | 
					3361fabfc4 | ||
| 
						 | 
					030682c754 | ||
| 
						 | 
					3029e69767 | ||
| 
						 | 
					7dcc717017 | ||
| 
						 | 
					9825506ab7 | ||
| 
						 | 
					f1eca8a4bf | ||
| 
						 | 
					199d304841 | ||
| 
						 | 
					4163526379 | ||
| 
						 | 
					9272a1181c | ||
| 
						 | 
					2e51c289ca | ||
| 
						 | 
					03828943b0 | ||
| 
						 | 
					d71ef779ec | ||
| 
						 | 
					9736d5c785 | ||
| 
						 | 
					ef33864adf | ||
| 
						 | 
					d7b6a97415 | ||
| 
						 | 
					5b4c417729 | ||
| 
						 | 
					9c4e9ed4be | ||
| 
						 | 
					5a25348e04 | ||
| 
						 | 
					f5a73a5449 | ||
| 
						 | 
					82fecd7bbd | ||
| 
						 | 
					9badef6f03 | ||
| 
						 | 
					0e2f711cac | ||
| 
						 | 
					fbec881f70 | ||
| 
						 | 
					a3f1ff30e0 | ||
| 
						 | 
					4eb93ea49b | ||
| 
						 | 
					7d8ecead7d | ||
| 
						 | 
					5cf1f880c6 | ||
| 
						 | 
					873ae3e8af | ||
| 
						 | 
					4a273c7134 | ||
| 
						 | 
					439a7ed9e8 | ||
| 
						 | 
					d941af4cf2 | ||
| 
						 | 
					cb79d7baab | ||
| 
						 | 
					fbe2fb10af | ||
| 
						 | 
					1a00ba109b | ||
| 
						 | 
					88ee57cf15 | ||
| 
						 | 
					857964653c | ||
| 
						 | 
					682674727c | ||
| 
						 | 
					5451e61484 | ||
| 
						 | 
					778b6be4e0 | ||
| 
						 | 
					c52c6ec3a3 | ||
| 
						 | 
					34837c7777 | ||
| 
						 | 
					f98124a57f | ||
| 
						 | 
					7838dd6277 | ||
| 
						 | 
					a6f656eacf | ||
| 
						 | 
					43646a8e19 | ||
| 
						 | 
					8b52639d23 | ||
| 
						 | 
					8afb439ed7 | ||
| 
						 | 
					42b175144a | ||
| 
						 | 
					cb6e2c4455 | ||
| 
						 | 
					8662be2e4e | ||
| 
						 | 
					f66f43d91a | ||
| 
						 | 
					c112edd8ac | ||
| 
						 | 
					398bae1f64 | ||
| 
						 | 
					7c2a6822b5 | ||
| 
						 | 
					3a33e006d4 | ||
| 
						 | 
					3aedafbfc6 | ||
| 
						 | 
					4587352377 | ||
| 
						 | 
					62dac32400 | ||
| 
						 | 
					401a9e1a45 | ||
| 
						 | 
					569d0ac374 | ||
| 
						 | 
					e75312007d | ||
| 
						 | 
					103a5371e6 | ||
| 
						 | 
					abfe17ce74 | ||
| 
						 | 
					86295fcf67 | ||
| 
						 | 
					c9012c54df | ||
| 
						 | 
					fd051552f3 | ||
| 
						 | 
					169076e68e | ||
| 
						 | 
					971aa5ba16 | ||
| 
						 | 
					6be54478f4 | ||
| 
						 | 
					6b225058de | ||
| 
						 | 
					78d96fdaa2 | ||
| 
						 | 
					8129e3cf39 | ||
| 
						 | 
					0e5f663df5 | ||
| 
						 | 
					de45527d45 | ||
| 
						 | 
					d7b3f33030 | ||
| 
						 | 
					88daaed113 | ||
| 
						 | 
					41744c0ab6 | ||
| 
						 | 
					c3cd5314fe | ||
| 
						 | 
					6f29ab8942 | ||
| 
						 | 
					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 | 
@@ -40,32 +40,38 @@ Before contributing, please ensure that you have the following setup:
 | 
			
		||||
   - [Shell Format](https://marketplace.visualstudio.com/items?itemName=foxundermoon.shell-format)
 | 
			
		||||
 | 
			
		||||
### Important Notes
 | 
			
		||||
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.sh) as templates when creating new scripts.
 | 
			
		||||
- Use [AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh) and [AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh) as templates when creating new scripts. Final version of the script (the one you will push for review), must have all comments removed, except the ones in the file header.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# 🚀 The Application Script (ct/AppName.sh)
 | 
			
		||||
 | 
			
		||||
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/ct/AppName.md).
 | 
			
		||||
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.md).
 | 
			
		||||
- These scripts are responsible for container creation, setting the necessary variables and handling the update of the application once installed.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# 🛠 The Installation Script (install/AppName-install.sh)
 | 
			
		||||
 | 
			
		||||
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.md).
 | 
			
		||||
- You can find all coding standards, as well as the structure for this file [here](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.md).
 | 
			
		||||
- These scripts are responsible for the installation of the application.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 🚀 Building Your Own Scripts
 | 
			
		||||
 | 
			
		||||
Start with the [template script](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.sh)
 | 
			
		||||
Start with the [template script](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 🤝 Contribution Process
 | 
			
		||||
 | 
			
		||||
All PR's related to new scripts should be made against our Dev repository first, where we can test the scripts before they are pushed and merged in the official repository.
 | 
			
		||||
 | 
			
		||||
**Our Dev repo is `http://www.github.com/community-scripts/ProxmoxVED`**
 | 
			
		||||
 | 
			
		||||
You will need to adjust paths mentioned further down this document to match the repo you're pushing the scripts to.
 | 
			
		||||
 | 
			
		||||
### 1. Fork the repository
 | 
			
		||||
Fork to your GitHub account
 | 
			
		||||
 | 
			
		||||
@@ -80,7 +86,24 @@ 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]`\
 | 
			
		||||
 in following files:
 | 
			
		||||
 | 
			
		||||
`misc/build.func`\
 | 
			
		||||
`misc/install.func`\
 | 
			
		||||
`ct/AppName.sh`
 | 
			
		||||
 | 
			
		||||
Example: `https://raw.githubusercontent.com/tremor021/PromoxVE/refs/heads/testbranch`
 | 
			
		||||
 | 
			
		||||
Also you need to change:\
 | 
			
		||||
`https://github.com/community-scripts/ProxmoxVE/raw/main`\
 | 
			
		||||
to\
 | 
			
		||||
`https://github.com/[USER]/[REPOSITORY]/raw/[BRANCH]`\
 | 
			
		||||
in `misc/install.func` in order for `update` shell command to work.\
 | 
			
		||||
These changes are only while writing and testing your scripts. Before opening a Pull Request, you should change all above mentioned paths in `misc/build.func`, `misc/install.func` and `ct/AppName.sh` to point to the original paths.
 | 
			
		||||
 | 
			
		||||
### 4. Commit changes (without build.func and install.func!)
 | 
			
		||||
```bash
 | 
			
		||||
@@ -93,14 +116,14 @@ git push origin your-feature-branch
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 6. Create a Pull Request
 | 
			
		||||
Open a Pull Request from your feature branch to the main repository branch. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
 | 
			
		||||
Open a Pull Request from your feature branch to the main branch on the Dev repository. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## 📚 Pages
 | 
			
		||||
 | 
			
		||||
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/ct/AppName.sh)
 | 
			
		||||
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/install/AppName-install.sh)
 | 
			
		||||
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_GUIDE/json/AppName.json)
 | 
			
		||||
- [CT Template: AppName.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/ct/AppName.sh)
 | 
			
		||||
- [Install Template: AppName-install.sh](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/install/AppName-install.sh)
 | 
			
		||||
- [JSON Template: AppName.json](https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/json/AppName.json)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -75,6 +75,7 @@ Example:
 | 
			
		||||
>
 | 
			
		||||
> - Add your username and source URL
 | 
			
		||||
> - For existing scripts, add "| Co-Author [YourUserName]" after the current author
 | 
			
		||||
> - Source is a URL of github repo containting source files of the application you're installing (not URL of your homepage or a blog)
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +96,7 @@ Example:
 | 
			
		||||
>| Variable | Description | Notes |
 | 
			
		||||
>|----------|-------------|-------|
 | 
			
		||||
>| `APP` | Application name | Must match ct\AppName.sh |
 | 
			
		||||
>| `TAGS` | Proxmox display tags without Spaces, only ; | Limit the number |  
 | 
			
		||||
>| `var_tags` | Proxmox display tags without Spaces, only ; | Limit the number to 2 |  
 | 
			
		||||
>| `var_cpu` | CPU cores | Number of cores |
 | 
			
		||||
>| `var_ram` | RAM | In MB |
 | 
			
		||||
>| `var_disk` | Disk capacity | In GB |
 | 
			
		||||
@@ -119,18 +120,13 @@ var_unprivileged="1"
 | 
			
		||||
## 2.2 **📋 App output & base settings**
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- `header_info`: Generates ASCII header for APP
 | 
			
		||||
- `base_settings`: Allows overwriting variable values
 | 
			
		||||
 | 
			
		||||
## 2.3 **🛠 Core functions**
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -171,7 +167,7 @@ if [[ ! -d /opt/snipe-it ]]; then
 | 
			
		||||
 | 
			
		||||
### 3.3 **Check version**
 | 
			
		||||
 | 
			
		||||
- Befoer updating, check if a new version exists.
 | 
			
		||||
- Before updating, check if a new version exists.
 | 
			
		||||
  - We use the `${APPLICATION}_version.txt` file created in `/opt` during the install to compare new versions against the currently installed version.
 | 
			
		||||
 | 
			
		||||
Example with a Github Release:
 | 
			
		||||
@@ -198,13 +194,13 @@ wget -q
 | 
			
		||||
unzip -q
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
- If a command does not come with this functionality use `&>/dev/null` to suppress it's output.
 | 
			
		||||
- If a command does not come with this functionality use `$STD` to suppress it's output.
 | 
			
		||||
 | 
			
		||||
Example:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
php artisan migrate --force &>/dev/null
 | 
			
		||||
php artisan config:clear &>/dev/null
 | 
			
		||||
$STD php artisan migrate --force 
 | 
			
		||||
$STD php artisan config:clear 
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 3.5 **Backups**
 | 
			
		||||
@@ -241,7 +237,7 @@ Example:
 | 
			
		||||
 | 
			
		||||
### 3.7 **No update function**
 | 
			
		||||
 | 
			
		||||
- In case you can not provide a update function use the following code to provide user feedback.
 | 
			
		||||
- In case you can not provide an update function use the following code to provide user feedback.
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
function update_script() {
 | 
			
		||||
@@ -252,7 +248,7 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_error "Ther is currently no automatic update function for ${APP}."
 | 
			
		||||
    msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
@@ -286,6 +282,6 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
- [ ] Metadata (author, license) is included at the top.
 | 
			
		||||
- [ ] Variables follow naming conventions.
 | 
			
		||||
- [ ] Update function exists.
 | 
			
		||||
- [ ] Update functions checks if app is installed an for new version.
 | 
			
		||||
- [ ] Update function up temporary files.
 | 
			
		||||
- [ ] Update functions checks if app is installed and for new version.
 | 
			
		||||
- [ ] Update function cleans up temporary files.
 | 
			
		||||
- [ ] Script ends with a helpful message for the user to reach the application.
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2024 community-scripts ORG
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: [YourUserName]
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: [SOURCE_URL]
 | 
			
		||||
@@ -8,7 +8,7 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="[APP_NAME]"
 | 
			
		||||
# Name of the app (e.g. Google, Adventurelog, Apache-Guacamole"
 | 
			
		||||
TAGS="[TAGS]"
 | 
			
		||||
var_tags="[TAGS]"
 | 
			
		||||
# Tags for Proxmox VE, maximum 2 pcs., no spaces allowed, separated by a semicolon ; (e.g. database | adblock;dhcp) 
 | 
			
		||||
var_cpu="[CPU]"
 | 
			
		||||
# Number of cores (1-X) (e.g. 4) - default are 2
 | 
			
		||||
@@ -23,11 +23,7 @@ var_version="[VERSION]"
 | 
			
		||||
var_unprivileged="[UNPRIVILEGED]"
 | 
			
		||||
# 1 = unprivileged container, 0 = privileged container
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -46,8 +42,6 @@ function update_script() {
 | 
			
		||||
    # Crawling the new version and checking whether an update is required
 | 
			
		||||
    RELEASE=$(curl -fsSL [RELEASE_URL] | [PARSE_RELEASE_COMMAND])
 | 
			
		||||
    if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
        msg_info "Updating $APP"
 | 
			
		||||
 | 
			
		||||
        # Stopping Services
 | 
			
		||||
        msg_info "Stopping $APP"
 | 
			
		||||
        systemctl stop [SERVICE_NAME]
 | 
			
		||||
@@ -66,7 +60,6 @@ function update_script() {
 | 
			
		||||
        # Starting Services
 | 
			
		||||
        msg_info "Starting $APP"
 | 
			
		||||
        systemctl start [SERVICE_NAME]
 | 
			
		||||
        sleep 2
 | 
			
		||||
        msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
        # Cleaning up
 | 
			
		||||
@@ -67,6 +67,7 @@ Example:
 | 
			
		||||
>
 | 
			
		||||
> - Add your username
 | 
			
		||||
> - When updating/reworking scripts, add "| Co-Author [YourUserName]"
 | 
			
		||||
> - Source is a URL of github repo containting source files of the application you're installing (not URL of your homepage or a blog)
 | 
			
		||||
 | 
			
		||||
### 1.3 **Variables and function import**
 | 
			
		||||
 | 
			
		||||
@@ -177,6 +178,7 @@ echo "${RELEASE}" >"/opt/AppName_version.txt"
 | 
			
		||||
- Use standard functions like `msg_info`, `msg_ok` or `msg_error` to print status messages.
 | 
			
		||||
- Each `msg_info` must be followed with a `msg_ok` before any other output is made.
 | 
			
		||||
- Display meaningful progress messages at key stages.
 | 
			
		||||
- Taking user input with `read -p` must be outside of `msg_info`...`msg_ok` code block
 | 
			
		||||
 | 
			
		||||
Example:
 | 
			
		||||
 | 
			
		||||
@@ -184,6 +186,8 @@ Example:
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt-get install -y ...
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
read -p "Do you wish to enable HTTPS mode? (y/N): " httpschoice
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 6.2 **Verbosity**
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2024 community-scripts ORG
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: [YourUserName]
 | 
			
		||||
# License: MIT
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: [SOURCE_URL]
 | 
			
		||||
 | 
			
		||||
# Import Functions und Setup
 | 
			
		||||
@@ -80,7 +80,4 @@ msg_info "Cleaning up"
 | 
			
		||||
rm -f ${RELEASE}.zip
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
    "documentation": null,
 | 
			
		||||
    "website": "LINK TO WEBSITE",
 | 
			
		||||
    "logo": "LINK TO LOGO",
 | 
			
		||||
    "description": "Deescription of the app",
 | 
			
		||||
    "description": "Description of the app",
 | 
			
		||||
    "install_methods": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "default",
 | 
			
		||||
@@ -30,8 +30,6 @@ body:
 | 
			
		||||
        required: true
 | 
			
		||||
      - label: "I have searched existing [discussions](https://github.com/community-scripts/ProxmoxVE/discussions?discussions_q=) and found no duplicate requests."
 | 
			
		||||
        required: true
 | 
			
		||||
      - label: "This is not a game-related request."
 | 
			
		||||
        required: true
 | 
			
		||||
- type: markdown
 | 
			
		||||
  attributes:
 | 
			
		||||
    value: "Thanks for submitting your request! The team will review it and reach out if we need more information."
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							@@ -1 +1,2 @@
 | 
			
		||||
ko_fi: community_scripts
 | 
			
		||||
github: community_scripts
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
name: "🐞 Script Issue Report"
 | 
			
		||||
description: Report a specific issue with a script. For other inquiries, please use the Discussions section.
 | 
			
		||||
 | 
			
		||||
labels: ["bug"]
 | 
			
		||||
body:
 | 
			
		||||
  - type: markdown
 | 
			
		||||
    attributes:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							@@ -3,7 +3,7 @@ contact_links:
 | 
			
		||||
    - name: 🤔 Questions and Help
 | 
			
		||||
      url: https://github.com/community-scripts/ProxmoxVE/discussions
 | 
			
		||||
      about: For suggestions or questions, please use the Discussions section.
 | 
			
		||||
    - name: 🌟 Feature request
 | 
			
		||||
    - name: 🌟 new Script request
 | 
			
		||||
      url: https://github.com/community-scripts/ProxmoxVE/discussions/new?category=request-script
 | 
			
		||||
      about: For feature/script requests, please use the Discussions section.
 | 
			
		||||
    - name: 💻 Discord
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								.github/ISSUE_TEMPLATE/feature_request.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								.github/ISSUE_TEMPLATE/feature_request.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
name: "✨ Feature Request"
 | 
			
		||||
description: "Suggest a new feature or enhancement."
 | 
			
		||||
labels: ["enhancement"]
 | 
			
		||||
body:
 | 
			
		||||
  - type: markdown
 | 
			
		||||
    attributes:
 | 
			
		||||
      value: |
 | 
			
		||||
        # ✨ **Feature Request**
 | 
			
		||||
        Have an idea for a new feature? Share your thoughts below!
 | 
			
		||||
 | 
			
		||||
  - type: input
 | 
			
		||||
    id: feature_summary
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: "🌟 Briefly describe the feature"
 | 
			
		||||
      placeholder: "e.g., Add support for XYZ"
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: feature_description
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: "📝 Detailed description"
 | 
			
		||||
      placeholder: "Explain the feature in detail"
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: use_case
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: "💡 Why is this useful?"
 | 
			
		||||
      placeholder: "Describe the benefit of this feature"
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
							
								
								
									
										25
									
								
								.github/ISSUE_TEMPLATE/task.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.github/ISSUE_TEMPLATE/task.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
name: "🛠️ Task / General Request"
 | 
			
		||||
description: "Request a general task, improvement, or refactor."
 | 
			
		||||
labels: ["task"]
 | 
			
		||||
body:
 | 
			
		||||
  - type: markdown
 | 
			
		||||
    attributes:
 | 
			
		||||
      value: |
 | 
			
		||||
        # 🛠️ **Task / General Request**
 | 
			
		||||
        Request a task that isn't a bug or feature request.
 | 
			
		||||
 | 
			
		||||
  - type: input
 | 
			
		||||
    id: task_summary
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: "📌 Task summary"
 | 
			
		||||
      placeholder: "e.g., Refactor XYZ"
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
 | 
			
		||||
  - type: textarea
 | 
			
		||||
    id: task_details
 | 
			
		||||
    attributes:
 | 
			
		||||
      label: "📋 Task details"
 | 
			
		||||
      placeholder: "Explain what needs to be done"
 | 
			
		||||
    validations:
 | 
			
		||||
      required: true
 | 
			
		||||
							
								
								
									
										52
									
								
								.github/autolabeler-config.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								.github/autolabeler-config.json
									
									
									
									
										vendored
									
									
								
							@@ -1,17 +1,5 @@
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  "breaking change": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": "renamed",
 | 
			
		||||
      "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": "removed", 
 | 
			
		||||
      "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "new script": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": "added",
 | 
			
		||||
@@ -23,7 +11,7 @@
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": "modified",
 | 
			
		||||
      "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
 | 
			
		||||
      "excludeGlobs": ["misc/build.func", "misc/install.func"]
 | 
			
		||||
      "excludeGlobs": ["misc/build.func", "misc/install.func", "misc/api.func"]
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "delete script": [
 | 
			
		||||
@@ -33,10 +21,17 @@
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "rename script": [
 | 
			
		||||
  "maintenance": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": "renamed", 
 | 
			
		||||
      "includeGlobs": ["ct/**", "install/**", "misc/**", "turnkey/**", "vm/**"],
 | 
			
		||||
      "fileStatus": null,
 | 
			
		||||
      "includeGlobs": ["*.md", ".github/**", "misc/*.func", "ct/create_lxc.sh", "api/**"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "core": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": null,
 | 
			
		||||
      "includeGlobs": ["misc/*.func", "ct/create_lxc.sh"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
@@ -47,18 +42,35 @@
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "maintenance": [
 | 
			
		||||
  "api": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": null,
 | 
			
		||||
      "includeGlobs": ["*.md", ".github/**", "misc/*.func", "ct/create_lxc.sh"],
 | 
			
		||||
      "includeGlobs": ["api/**", "misc/api.func"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "github": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": null,
 | 
			
		||||
      "includeGlobs": [".github/**"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "json": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": "modified",
 | 
			
		||||
      "includeGlobs": ["json/**"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
 | 
			
		||||
  "high risk": [
 | 
			
		||||
    {
 | 
			
		||||
      "fileStatus": null,
 | 
			
		||||
      "includeGlobs": ["misc/build.func", "misc/install.func"],
 | 
			
		||||
      "includeGlobs": ["misc/build.func", "misc/install.func", "ct/create_lxc.sh"],
 | 
			
		||||
      "excludeGlobs": []
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										121
									
								
								.github/changelog-pr-config.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										121
									
								
								.github/changelog-pr-config.json
									
									
									
									
										vendored
									
									
								
							@@ -1,30 +1,97 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "title": "💥 Breaking Changes",
 | 
			
		||||
        "labels": ["breaking change"]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "title": "✨ New Scripts",
 | 
			
		||||
        "labels": ["new script"]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "title": "🚀 Updated Scripts",
 | 
			
		||||
        "labels": ["update script"]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "title": "🌐 Website",
 | 
			
		||||
        "labels": ["website"]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
  {
 | 
			
		||||
    "title": "🆕 New Scripts",
 | 
			
		||||
    "labels": ["new script"]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "title": "🚀 Updated Scripts",
 | 
			
		||||
    "labels": ["update script"],
 | 
			
		||||
    "subCategories": [
 | 
			
		||||
      {
 | 
			
		||||
        "title": "🐞 Bug Fixes",
 | 
			
		||||
        "labels": ["bug fix"]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "title": "🧰 Maintenance",
 | 
			
		||||
        "labels": ["maintenance"]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "title": "❔ Unlabelled",
 | 
			
		||||
        "labels": []
 | 
			
		||||
    }
 | 
			
		||||
        "labels": ["bugfix"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "✨ New Features",
 | 
			
		||||
        "labels": ["feature"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "💥 Breaking Changes",
 | 
			
		||||
        "labels": ["breaking change"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "title": "🧰 Maintenance",
 | 
			
		||||
    "labels": ["maintenance"],
 | 
			
		||||
    "subCategories": [
 | 
			
		||||
      {
 | 
			
		||||
        "title": "🐞 Bug Fixes",
 | 
			
		||||
        "labels": ["bugfix"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "✨ New Features",
 | 
			
		||||
        "labels": ["feature"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "💥 Breaking Changes",
 | 
			
		||||
        "labels": ["breaking change"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "📡 API",
 | 
			
		||||
        "labels": ["api"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "💾 Core",
 | 
			
		||||
        "labels": ["core"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "📂 Github",
 | 
			
		||||
        "labels": ["github"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "title": "🌐 Website",
 | 
			
		||||
    "labels": ["website"],
 | 
			
		||||
    "subCategories": [
 | 
			
		||||
      {
 | 
			
		||||
        "title": "🐞 Bug Fixes",
 | 
			
		||||
        "labels": ["bugfix"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "✨ New Features",
 | 
			
		||||
        "labels": ["feature"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "💥 Breaking Changes",
 | 
			
		||||
        "labels": ["breaking change"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "title": "📝 Script Information",
 | 
			
		||||
        "labels": ["json"],
 | 
			
		||||
        "notes" : []
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "title": "❔ Unlabelled",
 | 
			
		||||
    "labels": []
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "title": "💥 Breaking Changes",
 | 
			
		||||
    "labels": ["breaking change"]
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
								
							@@ -1,28 +1,25 @@
 | 
			
		||||
## ✍️ Description
 | 
			
		||||
## ✍️ Description  
 | 
			
		||||
<!-- Provide a clear and concise description of your changes. -->  
 | 
			
		||||
 | 
			
		||||
## 🔗 Related PR / Discussion / Issue  
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Link: #
 | 
			
		||||
 | 
			
		||||
- - -
 | 
			
		||||
- Related Issue: #
 | 
			
		||||
- Related PR: #
 | 
			
		||||
- Related Discussion: #
 | 
			
		||||
- - - 
 | 
			
		||||
## ✅ Prerequisites  
 | 
			
		||||
 | 
			
		||||
Before this PR can be reviewed, the following must be completed:  
 | 
			
		||||
 | 
			
		||||
## ✅ Prerequisites
 | 
			
		||||
The following steps must be completed for the pull request to be considered:  
 | 
			
		||||
- [] Self-review performed (I have reviewed my code to ensure it follows established patterns and conventions.)  
 | 
			
		||||
- [] Testing performed (I have thoroughly tested my changes and verified expected functionality.)
 | 
			
		||||
- [] **Self-review performed** – Code follows established patterns and conventions.  
 | 
			
		||||
- [] **Testing performed** – Changes have been thoroughly tested and verified.  
 | 
			
		||||
 | 
			
		||||
## 🛠️ Type of Change
 | 
			
		||||
Please check the relevant options:  
 | 
			
		||||
- [] Bug fix (non-breaking change that resolves an issue)  
 | 
			
		||||
- [] New feature (non-breaking change that adds functionality)  
 | 
			
		||||
- [] Breaking change (fix or feature that would cause existing functionality to change unexpectedly)  
 | 
			
		||||
- [] New script (a fully functional and thoroughly tested script or set of scripts)  
 | 
			
		||||
## 🛠️ Type of Change  
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
## 📋 Additional Information (optional)
 | 
			
		||||
Provide any extra context or screenshots about the feature or fix here.  
 | 
			
		||||
Select all that apply:
 | 
			
		||||
 | 
			
		||||
- [] 🆕 **New script** – A fully functional and tested script or script set.
 | 
			
		||||
- [] 🐞 **Bug fix**  – Resolves an issue without breaking functionality.  
 | 
			
		||||
- [] ✨ **New feature**  – Adds new, non-breaking functionality.  
 | 
			
		||||
- [] 💥 **Breaking change**  – Alters existing functionality in a way that may require updates.  
 | 
			
		||||
 | 
			
		||||
## 📋 Additional Information (optional)  
 | 
			
		||||
<!-- Provide extra context, screenshots, or references if needed. -->  
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								.github/runner/docker/gh-runner-self.dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								.github/runner/docker/gh-runner-self.dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy as build
 | 
			
		||||
 | 
			
		||||
ARG TARGETOS
 | 
			
		||||
ARG TARGETARCH
 | 
			
		||||
ARG DOCKER_VERSION=27.5.1
 | 
			
		||||
ARG BUILDX_VERSION=0.20.1
 | 
			
		||||
ARG RUNNER_ARCH="x64"
 | 
			
		||||
 | 
			
		||||
RUN apt update -y && apt install sudo curl unzip -y
 | 
			
		||||
 | 
			
		||||
WORKDIR /actions-runner
 | 
			
		||||
 | 
			
		||||
RUN RUNNER_VERSION=$(curl -s https://api.github.com/repos/actions/runner/releases/latest | grep "tag_name" | head -n 1 | awk '{print substr($2, 3, length($2)-4)}') \
 | 
			
		||||
    && curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
 | 
			
		||||
    && tar xzf ./runner.tar.gz \
 | 
			
		||||
    && rm runner.tar.gz
 | 
			
		||||
 | 
			
		||||
RUN RUNNER_CONTAINER_HOOKS_VERSION=$(curl -s https://api.github.com/repos/actions/runner-container-hooks/releases/latest | grep "tag_name" | head -n 1 | awk '{print substr($2, 3, length($2)-4)}') \
 | 
			
		||||
    && curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
 | 
			
		||||
    && unzip ./runner-container-hooks.zip -d ./k8s \
 | 
			
		||||
    && rm runner-container-hooks.zip
 | 
			
		||||
 | 
			
		||||
RUN export RUNNER_ARCH=${TARGETARCH} \
 | 
			
		||||
    && if [ "$RUNNER_ARCH" = "amd64" ]; then export DOCKER_ARCH=x86_64 ; fi \
 | 
			
		||||
    && if [ "$RUNNER_ARCH" = "arm64" ]; then export DOCKER_ARCH=aarch64 ; fi \
 | 
			
		||||
    && curl -fLo docker.tgz https://download.docker.com/${TARGETOS}/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz \
 | 
			
		||||
    && tar zxvf docker.tgz \
 | 
			
		||||
    && rm -rf docker.tgz \
 | 
			
		||||
    && mkdir -p /usr/local/lib/docker/cli-plugins \
 | 
			
		||||
    && curl -fLo /usr/local/lib/docker/cli-plugins/docker-buildx \
 | 
			
		||||
        "https://github.com/docker/buildx/releases/download/v${BUILDX_VERSION}/buildx-v${BUILDX_VERSION}.linux-${TARGETARCH}" \
 | 
			
		||||
    && chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
 | 
			
		||||
 | 
			
		||||
FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-jammy
 | 
			
		||||
 | 
			
		||||
ENV DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
ENV RUNNER_MANUALLY_TRAP_SIG=1
 | 
			
		||||
ENV ACTIONS_RUNNER_PRINT_LOG_TO_STDOUT=1
 | 
			
		||||
ENV ImageOS=ubuntu22
 | 
			
		||||
 | 
			
		||||
RUN apt update -y \
 | 
			
		||||
    && apt install -y --no-install-recommends sudo lsb-release gpg-agent software-properties-common curl jq unzip \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
RUN add-apt-repository ppa:git-core/ppa \
 | 
			
		||||
    && apt update -y \
 | 
			
		||||
    && apt install -y git \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
RUN adduser --disabled-password --gecos "" --uid 1001 runner \
 | 
			
		||||
    && groupadd docker --gid 123 \
 | 
			
		||||
    && usermod -aG sudo runner \
 | 
			
		||||
    && usermod -aG docker runner \
 | 
			
		||||
    && echo "%sudo   ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers \
 | 
			
		||||
    && echo "Defaults env_keep += \"DEBIAN_FRONTEND\"" >> /etc/sudoers
 | 
			
		||||
 | 
			
		||||
# Install own dependencies in final image
 | 
			
		||||
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
 | 
			
		||||
    && apt-get install -y nodejs \
 | 
			
		||||
    && apt-get install -y gh jq git
 | 
			
		||||
 | 
			
		||||
WORKDIR /home/runner
 | 
			
		||||
 | 
			
		||||
COPY --chown=runner:docker --from=build /actions-runner .
 | 
			
		||||
COPY --from=build /usr/local/lib/docker/cli-plugins/docker-buildx /usr/local/lib/docker/cli-plugins/docker-buildx
 | 
			
		||||
RUN install -o root -g root -m 755 docker/* /usr/bin/ && rm -rf docker
 | 
			
		||||
 | 
			
		||||
USER runner
 | 
			
		||||
							
								
								
									
										29
									
								
								.github/workflows/auto-update-app-headers.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								.github/workflows/auto-update-app-headers.yml
									
									
									
									
										vendored
									
									
								
							@@ -10,13 +10,20 @@ on:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  update-app-files:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: write
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Generate a token
 | 
			
		||||
        id: generate-token
 | 
			
		||||
        uses: actions/create-github-app-token@v1
 | 
			
		||||
        with:
 | 
			
		||||
          app-id: ${{ vars.APP_ID }}
 | 
			
		||||
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
 | 
			
		||||
 | 
			
		||||
      # Step 1: Checkout repository
 | 
			
		||||
      - name: Checkout repository
 | 
			
		||||
        uses: actions/checkout@v2
 | 
			
		||||
@@ -70,8 +77,28 @@ jobs:
 | 
			
		||||
                       --head pr-update-app-files \
 | 
			
		||||
                       --base main \
 | 
			
		||||
                       --label "automated pr"
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
 | 
			
		||||
      
 | 
			
		||||
      - name: Approve pull request
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          PR_NUMBER=$(gh pr list --head "pr-update-app-files" --json number --jq '.[].number')
 | 
			
		||||
          if [ -n "$PR_NUMBER" ]; then
 | 
			
		||||
            gh pr review $PR_NUMBER --approve
 | 
			
		||||
          fi
 | 
			
		||||
          
 | 
			
		||||
      - name: Re-approve pull request after update
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          PR_NUMBER=$(gh pr list --head "pr-update-app-files" --json number --jq '.[].number')
 | 
			
		||||
          if [ -n "$PR_NUMBER" ]; then
 | 
			
		||||
            gh pr review $PR_NUMBER --approve
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      # Step 8: Output success message when no changes
 | 
			
		||||
      - name: No changes detected
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								.github/workflows/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										59
									
								
								.github/workflows/autolabeler.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@ on:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  autolabeler:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
    permissions:
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
    env:
 | 
			
		||||
@@ -16,10 +16,10 @@ jobs:
 | 
			
		||||
      - name: Checkout repository
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
 | 
			
		||||
      - name: Install minimatch
 | 
			
		||||
      - name: Install dependencies
 | 
			
		||||
        run: npm install minimatch
 | 
			
		||||
 | 
			
		||||
      - name: Label PR based on config rules
 | 
			
		||||
      
 | 
			
		||||
      - name: Label PR based on file changes and PR template
 | 
			
		||||
        uses: actions/github-script@v7
 | 
			
		||||
        with:
 | 
			
		||||
          script: |
 | 
			
		||||
@@ -30,33 +30,66 @@ jobs:
 | 
			
		||||
            const configPath = path.resolve(process.env.CONFIG_PATH);
 | 
			
		||||
            const fileContent = await fs.readFile(configPath, 'utf-8');
 | 
			
		||||
            const autolabelerConfig = JSON.parse(fileContent);
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
            const prNumber = context.payload.pull_request.number;
 | 
			
		||||
            const prBody = context.payload.pull_request.body.toLowerCase();
 | 
			
		||||
 | 
			
		||||
            let labelsToAdd = new Set();
 | 
			
		||||
 | 
			
		||||
            const prListFilesResponse = await github.rest.pulls.listFiles({
 | 
			
		||||
              owner: context.repo.owner,
 | 
			
		||||
              repo: context.repo.repo,
 | 
			
		||||
              pull_number: prNumber,
 | 
			
		||||
            });
 | 
			
		||||
            const prFiles = prListFilesResponse.data;
 | 
			
		||||
           
 | 
			
		||||
 | 
			
		||||
          
 | 
			
		||||
            // Apply labels based on file changes
 | 
			
		||||
            for (const [label, rules] of Object.entries(autolabelerConfig)) {
 | 
			
		||||
              const shouldAddLabel = prFiles.some((prFile) => {
 | 
			
		||||
                return rules.some((rule) => {
 | 
			
		||||
                  const isFileStatusMatch = rule.fileStatus ? rule.fileStatus === prFile.status : true;
 | 
			
		||||
                  const isIncludeGlobMatch = rule.includeGlobs.some((glob) => minimatch(prFile.filename, glob));
 | 
			
		||||
                  const isExcludeGlobMatch = rule.excludeGlobs.some((glob) => minimatch(prFile.filename, glob));
 | 
			
		||||
                  
 | 
			
		||||
 | 
			
		||||
                  return isFileStatusMatch && isIncludeGlobMatch && !isExcludeGlobMatch;
 | 
			
		||||
                });
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              if (shouldAddLabel) {
 | 
			
		||||
                console.log(`Adding label ${label} to PR ${prNumber}`);
 | 
			
		||||
                await github.rest.issues.addLabels({
 | 
			
		||||
                  owner: context.repo.owner,
 | 
			
		||||
                  repo: context.repo.repo,
 | 
			
		||||
                  issue_number: prNumber,
 | 
			
		||||
                  labels: [label],
 | 
			
		||||
                });
 | 
			
		||||
                labelsToAdd.add(label);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            //if two labels or more are added, return
 | 
			
		||||
              if (labelsToAdd.size < 2) {
 | 
			
		||||
                const templateLabelMappings = {
 | 
			
		||||
                "🐞 **Bug fix**": "bugfix",
 | 
			
		||||
                "✨ **New feature**": "feature",
 | 
			
		||||
                "💥 **Breaking change**": "breaking change",
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              for (const [checkbox, label] of Object.entries(templateLabelMappings)) {
 | 
			
		||||
                const escapedCheckbox = checkbox.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
 | 
			
		||||
                const regex = new RegExp(`- \\[(x|X)\\]\\s*.*${escapedCheckbox}`, "i");
 | 
			
		||||
                const match = prBody.match(regex);              
 | 
			
		||||
                if (match) {
 | 
			
		||||
                  console.log(`Match: ${match}`);
 | 
			
		||||
                  labelsToAdd.add(label);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
            
 | 
			
		||||
            console.log(`Labels to add: ${Array.from(labelsToAdd).join(", ")}`);
 | 
			
		||||
 | 
			
		||||
            if (labelsToAdd.size > 0) {
 | 
			
		||||
              console.log(`Adding labels ${Array.from(labelsToAdd).join(", ")} to PR ${prNumber}`);
 | 
			
		||||
              await github.rest.issues.addLabels({
 | 
			
		||||
                owner: context.repo.owner,
 | 
			
		||||
                repo: context.repo.repo,
 | 
			
		||||
                issue_number: prNumber,
 | 
			
		||||
                labels: Array.from(labelsToAdd),
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										88
									
								
								.github/workflows/backup/update_json_date.yml.bak
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								.github/workflows/backup/update_json_date.yml.bak
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
name: Auto Update JSON-Date
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  update-json-dates:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: write
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Generate a token
 | 
			
		||||
        id: generate-token
 | 
			
		||||
        uses: actions/create-github-app-token@v1
 | 
			
		||||
        with:
 | 
			
		||||
          app-id: ${{ vars.APP_ID }}
 | 
			
		||||
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
 | 
			
		||||
 | 
			
		||||
      - name: Checkout repository
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 0  # Full history for proper detection
 | 
			
		||||
 | 
			
		||||
      - name: Set up Git
 | 
			
		||||
        run: |
 | 
			
		||||
          git config --global user.name "GitHub Actions"
 | 
			
		||||
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
 | 
			
		||||
 | 
			
		||||
      - name: Find JSON files with incorrect date_created
 | 
			
		||||
        id: find_wrong_json
 | 
			
		||||
        run: |
 | 
			
		||||
          TODAY=$(date -u +"%Y-%m-%d")
 | 
			
		||||
          > incorrect_json_files.txt
 | 
			
		||||
 | 
			
		||||
          for FILE in json/*.json; do
 | 
			
		||||
            if [[ -f "$FILE" ]]; then
 | 
			
		||||
              DATE_IN_JSON=$(jq -r '.date_created' "$FILE" 2>/dev/null || echo "")
 | 
			
		||||
 | 
			
		||||
              if [[ "$DATE_IN_JSON" != "$TODAY" ]]; then
 | 
			
		||||
                echo "$FILE" >> incorrect_json_files.txt
 | 
			
		||||
              fi
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
 | 
			
		||||
          if [[ -s incorrect_json_files.txt ]]; then
 | 
			
		||||
            echo "CHANGED=true" >> $GITHUB_ENV
 | 
			
		||||
          else
 | 
			
		||||
            echo "CHANGED=false" >> $GITHUB_ENV
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: Run update script
 | 
			
		||||
        if: env.CHANGED == 'true'
 | 
			
		||||
        run: |
 | 
			
		||||
          chmod +x .github/workflows/scripts/update-json.sh
 | 
			
		||||
          while read -r FILE; do
 | 
			
		||||
            .github/workflows/scripts/update-json.sh "$FILE"
 | 
			
		||||
          done < incorrect_json_files.txt
 | 
			
		||||
 | 
			
		||||
      - name: Commit and create PR if changes exist
 | 
			
		||||
        if: env.CHANGED == 'true'
 | 
			
		||||
        run: |
 | 
			
		||||
          git add json/*.json
 | 
			
		||||
          git commit -m "Auto-update date_created in incorrect JSON files"
 | 
			
		||||
          git checkout -b pr-fix-json-dates
 | 
			
		||||
          git push origin pr-fix-json-dates --force
 | 
			
		||||
          gh pr create --title "[core] Fix incorrect JSON date_created fields" \
 | 
			
		||||
                       --body "This PR is auto-generated to fix incorrect `date_created` fields in JSON files." \
 | 
			
		||||
                       --head pr-fix-json-dates \
 | 
			
		||||
                       --base main \
 | 
			
		||||
                       --label "automated pr"
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
 | 
			
		||||
 | 
			
		||||
      - name: Approve pull request
 | 
			
		||||
        if: env.CHANGED == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          PR_NUMBER=$(gh pr list --head "pr-fix-json-dates" --json number --jq '.[].number')
 | 
			
		||||
          if [ -n "$PR_NUMBER" ]; then
 | 
			
		||||
            gh pr review $PR_NUMBER --approve
 | 
			
		||||
          fi
 | 
			
		||||
							
								
								
									
										132
									
								
								.github/workflows/changelog-pr.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										132
									
								
								.github/workflows/changelog-pr.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@ on:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  update-changelog-pull-request:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
    env:
 | 
			
		||||
      CONFIG_PATH: .github/changelog-pr-config.json
 | 
			
		||||
      BRANCH_NAME: github-action-update-changelog
 | 
			
		||||
@@ -30,15 +30,14 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      - name: Get latest dates in changelog
 | 
			
		||||
        run: |
 | 
			
		||||
          # Extract the latest and second latest dates from changelog
 | 
			
		||||
          DATES=$(grep '^## [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}' CHANGELOG.md | head -n 2 | awk '{print $2}')
 | 
			
		||||
          DATES=$(grep -E '^## [0-9]{4}-[0-9]{2}-[0-9]{2}' CHANGELOG.md | head -n 2 | awk '{print $2}')
 | 
			
		||||
 | 
			
		||||
          LATEST_DATE=$(echo "$DATES" | sed -n '1p')
 | 
			
		||||
          SECOND_LATEST_DATE=$(echo "$DATES" | sed -n '2p')
 | 
			
		||||
          TODAY=$(date -u +%Y-%m-%d)
 | 
			
		||||
 | 
			
		||||
          echo "TODAY=$TODAY" >> $GITHUB_ENV
 | 
			
		||||
          if [ "$LATEST_DATE" == "$TODAY" ]; then
 | 
			
		||||
          if [[ "$LATEST_DATE" == "$TODAY" ]]; then
 | 
			
		||||
            echo "LATEST_DATE=$SECOND_LATEST_DATE" >> $GITHUB_ENV
 | 
			
		||||
          else
 | 
			
		||||
            echo "LATEST_DATE=$LATEST_DATE" >> $GITHUB_ENV
 | 
			
		||||
@@ -55,10 +54,34 @@ jobs:
 | 
			
		||||
            const configPath = path.resolve(process.env.CONFIG_PATH);
 | 
			
		||||
            const fileContent = await fs.readFile(configPath, 'utf-8');
 | 
			
		||||
            const changelogConfig = JSON.parse(fileContent);
 | 
			
		||||
            const categorizedPRs = changelogConfig.map((obj) => ({ ...obj, notes: [] }));
 | 
			
		||||
 | 
			
		||||
            const categorizedPRs = changelogConfig.map(obj => ({
 | 
			
		||||
              ...obj,
 | 
			
		||||
              notes: [],
 | 
			
		||||
              subCategories: obj.subCategories ?? (
 | 
			
		||||
                obj.labels.includes("update script") ? [
 | 
			
		||||
                  { title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
 | 
			
		||||
                  { title: "✨ New Features", labels: ["feature"], notes: [] },
 | 
			
		||||
                  { title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] }
 | 
			
		||||
                ] :
 | 
			
		||||
                obj.labels.includes("maintenance") ? [
 | 
			
		||||
                  { title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
 | 
			
		||||
                  { title: "✨ New Features", labels: ["feature"], notes: [] },
 | 
			
		||||
                  { title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
 | 
			
		||||
                  { title: "📡 API", labels: ["api"], notes: [] },
 | 
			
		||||
                  { title: "Github", labels: ["github"], notes: [] }
 | 
			
		||||
                ] :
 | 
			
		||||
                obj.labels.includes("website") ? [
 | 
			
		||||
                  { title: "🐞 Bug Fixes", labels: ["bugfix"], notes: [] },
 | 
			
		||||
                  { title: "✨ New Features", labels: ["feature"], notes: [] },
 | 
			
		||||
                  { title: "💥 Breaking Changes", labels: ["breaking change"], notes: [] },
 | 
			
		||||
                  { title: "Script Information", labels: ["json"], notes: [] }
 | 
			
		||||
                ] : []
 | 
			
		||||
              )
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
            const latestDateInChangelog = new Date(process.env.LATEST_DATE);
 | 
			
		||||
            latestDateInChangelog.setUTCHours(23,59,59,999);
 | 
			
		||||
            latestDateInChangelog.setUTCHours(23, 59, 59, 999);
 | 
			
		||||
 | 
			
		||||
            const { data: pulls } = await github.rest.pulls.list({
 | 
			
		||||
              owner: context.repo.owner,
 | 
			
		||||
@@ -70,26 +93,40 @@ jobs:
 | 
			
		||||
              per_page: 100,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            pulls.filter((pr) => 
 | 
			
		||||
              pr.merged_at && 
 | 
			
		||||
              new Date(pr.merged_at) > latestDateInChangelog && 
 | 
			
		||||
              !pr.labels.some((label) => ["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase()))
 | 
			
		||||
            ).forEach((pr) => {
 | 
			
		||||
              const prLabels = pr.labels.map((label) => label.name.toLowerCase());
 | 
			
		||||
            pulls.filter(pr =>
 | 
			
		||||
            pr.merged_at &&
 | 
			
		||||
            new Date(pr.merged_at) > latestDateInChangelog &&
 | 
			
		||||
            !pr.labels.some(label =>
 | 
			
		||||
              ["invalid", "wontdo", process.env.AUTOMATED_PR_LABEL].includes(label.name.toLowerCase())
 | 
			
		||||
              )
 | 
			
		||||
            ).forEach(pr => {
 | 
			
		||||
 | 
			
		||||
              const prLabels = pr.labels.map(label => label.name.toLowerCase());
 | 
			
		||||
              const prNote = `- ${pr.title} [@${pr.user.login}](https://github.com/${pr.user.login}) ([#${pr.number}](${pr.html_url}))`;
 | 
			
		||||
 | 
			
		||||
              for (const { labels, notes } of categorizedPRs) {
 | 
			
		||||
                const prHasCategoryLabel = labels.some((label) => prLabels.includes(label));
 | 
			
		||||
                const isUnlabelledCategory = labels.length === 0;
 | 
			
		||||
                if (prHasCategoryLabel || isUnlabelledCategory) {
 | 
			
		||||
                  notes.push(prNote);
 | 
			
		||||
                  break;
 | 
			
		||||
              const updateScriptsCategory = categorizedPRs.find(category =>
 | 
			
		||||
                category.labels.some(label => prLabels.includes(label))
 | 
			
		||||
              );
 | 
			
		||||
 | 
			
		||||
              if (updateScriptsCategory) {
 | 
			
		||||
                
 | 
			
		||||
                const subCategory = updateScriptsCategory.subCategories.find(sub =>
 | 
			
		||||
                  sub.labels.some(label => prLabels.includes(label))
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                if (subCategory) {
 | 
			
		||||
                  subCategory.notes.push(prNote);
 | 
			
		||||
                } else {
 | 
			
		||||
                  updateScriptsCategory.notes.push(prNote);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            console.log(JSON.stringify(categorizedPRs, null, 2));
 | 
			
		||||
 | 
			
		||||
            return categorizedPRs;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      - name: Update CHANGELOG.md
 | 
			
		||||
        uses: actions/github-script@v7
 | 
			
		||||
        with:
 | 
			
		||||
@@ -102,31 +139,50 @@ jobs:
 | 
			
		||||
            const changelogPath = path.resolve('CHANGELOG.md');
 | 
			
		||||
            const categorizedPRs = ${{ steps.get-categorized-prs.outputs.result }};
 | 
			
		||||
 | 
			
		||||
            let newReleaseNotes = `## ${today}\n\n### Changed\n\n`;
 | 
			
		||||
            for (const { title, notes } of categorizedPRs) {
 | 
			
		||||
              if (notes.length > 0) {
 | 
			
		||||
                newReleaseNotes += `### ${title}\n\n${notes.join("\n")}\n\n`;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            console.log(JSON.stringify(categorizedPRs, null, 2));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            let newReleaseNotes = `## ${today}\n\n`;
 | 
			
		||||
            for (const { title, notes, subCategories } of categorizedPRs) {
 | 
			
		||||
              const hasSubcategories = subCategories && subCategories.length > 0;
 | 
			
		||||
              const hasMainNotes = notes.length > 0;
 | 
			
		||||
              const hasSubNotes = hasSubcategories && subCategories.some(sub => sub.notes && sub.notes.length > 0);
 | 
			
		||||
        
 | 
			
		||||
    
 | 
			
		||||
              if (hasMainNotes || hasSubNotes) {
 | 
			
		||||
                newReleaseNotes += `### ${title}\n\n`;
 | 
			
		||||
              }
 | 
			
		||||
            
 | 
			
		||||
              if (hasMainNotes) {
 | 
			
		||||
                newReleaseNotes += `  ${notes.join("\n")}\n\n`;
 | 
			
		||||
              }
 | 
			
		||||
              if (hasSubcategories) {
 | 
			
		||||
                for (const { title: subTitle, notes: subNotes } of subCategories) {
 | 
			
		||||
                  if (subNotes && subNotes.length > 0) {
 | 
			
		||||
                    newReleaseNotes += `  - #### ${subTitle}\n\n`; 
 | 
			
		||||
                    newReleaseNotes += `    ${subNotes.join("\n    ")}\n\n`; 
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }        
 | 
			
		||||
        
 | 
			
		||||
            const changelogContent = await fs.readFile(changelogPath, 'utf-8');
 | 
			
		||||
            const changelogIncludesTodaysReleaseNotes = changelogContent.includes(`\n## ${today}`);
 | 
			
		||||
 | 
			
		||||
            // Replace todays release notes or insert release notes above previous release notes
 | 
			
		||||
            const regex = changelogIncludesTodaysReleaseNotes ? 
 | 
			
		||||
              new RegExp(`## ${today}.*(?=## ${latestDateInChangelog})`, "gs") :
 | 
			
		||||
              new RegExp(`(?=## ${latestDateInChangelog})`, "gs");
 | 
			
		||||
            const regex = changelogIncludesTodaysReleaseNotes 
 | 
			
		||||
              ? new RegExp(`## ${today}.*(?=## ${latestDateInChangelog})`, "gs") 
 | 
			
		||||
              : new RegExp(`(?=## ${latestDateInChangelog})`, "gs");
 | 
			
		||||
 | 
			
		||||
            const newChangelogContent = changelogContent.replace(regex, newReleaseNotes)
 | 
			
		||||
            const newChangelogContent = changelogContent.replace(regex, newReleaseNotes);
 | 
			
		||||
            await fs.writeFile(changelogPath, newChangelogContent);
 | 
			
		||||
 | 
			
		||||
      - name: Check if there are any changes
 | 
			
		||||
      - name: Check for changes
 | 
			
		||||
        id: verify-diff
 | 
			
		||||
        run: |
 | 
			
		||||
          git diff --quiet . || echo "changed=true" >> $GITHUB_OUTPUT
 | 
			
		||||
          git diff --quiet . || echo "changed=true" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Commit and push changes to separate branch
 | 
			
		||||
        if: steps.verify-diff.outputs.changed == 'true'
 | 
			
		||||
      - name: Commit and push changes
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        run: |
 | 
			
		||||
          git config --global user.name "github-actions[bot]"
 | 
			
		||||
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
 | 
			
		||||
@@ -136,7 +192,7 @@ jobs:
 | 
			
		||||
          git push origin $BRANCH_NAME --force
 | 
			
		||||
 | 
			
		||||
      - name: Create pull request if not exists
 | 
			
		||||
        if: steps.verify-diff.outputs.changed == 'true'
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
 | 
			
		||||
        run: |
 | 
			
		||||
@@ -150,7 +206,7 @@ jobs:
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: Approve pull request
 | 
			
		||||
        if: steps.verify-diff.outputs.changed == 'true'
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
@@ -158,13 +214,13 @@ jobs:
 | 
			
		||||
          if [ -n "$PR_NUMBER" ]; then
 | 
			
		||||
            gh pr review $PR_NUMBER --approve
 | 
			
		||||
          fi
 | 
			
		||||
          
 | 
			
		||||
 | 
			
		||||
      - name: Re-approve pull request after update
 | 
			
		||||
        if: steps.verify-diff.outputs.changed == 'true'
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          PR_NUMBER=$(gh pr list --head "${BRANCH_NAME}" --json number --jq '.[].number')
 | 
			
		||||
          if [ -n "$PR_NUMBER" ]; then
 | 
			
		||||
            gh pr review $PR_NUMBER --approve
 | 
			
		||||
          fi
 | 
			
		||||
          fi
 | 
			
		||||
							
								
								
									
										122
									
								
								.github/workflows/close-discussion.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								.github/workflows/close-discussion.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
name: Close Discussion on PR Merge
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    types: [closed]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  close-discussion:
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout Repository
 | 
			
		||||
        uses: actions/checkout@v4  
 | 
			
		||||
 | 
			
		||||
      - name: Set Up Node.js
 | 
			
		||||
        uses: actions/setup-node@v4
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: "20"
 | 
			
		||||
      - name: Install Dependencies
 | 
			
		||||
        run: npm install zx @octokit/graphql
 | 
			
		||||
 | 
			
		||||
      - name: Close Discussion
 | 
			
		||||
        env:
 | 
			
		||||
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          PR_BODY: ${{ github.event.pull_request.body }}
 | 
			
		||||
          PR_NUMBER: ${{ github.event.pull_request.number }}
 | 
			
		||||
          REPO_OWNER: ${{ github.repository_owner }}
 | 
			
		||||
          REPO_NAME: ${{ github.event.repository.name }}
 | 
			
		||||
        run: |
 | 
			
		||||
          npx zx << 'EOF'
 | 
			
		||||
          import { graphql } from "@octokit/graphql";
 | 
			
		||||
          (async function() {
 | 
			
		||||
            try {
 | 
			
		||||
              const token = process.env.GITHUB_TOKEN;
 | 
			
		||||
              const prBody = process.env.PR_BODY;
 | 
			
		||||
              const prNumber = process.env.PR_NUMBER;
 | 
			
		||||
              const owner = process.env.REPO_OWNER;
 | 
			
		||||
              const repo = process.env.REPO_NAME;
 | 
			
		||||
 | 
			
		||||
              if (!token || !prBody || !prNumber || !owner || !repo) {
 | 
			
		||||
                console.log("Missing required environment variables.");
 | 
			
		||||
                process.exit(1);
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              const match = prBody.match(/#(\d+)/);
 | 
			
		||||
              if (!match) {
 | 
			
		||||
                console.log("No discussion ID found in PR body.");
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
              const discussionNumber = match[1];
 | 
			
		||||
 | 
			
		||||
              console.log(`Extracted Discussion Number: ${discussionNumber}`);
 | 
			
		||||
              console.log(`PR Number: ${prNumber}`);
 | 
			
		||||
              console.log(`Repository: ${owner}/${repo}`);
 | 
			
		||||
 | 
			
		||||
              const graphqlWithAuth = graphql.defaults({
 | 
			
		||||
                headers: { authorization: `Bearer ${token}` },
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              const discussionQuery = `
 | 
			
		||||
                query($owner: String!, $repo: String!, $number: Int!) {
 | 
			
		||||
                  repository(owner: $owner, name: $repo) {
 | 
			
		||||
                    discussion(number: $number) {
 | 
			
		||||
                      id
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              `;
 | 
			
		||||
              
 | 
			
		||||
              const discussionResponse = await graphqlWithAuth(discussionQuery, {
 | 
			
		||||
                  owner,
 | 
			
		||||
                  repo,
 | 
			
		||||
                  number: parseInt(discussionNumber, 10),
 | 
			
		||||
              });              
 | 
			
		||||
              
 | 
			
		||||
              const discussionQLId = discussionResponse.repository.discussion.id;
 | 
			
		||||
              if (!discussionQLId) {
 | 
			
		||||
                console.log("Failed to fetch discussion GraphQL ID.");
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              console.log(`GraphQL Discussion ID: ${discussionQLId}`);
 | 
			
		||||
              
 | 
			
		||||
              const commentMutation = `
 | 
			
		||||
                mutation($discussionId: ID!, $body: String!) {
 | 
			
		||||
                  addDiscussionComment(input: { discussionId: $discussionId, body: $body }) {
 | 
			
		||||
                    comment { id body }
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              `;
 | 
			
		||||
 | 
			
		||||
              const commentResponse = await graphqlWithAuth(commentMutation, {
 | 
			
		||||
                discussionId: discussionQLId,
 | 
			
		||||
                body: `Merged with PR #${prNumber}`,
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              const commentId = commentResponse.addDiscussionComment.comment.id;
 | 
			
		||||
              if (!commentId) {
 | 
			
		||||
                console.log("Failed to post the comment.");
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              console.log(`Comment Posted Successfully! Comment ID: ${commentId}`);
 | 
			
		||||
 | 
			
		||||
              const markAnswerMutation = `
 | 
			
		||||
                mutation($id: ID!) {
 | 
			
		||||
                  markDiscussionCommentAsAnswer(input: { id: $id }) {
 | 
			
		||||
                    discussion { id title }
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              `;
 | 
			
		||||
 | 
			
		||||
              await graphqlWithAuth(markAnswerMutation, { id: commentId });
 | 
			
		||||
 | 
			
		||||
              console.log("Comment marked as answer successfully!");
 | 
			
		||||
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
              console.error("Error:", error);
 | 
			
		||||
              return;
 | 
			
		||||
            }
 | 
			
		||||
          })();
 | 
			
		||||
          EOF
 | 
			
		||||
							
								
								
									
										58
									
								
								.github/workflows/close_issue_in_dev.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								.github/workflows/close_issue_in_dev.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
name: Close Matching Issue on PR Merge
 | 
			
		||||
on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    types:
 | 
			
		||||
      - closed
 | 
			
		||||
jobs:
 | 
			
		||||
  close_issue:
 | 
			
		||||
    if: github.event.pull_request.merged == true
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    
 | 
			
		||||
    steps:        
 | 
			
		||||
      - name: Extract and Process PR Title
 | 
			
		||||
        id: extract_title
 | 
			
		||||
        run: |
 | 
			
		||||
          title=$(echo "${{ github.event.pull_request.title }}" | sed 's/^New Script://g' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g')
 | 
			
		||||
          echo "Processed Title: $title"
 | 
			
		||||
          echo "title=$title" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Search for Issues with Similar Titles
 | 
			
		||||
        id: find_issue
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          issues=$(gh issue list --repo community-scripts/ProxmoxVED --json number,title --jq '.[] | {number, title}')
 | 
			
		||||
          
 | 
			
		||||
          best_match_score=0
 | 
			
		||||
          best_match_number=0
 | 
			
		||||
          
 | 
			
		||||
          for issue in $(echo "$issues" | jq -r '. | @base64'); do
 | 
			
		||||
            _jq() {
 | 
			
		||||
              echo ${issue} | base64 --decode | jq -r ${1}
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            issue_title=$(_jq '.title' | tr '[:upper:]' '[:lower:]' | sed 's/ //g' | sed 's/-//g')
 | 
			
		||||
            issue_number=$(_jq '.number')
 | 
			
		||||
 | 
			
		||||
            match_score=$(echo "$title" | grep -o "$issue_title" | wc -l)
 | 
			
		||||
            
 | 
			
		||||
            if [ "$match_score" -gt "$best_match_score" ]; then
 | 
			
		||||
              best_match_score=$match_score
 | 
			
		||||
              best_match_number=$issue_number
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
 | 
			
		||||
          if [ "$best_match_number" != "0" ]; then
 | 
			
		||||
            echo "issue_number=$best_match_number" >> $GITHUB_ENV
 | 
			
		||||
          else
 | 
			
		||||
            echo "No matching issue found."
 | 
			
		||||
            exit 0
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: Comment on the Best-Matching Issue and Close It
 | 
			
		||||
        if: env.issue_number != ''
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.PAT_MICHEL }}
 | 
			
		||||
        run: |
 | 
			
		||||
          gh issue comment $issue_number --repo community-scripts/ProxmoxVED --body "Merged with #${{ github.event.pull_request.number }} in ProxmoxVE"
 | 
			
		||||
          gh issue close $issue_number --repo community-scripts/ProxmoxVED
 | 
			
		||||
							
								
								
									
										37
									
								
								.github/workflows/create-docker-for-runner.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/create-docker-for-runner.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
name: Build and Publish Docker Image
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main 
 | 
			
		||||
    paths:
 | 
			
		||||
      - '.github/runner/docker/**' 
 | 
			
		||||
  schedule:
 | 
			
		||||
    - cron: '0 0 * * *'  
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    runs-on: ubuntu-latest #To ensure it always builds we use the github runner with all the right tooling
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout code
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
 | 
			
		||||
      - name: Log in to GHCR
 | 
			
		||||
        uses: docker/login-action@v2
 | 
			
		||||
        with:
 | 
			
		||||
          registry: ghcr.io
 | 
			
		||||
          username: ${{ github.actor }}
 | 
			
		||||
          password: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Build Docker image
 | 
			
		||||
        run: |
 | 
			
		||||
          repo_name=${{ github.repository }}  # Get repository name
 | 
			
		||||
          repo_name_lower=$(echo $repo_name | tr '[:upper:]' '[:lower:]')  # Convert to lowercase
 | 
			
		||||
          docker build -t ghcr.io/$repo_name_lower/gh-runner-self:latest -f .github/runner/docker/gh-runner-self.dockerfile .
 | 
			
		||||
  
 | 
			
		||||
      - name: Push Docker image to GHCR
 | 
			
		||||
        run: |
 | 
			
		||||
          repo_name=${{ github.repository }}  # Get repository name
 | 
			
		||||
          repo_name_lower=$(echo $repo_name | tr '[:upper:]' '[:lower:]')  # Convert to lowercase
 | 
			
		||||
          docker push ghcr.io/$repo_name_lower/gh-runner-self:latest
 | 
			
		||||
							
								
								
									
										28
									
								
								.github/workflows/delete-json-branch.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								.github/workflows/delete-json-branch.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
 | 
			
		||||
name: Delete JSON date PR  Branch
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    types: [closed]
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  delete_branch:
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout the code
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
 | 
			
		||||
      - name: Delete PR Update Branch
 | 
			
		||||
        if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'pr-update-json-')
 | 
			
		||||
        run: |
 | 
			
		||||
          PR_BRANCH="${{ github.event.pull_request.head.ref }}"
 | 
			
		||||
          echo "Deleting branch $PR_BRANCH..."
 | 
			
		||||
 | 
			
		||||
          # Avoid deleting the default branch (e.g., main)
 | 
			
		||||
          if [[ "$PR_BRANCH" != "main" ]]; then
 | 
			
		||||
            git push origin --delete "$PR_BRANCH"
 | 
			
		||||
          else
 | 
			
		||||
            echo "Skipping deletion of the main branch"
 | 
			
		||||
          fi
 | 
			
		||||
							
								
								
									
										2
									
								
								.github/workflows/frontend-cicd.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/frontend-cicd.yml
									
									
									
									
										vendored
									
									
								
							@@ -27,7 +27,7 @@ concurrency:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
    defaults:
 | 
			
		||||
      run:
 | 
			
		||||
        working-directory: frontend  # Set default working directory for all run steps
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								.github/workflows/github-release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								.github/workflows/github-release.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,25 +1,46 @@
 | 
			
		||||
name: Create new release
 | 
			
		||||
name: Create Daily Release
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  schedule:
 | 
			
		||||
    # Runs "At 00:01 every night" (UTC)
 | 
			
		||||
    - cron: '1 0 * * *'
 | 
			
		||||
 | 
			
		||||
    - cron: '1 0 * * *'  # Runs daily at 00:01 UTC
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
  
 | 
			
		||||
jobs:
 | 
			
		||||
  create-new-release:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
  create-daily-release:
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: write
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout code
 | 
			
		||||
      - name: Checkout repository
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
      - name: Parse CHANGELOG.md for yesterday's entries and create a new release
 | 
			
		||||
 | 
			
		||||
      - name: Clean CHANGELOG (remove HTML header)
 | 
			
		||||
        run: sed -n '/^## /,$p' CHANGELOG.md > changelog_cleaned.md
 | 
			
		||||
 | 
			
		||||
      - name: Extract relevant changelog section
 | 
			
		||||
        run: |
 | 
			
		||||
          YESTERDAY=$(date -u --date="yesterday" +%Y-%m-%d)
 | 
			
		||||
          echo "Checking for changes on: $YESTERDAY"
 | 
			
		||||
 | 
			
		||||
          # Extract the section from "## $YESTERDAY" until the next "## YYYY-MM-DD"
 | 
			
		||||
          sed -n "/^## $YESTERDAY/,/^## [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/p" changelog_cleaned.md | head -n -1 > changelog_tmp_full.md
 | 
			
		||||
 | 
			
		||||
          # Truncate the extracted section to 5000 characters
 | 
			
		||||
          head -c 5000 changelog_tmp_full.md > changelog_tmp.md
 | 
			
		||||
 | 
			
		||||
          echo "=== Extracted Changelog ==="
 | 
			
		||||
          cat changelog_tmp.md
 | 
			
		||||
          echo "==========================="
 | 
			
		||||
 | 
			
		||||
          # Abort if no content was found
 | 
			
		||||
          if [ ! -s changelog_tmp.md ]; then
 | 
			
		||||
            echo "No changes found for $YESTERDAY, skipping release."
 | 
			
		||||
            exit 0
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: Create GitHub release
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          YESTERDAY=$(date -u --date="yesterday" +%Y-%m-%d)
 | 
			
		||||
          YESTERDAY_CHANGELOG_NOTES=$(awk '/^## '"$YESTERDAY"'/ {f=1; next} f && /^## [0-9]{4}-[0-9]{2}-[0-9]{2}/ {f=0} f && !/^## / {print}' CHANGELOG.md)
 | 
			
		||||
          
 | 
			
		||||
          if [ -n "$YESTERDAY_CHANGELOG_NOTES" ]; then
 | 
			
		||||
            gh release create "$YESTERDAY" -t "$YESTERDAY" -n "$YESTERDAY_CHANGELOG_NOTES" --latest
 | 
			
		||||
          fi
 | 
			
		||||
          gh release create "$YESTERDAY" -t "$YESTERDAY" -F changelog_tmp.md
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										177
									
								
								.github/workflows/script-test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								.github/workflows/script-test.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,177 @@
 | 
			
		||||
name: Run Scripts on PVE Node for testing
 | 
			
		||||
permissions:
 | 
			
		||||
    pull-requests: write
 | 
			
		||||
on:
 | 
			
		||||
  pull_request_target:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
    paths:
 | 
			
		||||
      - 'install/**.sh'
 | 
			
		||||
      - 'ct/**.sh'
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  run-install-script:
 | 
			
		||||
    runs-on: pvenode
 | 
			
		||||
    steps:          
 | 
			
		||||
      - name: Checkout PR branch
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
        with:
 | 
			
		||||
          ref: ${{ github.event.pull_request.head.ref }}
 | 
			
		||||
          repository: ${{ github.event.pull_request.head.repo.full_name }}
 | 
			
		||||
          fetch-depth: 0          
 | 
			
		||||
          
 | 
			
		||||
      - name: Add Git safe directory
 | 
			
		||||
        run: |
 | 
			
		||||
          git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
 | 
			
		||||
      
 | 
			
		||||
      - name: Set up GH_TOKEN
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Get Changed Files
 | 
			
		||||
        run: |
 | 
			
		||||
          CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
 | 
			
		||||
          CHANGED_FILES=$(echo "$CHANGED_FILES" | tr '\n' ' ')
 | 
			
		||||
          echo "Changed files: $CHANGED_FILES"
 | 
			
		||||
          echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
      - name: Get scripts
 | 
			
		||||
        id: check-install-script
 | 
			
		||||
        run: |
 | 
			
		||||
          ALL_FILES=()
 | 
			
		||||
          ADDED_FILES=()  
 | 
			
		||||
          for FILE in ${{ env.SCRIPT }}; do           
 | 
			
		||||
            if [[ $FILE =~ ^install/.*-install\.sh$ ]] || [[ $FILE =~ ^ct/.*\.sh$ ]]; then             
 | 
			
		||||
              STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
 | 
			
		||||
              if [[ ! " ${ADDED_FILES[@]} " =~ " $STRIPPED_NAME " ]]; then
 | 
			
		||||
                ALL_FILES+=("$FILE")
 | 
			
		||||
                ADDED_FILES+=("$STRIPPED_NAME")  # Mark this base file as added (without the path)
 | 
			
		||||
              fi
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
          ALL_FILES=$(echo "${ALL_FILES[@]}" | xargs)
 | 
			
		||||
          echo "$ALL_FILES"
 | 
			
		||||
          echo "ALL_FILES=$ALL_FILES" >> $GITHUB_ENV
 | 
			
		||||
     
 | 
			
		||||
      - name: Run scripts
 | 
			
		||||
        id: run-install
 | 
			
		||||
        continue-on-error: true
 | 
			
		||||
        run: |
 | 
			
		||||
            set +e  
 | 
			
		||||
            #run for each files in /ct
 | 
			
		||||
            for FILE in ${{ env.ALL_FILES }}; do            
 | 
			
		||||
              STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
 | 
			
		||||
              echo "Running Test for: $STRIPPED_NAME"
 | 
			
		||||
              if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "$FILE"; then
 | 
			
		||||
                echo "The script contains an interactive prompt. Skipping execution."
 | 
			
		||||
                continue
 | 
			
		||||
              fi
 | 
			
		||||
              if [[ $FILE =~ ^install/.*-install\.sh$ ]]; then
 | 
			
		||||
                CT_SCRIPT="ct/$STRIPPED_NAME.sh"
 | 
			
		||||
                if [[ ! -f $CT_SCRIPT ]]; then
 | 
			
		||||
                  echo "No CT script found for $STRIPPED_NAME"
 | 
			
		||||
                  ERROR_MSG="No CT script found for $FILE"
 | 
			
		||||
                  echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
 | 
			
		||||
                  continue
 | 
			
		||||
                fi
 | 
			
		||||
                  if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "install/$STRIPPED_NAME-install.sh"; then
 | 
			
		||||
                    echo "The script contains an interactive prompt. Skipping execution."
 | 
			
		||||
                    continue
 | 
			
		||||
                  fi
 | 
			
		||||
                  echo "Found CT script for $STRIPPED_NAME"
 | 
			
		||||
                  chmod +x "$CT_SCRIPT"
 | 
			
		||||
                  RUNNING_FILE=$CT_SCRIPT
 | 
			
		||||
              elif [[ $FILE =~ ^ct/.*\.sh$ ]]; then
 | 
			
		||||
                INSTALL_SCRIPT="install/$STRIPPED_NAME-install.sh"
 | 
			
		||||
                if [[ ! -f $INSTALL_SCRIPT ]]; then
 | 
			
		||||
                  echo "No install script found for $STRIPPED_NAME"
 | 
			
		||||
                  ERROR_MSG="No install script found for $FILE"
 | 
			
		||||
                  echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
 | 
			
		||||
                  continue
 | 
			
		||||
                fi                
 | 
			
		||||
                  echo "Found install script for $STRIPPED_NAME"
 | 
			
		||||
                  chmod +x "$INSTALL_SCRIPT"
 | 
			
		||||
                  RUNNING_FILE=$FILE
 | 
			
		||||
                  if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "ct/$STRIPPED_NAME.sh"; then
 | 
			
		||||
                    echo "The script contains an interactive prompt. Skipping execution."
 | 
			
		||||
                    continue
 | 
			
		||||
                  fi
 | 
			
		||||
              fi
 | 
			
		||||
              git remote add community-scripts https://github.com/community-scripts/ProxmoxVE.git
 | 
			
		||||
              git fetch community-scripts
 | 
			
		||||
              rm -f .github/workflows/scripts/app-test/pr-build.func || true
 | 
			
		||||
              rm -f .github/workflows/scripts/app-test/pr-install.func || true
 | 
			
		||||
              rm -f .github/workflows/scripts/app-test/pr-alpine-install.func || true
 | 
			
		||||
              rm -f .github/workflows/scripts/app-test/pr-create-lxc.sh || true
 | 
			
		||||
              git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-build.func
 | 
			
		||||
              git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-install.func
 | 
			
		||||
              git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-alpine-install.func
 | 
			
		||||
              git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-create-lxc.sh
 | 
			
		||||
              chmod +x $RUNNING_FILE         
 | 
			
		||||
              chmod +x .github/workflows/scripts/app-test/pr-create-lxc.sh
 | 
			
		||||
              chmod +x .github/workflows/scripts/app-test/pr-install.func
 | 
			
		||||
              chmod +x .github/workflows/scripts/app-test/pr-alpine-install.func
 | 
			
		||||
              chmod +x .github/workflows/scripts/app-test/pr-build.func
 | 
			
		||||
              sed -i 's|source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)|source .github/workflows/scripts/app-test/pr-build.func|g' "$RUNNING_FILE"
 | 
			
		||||
              echo "Executing $RUNNING_FILE"
 | 
			
		||||
              ERROR_MSG=$(./$RUNNING_FILE 2>&1 > /dev/null)
 | 
			
		||||
              echo "Finished running $FILE"
 | 
			
		||||
              if [ -n "$ERROR_MSG" ]; then
 | 
			
		||||
                echo "ERROR in $STRIPPED_NAME: $ERROR_MSG"
 | 
			
		||||
                echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
 | 
			
		||||
              fi
 | 
			
		||||
            done
 | 
			
		||||
            set -e  # Restore exit-on-error
 | 
			
		||||
      
 | 
			
		||||
      - name: Cleanup PVE Node
 | 
			
		||||
        run: |
 | 
			
		||||
          containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}' | awk '{print $1}')
 | 
			
		||||
        
 | 
			
		||||
          for container_id in $containers; do
 | 
			
		||||
            status=$(pct status $container_id | awk '{print $2}')
 | 
			
		||||
            if [[ $status == "running" ]]; then
 | 
			
		||||
                pct stop $container_id
 | 
			
		||||
                pct destroy $container_id
 | 
			
		||||
            fi            
 | 
			
		||||
          done
 | 
			
		||||
   
 | 
			
		||||
      - name: Post error comments
 | 
			
		||||
        run: |
 | 
			
		||||
          ERROR="false"
 | 
			
		||||
          SEARCH_LINE=".github/workflows/scripts/app-test/pr-build.func: line 255:"
 | 
			
		||||
          
 | 
			
		||||
          # Get all existing comments on the PR
 | 
			
		||||
          EXISTING_COMMENTS=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json comments --jq '.comments[].body')
 | 
			
		||||
          
 | 
			
		||||
          for FILE in ${{ env.ALL_FILES }}; do
 | 
			
		||||
            STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
 | 
			
		||||
            if [[ ! -f result_$STRIPPED_NAME.log ]]; then
 | 
			
		||||
              continue
 | 
			
		||||
            fi
 | 
			
		||||
            ERROR_MSG=$(cat result_$STRIPPED_NAME.log)
 | 
			
		||||
          
 | 
			
		||||
            if [ -n "$ERROR_MSG" ]; then
 | 
			
		||||
              CLEANED_ERROR_MSG=$(echo "$ERROR_MSG" | sed "s|$SEARCH_LINE.*||")
 | 
			
		||||
              COMMENT_BODY=":warning: The script _**$FILE**_ failed with the following message: <br> <div><strong>${CLEANED_ERROR_MSG}</strong></div>"
 | 
			
		||||
          
 | 
			
		||||
              # Check if the comment already exists
 | 
			
		||||
              if echo "$EXISTING_COMMENTS" | grep -qF "$COMMENT_BODY"; then
 | 
			
		||||
                echo "Skipping duplicate comment for $FILE"
 | 
			
		||||
              else
 | 
			
		||||
                echo "Posting error message for $FILE"
 | 
			
		||||
                gh pr comment ${{ github.event.pull_request.number }} \
 | 
			
		||||
                  --repo ${{ github.repository }} \
 | 
			
		||||
                  --body "$COMMENT_BODY"
 | 
			
		||||
                ERROR="true"
 | 
			
		||||
              fi
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
          
 | 
			
		||||
          echo "ERROR=$ERROR" >> $GITHUB_ENV
 | 
			
		||||
      
 | 
			
		||||
  
 | 
			
		||||
							
								
								
									
										243
									
								
								.github/workflows/script_format.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								.github/workflows/script_format.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,243 @@
 | 
			
		||||
name: Script Format Check
 | 
			
		||||
permissions:
 | 
			
		||||
    pull-requests: write
 | 
			
		||||
on:
 | 
			
		||||
  pull_request_target:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
    paths:
 | 
			
		||||
      - 'install/*.sh'
 | 
			
		||||
      - 'ct/*.sh'
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  run-install-script:
 | 
			
		||||
    runs-on: pvenode
 | 
			
		||||
    steps:          
 | 
			
		||||
      - name: Checkout PR branch (supports forks)
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
        with:
 | 
			
		||||
          ref: ${{ github.event.pull_request.head.ref }}
 | 
			
		||||
          repository: ${{ github.event.pull_request.head.repo.full_name }} 
 | 
			
		||||
          fetch-depth: 0          
 | 
			
		||||
          
 | 
			
		||||
      - name: Add Git safe directory
 | 
			
		||||
        run: |
 | 
			
		||||
          git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
 | 
			
		||||
      
 | 
			
		||||
      - name: Set up GH_TOKEN
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Get Changed Files
 | 
			
		||||
        run: |
 | 
			
		||||
          CHANGED_FILES=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --name-only)
 | 
			
		||||
          CHANGED_FILES=$(echo "$CHANGED_FILES" | tr '\n' ' ')
 | 
			
		||||
          echo "Changed files: $CHANGED_FILES"
 | 
			
		||||
          echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
            
 | 
			
		||||
      - name: Check scripts
 | 
			
		||||
        id: run-install
 | 
			
		||||
        continue-on-error: true
 | 
			
		||||
        run: |
 | 
			
		||||
          for FILE in ${{ env.SCRIPT }}; do
 | 
			
		||||
              STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
 | 
			
		||||
              echo "Running Test for: $STRIPPED_NAME"
 | 
			
		||||
              FILE_STRIPPED="${FILE##*/}"
 | 
			
		||||
              LOG_FILE="result_$FILE_STRIPPED.log"
 | 
			
		||||
 | 
			
		||||
              if [[ $FILE =~ ^ct/.*\.sh$ ]]; then
 | 
			
		||||
 | 
			
		||||
                FIRST_LINE=$(sed -n '1p' "$FILE")
 | 
			
		||||
                [[ "$FIRST_LINE" != "#!/usr/bin/env bash" ]] && echo "Line 1 was $FIRST_LINE | Should be: #!/usr/bin/env bash" >> "$LOG_FILE"
 | 
			
		||||
                SECOND_LINE=$(sed -n '2p' "$FILE")
 | 
			
		||||
                [[ "$SECOND_LINE" != "source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" ]] && 
 | 
			
		||||
                echo "Line 2 was $SECOND_LINE | Should be: source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)" >> "$LOG_FILE"
 | 
			
		||||
                THIRD_LINE=$(sed -n '3p' "$FILE")
 | 
			
		||||
                 if ! [[ "$THIRD_LINE" =~ ^#\ Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ community-scripts\ ORG$ || "$THIRD_LINE" =~ ^Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ tteck$ ]]; then
 | 
			
		||||
                     echo "Line 3 was $THIRD_LINE | Should be: # Copyright (c) 2021-2025 community-scripts ORG" >> "$LOG_FILE"
 | 
			
		||||
                 fi
 | 
			
		||||
      
 | 
			
		||||
              EXPECTED_AUTHOR="# Author:"
 | 
			
		||||
              EXPECTED_LICENSE="# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE"
 | 
			
		||||
              EXPECTED_SOURCE="# Source:"
 | 
			
		||||
              EXPECTED_EMPTY=""
 | 
			
		||||
 | 
			
		||||
              for i in {4..7}; do
 | 
			
		||||
                  LINE=$(sed -n "${i}p" "$FILE")
 | 
			
		||||
 | 
			
		||||
                  case $i in
 | 
			
		||||
                      4) 
 | 
			
		||||
                          [[ $LINE == $EXPECTED_AUTHOR* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_AUTHOR" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                      5) 
 | 
			
		||||
                          [[ "$LINE" == "$EXPECTED_LICENSE" ]] || printf "Line %d was: '%s' | Should be: '%s'\n" "$i" "$LINE" "$EXPECTED_LICENSE" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                      6) 
 | 
			
		||||
                          [[ $LINE == $EXPECTED_SOURCE* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_SOURCE" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                      7) 
 | 
			
		||||
                          [[ -z $LINE ]] || printf "Line %d was: '%s' | Should be empty\n" "$i" "$LINE" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                  esac
 | 
			
		||||
              done
 | 
			
		||||
                  
 | 
			
		||||
              
 | 
			
		||||
              EXPECTED_PREFIXES=(
 | 
			
		||||
                  "APP="
 | 
			
		||||
                  "var_tags="
 | 
			
		||||
                  "var_cpu="   # Must be a number
 | 
			
		||||
                  "var_ram="   # Must be a number
 | 
			
		||||
                  "var_disk="  # Must be a number
 | 
			
		||||
                  "var_os="    # Must be debian, alpine, or ubuntu
 | 
			
		||||
                  "var_version="
 | 
			
		||||
                  "var_unprivileged="  # Must be 0 or 1
 | 
			
		||||
              )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
              for i in {8..15}; do
 | 
			
		||||
                  LINE=$(sed -n "${i}p" "$FILE")
 | 
			
		||||
                  INDEX=$((i - 8))
 | 
			
		||||
 | 
			
		||||
                  case $INDEX in
 | 
			
		||||
                      2|3|4)  # var_cpu, var_ram, var_disk (must be numbers)
 | 
			
		||||
                          if [[ "$LINE" =~ ^${EXPECTED_PREFIXES[$INDEX]}([0-9]+)$ ]]; then
 | 
			
		||||
                              continue  # Valid
 | 
			
		||||
                          else
 | 
			
		||||
                              echo "Line $i was '$LINE' | Should be: '${EXPECTED_PREFIXES[$INDEX]}<NUMBER>'" >> "$LOG_FILE"
 | 
			
		||||
                          fi
 | 
			
		||||
                          ;;
 | 
			
		||||
                      5)  # var_os (must be debian, alpine, or ubuntu)
 | 
			
		||||
                          if [[ "$LINE" =~ ^var_os=(debian|alpine|ubuntu)$ ]]; then
 | 
			
		||||
                              continue  # Valid
 | 
			
		||||
                          else
 | 
			
		||||
                              echo "Line $i was '$LINE' | Should be: 'var_os=[debian|alpine|ubuntu]'" >> "$LOG_FILE"
 | 
			
		||||
                          fi
 | 
			
		||||
                          ;;
 | 
			
		||||
                      7)  # var_unprivileged (must be 0 or 1)
 | 
			
		||||
                          if [[ "$LINE" =~ ^var_unprivileged=[01]$ ]]; then
 | 
			
		||||
                              continue  # Valid
 | 
			
		||||
                          else
 | 
			
		||||
                              echo "Line $i was '$LINE' | Should be: 'var_unprivileged=[0|1]'" >> "$LOG_FILE"
 | 
			
		||||
                          fi
 | 
			
		||||
                          ;;
 | 
			
		||||
                      *)  # Other lines (must start with expected prefix)
 | 
			
		||||
                          if [[ "$LINE" == ${EXPECTED_PREFIXES[$INDEX]}* ]]; then
 | 
			
		||||
                              continue  # Valid
 | 
			
		||||
                          else
 | 
			
		||||
                              echo "Line $i was '$LINE' | Should start with '${EXPECTED_PREFIXES[$INDEX]}'" >> "$LOG_FILE"
 | 
			
		||||
                          fi
 | 
			
		||||
                          ;;
 | 
			
		||||
                  esac
 | 
			
		||||
              done
 | 
			
		||||
 | 
			
		||||
              for i in {16..20}; do
 | 
			
		||||
                  LINE=$(sed -n "${i}p" "$FILE")
 | 
			
		||||
                  EXPECTED=(
 | 
			
		||||
                      "header_info \"$APP\""
 | 
			
		||||
                      "variables"
 | 
			
		||||
                      "color"
 | 
			
		||||
                      "catch_errors"
 | 
			
		||||
                      "function update_script() {"
 | 
			
		||||
                  )
 | 
			
		||||
                  [[ "$LINE" != "${EXPECTED[$((i-16))]}" ]] && echo "Line $i was $LINE | Should be: ${EXPECTED[$((i-16))]}" >> "$LOG_FILE"
 | 
			
		||||
              done
 | 
			
		||||
            cat "$LOG_FILE"
 | 
			
		||||
          elif [[ $FILE =~ ^install/.*-install\.sh$ ]]; then
 | 
			
		||||
 | 
			
		||||
              FIRST_LINE=$(sed -n '1p' "$FILE")
 | 
			
		||||
              [[ "$FIRST_LINE" != "#!/usr/bin/env bash" ]] && echo "Line 1 was $FIRST_LINE | Should be: #!/usr/bin/env bash" >> "$LOG_FILE"
 | 
			
		||||
 | 
			
		||||
              SECOND_LINE=$(sed -n '2p' "$FILE")
 | 
			
		||||
              [[ -n "$SECOND_LINE" ]] && echo "Line 2 should be empty" >> "$LOG_FILE"
 | 
			
		||||
 | 
			
		||||
              THIRD_LINE=$(sed -n '3p' "$FILE")
 | 
			
		||||
              if ! [[ "$THIRD_LINE" =~ ^#\ Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ community-scripts\ ORG$ || "$THIRD_LINE" =~ ^Copyright\ \(c\)\ [0-9]{4}-[0-9]{4}\ tteck$ ]]; then
 | 
			
		||||
                  echo "Line 3 was $THIRD_LINE | Should be: # Copyright (c) 2021-2025 community-scripts ORG" >> "$LOG_FILE"
 | 
			
		||||
              fi
 | 
			
		||||
 | 
			
		||||
              EXPECTED_AUTHOR="# Author:"
 | 
			
		||||
              EXPECTED_LICENSE="# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE"
 | 
			
		||||
              EXPECTED_SOURCE="# Source:"
 | 
			
		||||
              EXPECTED_EMPTY=""
 | 
			
		||||
 | 
			
		||||
              for i in {4..7}; do
 | 
			
		||||
                  LINE=$(sed -n "${i}p" "$FILE")
 | 
			
		||||
 | 
			
		||||
                  case $i in
 | 
			
		||||
                      4) 
 | 
			
		||||
                          [[ $LINE == $EXPECTED_AUTHOR* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_AUTHOR" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                      5) 
 | 
			
		||||
                          [[ "$LINE" == "$EXPECTED_LICENSE" ]] || printf "Line %d was: '%s' | Should be: '%s'\n" "$i" "$LINE" "$EXPECTED_LICENSE" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                      6) 
 | 
			
		||||
                          [[ $LINE == $EXPECTED_SOURCE* ]] || printf "Line %d was: '%s' | Should start with: '%s'\n" "$i" "$LINE" "$EXPECTED_SOURCE" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                      7) 
 | 
			
		||||
                          [[ -z $LINE ]] || printf "Line %d was: '%s' | Should be empty\n" "$i" "$LINE" >> $LOG_FILE
 | 
			
		||||
                          ;;
 | 
			
		||||
                  esac
 | 
			
		||||
              done
 | 
			
		||||
 | 
			
		||||
            [[ "$(sed -n '8p' "$FILE")" != 'source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"' ]] && echo 'Line 8 should be: source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"' >> "$LOG_FILE"
 | 
			
		||||
 | 
			
		||||
            for i in {9..14}; do
 | 
			
		||||
                LINE=$(sed -n "${i}p" "$FILE")
 | 
			
		||||
                EXPECTED=(
 | 
			
		||||
                    "color"
 | 
			
		||||
                    "verb_ip6"
 | 
			
		||||
                    "catch_errors"
 | 
			
		||||
                    "setting_up_container"
 | 
			
		||||
                    "network_check"
 | 
			
		||||
                    "update_os"
 | 
			
		||||
                )
 | 
			
		||||
                [[ "$LINE" != "${EXPECTED[$((i-9))]}" ]] && echo "Line $i was $LINE | Should be: ${EXPECTED[$((i-9))]}" >> "$LOG_FILE"
 | 
			
		||||
            done
 | 
			
		||||
 | 
			
		||||
            [[ -n "$(sed -n '15p' "$FILE")" ]] && echo "Line 15 should be empty" >> "$LOG_FILE"
 | 
			
		||||
            [[ "$(sed -n '16p' "$FILE")" != 'msg_info "Installing Dependencies"' ]] && echo 'Line 16 should be: msg_info "Installing Dependencies"' >> "$LOG_FILE"
 | 
			
		||||
 | 
			
		||||
            LAST_3_LINES=$(tail -n 3 "$FILE")
 | 
			
		||||
            [[ "$LAST_3_LINES" != *"$STD apt-get -y autoremove"* ]] && echo 'Third to last line should be: $STD apt-get -y autoremove' >> "$LOG_FILE"
 | 
			
		||||
            [[ "$LAST_3_LINES" != *"$STD apt-get -y autoclean"* ]] && echo 'Second to last line should be: $STD apt-get -y clean' >> "$LOG_FILE"
 | 
			
		||||
            [[ "$LAST_3_LINES" != *'msg_ok "Cleaned"'* ]] && echo 'Last line should be: msg_ok "Cleaned"' >> "$LOG_FILE"
 | 
			
		||||
          cat "$LOG_FILE"
 | 
			
		||||
          fi
 | 
			
		||||
            
 | 
			
		||||
          done
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      - name: Post error comments
 | 
			
		||||
        run: |
 | 
			
		||||
          ERROR="false"
 | 
			
		||||
          for FILE in ${{ env.SCRIPT }}; do
 | 
			
		||||
            FILE_STRIPPED="${FILE##*/}"
 | 
			
		||||
            LOG_FILE="result_$FILE_STRIPPED.log"
 | 
			
		||||
            echo $LOG_FILE
 | 
			
		||||
            if [[ ! -f $LOG_FILE ]]; then
 | 
			
		||||
              continue
 | 
			
		||||
            fi
 | 
			
		||||
            ERROR_MSG=$(cat $LOG_FILE)
 | 
			
		||||
      
 | 
			
		||||
            if [ -n "$ERROR_MSG" ]; then
 | 
			
		||||
              echo "Posting error message for $FILE"
 | 
			
		||||
              echo ${ERROR_MSG}
 | 
			
		||||
              gh pr comment ${{ github.event.pull_request.number }} \
 | 
			
		||||
                --repo ${{ github.repository }} \
 | 
			
		||||
                --body ":warning: The script _**$FILE**_ has the following formatting errors: <br> <div><strong>${ERROR_MSG}</strong></div>"
 | 
			
		||||
 | 
			
		||||
              
 | 
			
		||||
              ERROR="true"
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
          echo "ERROR=$ERROR" >> $GITHUB_ENV
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
 | 
			
		||||
      - name: Fail if error
 | 
			
		||||
        if: ${{ env.ERROR == 'true' }}
 | 
			
		||||
        run: exit 1 
 | 
			
		||||
							
								
								
									
										86
									
								
								.github/workflows/scripts/app-test/pr-alpine-install.func
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								.github/workflows/scripts/app-test/pr-alpine-install.func
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
color() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
catch_errors() {
 | 
			
		||||
  set -Eeuo pipefail
 | 
			
		||||
  trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function handles errors
 | 
			
		||||
error_handler() {
 | 
			
		||||
  local line_number="$1"
 | 
			
		||||
  local command="$2"
 | 
			
		||||
  SCRIPT_NAME=$(basename "$0")
 | 
			
		||||
  local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command $command"
 | 
			
		||||
  echo -e "\n$error_message"
 | 
			
		||||
  exit 0
 | 
			
		||||
}
 | 
			
		||||
verb_ip6() {
 | 
			
		||||
  STD=""
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_info() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -ne "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_ok() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_error() {
 | 
			
		||||
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RETRY_NUM=10
 | 
			
		||||
RETRY_EVERY=3
 | 
			
		||||
i=$RETRY_NUM
 | 
			
		||||
 | 
			
		||||
setting_up_container() {
 | 
			
		||||
  while [ $i -gt 0 ]; do
 | 
			
		||||
    if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" != "" ]; then
 | 
			
		||||
      break
 | 
			
		||||
    fi
 | 
			
		||||
    echo 1>&2 -en "No Network! "
 | 
			
		||||
    sleep $RETRY_EVERY
 | 
			
		||||
    i=$((i - 1))
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" = "" ]; then
 | 
			
		||||
    echo 1>&2 -e "\n No Network After $RETRY_NUM Tries"
 | 
			
		||||
    echo -e "Check Network Settings"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  msg_ok "Set up Container OS"
 | 
			
		||||
  msg_ok "Network Connected: $(hostname -i)"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
network_check() {
 | 
			
		||||
  RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
 | 
			
		||||
  if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi
 | 
			
		||||
  set -e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
update_os() {
 | 
			
		||||
  msg_info "Updating Container OS"
 | 
			
		||||
  apk update
 | 
			
		||||
  apk upgrade
 | 
			
		||||
  msg_ok "Updated Container OS"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
motd_ssh() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customize() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										260
									
								
								.github/workflows/scripts/app-test/pr-build.func
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								.github/workflows/scripts/app-test/pr-build.func
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,260 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
variables() {
 | 
			
		||||
  NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces.
 | 
			
		||||
  var_install="${NSAPP}-install"     # sets the var_install variable by appending "-install" to the value of NSAPP.
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NEXTID=$(pvesh get /cluster/nextid)
 | 
			
		||||
timezone=$(cat /etc/timezone)
 | 
			
		||||
header_info() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
base_settings() {
 | 
			
		||||
  # Default Settings
 | 
			
		||||
  CT_TYPE="1"
 | 
			
		||||
  DISK_SIZE="4"
 | 
			
		||||
  CORE_COUNT="1"
 | 
			
		||||
  RAM_SIZE="1024"
 | 
			
		||||
  VERBOSE="no"
 | 
			
		||||
  PW=""
 | 
			
		||||
  CT_ID=$NEXTID
 | 
			
		||||
  HN=$NSAPP
 | 
			
		||||
  BRG="vmbr0"
 | 
			
		||||
  NET="dhcp"
 | 
			
		||||
  GATE=""
 | 
			
		||||
  APT_CACHER=""
 | 
			
		||||
  APT_CACHER_IP=""
 | 
			
		||||
  DISABLEIP6="no"
 | 
			
		||||
  MTU=""
 | 
			
		||||
  SD=""
 | 
			
		||||
  NS=""
 | 
			
		||||
  MAC=""
 | 
			
		||||
  VLAN=""
 | 
			
		||||
  SSH="no"
 | 
			
		||||
  SSH_AUTHORIZED_KEY=""
 | 
			
		||||
  TAGS="community-script;"
 | 
			
		||||
 | 
			
		||||
  # Override default settings with variables from ct script
 | 
			
		||||
  CT_TYPE=${var_unprivileged:-$CT_TYPE}
 | 
			
		||||
  DISK_SIZE=${var_disk:-$DISK_SIZE}
 | 
			
		||||
  CORE_COUNT=${var_cpu:-$CORE_COUNT}
 | 
			
		||||
  RAM_SIZE=${var_ram:-$RAM_SIZE}
 | 
			
		||||
  VERB=${var_verbose:-$VERBOSE}
 | 
			
		||||
  TAGS="${TAGS}${var_tags:-}"
 | 
			
		||||
 | 
			
		||||
  # Since these 2 are only defined outside of default_settings function, we add a temporary fallback. TODO: To align everything, we should add these as constant variables (e.g. OSTYPE and OSVERSION), but that would currently require updating the default_settings function for all existing scripts
 | 
			
		||||
  if [ -z "$var_os" ]; then
 | 
			
		||||
    var_os="debian"
 | 
			
		||||
  fi
 | 
			
		||||
  if [ -z "$var_version" ]; then
 | 
			
		||||
    var_version="12"
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
color() {
 | 
			
		||||
  # Colors
 | 
			
		||||
  YW=$(echo "\033[33m")
 | 
			
		||||
  YWB=$(echo "\033[93m")
 | 
			
		||||
  BL=$(echo "\033[36m")
 | 
			
		||||
  RD=$(echo "\033[01;31m")
 | 
			
		||||
  BGN=$(echo "\033[4;92m")
 | 
			
		||||
  GN=$(echo "\033[1;92m")
 | 
			
		||||
  DGN=$(echo "\033[32m")
 | 
			
		||||
 | 
			
		||||
  # Formatting
 | 
			
		||||
  CL=$(echo "\033[m")
 | 
			
		||||
  UL=$(echo "\033[4m")
 | 
			
		||||
  BOLD=$(echo "\033[1m")
 | 
			
		||||
  BFR="\\r\\033[K"
 | 
			
		||||
  HOLD=" "
 | 
			
		||||
  TAB="  "
 | 
			
		||||
 | 
			
		||||
  # Icons
 | 
			
		||||
  CM="${TAB}✔️${TAB}${CL}"
 | 
			
		||||
  CROSS="${TAB}✖️${TAB}${CL}"
 | 
			
		||||
  INFO="${TAB}💡${TAB}${CL}"
 | 
			
		||||
  OS="${TAB}🖥️${TAB}${CL}"
 | 
			
		||||
  OSVERSION="${TAB}🌟${TAB}${CL}"
 | 
			
		||||
  CONTAINERTYPE="${TAB}📦${TAB}${CL}"
 | 
			
		||||
  DISKSIZE="${TAB}💾${TAB}${CL}"
 | 
			
		||||
  CPUCORE="${TAB}🧠${TAB}${CL}"
 | 
			
		||||
  RAMSIZE="${TAB}🛠️${TAB}${CL}"
 | 
			
		||||
  SEARCH="${TAB}🔍${TAB}${CL}"
 | 
			
		||||
  VERIFYPW="${TAB}🔐${TAB}${CL}"
 | 
			
		||||
  CONTAINERID="${TAB}🆔${TAB}${CL}"
 | 
			
		||||
  HOSTNAME="${TAB}🏠${TAB}${CL}"
 | 
			
		||||
  BRIDGE="${TAB}🌉${TAB}${CL}"
 | 
			
		||||
  NETWORK="${TAB}📡${TAB}${CL}"
 | 
			
		||||
  GATEWAY="${TAB}🌐${TAB}${CL}"
 | 
			
		||||
  DISABLEIPV6="${TAB}🚫${TAB}${CL}"
 | 
			
		||||
  DEFAULT="${TAB}⚙️${TAB}${CL}"
 | 
			
		||||
  MACADDRESS="${TAB}🔗${TAB}${CL}"
 | 
			
		||||
  VLANTAG="${TAB}🏷️${TAB}${CL}"
 | 
			
		||||
  ROOTSSH="${TAB}🔑${TAB}${CL}"
 | 
			
		||||
  CREATING="${TAB}🚀${TAB}${CL}"
 | 
			
		||||
  ADVANCED="${TAB}🧩${TAB}${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
catch_errors() {
 | 
			
		||||
  set -Eeuo pipefail
 | 
			
		||||
  trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function handles errors
 | 
			
		||||
error_handler() {
 | 
			
		||||
  local line_number="$1"
 | 
			
		||||
  local command="$2"
 | 
			
		||||
  SCRIPT_NAME=$(basename "$0")
 | 
			
		||||
  local error_message="$SCRIPT_NAME: Failure in line $line_number while executing command $command"
 | 
			
		||||
  echo -e "\n$error_message"
 | 
			
		||||
  exit 100
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_info() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -ne "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_ok() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_error() {
 | 
			
		||||
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
start() {
 | 
			
		||||
  base_settings
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
build_container() {
 | 
			
		||||
  #  if [ "$VERB" == "yes" ]; then set -x; fi
 | 
			
		||||
 | 
			
		||||
  if [ "$CT_TYPE" == "1" ]; then
 | 
			
		||||
    FEATURES="keyctl=1,nesting=1"
 | 
			
		||||
  else
 | 
			
		||||
    FEATURES="nesting=1"
 | 
			
		||||
  fi
 | 
			
		||||
  TEMP_DIR=$(mktemp -d)
 | 
			
		||||
  pushd $TEMP_DIR >/dev/null
 | 
			
		||||
  if [ "$var_os" == "alpine" ]; then
 | 
			
		||||
    export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-alpine-install.func)"
 | 
			
		||||
  else
 | 
			
		||||
    export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-install.func)"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  export CACHER="$APT_CACHER"
 | 
			
		||||
  export CACHER_IP="$APT_CACHER_IP"
 | 
			
		||||
  export tz=""
 | 
			
		||||
  export DISABLEIPV6="$DISABLEIP6"
 | 
			
		||||
  export APPLICATION="$APP"
 | 
			
		||||
  export app="$NSAPP"
 | 
			
		||||
  export PASSWORD="$PW"
 | 
			
		||||
  export VERBOSE="$VERB"
 | 
			
		||||
  export SSH_ROOT="${SSH}"
 | 
			
		||||
  export SSH_AUTHORIZED_KEY
 | 
			
		||||
  export CTID="$CT_ID"
 | 
			
		||||
  export CTTYPE="$CT_TYPE"
 | 
			
		||||
  export PCT_OSTYPE="$var_os"
 | 
			
		||||
  export PCT_OSVERSION="$var_version"
 | 
			
		||||
  export PCT_DISK_SIZE="$DISK_SIZE"
 | 
			
		||||
  export tz="$timezone"
 | 
			
		||||
  export PCT_OPTIONS="
 | 
			
		||||
    -features $FEATURES
 | 
			
		||||
    -hostname $HN
 | 
			
		||||
    -tags $TAGS
 | 
			
		||||
    $SD
 | 
			
		||||
    $NS
 | 
			
		||||
    -net0 name=eth0,bridge=$BRG$MAC,ip=$NET$GATE$VLAN$MTU
 | 
			
		||||
    -onboot 1
 | 
			
		||||
    -cores $CORE_COUNT
 | 
			
		||||
    -memory $RAM_SIZE
 | 
			
		||||
    -unprivileged $CT_TYPE
 | 
			
		||||
    $PW
 | 
			
		||||
  "
 | 
			
		||||
  echo "Container ID: $CTID"
 | 
			
		||||
 | 
			
		||||
  # This executes create_lxc.sh and creates the container and .conf file
 | 
			
		||||
  bash -c "$(wget -qLO - https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/.github/workflows/scripts/app-test/pr-create-lxc.sh)"
 | 
			
		||||
 | 
			
		||||
  LXC_CONFIG=/etc/pve/lxc/${CTID}.conf
 | 
			
		||||
  if [ "$CT_TYPE" == "0" ]; then
 | 
			
		||||
    cat <<EOF >>$LXC_CONFIG
 | 
			
		||||
# USB passthrough
 | 
			
		||||
lxc.cgroup2.devices.allow: a
 | 
			
		||||
lxc.cap.drop:
 | 
			
		||||
lxc.cgroup2.devices.allow: c 188:* rwm
 | 
			
		||||
lxc.cgroup2.devices.allow: c 189:* rwm
 | 
			
		||||
lxc.mount.entry: /dev/serial/by-id  dev/serial/by-id  none bind,optional,create=dir
 | 
			
		||||
lxc.mount.entry: /dev/ttyUSB0       dev/ttyUSB0       none bind,optional,create=file
 | 
			
		||||
lxc.mount.entry: /dev/ttyUSB1       dev/ttyUSB1       none bind,optional,create=file
 | 
			
		||||
lxc.mount.entry: /dev/ttyACM0       dev/ttyACM0       none bind,optional,create=file
 | 
			
		||||
lxc.mount.entry: /dev/ttyACM1       dev/ttyACM1       none bind,optional,create=file
 | 
			
		||||
EOF
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [ "$CT_TYPE" == "0" ]; then
 | 
			
		||||
    if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" ]]; then
 | 
			
		||||
      cat <<EOF >>$LXC_CONFIG
 | 
			
		||||
# VAAPI hardware transcoding
 | 
			
		||||
lxc.cgroup2.devices.allow: c 226:0 rwm
 | 
			
		||||
lxc.cgroup2.devices.allow: c 226:128 rwm
 | 
			
		||||
lxc.cgroup2.devices.allow: c 29:0 rwm
 | 
			
		||||
lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file
 | 
			
		||||
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
 | 
			
		||||
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
 | 
			
		||||
EOF
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    if [[ "$APP" == "Channels" || "$APP" == "Emby" || "$APP" == "ErsatzTV" || "$APP" == "Frigate" || "$APP" == "Jellyfin" || "$APP" == "Plex" || "$APP" == "Scrypted" || "$APP" == "Tdarr" || "$APP" == "Unmanic" || "$APP" == "Ollama" ]]; then
 | 
			
		||||
      if [[ -e "/dev/dri/renderD128" ]]; then
 | 
			
		||||
        if [[ -e "/dev/dri/card0" ]]; then
 | 
			
		||||
          cat <<EOF >>$LXC_CONFIG
 | 
			
		||||
# VAAPI hardware transcoding
 | 
			
		||||
dev0: /dev/dri/card0,gid=44
 | 
			
		||||
dev1: /dev/dri/renderD128,gid=104
 | 
			
		||||
EOF
 | 
			
		||||
        else
 | 
			
		||||
          cat <<EOF >>$LXC_CONFIG
 | 
			
		||||
# VAAPI hardware transcoding
 | 
			
		||||
dev0: /dev/dri/card1,gid=44
 | 
			
		||||
dev1: /dev/dri/renderD128,gid=104
 | 
			
		||||
EOF
 | 
			
		||||
        fi
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # This starts the container and executes <app>-install.sh
 | 
			
		||||
  msg_info "Starting LXC Container"
 | 
			
		||||
  pct start "$CTID"
 | 
			
		||||
  msg_ok "Started LXC Container"
 | 
			
		||||
 | 
			
		||||
  if [[ ! -f "/root/actions-runner/_work/ProxmoxVE/ProxmoxVE/install/$var_install.sh" ]]; then
 | 
			
		||||
    msg_error "No install script found for $APP"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$var_os" == "alpine" ]; then
 | 
			
		||||
    sleep 3
 | 
			
		||||
    pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
 | 
			
		||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
 | 
			
		||||
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
 | 
			
		||||
EOF'
 | 
			
		||||
    pct exec "$CTID" -- ash -c "apk add bash >/dev/null"
 | 
			
		||||
  fi
 | 
			
		||||
  lxc-attach -n "$CTID" -- bash -c "$(cat /root/actions-runner/_work/ProxmoxVE/ProxmoxVE/install/$var_install.sh)"
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
description() {
 | 
			
		||||
  IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										163
									
								
								.github/workflows/scripts/app-test/pr-create-lxc.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								.github/workflows/scripts/app-test/pr-create-lxc.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
color() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
catch_errors() {
 | 
			
		||||
  set -Eeuo pipefail
 | 
			
		||||
  trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function handles errors
 | 
			
		||||
error_handler() {
 | 
			
		||||
  local exit_code="$?"
 | 
			
		||||
  local line_number="$1"
 | 
			
		||||
  local command="$2"
 | 
			
		||||
  local error_message="Failure in line $line_number: exit code $exit_code: while executing command $command"
 | 
			
		||||
  echo -e "\n$error_message"
 | 
			
		||||
  exit 100
 | 
			
		||||
}
 | 
			
		||||
verb_ip6() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_info() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -ne "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_ok() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_error() {
 | 
			
		||||
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALIDCT=$(pvesm status -content rootdir | awk 'NR>1')
 | 
			
		||||
if [ -z "$VALIDCT" ]; then
 | 
			
		||||
  msg_error "Unable to detect a valid Container Storage location."
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
VALIDTMP=$(pvesm status -content vztmpl | awk 'NR>1')
 | 
			
		||||
if [ -z "$VALIDTMP" ]; then
 | 
			
		||||
  msg_error "Unable to detect a valid Template Storage location."
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
function select_storage() {
 | 
			
		||||
  local CLASS=$1
 | 
			
		||||
  local CONTENT
 | 
			
		||||
  local CONTENT_LABEL
 | 
			
		||||
  case $CLASS in
 | 
			
		||||
  container)
 | 
			
		||||
    CONTENT='rootdir'
 | 
			
		||||
    CONTENT_LABEL='Container'
 | 
			
		||||
    ;;
 | 
			
		||||
  template)
 | 
			
		||||
    CONTENT='vztmpl'
 | 
			
		||||
    CONTENT_LABEL='Container template'
 | 
			
		||||
    ;;
 | 
			
		||||
  *) false || {
 | 
			
		||||
    msg_error "Invalid storage class."
 | 
			
		||||
    exit 201
 | 
			
		||||
  } ;;
 | 
			
		||||
  esac
 | 
			
		||||
 | 
			
		||||
  # This Queries all storage locations
 | 
			
		||||
  local -a MENU
 | 
			
		||||
  while read -r line; do
 | 
			
		||||
    local TAG=$(echo $line | awk '{print $1}')
 | 
			
		||||
    local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
 | 
			
		||||
    local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
 | 
			
		||||
    local ITEM="Type: $TYPE Free: $FREE "
 | 
			
		||||
    local OFFSET=2
 | 
			
		||||
    if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
 | 
			
		||||
      local MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
 | 
			
		||||
    fi
 | 
			
		||||
    MENU+=("$TAG" "$ITEM" "OFF")
 | 
			
		||||
  done < <(pvesm status -content $CONTENT | awk 'NR>1')
 | 
			
		||||
 | 
			
		||||
  # Select storage location
 | 
			
		||||
  if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
    printf ${MENU[0]}
 | 
			
		||||
  else
 | 
			
		||||
    msg_error "STORAGE ISSUES!"
 | 
			
		||||
    exit 202
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[[ "${CTID:-}" ]] || {
 | 
			
		||||
  msg_error "You need to set 'CTID' variable."
 | 
			
		||||
  exit 203
 | 
			
		||||
}
 | 
			
		||||
[[ "${PCT_OSTYPE:-}" ]] || {
 | 
			
		||||
  msg_error "You need to set 'PCT_OSTYPE' variable."
 | 
			
		||||
  exit 204
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test if ID is valid
 | 
			
		||||
[ "$CTID" -ge "100" ] || {
 | 
			
		||||
  msg_error "ID cannot be less than 100."
 | 
			
		||||
  exit 205
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test if ID is in use
 | 
			
		||||
if pct status $CTID &>/dev/null; then
 | 
			
		||||
  echo -e "ID '$CTID' is already in use."
 | 
			
		||||
  unset CTID
 | 
			
		||||
  msg_error "Cannot use ID that is already in use."
 | 
			
		||||
  exit 206
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
TEMPLATE_STORAGE=$(select_storage template) || exit
 | 
			
		||||
 | 
			
		||||
CONTAINER_STORAGE=$(select_storage container) || exit
 | 
			
		||||
 | 
			
		||||
pveam update >/dev/null
 | 
			
		||||
 | 
			
		||||
TEMPLATE_SEARCH=${PCT_OSTYPE}-${PCT_OSVERSION:-}
 | 
			
		||||
mapfile -t TEMPLATES < <(pveam available -section system | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
 | 
			
		||||
[ ${#TEMPLATES[@]} -gt 0 ] || {
 | 
			
		||||
  msg_error "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
 | 
			
		||||
  exit 207
 | 
			
		||||
}
 | 
			
		||||
TEMPLATE="${TEMPLATES[-1]}"
 | 
			
		||||
 | 
			
		||||
TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
 | 
			
		||||
 | 
			
		||||
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE"; then
 | 
			
		||||
  [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
 | 
			
		||||
  pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null ||
 | 
			
		||||
    {
 | 
			
		||||
      msg_error "A problem occurred while downloading the LXC template."
 | 
			
		||||
      exit 208
 | 
			
		||||
    }
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
 | 
			
		||||
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
 | 
			
		||||
 | 
			
		||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
 | 
			
		||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
 | 
			
		||||
 | 
			
		||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
 | 
			
		||||
  [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
 | 
			
		||||
 | 
			
		||||
  pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null ||
 | 
			
		||||
    {
 | 
			
		||||
      msg_error "A problem occurred while re-downloading the LXC template."
 | 
			
		||||
      exit 208
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
 | 
			
		||||
    msg_error "A problem occurred while trying to create container after re-downloading template."
 | 
			
		||||
    exit 200
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										93
									
								
								.github/workflows/scripts/app-test/pr-install.func
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								.github/workflows/scripts/app-test/pr-install.func
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
color() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
catch_errors() {
 | 
			
		||||
  set -Euo pipefail
 | 
			
		||||
  trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
error_handler() {
 | 
			
		||||
  local line_number="$1"
 | 
			
		||||
  local command="$2"
 | 
			
		||||
  local error_message="Failure in line $line_number while executing command '$command'"   
 | 
			
		||||
  echo -e "\n$error_message\n" >&2
 | 
			
		||||
  exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
verb_ip6() {
 | 
			
		||||
  STD="silent"
 | 
			
		||||
  silent() {
 | 
			
		||||
    "$@" >/dev/null 2>&1 || error_handler "${BASH_LINENO[0]}" "$*"
 | 
			
		||||
  }
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_info() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -ne "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_ok() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
msg_error() {
 | 
			
		||||
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${msg}\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RETRY_NUM=10
 | 
			
		||||
RETRY_EVERY=3
 | 
			
		||||
setting_up_container() {
 | 
			
		||||
 | 
			
		||||
  sed -i "/$LANG/ s/\(^# \)//" /etc/locale.gen
 | 
			
		||||
  locale_line=$(grep -v '^#' /etc/locale.gen | grep -E '^[a-zA-Z]' | awk '{print $1}' | head -n 1)
 | 
			
		||||
  echo "LANG=${locale_line}" >/etc/default/locale
 | 
			
		||||
  locale-gen >/dev/null
 | 
			
		||||
  export LANG=${locale_line}
 | 
			
		||||
  echo $tz >/etc/timezone
 | 
			
		||||
  ln -sf /usr/share/zoneinfo/$tz /etc/localtime
 | 
			
		||||
 | 
			
		||||
  for ((i = RETRY_NUM; i > 0; i--)); do
 | 
			
		||||
    if [ "$(hostname -I)" != "" ]; then
 | 
			
		||||
      break
 | 
			
		||||
    fi
 | 
			
		||||
    sleep $RETRY_EVERY
 | 
			
		||||
  done
 | 
			
		||||
  if [ "$(hostname -I)" = "" ]; then
 | 
			
		||||
    echo 1>&2 -e "\nNo Network After $RETRY_NUM Tries"
 | 
			
		||||
    echo -e "Check Network Settings"
 | 
			
		||||
    exit 101
 | 
			
		||||
  fi
 | 
			
		||||
  rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
  systemctl disable -q --now systemd-networkd-wait-online.service
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
network_check() {
 | 
			
		||||
  RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
 | 
			
		||||
  if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to $RESOLVEDIP"; fi
 | 
			
		||||
  set -e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
update_os() {
 | 
			
		||||
  export DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
  apt-get update >/dev/null 2>&1
 | 
			
		||||
  apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade >/dev/null
 | 
			
		||||
  rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
motd_ssh() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customize() {
 | 
			
		||||
  return
 | 
			
		||||
}
 | 
			
		||||
@@ -17,7 +17,7 @@ find ./ct -type f -name "*.sh" | sort | while read -r script; do
 | 
			
		||||
    output_file="${headers_dir}/$(basename "${script%.*}")"
 | 
			
		||||
 | 
			
		||||
    # Generate figlet output
 | 
			
		||||
    figlet_output=$(figlet -f slant "$app_name")
 | 
			
		||||
    figlet_output=$(figlet -w 500 -f slant "$app_name")
 | 
			
		||||
 | 
			
		||||
    # Check if figlet output is not empty
 | 
			
		||||
    if [[ -n "$figlet_output" ]]; then
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								.github/workflows/scripts/update-json.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/scripts/update-json.sh
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
FILE=$1
 | 
			
		||||
TODAY=$(date -u +"%Y-%m-%d")
 | 
			
		||||
 | 
			
		||||
if [[ -z "$FILE" ]]; then
 | 
			
		||||
    echo "No file specified. Exiting."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [[ ! -f "$FILE" ]]; then
 | 
			
		||||
    echo "File $FILE not found. Exiting."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
DATE_IN_JSON=$(jq -r '.date_created' "$FILE" 2>/dev/null || echo "")
 | 
			
		||||
 | 
			
		||||
if [[ "$DATE_IN_JSON" != "$TODAY" ]]; then
 | 
			
		||||
    jq --arg date "$TODAY" '.date_created = $date' "$FILE" > tmp.json && mv tmp.json "$FILE"
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										131
									
								
								.github/workflows/update-json-date.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								.github/workflows/update-json-date.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
name: Update JSON Date
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
    paths:
 | 
			
		||||
      - 'json/**.json'
 | 
			
		||||
  workflow_dispatch: 
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  update-app-files:
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
 | 
			
		||||
    permissions:
 | 
			
		||||
      contents: write
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Generate a token
 | 
			
		||||
        id: generate-token
 | 
			
		||||
        uses: actions/create-github-app-token@v1
 | 
			
		||||
        with:
 | 
			
		||||
          app-id: ${{ vars.APP_ID }}
 | 
			
		||||
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
 | 
			
		||||
 | 
			
		||||
      - name: Generate dynamic branch name
 | 
			
		||||
        id: timestamp
 | 
			
		||||
        run: echo "BRANCH_NAME=pr-update-json-$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
 | 
			
		||||
      
 | 
			
		||||
      - name: Set up GH_TOKEN
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Checkout Repository
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
        with:
 | 
			
		||||
          fetch-depth: 2  # Ensure we have the last two commits
 | 
			
		||||
 | 
			
		||||
      - name: Get Previous Commit
 | 
			
		||||
        id: prev_commit
 | 
			
		||||
        run: |
 | 
			
		||||
          PREV_COMMIT=$(git rev-parse HEAD^)
 | 
			
		||||
          echo "Previous commit: $PREV_COMMIT"
 | 
			
		||||
          echo "prev_commit=$PREV_COMMIT" >> $GITHUB_ENV
 | 
			
		||||
 | 
			
		||||
      - name: Get Newly Added JSON Files
 | 
			
		||||
        id: new_json_files
 | 
			
		||||
        run: |
 | 
			
		||||
          git diff --name-only --diff-filter=A ${{ env.prev_commit }} HEAD | grep '^json/.*\.json$' > new_files.txt || true
 | 
			
		||||
          echo "New files detected:"
 | 
			
		||||
          cat new_files.txt || echo "No new files."
 | 
			
		||||
 | 
			
		||||
      - name: Disable file mode changes
 | 
			
		||||
        run: git config core.fileMode false
 | 
			
		||||
 | 
			
		||||
      - name: Set up Git
 | 
			
		||||
        run: |
 | 
			
		||||
          git config --global user.name "GitHub Actions"
 | 
			
		||||
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
 | 
			
		||||
 | 
			
		||||
      - name: Change JSON Date
 | 
			
		||||
        id: change-json-date
 | 
			
		||||
        run: |
 | 
			
		||||
          current_date=$(date +"%Y-%m-%d")
 | 
			
		||||
          while IFS= read -r file; do
 | 
			
		||||
            # Skip empty lines
 | 
			
		||||
            [[ -z "$file" ]] && continue
 | 
			
		||||
 | 
			
		||||
            if [[ -f "$file" ]]; then
 | 
			
		||||
              echo "Processing $file..."
 | 
			
		||||
              current_json_date=$(jq -r '.date_created // empty' "$file")
 | 
			
		||||
              if [[ -z "$current_json_date" || "$current_json_date" != "$current_date" ]]; then
 | 
			
		||||
                echo "Updating $file with date $current_date"
 | 
			
		||||
                jq --arg date "$current_date" '.date_created = $date' "$file" > temp.json && mv temp.json "$file"
 | 
			
		||||
              else
 | 
			
		||||
                echo "Date in $file is already up to date."
 | 
			
		||||
              fi
 | 
			
		||||
            else
 | 
			
		||||
              echo "Warning: File $file not found!"
 | 
			
		||||
            fi
 | 
			
		||||
          done < new_files.txt
 | 
			
		||||
          rm new_files.txt
 | 
			
		||||
 | 
			
		||||
      - name: Check if there are any changes
 | 
			
		||||
        run: |
 | 
			
		||||
          echo "Checking for changes..."
 | 
			
		||||
          git add -A  # Untracked Dateien aufnehmen
 | 
			
		||||
          git status
 | 
			
		||||
          if git diff --cached --quiet; then
 | 
			
		||||
            echo "No changes detected."
 | 
			
		||||
            echo "changed=false" >> "$GITHUB_ENV"
 | 
			
		||||
          else
 | 
			
		||||
            echo "Changes detected:"
 | 
			
		||||
            git diff --stat --cached
 | 
			
		||||
            echo "changed=true" >> "$GITHUB_ENV"
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      # Step 7: Commit and create PR if changes exist
 | 
			
		||||
      - name: Commit and create PR if changes exist
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        run: |
 | 
			
		||||
         
 | 
			
		||||
          
 | 
			
		||||
          git commit -m "Update date in json"
 | 
			
		||||
          git checkout -b ${{ env.BRANCH_NAME }}
 | 
			
		||||
          git push origin ${{ env.BRANCH_NAME }}
 | 
			
		||||
 | 
			
		||||
          gh pr create --title "[core] update date in json" \
 | 
			
		||||
                       --body "This PR is auto-generated by a GitHub Action to update the date in json." \
 | 
			
		||||
                       --head ${{ env.BRANCH_NAME }} \
 | 
			
		||||
                       --base main \
 | 
			
		||||
                       --label "automated pr"
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
 | 
			
		||||
 | 
			
		||||
      - name: Approve pull request
 | 
			
		||||
        if: env.changed == 'true'
 | 
			
		||||
        env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
        run: |
 | 
			
		||||
          PR_NUMBER=$(gh pr list --head "${{ env.BRANCH_NAME }}" --json number --jq '.[].number')
 | 
			
		||||
          if [ -n "$PR_NUMBER" ]; then
 | 
			
		||||
            gh pr review $PR_NUMBER --approve
 | 
			
		||||
          fi
 | 
			
		||||
 | 
			
		||||
      - name: No changes detected
 | 
			
		||||
        if: env.changed == 'false'
 | 
			
		||||
        run: echo "No changes to commit. Workflow completed successfully."
 | 
			
		||||
							
								
								
									
										48
									
								
								.github/workflows/update_json_date.yml.bak
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/update_json_date.yml.bak
									
									
									
									
										vendored
									
									
								
							@@ -1,48 +0,0 @@
 | 
			
		||||
name: Update JSON Date
 | 
			
		||||
on:
 | 
			
		||||
  pull_request:
 | 
			
		||||
    types: [opened, synchronize, reopened]
 | 
			
		||||
        
 | 
			
		||||
jobs:
 | 
			
		||||
  list-files:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - name: Checkout PR Branch
 | 
			
		||||
      uses: actions/checkout@v4
 | 
			
		||||
      with:
 | 
			
		||||
        ref: ${{ github.event.pull_request.head.ref }}
 | 
			
		||||
 | 
			
		||||
    - name: Fetch PR changes
 | 
			
		||||
      run: |
 | 
			
		||||
          git remote add fork https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git
 | 
			
		||||
          git fetch fork ${{ github.event.pull_request.head.ref }}:pullreq
 | 
			
		||||
          git checkout pullreq
 | 
			
		||||
 | 
			
		||||
    - name: Update JSON
 | 
			
		||||
      id: changed-files
 | 
			
		||||
      run: |
 | 
			
		||||
          FILES=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --jq '.[].filename' | tr '\n' ' ')
 | 
			
		||||
          echo "changed_files=${FILES}"
 | 
			
		||||
          for FILE in $FILES; do
 | 
			
		||||
            if [[ "$FILE" =~ /(.*)\.json ]]; then
 | 
			
		||||
              NAME="${BASH_REMATCH[1]}"
 | 
			
		||||
            else
 | 
			
		||||
              echo "no new JSON in ${FILES}"
 | 
			
		||||
              continue
 | 
			
		||||
            fi
 | 
			
		||||
          
 | 
			
		||||
            JSON_FILE="json/${NAME}.json"
 | 
			
		||||
            if [[ -f "$JSON_FILE" ]]; then
 | 
			
		||||
              echo "Updating date_created in $JSON_FILE"
 | 
			
		||||
              jq --arg date "$(date +%Y-%m-%d)" '.date_created = $date' "$JSON_FILE" > tmp.json && mv tmp.json "$JSON_FILE"
 | 
			
		||||
            else
 | 
			
		||||
              echo "JSON file $FILES not found"
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
             
 | 
			
		||||
          git config --global user.name "github-actions[bot]"
 | 
			
		||||
          git config --global user.email "github-actions[bot]@users.noreply.github.com"
 | 
			
		||||
          git diff --exit-code || git commit -am "Updating Dates in affected JSON files."
 | 
			
		||||
          git push 
 | 
			
		||||
      env:
 | 
			
		||||
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
							
								
								
									
										8
									
								
								.github/workflows/validate-filenames.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/validate-filenames.yml
									
									
									
									
										vendored
									
									
								
							@@ -10,7 +10,7 @@ on:
 | 
			
		||||
jobs:
 | 
			
		||||
  check-files:
 | 
			
		||||
    name: Check changed files
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    runs-on: runner-cluster-htl-set
 | 
			
		||||
    permissions:
 | 
			
		||||
      pull-requests: write
 | 
			
		||||
 | 
			
		||||
@@ -50,9 +50,13 @@ jobs:
 | 
			
		||||
 | 
			
		||||
          NON_COMPLIANT_FILES=""
 | 
			
		||||
          for FILE in $CHANGED_FILES; do
 | 
			
		||||
            # Datei "ct/create_lxc.sh" explizit überspringen
 | 
			
		||||
            if [[ "$FILE" == "ct/create_lxc.sh" ]]; then
 | 
			
		||||
              continue
 | 
			
		||||
            fi
 | 
			
		||||
            BASENAME=$(echo "$(basename "${FILE%.*}")")
 | 
			
		||||
            if [[ ! "$BASENAME" =~ ^[a-z0-9-]+$ ]]; then
 | 
			
		||||
                    NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
 | 
			
		||||
              NON_COMPLIANT_FILES="$NON_COMPLIANT_FILES $FILE"
 | 
			
		||||
            fi
 | 
			
		||||
          done
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								.editorconfig → .vscode/.editorconfig
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								.editorconfig → .vscode/.editorconfig
									
									
									
									
										vendored
									
									
								
							
							
								
								
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "files.associations": {
 | 
			
		||||
        "*.func": "shellscript"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1002
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										1002
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
									
									
									
									
								
							@@ -19,10 +19,10 @@
 | 
			
		||||
    <a href="https://ko-fi.com/community_scripts">
 | 
			
		||||
      <img src="https://img.shields.io/badge/Support-FF5F5F?style=for-the-badge&logo=ko-fi&logoColor=white" alt="Donate" />
 | 
			
		||||
    </a>
 | 
			
		||||
    <a href="https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTING.md">
 | 
			
		||||
    <a href="https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/CONTRIBUTING.md">
 | 
			
		||||
      <img src="https://img.shields.io/badge/Contribute-ff4785?style=for-the-badge&logo=git&logoColor=white" alt="Contribute" />
 | 
			
		||||
    </a> 
 | 
			
		||||
    <a href="https://github.com/community-scripts/ProxmoxVE/blob/main/USER_SUBMITTED_GUIDES.md">
 | 
			
		||||
    <a href="https://github.com/community-scripts/ProxmoxVE/blob/main/.github/CONTRIBUTOR_AND_GUIDES/USER_SUBMITTED_GUIDES.md">
 | 
			
		||||
      <img src="https://img.shields.io/badge/Guides-0077b5?style=for-the-badge&logo=read-the-docs&logoColor=white" alt="Guides" />
 | 
			
		||||
    </a> 
 | 
			
		||||
    <a href="https://github.com/community-scripts/ProxmoxVE/blob/main/CHANGELOG.md">
 | 
			
		||||
@@ -91,6 +91,16 @@ If you encounter any issues or have suggestions for improvement, file a new issu
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## ⭐ Star History
 | 
			
		||||
 | 
			
		||||
<a href="https://star-history.com/#community-scripts/ProxmoxVE&Date">
 | 
			
		||||
 <picture>
 | 
			
		||||
   <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date&theme=dark" />
 | 
			
		||||
   <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
 | 
			
		||||
   <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=community-scripts/ProxmoxVE&type=Date" />
 | 
			
		||||
 </picture>
 | 
			
		||||
</a>
 | 
			
		||||
 | 
			
		||||
## 📜 License
 | 
			
		||||
 | 
			
		||||
This project is licensed under the [MIT License](LICENSE).
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								api/.env.example
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								api/.env.example
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
MONGO_USER=
 | 
			
		||||
MONGO_PASSWORD=
 | 
			
		||||
MONGO_IP=
 | 
			
		||||
MONGO_PORT=
 | 
			
		||||
MONGO_DATABASE=
 | 
			
		||||
							
								
								
									
										32
									
								
								api/go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								api/go.mod
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
module proxmox-api
 | 
			
		||||
 | 
			
		||||
go 1.23.2
 | 
			
		||||
 | 
			
		||||
require go.mongodb.org/mongo-driver v1.17.2
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	filippo.io/edwards25519 v1.1.0 // indirect
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.8.1 // indirect
 | 
			
		||||
	github.com/golang/snappy v0.0.4 // indirect
 | 
			
		||||
	github.com/gorilla/mux v1.8.1 // indirect
 | 
			
		||||
	github.com/jackc/pgpassfile v1.0.0 // indirect
 | 
			
		||||
	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
 | 
			
		||||
	github.com/jackc/pgx/v5 v5.7.2 // indirect
 | 
			
		||||
	github.com/jackc/puddle/v2 v2.2.2 // indirect
 | 
			
		||||
	github.com/jinzhu/inflection v1.0.0 // indirect
 | 
			
		||||
	github.com/jinzhu/now v1.1.5 // indirect
 | 
			
		||||
	github.com/joho/godotenv v1.5.1 // indirect
 | 
			
		||||
	github.com/klauspost/compress v1.16.7 // indirect
 | 
			
		||||
	github.com/montanaflynn/stats v0.7.1 // indirect
 | 
			
		||||
	github.com/rs/cors v1.11.1 // indirect
 | 
			
		||||
	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 | 
			
		||||
	github.com/xdg-go/scram v1.1.2 // indirect
 | 
			
		||||
	github.com/xdg-go/stringprep v1.0.4 // indirect
 | 
			
		||||
	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.32.0 // indirect
 | 
			
		||||
	golang.org/x/sync v0.10.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.21.0 // indirect
 | 
			
		||||
	gorm.io/driver/mysql v1.5.7 // indirect
 | 
			
		||||
	gorm.io/driver/postgres v1.5.11 // indirect
 | 
			
		||||
	gorm.io/gorm v1.25.12 // indirect
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										83
									
								
								api/go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								api/go.sum
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 | 
			
		||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 | 
			
		||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
 | 
			
		||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
 | 
			
		||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
 | 
			
		||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
 | 
			
		||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
 | 
			
		||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
 | 
			
		||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
 | 
			
		||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
 | 
			
		||||
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
 | 
			
		||||
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
 | 
			
		||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
 | 
			
		||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
 | 
			
		||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
 | 
			
		||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
 | 
			
		||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
 | 
			
		||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
 | 
			
		||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
 | 
			
		||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
 | 
			
		||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
 | 
			
		||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
 | 
			
		||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
 | 
			
		||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
 | 
			
		||||
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
			
		||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
			
		||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 | 
			
		||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 | 
			
		||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
 | 
			
		||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
 | 
			
		||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
 | 
			
		||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
 | 
			
		||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
 | 
			
		||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
 | 
			
		||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
			
		||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
 | 
			
		||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
 | 
			
		||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
 | 
			
		||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
			
		||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 | 
			
		||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
 | 
			
		||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
			
		||||
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
 | 
			
		||||
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
 | 
			
		||||
gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
 | 
			
		||||
gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
 | 
			
		||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
 | 
			
		||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
 | 
			
		||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
 | 
			
		||||
							
								
								
									
										450
									
								
								api/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										450
									
								
								api/main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,450 @@
 | 
			
		||||
// Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
// Author: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
// License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/gorilla/mux"
 | 
			
		||||
	"github.com/joho/godotenv"
 | 
			
		||||
	"github.com/rs/cors"
 | 
			
		||||
	"go.mongodb.org/mongo-driver/bson"
 | 
			
		||||
	"go.mongodb.org/mongo-driver/bson/primitive"
 | 
			
		||||
	"go.mongodb.org/mongo-driver/mongo"
 | 
			
		||||
	"go.mongodb.org/mongo-driver/mongo/options"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var client *mongo.Client
 | 
			
		||||
var collection *mongo.Collection
 | 
			
		||||
 | 
			
		||||
func loadEnv() {
 | 
			
		||||
	if err := godotenv.Load(); err != nil {
 | 
			
		||||
		log.Fatal("Error loading .env file")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DataModel represents a single document in MongoDB
 | 
			
		||||
type DataModel struct {
 | 
			
		||||
	ID         primitive.ObjectID `json:"id" bson:"_id,omitempty"`
 | 
			
		||||
	CT_TYPE    uint               `json:"ct_type" bson:"ct_type"`
 | 
			
		||||
	DISK_SIZE  float32            `json:"disk_size" bson:"disk_size"`
 | 
			
		||||
	CORE_COUNT uint               `json:"core_count" bson:"core_count"`
 | 
			
		||||
	RAM_SIZE   uint               `json:"ram_size" bson:"ram_size"`
 | 
			
		||||
	OS_TYPE    string             `json:"os_type" bson:"os_type"`
 | 
			
		||||
	OS_VERSION string             `json:"os_version" bson:"os_version"`
 | 
			
		||||
	DISABLEIP6 string             `json:"disableip6" bson:"disableip6"`
 | 
			
		||||
	NSAPP      string             `json:"nsapp" bson:"nsapp"`
 | 
			
		||||
	METHOD     string             `json:"method" bson:"method"`
 | 
			
		||||
	CreatedAt  time.Time          `json:"created_at" bson:"created_at"`
 | 
			
		||||
	PVEVERSION string             `json:"pve_version" bson:"pve_version"`
 | 
			
		||||
	STATUS     string             `json:"status" bson:"status"`
 | 
			
		||||
	RANDOM_ID  string             `json:"random_id" bson:"random_id"`
 | 
			
		||||
	TYPE       string             `json:"type" bson:"type"`
 | 
			
		||||
	ERROR      string             `json:"error" bson:"error"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StatusModel struct {
 | 
			
		||||
	RANDOM_ID string `json:"random_id" bson:"random_id"`
 | 
			
		||||
	ERROR     string `json:"error" bson:"error"`
 | 
			
		||||
	STATUS    string `json:"status" bson:"status"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CountResponse struct {
 | 
			
		||||
	TotalEntries int64            `json:"total_entries"`
 | 
			
		||||
	StatusCount  map[string]int64 `json:"status_count"`
 | 
			
		||||
	NSAPPCount   map[string]int64 `json:"nsapp_count"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConnectDatabase initializes the MongoDB connection
 | 
			
		||||
func ConnectDatabase() {
 | 
			
		||||
	loadEnv()
 | 
			
		||||
 | 
			
		||||
	mongoURI := fmt.Sprintf("mongodb://%s:%s@%s:%s",
 | 
			
		||||
		os.Getenv("MONGO_USER"),
 | 
			
		||||
		os.Getenv("MONGO_PASSWORD"),
 | 
			
		||||
		os.Getenv("MONGO_IP"),
 | 
			
		||||
		os.Getenv("MONGO_PORT"))
 | 
			
		||||
 | 
			
		||||
	database := os.Getenv("MONGO_DATABASE")
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	client, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURI))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal("Failed to connect to MongoDB!", err)
 | 
			
		||||
	}
 | 
			
		||||
	collection = client.Database(database).Collection("data_models")
 | 
			
		||||
	fmt.Println("Connected to MongoDB on 10.10.10.18")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UploadJSON handles API requests and stores data as a document in MongoDB
 | 
			
		||||
func UploadJSON(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	var input DataModel
 | 
			
		||||
 | 
			
		||||
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	input.CreatedAt = time.Now()
 | 
			
		||||
 | 
			
		||||
	_, err := collection.InsertOne(context.Background(), input)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Println("Received data:", input)
 | 
			
		||||
	w.WriteHeader(http.StatusCreated)
 | 
			
		||||
	json.NewEncoder(w).Encode(map[string]string{"message": "Data saved successfully"})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateStatus updates the status of a record based on RANDOM_ID
 | 
			
		||||
func UpdateStatus(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	var input StatusModel
 | 
			
		||||
 | 
			
		||||
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	filter := bson.M{"random_id": input.RANDOM_ID}
 | 
			
		||||
	update := bson.M{"$set": bson.M{"status": input.STATUS, "error": input.ERROR}}
 | 
			
		||||
 | 
			
		||||
	_, err := collection.UpdateOne(context.Background(), filter, update)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Println("Updated data:", input)
 | 
			
		||||
	w.WriteHeader(http.StatusOK)
 | 
			
		||||
	json.NewEncoder(w).Encode(map[string]string{"message": "Record updated successfully"})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDataJSON fetches all data from MongoDB
 | 
			
		||||
func GetDataJSON(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	var records []DataModel
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(records)
 | 
			
		||||
}
 | 
			
		||||
func GetPaginatedData(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	page, _ := strconv.Atoi(r.URL.Query().Get("page"))
 | 
			
		||||
	limit, _ := strconv.Atoi(r.URL.Query().Get("limit"))
 | 
			
		||||
	if page < 1 {
 | 
			
		||||
		page = 1
 | 
			
		||||
	}
 | 
			
		||||
	if limit < 1 {
 | 
			
		||||
		limit = 10
 | 
			
		||||
	}
 | 
			
		||||
	skip := (page - 1) * limit
 | 
			
		||||
	var records []DataModel
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	options := options.Find().SetSkip(int64(skip)).SetLimit(int64(limit))
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{}, options)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(records)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetSummary(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	totalCount, err := collection.CountDocuments(ctx, bson.M{})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	statusCount := make(map[string]int64)
 | 
			
		||||
	nsappCount := make(map[string]int64)
 | 
			
		||||
 | 
			
		||||
	pipeline := []bson.M{
 | 
			
		||||
		{"$group": bson.M{"_id": "$status", "count": bson.M{"$sum": 1}}},
 | 
			
		||||
	}
 | 
			
		||||
	cursor, err := collection.Aggregate(ctx, pipeline)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		for cursor.Next(ctx) {
 | 
			
		||||
			var result struct {
 | 
			
		||||
				ID    string `bson:"_id"`
 | 
			
		||||
				Count int64  `bson:"count"`
 | 
			
		||||
			}
 | 
			
		||||
			if err := cursor.Decode(&result); err == nil {
 | 
			
		||||
				statusCount[result.ID] = result.Count
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pipeline = []bson.M{
 | 
			
		||||
		{"$group": bson.M{"_id": "$nsapp", "count": bson.M{"$sum": 1}}},
 | 
			
		||||
	}
 | 
			
		||||
	cursor, err = collection.Aggregate(ctx, pipeline)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		for cursor.Next(ctx) {
 | 
			
		||||
			var result struct {
 | 
			
		||||
				ID    string `bson:"_id"`
 | 
			
		||||
				Count int64  `bson:"count"`
 | 
			
		||||
			}
 | 
			
		||||
			if err := cursor.Decode(&result); err == nil {
 | 
			
		||||
				nsappCount[result.ID] = result.Count
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	response := CountResponse{
 | 
			
		||||
		TotalEntries: totalCount,
 | 
			
		||||
		StatusCount:  statusCount,
 | 
			
		||||
		NSAPPCount:   nsappCount,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(response)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetByNsapp(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	nsapp := r.URL.Query().Get("nsapp")
 | 
			
		||||
	var records []DataModel
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{"nsapp": nsapp})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(records)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetByDateRange(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
	startDate := r.URL.Query().Get("start_date")
 | 
			
		||||
	endDate := r.URL.Query().Get("end_date")
 | 
			
		||||
 | 
			
		||||
	if startDate == "" || endDate == "" {
 | 
			
		||||
		http.Error(w, "Both start_date and end_date are required", http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	start, err := time.Parse("2006-01-02T15:04:05.999999+00:00", startDate+"T00:00:00+00:00")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, "Invalid start_date format", http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	end, err := time.Parse("2006-01-02T15:04:05.999999+00:00", endDate+"T23:59:59+00:00")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, "Invalid end_date format", http.StatusBadRequest)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var records []DataModel
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{
 | 
			
		||||
		"created_at": bson.M{
 | 
			
		||||
			"$gte": start,
 | 
			
		||||
			"$lte": end,
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(records)
 | 
			
		||||
}
 | 
			
		||||
func GetByStatus(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	status := r.URL.Query().Get("status")
 | 
			
		||||
	var records []DataModel
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{"status": status})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(records)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetByOS(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	osType := r.URL.Query().Get("os_type")
 | 
			
		||||
	osVersion := r.URL.Query().Get("os_version")
 | 
			
		||||
	var records []DataModel
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{"os_type": osType, "os_version": osVersion})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(records)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetErrors(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	errorCount := make(map[string]int)
 | 
			
		||||
 | 
			
		||||
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
 | 
			
		||||
	defer cancel()
 | 
			
		||||
 | 
			
		||||
	cursor, err := collection.Find(ctx, bson.M{"error": bson.M{"$ne": ""}})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer cursor.Close(ctx)
 | 
			
		||||
 | 
			
		||||
	for cursor.Next(ctx) {
 | 
			
		||||
		var record DataModel
 | 
			
		||||
		if err := cursor.Decode(&record); err != nil {
 | 
			
		||||
			http.Error(w, err.Error(), http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if record.ERROR != "" {
 | 
			
		||||
			errorCount[record.ERROR]++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type ErrorCountResponse struct {
 | 
			
		||||
		Error string `json:"error"`
 | 
			
		||||
		Count int    `json:"count"`
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var errorCounts []ErrorCountResponse
 | 
			
		||||
	for err, count := range errorCount {
 | 
			
		||||
		errorCounts = append(errorCounts, ErrorCountResponse{
 | 
			
		||||
			Error: err,
 | 
			
		||||
			Count: count,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(struct {
 | 
			
		||||
		ErrorCounts []ErrorCountResponse `json:"error_counts"`
 | 
			
		||||
	}{
 | 
			
		||||
		ErrorCounts: errorCounts,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	ConnectDatabase()
 | 
			
		||||
 | 
			
		||||
	router := mux.NewRouter()
 | 
			
		||||
	router.HandleFunc("/upload", UploadJSON).Methods("POST")
 | 
			
		||||
	router.HandleFunc("/upload/updatestatus", UpdateStatus).Methods("POST")
 | 
			
		||||
	router.HandleFunc("/data/json", GetDataJSON).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/paginated", GetPaginatedData).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/summary", GetSummary).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/nsapp", GetByNsapp).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/date", GetByDateRange).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/status", GetByStatus).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/os", GetByOS).Methods("GET")
 | 
			
		||||
	router.HandleFunc("/data/errors", GetErrors).Methods("GET")
 | 
			
		||||
 | 
			
		||||
	c := cors.New(cors.Options{
 | 
			
		||||
		AllowedOrigins:   []string{"*"},
 | 
			
		||||
		AllowedMethods:   []string{"GET", "POST"},
 | 
			
		||||
		AllowedHeaders:   []string{"Content-Type", "Authorization"},
 | 
			
		||||
		AllowCredentials: true,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	handler := c.Handler(router)
 | 
			
		||||
 | 
			
		||||
	fmt.Println("Server running on port 8080")
 | 
			
		||||
	log.Fatal(http.ListenAndServe(":8080", handler))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								ct/2fauth.sh
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								ct/2fauth.sh
									
									
									
									
									
								
							@@ -5,9 +5,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://docs.2fauth.app/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="2FAuth"
 | 
			
		||||
TAGS="2fa;authenticator"
 | 
			
		||||
var_tags="2fa;authenticator"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -40,8 +35,8 @@ function update_script() {
 | 
			
		||||
    if [[ "${RELEASE}" != "$(cat /opt/2fauth_version.txt)" ]] || [[ ! -f /opt/2fauth_version.txt ]]; then
 | 
			
		||||
        msg_info "Updating $APP to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
        apt-get update &>/dev/null
 | 
			
		||||
        apt-get -y upgrade &>/dev/null
 | 
			
		||||
        $STD apt-get update
 | 
			
		||||
        $STD apt-get -y upgrade
 | 
			
		||||
 | 
			
		||||
        # Creating Backup
 | 
			
		||||
        msg_info "Creating Backup"
 | 
			
		||||
@@ -60,7 +55,7 @@ function update_script() {
 | 
			
		||||
        chmod -R 755 "/opt/2fauth"
 | 
			
		||||
 | 
			
		||||
        export COMPOSER_ALLOW_SUPERUSER=1
 | 
			
		||||
        composer install --no-dev --prefer-source &>/dev/null
 | 
			
		||||
        $STD composer install --no-dev --prefer-source
 | 
			
		||||
 | 
			
		||||
        php artisan 2fauth:install
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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}"
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://actualbudget.org/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Actual Budget"
 | 
			
		||||
var_tags="finance"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,35 +28,86 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/actualbudget/actual/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
    if [[ ! -f /opt/actualbudget_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/actualbudget_version.txt)" ]]; then
 | 
			
		||||
        msg_info "Stopping ${APP}"
 | 
			
		||||
        systemctl stop actualbudget
 | 
			
		||||
        msg_ok "${APP} Stopped"
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating ${APP} to ${RELEASE}"
 | 
			
		||||
        cd /tmp
 | 
			
		||||
        wget -q https://github.com/actualbudget/actual-server/archive/refs/tags/v${RELEASE}.tar.gz
 | 
			
		||||
        wget -q https://github.com/actualbudget/actual/archive/refs/tags/v${RELEASE}.tar.gz
 | 
			
		||||
 | 
			
		||||
        mv /opt/actualbudget /opt/actualbudget_bak
 | 
			
		||||
        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
 | 
			
		||||
        tar -xzf "v${RELEASE}.tar.gz"
 | 
			
		||||
        mv actual-${RELEASE} /opt/actualbudget
 | 
			
		||||
 | 
			
		||||
        mkdir -p /opt/actualbudget-data/{server-files,upload,migrate,user-files,migrations,config}
 | 
			
		||||
        for dir in server-files .migrate user-files migrations; do
 | 
			
		||||
            if [[ -d /opt/actualbudget_bak/$dir ]]; then
 | 
			
		||||
                mv /opt/actualbudget_bak/$dir/* /opt/actualbudget-data/$dir/ || true
 | 
			
		||||
            fi
 | 
			
		||||
        done
 | 
			
		||||
        if [[ -f /opt/actualbudget-data/migrate/.migrations ]]; then
 | 
			
		||||
            sed -i 's/null/1732656575219/g' /opt/actualbudget-data/migrate/.migrations
 | 
			
		||||
            sed -i 's/null/1732656575220/g' /opt/actualbudget-data/migrate/.migrations
 | 
			
		||||
        fi
 | 
			
		||||
        if [[ -f /opt/actualbudget/server-files/account.sqlite ]] && [[ ! -f /opt/actualbudget-data/server-files/account.sqlite ]]; then
 | 
			
		||||
            mv /opt/actualbudget/server-files/account.sqlite /opt/actualbudget-data/server-files/account.sqlite
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        if [[ -f /opt/actualbudget_bak/selfhost.key ]]; then
 | 
			
		||||
            mv /opt/actualbudget_bak/selfhost.key /opt/actualbudget/selfhost.key
 | 
			
		||||
            mv /opt/actualbudget_bak/selfhost.crt /opt/actualbudget/selfhost.crt
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        if [[ -f /opt/actualbudget_bak/.env ]]; then
 | 
			
		||||
            mv /opt/actualbudget_bak/.env /opt/actualbudget-data/.env
 | 
			
		||||
        else
 | 
			
		||||
            cat <<EOF >/opt/actualbudget-data/.env
 | 
			
		||||
ACTUAL_UPLOAD_DIR=/opt/actualbudget-data/upload
 | 
			
		||||
ACTUAL_DATA_DIR=/opt/actualbudget-data
 | 
			
		||||
ACTUAL_SERVER_FILES_DIR=/opt/actualbudget-data/server-files
 | 
			
		||||
ACTUAL_USER_FILES=/opt/actualbudget-data/user-files
 | 
			
		||||
PORT=5006
 | 
			
		||||
ACTUAL_TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1/32,::1/128,fc00::/7"
 | 
			
		||||
ACTUAL_HTTPS_KEY=/opt/actualbudget/selfhost.key
 | 
			
		||||
ACTUAL_HTTPS_CERT=/opt/actualbudget/selfhost.crt
 | 
			
		||||
EOF
 | 
			
		||||
        fi
 | 
			
		||||
        cd /opt/actualbudget
 | 
			
		||||
        yarn install &>/dev/null
 | 
			
		||||
        $STD yarn workspaces focus @actual-app/sync-server --production
 | 
			
		||||
        echo "${RELEASE}" >/opt/actualbudget_version.txt
 | 
			
		||||
        msg_ok "Updated ${APP}"
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting ${APP}"
 | 
			
		||||
        cat <<EOF >/etc/systemd/system/actualbudget.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Actual Budget Service
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
User=root
 | 
			
		||||
Group=root
 | 
			
		||||
WorkingDirectory=/opt/actualbudget
 | 
			
		||||
EnvironmentFile=/opt/actualbudget-data/.env
 | 
			
		||||
ExecStart=/usr/bin/yarn start:server
 | 
			
		||||
Restart=always
 | 
			
		||||
RestartSec=10
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
        systemctl daemon-reload
 | 
			
		||||
        systemctl start actualbudget
 | 
			
		||||
        msg_ok "Started ${APP}"
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -rf /opt/actualbudget_bak
 | 
			
		||||
        rm -rf /tmp/actual-server.tar.gz
 | 
			
		||||
        rm -rf "/tmp/v${RELEASE}.tar.gz"
 | 
			
		||||
        msg_ok "Cleaned"
 | 
			
		||||
        msg_ok "Updated Successfully"
 | 
			
		||||
    else
 | 
			
		||||
@@ -77,4 +123,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}:5006${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:5006${CL}"
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://adguard.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Adguard"
 | 
			
		||||
var_tags="adblock"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://adventurelog.app/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="AdventureLog"
 | 
			
		||||
var_tags="traveling"
 | 
			
		||||
var_disk="7"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -48,15 +43,15 @@ function update_script() {
 | 
			
		||||
    mv /opt/adventurelog-backup/backend/server/.env /opt/adventurelog/backend/server/.env
 | 
			
		||||
    mv /opt/adventurelog-backup/backend/server/media /opt/adventurelog/backend/server/media
 | 
			
		||||
    cd /opt/adventurelog/backend/server
 | 
			
		||||
    pip install --upgrade pip &>/dev/null
 | 
			
		||||
    pip install -r requirements.txt &>/dev/null
 | 
			
		||||
    python3 manage.py collectstatic --noinput &>/dev/null
 | 
			
		||||
    python3 manage.py migrate &>/dev/null
 | 
			
		||||
    $STD pip install --upgrade pip
 | 
			
		||||
    $STD pip install -r requirements.txt
 | 
			
		||||
    $STD python3 manage.py collectstatic --noinput
 | 
			
		||||
    $STD python3 manage.py migrate
 | 
			
		||||
 | 
			
		||||
    mv /opt/adventurelog-backup/frontend/.env /opt/adventurelog/frontend/.env
 | 
			
		||||
    cd /opt/adventurelog/frontend
 | 
			
		||||
    pnpm install &>/dev/null
 | 
			
		||||
    pnpm run build &>/dev/null
 | 
			
		||||
    $STD pnpm install
 | 
			
		||||
    $STD pnpm run build
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated ${APP}"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.ispyconnect.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="AgentDVR"
 | 
			
		||||
var_tags="dvr"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="ubuntu"
 | 
			
		||||
var_version="22.04"
 | 
			
		||||
var_unprivileged="0"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -32,7 +27,7 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_error "There is currently no update path available."
 | 
			
		||||
    msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.docker.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine-Docker"
 | 
			
		||||
var_tags="docker;alpine"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -14,11 +14,7 @@ var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://grafana.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine-Grafana"
 | 
			
		||||
var_tags="alpine;monitoring"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -14,11 +14,7 @@ var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										58
									
								
								ct/alpine-it-tools.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								ct/alpine-it-tools.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: nicedevil007 (NiceDevil)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://it-tools.tech/
 | 
			
		||||
 | 
			
		||||
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"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
if [ ! -d /usr/share/nginx/html ]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
RELEASE=$(curl -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 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following IP:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
 | 
			
		||||
@@ -3,8 +3,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://nextcloud.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine-Nextcloud"
 | 
			
		||||
var_tags="alpine;cloud"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -14,11 +14,7 @@ var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core 
 | 
			
		||||
header_info "$APP" 
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/dani-garcia/vaultwarden
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine-Vaultwarden"
 | 
			
		||||
var_tags="alpine;vault"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -14,11 +14,7 @@ var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.zigbee2mqtt.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine-Zigbee2MQTT"
 | 
			
		||||
var_tags="alpine;zigbee;mqtt;smarthome"
 | 
			
		||||
var_disk="0.3"
 | 
			
		||||
@@ -14,11 +14,7 @@ var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="0"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# Copyright (c) 2021-2025 tteck
 | 
			
		||||
# Author: tteck (tteckster)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://alpinelinux.org/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Alpine"
 | 
			
		||||
var_tags="os;alpine"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -14,11 +14,7 @@ var_os="alpine"
 | 
			
		||||
var_version="3.21"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://cassandra.apache.org/_/index.html
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Apache-Cassandra"
 | 
			
		||||
var_tags="database;NoSQL"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -16,11 +15,7 @@ var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,7 +28,7 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_error "There is currently no update path available."
 | 
			
		||||
    msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://couchdb.apache.org/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Apache-CouchDB"
 | 
			
		||||
var_tags="database"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -32,7 +27,7 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_error "There is currently no update path available."
 | 
			
		||||
    msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,12 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/refs/heads/main/misc/build.func)
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
# License: | MIT https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://guacamole.apache.org/
 | 
			
		||||
 | 
			
		||||
#App Default Values
 | 
			
		||||
APP="Apache-Guacamole"
 | 
			
		||||
TAGS="webserver;remote"
 | 
			
		||||
var_tags="webserver;remote"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -32,7 +27,7 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_error "Ther is currently no automatic update function for ${APP}."
 | 
			
		||||
    msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								ct/apache-tika.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										64
									
								
								ct/apache-tika.sh
									
									
									
									
									
										Executable 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: Andy Grunwald (andygrunwald)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/apache/tika/
 | 
			
		||||
 | 
			
		||||
APP="Apache-Tika"
 | 
			
		||||
var_tags="document"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="10"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -f /etc/systemd/system/apache-tika.service ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE="$(wget -qO- https://dlcdn.apache.org/tika/ | grep -oP '(?<=href=")[0-9]+\.[0-9]+\.[0-9]+(?=/")' | sort -V | tail -n1)"
 | 
			
		||||
  if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
 | 
			
		||||
    msg_info "Stopping ${APP}"
 | 
			
		||||
    systemctl stop apache-tika
 | 
			
		||||
    msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    cd /opt/apache-tika
 | 
			
		||||
    wget -q "https://dlcdn.apache.org/tika/${RELEASE}/tika-server-standard-${RELEASE}.jar"
 | 
			
		||||
    mv --force tika-server-standard.jar tika-server-standard-prev-version.jar
 | 
			
		||||
    mv tika-server-standard-${RELEASE}.jar tika-server-standard.jar
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated ${APP} to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting ${APP}"
 | 
			
		||||
    systemctl start apache-tika
 | 
			
		||||
    msg_ok "Started ${APP}"
 | 
			
		||||
    msg_info "Cleaning Up"
 | 
			
		||||
    rm -rf /opt/apache-tika/tika-server-standard-prev-version.jar
 | 
			
		||||
    msg_ok "Cleanup Completed"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9998${CL}"
 | 
			
		||||
							
								
								
									
										41
									
								
								ct/apache-tomcat.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								ct/apache-tomcat.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: MickLesk (Canbiz)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://tomcat.apache.org/
 | 
			
		||||
 | 
			
		||||
APP="Apache-Tomcat"
 | 
			
		||||
var_tags="webserver"
 | 
			
		||||
var_disk="5"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if ! ls -d /opt/tomcat-* >/dev/null 2>&1; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://wiki.debian.org/AptCacherNg
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Apt-Cacher-NG"
 | 
			
		||||
var_tags="caching"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Updating $APP LXC"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get -y upgrade &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
    msg_ok "Updated $APP LXC"
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://archivebox.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="ArchiveBox"
 | 
			
		||||
var_tags="archive;bookmark"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://aria2.github.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Aria2"
 | 
			
		||||
var_tags="download-utility"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Updating $APP LXC"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get -y upgrade &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
    msg_ok "Updated $APP LXC"
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.audiobookshelf.org/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="audiobookshelf"
 | 
			
		||||
var_tags="podcast;audiobook"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								ct/authelia.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								ct/authelia.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: thost96 (thost96)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.authelia.com/
 | 
			
		||||
 | 
			
		||||
APP="Authelia"
 | 
			
		||||
TAGS=""
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="2"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d "/etc/authelia/" ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/authelia/authelia/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
    if [[ "${RELEASE}" != "$(/usr/bin/authelia -v | awk '{print substr($3, 2, length($2)) }' )" ]]; then
 | 
			
		||||
        msg_info "Updating $APP to ${RELEASE}"
 | 
			
		||||
        $STD apt-get update
 | 
			
		||||
        $STD apt-get -y upgrade
 | 
			
		||||
        wget -q "https://github.com/authelia/authelia/releases/download/${RELEASE}/authelia_${RELEASE}_amd64.deb"
 | 
			
		||||
        $STD dpkg -i "authelia_${RELEASE}_amd64.deb"
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -f "authelia_${RELEASE}_amd64.deb"
 | 
			
		||||
        $STD apt-get -y autoremove
 | 
			
		||||
        $STD apt-get -y autoclean
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
        msg_ok "Updated $APP to ${RELEASE}"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:9091${CL}"
 | 
			
		||||
@@ -2,24 +2,19 @@
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: remz1337
 | 
			
		||||
# License: MIT
 | 
			
		||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://goauthentik.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Authentik"
 | 
			
		||||
var_tags="identity-provider"
 | 
			
		||||
var_disk="15"
 | 
			
		||||
var_disk="12"
 | 
			
		||||
var_cpu="6"
 | 
			
		||||
var_ram="8192"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -45,24 +40,31 @@ function update_script() {
 | 
			
		||||
    tar -xzf authentik.tar.gz -C /opt/authentik --strip-components 1 --overwrite
 | 
			
		||||
    rm -rf authentik.tar.gz
 | 
			
		||||
    cd /opt/authentik/website
 | 
			
		||||
    npm install &>/dev/null
 | 
			
		||||
    npm run build-bundled &>/dev/null
 | 
			
		||||
    $STD npm install
 | 
			
		||||
    $STD npm run build-bundled
 | 
			
		||||
    cd /opt/authentik/web
 | 
			
		||||
    npm install &>/dev/null
 | 
			
		||||
    npm run build &>/dev/null
 | 
			
		||||
    $STD npm install
 | 
			
		||||
    $STD npm run build
 | 
			
		||||
    msg_ok "Built ${APP} website"
 | 
			
		||||
 | 
			
		||||
    msg_info "Building ${APP} server"
 | 
			
		||||
    cd /opt/authentik
 | 
			
		||||
    go mod download
 | 
			
		||||
    go build -o /go/authentik ./cmd/server
 | 
			
		||||
    go build -o /opt/authentik/authentik-server /opt/authentik/cmd/server/
 | 
			
		||||
    msg_ok "Built ${APP} server"
 | 
			
		||||
 | 
			
		||||
    msg_info "Installing Python Dependencies"
 | 
			
		||||
    cd /opt/authentik
 | 
			
		||||
    poetry install --only=main --no-ansi --no-interaction --no-root &>/dev/null
 | 
			
		||||
    poetry export --without-hashes --without-urls -f requirements.txt --output requirements.txt &>/dev/null
 | 
			
		||||
    pip install --no-cache-dir -r requirements.txt &>/dev/null
 | 
			
		||||
    pip install . &>/dev/null
 | 
			
		||||
    $STD poetry install --only=main --no-ansi --no-interaction --no-root
 | 
			
		||||
    $STD poetry export --without-hashes --without-urls -f requirements.txt --output requirements.txt
 | 
			
		||||
    $STD pip install --no-cache-dir -r requirements.txt
 | 
			
		||||
    $STD pip install .
 | 
			
		||||
    msg_ok "Installed Python Dependencies"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE} (Patience)"
 | 
			
		||||
    cp -r /opt/authentik/authentik/blueprints /opt/authentik/blueprints
 | 
			
		||||
    bash /opt/authentik/lifecycle/ak migrate &>/dev/null
 | 
			
		||||
    $STD bash /opt/authentik/lifecycle/ak migrate
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated ${APP} to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://autobrr.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Autobrr"
 | 
			
		||||
var_tags="arr;"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								ct/baikal.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								ct/baikal.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
#!/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="Baikal"
 | 
			
		||||
var_tags="Dav"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/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}"
 | 
			
		||||
							
								
								
									
										71
									
								
								ct/barcode-buddy.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								ct/barcode-buddy.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: bvdberg01
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/Forceu/barcodebuddy
 | 
			
		||||
 | 
			
		||||
APP="Barcode-Buddy"
 | 
			
		||||
var_tags="grocery;household"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="512"
 | 
			
		||||
var_disk="3"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/barcodebuddy ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/Forceu/barcodebuddy/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
 | 
			
		||||
    systemctl stop barcodebuddy
 | 
			
		||||
    msg_ok "Stopped Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    cd /opt
 | 
			
		||||
    mv /opt/barcodebuddy/ /opt/barcodebuddy-backup
 | 
			
		||||
    wget -q "https://github.com/Forceu/barcodebuddy/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
    unzip -q "v${RELEASE}.zip"
 | 
			
		||||
    mv "/opt/barcodebuddy-${RELEASE}" /opt/barcodebuddy
 | 
			
		||||
    cp -r /opt/barcodebuddy-backup/data/. /opt/barcodebuddy/data
 | 
			
		||||
    chown -R www-data:www-data /opt/barcodebuddy/data
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting Service"
 | 
			
		||||
    systemctl start apache2
 | 
			
		||||
    systemctl start barcodebuddy
 | 
			
		||||
    msg_ok "Started Service"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning up"
 | 
			
		||||
    rm -r "/opt/v${RELEASE}.zip"
 | 
			
		||||
    rm -r /opt/barcodebuddy-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}"
 | 
			
		||||
							
								
								
									
										11
									
								
								ct/bazarr.sh
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								ct/bazarr.sh
									
									
									
									
									
								
							@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.bazarr.media/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Bazarr"
 | 
			
		||||
var_tags="arr"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core 
 | 
			
		||||
header_info "$APP" 
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -30,8 +25,8 @@ function update_script() {
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /var/lib/bazarr/ ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
 | 
			
		||||
    msg_info "Updating $APP LXC"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get -y upgrade &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
    msg_ok "Updated $APP LXC"
 | 
			
		||||
exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								ct/beszel.sh
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								ct/beszel.sh
									
									
									
									
									
								
							@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://beszel.dev/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Beszel"
 | 
			
		||||
var_tags="monitoring"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -32,8 +27,18 @@ function update_script() {
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    /opt/beszel/beszel update
 | 
			
		||||
    msg_error "Ther is currently no automatic update function for ${APP}."
 | 
			
		||||
    msg_info "Stopping $APP"
 | 
			
		||||
    systemctl stop beszel-hub
 | 
			
		||||
    msg_ok "Stopped $APP"
 | 
			
		||||
    
 | 
			
		||||
    msg_info "Updating $APP"
 | 
			
		||||
    $STD /opt/beszel/beszel update
 | 
			
		||||
    msg_ok "Updated $APP"
 | 
			
		||||
    
 | 
			
		||||
    msg_info "Starting $APP"
 | 
			
		||||
    systemctl start beszel-hub
 | 
			
		||||
    msg_ok "Successfully started $APP"
 | 
			
		||||
    msg_ok "Update Successful"
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								ct/blocky.sh
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								ct/blocky.sh
									
									
									
									
									
								
							@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://0xerr0r.github.io/blocky/latest/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Blocky"
 | 
			
		||||
var_tags="adblock"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core 
 | 
			
		||||
header_info "$APP" 
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -30,8 +25,8 @@ function update_script() {
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /var ]]; then msg_error "No ${APP} Installation Found!"; exit; fi
 | 
			
		||||
        msg_info "Updating $APP LXC"
 | 
			
		||||
        apt-get update &>/dev/null
 | 
			
		||||
        apt-get -y upgrade &>/dev/null
 | 
			
		||||
        $STD apt-get update
 | 
			
		||||
        $STD apt-get -y upgrade
 | 
			
		||||
        msg_ok "Updated $APP LXC"
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										71
									
								
								ct/boltdiy.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								ct/boltdiy.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/stackblitz-labs/bolt.diy/
 | 
			
		||||
 | 
			
		||||
APP="boltdiy"
 | 
			
		||||
TAGS="code;ai"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="3072"
 | 
			
		||||
var_disk="6"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /opt/bolt.diy ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/stackblitz-labs/bolt.diy/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
    if [[ "${RELEASE}" != "$(cat /opt/boltdiy_version.txt)" ]] || [[ ! -f /opt/boltdiy_version.txt ]]; then
 | 
			
		||||
        msg_info "Stopping $APP"
 | 
			
		||||
        systemctl stop boltdiy
 | 
			
		||||
        msg_ok "Stopped $APP"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating $APP to v${RELEASE}"
 | 
			
		||||
        temp_dir=$(mktemp -d)
 | 
			
		||||
        temp_file=$(mktemp)
 | 
			
		||||
        cd $temp_dir
 | 
			
		||||
        wget -q "https://github.com/stackblitz-labs/bolt.diy/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file
 | 
			
		||||
        tar xzf $temp_file
 | 
			
		||||
        cp -rf bolt.diy-${RELEASE}/* /opt/bolt.diy
 | 
			
		||||
        cd /opt/bolt.diy
 | 
			
		||||
        $STD pnpm install
 | 
			
		||||
        msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting $APP"
 | 
			
		||||
        systemctl start boltdiy
 | 
			
		||||
        msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -rf $temp_file
 | 
			
		||||
        rm -rf $temp_dir
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
        echo "${RELEASE}" >/opt/boltdiy_version.txt
 | 
			
		||||
        msg_ok "Update Successful"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:5173${CL}"
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/BookStackApp/BookStack
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Bookstack"
 | 
			
		||||
var_tags="organizer"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -44,12 +39,13 @@ function update_script() {
 | 
			
		||||
    unzip -q /opt/v${RELEASE}.zip -d /opt
 | 
			
		||||
    mv /opt/BookStack-${RELEASE} /opt/bookstack
 | 
			
		||||
    cp /opt/bookstack-backup/.env /opt/bookstack/.env
 | 
			
		||||
    cp -r /opt/bookstack-backup/public/uploads/* /opt/bookstack/public/uploads/ 2>/dev/null || true
 | 
			
		||||
    cp -r /opt/bookstack-backup/storage/uploads/* /opt/bookstack/storage/uploads/ 2>/dev/null || true
 | 
			
		||||
    cp -r /opt/bookstack-backup/themes/* /opt/bookstack/themes/ 2>/dev/null || true
 | 
			
		||||
    cp -r /opt/bookstack-backup/public/uploads/* /opt/bookstack/public/uploads/ || true
 | 
			
		||||
    cp -r /opt/bookstack-backup/storage/uploads/* /opt/bookstack/storage/uploads/ || true
 | 
			
		||||
    cp -r /opt/bookstack-backup/themes/* /opt/bookstack/themes/ || true
 | 
			
		||||
    cd /opt/bookstack
 | 
			
		||||
    COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev &>/dev/null
 | 
			
		||||
    php artisan migrate --force &>/dev/null
 | 
			
		||||
    export COMPOSER_ALLOW_SUPERUSER=1 
 | 
			
		||||
    $STD composer install --no-dev
 | 
			
		||||
    $STD php artisan migrate --force
 | 
			
		||||
    chown www-data:www-data -R /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage
 | 
			
		||||
    chmod -R 755 /opt/bookstack /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads /opt/bookstack/storage
 | 
			
		||||
    chmod -R 775 /opt/bookstack/storage /opt/bookstack/bootstrap/cache /opt/bookstack/public/uploads
 | 
			
		||||
 
 | 
			
		||||
@@ -5,21 +5,16 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.bunkerweb.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="BunkerWeb"
 | 
			
		||||
var_tags="webserver"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_ram="4096"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core 
 | 
			
		||||
header_info "$APP" 
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -39,7 +34,7 @@ Pin: version ${RELEASE}
 | 
			
		||||
Pin-Priority: 1001
 | 
			
		||||
EOF
 | 
			
		||||
  apt-get update
 | 
			
		||||
  apt-get install -y nginx=1.26.2*
 | 
			
		||||
  apt-get install -y nginx=1.26.3*
 | 
			
		||||
  apt-get install -y bunkerweb=${RELEASE}
 | 
			
		||||
  echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
  msg_ok "Updated ${APP} to ${RELEASE}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								ct/bytestash.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								ct/bytestash.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/jordan-dalby/ByteStash
 | 
			
		||||
 | 
			
		||||
APP="ByteStash"
 | 
			
		||||
var_tags="code"
 | 
			
		||||
var_disk="4"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /opt/bytestash ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    RELEASE=$(curl -s https://api.github.com/repos/jordan-dalby/ByteStash/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
    if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
 | 
			
		||||
        msg_info "Stopping Services"
 | 
			
		||||
        systemctl stop bytestash-backend
 | 
			
		||||
        systemctl stop bytestash-frontend
 | 
			
		||||
        msg_ok "Services Stopped"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating ${APP} to ${RELEASE}"
 | 
			
		||||
        temp_file=$(mktemp)
 | 
			
		||||
        wget -q "https://github.com/jordan-dalby/ByteStash/archive/refs/tags/v${RELEASE}.tar.gz" -O $temp_file
 | 
			
		||||
        tar zxf $temp_file
 | 
			
		||||
        rm -rf /opt/bytestash/server/node_modules
 | 
			
		||||
        rm -rf /opt/bytestash/client/node_modules
 | 
			
		||||
        cp -rf ByteStash-${RELEASE}/* /opt/bytestash
 | 
			
		||||
        cd /opt/bytestash/server
 | 
			
		||||
        $STD npm install
 | 
			
		||||
        cd /opt/bytestash/client
 | 
			
		||||
        $STD npm install
 | 
			
		||||
        echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
        msg_ok "Updated ${APP}"
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting Services"
 | 
			
		||||
        systemctl start bytestash-backend
 | 
			
		||||
        systemctl start bytestash-frontend
 | 
			
		||||
        msg_ok "Started Services"
 | 
			
		||||
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -f $temp_file
 | 
			
		||||
        msg_ok "Cleaned"
 | 
			
		||||
        msg_ok "Updated Successfully"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://caddyserver.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Caddy"
 | 
			
		||||
var_tags="webserver"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
      exit
 | 
			
		||||
   fi
 | 
			
		||||
   msg_info "Updating $APP LXC"
 | 
			
		||||
   apt-get update &>/dev/null
 | 
			
		||||
   apt-get -y upgrade &>/dev/null
 | 
			
		||||
   $STD apt-get update
 | 
			
		||||
   $STD apt-get -y upgrade
 | 
			
		||||
   msg_ok "Updated $APP LXC"
 | 
			
		||||
   exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/janeczku/calibre-web
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Calibre-Web"
 | 
			
		||||
var_tags="eBook"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -120,10 +115,10 @@ function update_script() {
 | 
			
		||||
      echo "${options[*]}"
 | 
			
		||||
    )
 | 
			
		||||
    echo $cps_options >/opt/calibre-web/options.txt
 | 
			
		||||
    pip install --upgrade calibreweb[$cps_options] &>/dev/null
 | 
			
		||||
    $STD pip install --upgrade calibreweb[$cps_options]
 | 
			
		||||
  else
 | 
			
		||||
    rm -rf /opt/calibre-web/options.txt
 | 
			
		||||
    pip install --upgrade calibreweb &>/dev/null
 | 
			
		||||
    $STD pip install --upgrade calibreweb
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  msg_info "Starting ${APP}"
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://casaos.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="CasaOS"
 | 
			
		||||
var_tags="cloud"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
      exit
 | 
			
		||||
   fi
 | 
			
		||||
   msg_info "Updating ${APP} LXC"
 | 
			
		||||
   apt-get update &>/dev/null
 | 
			
		||||
   apt-get -y upgrade &>/dev/null
 | 
			
		||||
   $STD apt-get update
 | 
			
		||||
   $STD apt-get -y upgrade
 | 
			
		||||
   msg_ok "Updated ${APP} LXC"
 | 
			
		||||
   exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,21 +5,16 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://changedetection.io/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Change Detection"
 | 
			
		||||
var_tags="monitoring;crawler"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="8"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="10"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -36,31 +31,31 @@ function update_script() {
 | 
			
		||||
 | 
			
		||||
  if ! dpkg -s libjpeg-dev >/dev/null 2>&1; then
 | 
			
		||||
    msg_info "Installing Dependencies"
 | 
			
		||||
    apt-get update
 | 
			
		||||
    apt-get install -y libjpeg-dev
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get install -y libjpeg-dev
 | 
			
		||||
    msg_ok "Updated Dependencies"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  msg_info "Updating ${APP}"
 | 
			
		||||
  pip3 install changedetection.io --upgrade &>/dev/null
 | 
			
		||||
  $STD pip3 install changedetection.io --upgrade
 | 
			
		||||
  msg_ok "Updated ${APP}"
 | 
			
		||||
 | 
			
		||||
  msg_info "Updating Playwright"
 | 
			
		||||
  pip3 install playwright --upgrade &>/dev/null
 | 
			
		||||
  $STD pip3 install playwright --upgrade
 | 
			
		||||
  msg_ok "Updated Playwright"
 | 
			
		||||
 | 
			
		||||
  if [[ -f /etc/systemd/system/browserless.service ]]; then
 | 
			
		||||
    msg_info "Updating Browserless (Patience)"
 | 
			
		||||
    git -C /opt/browserless/ fetch --all &>/dev/null
 | 
			
		||||
    git -C /opt/browserless/ reset --hard origin/main &>/dev/null
 | 
			
		||||
    npm update --prefix /opt/browserless &>/dev/null
 | 
			
		||||
    /opt/browserless/node_modules/playwright-core/cli.js install --with-deps &>/dev/null
 | 
			
		||||
    $STD git -C /opt/browserless/ fetch --all
 | 
			
		||||
    $STD git -C /opt/browserless/ reset --hard origin/main
 | 
			
		||||
    $STD npm update --prefix /opt/browserless
 | 
			
		||||
    $STD /opt/browserless/node_modules/playwright-core/cli.js install --with-deps
 | 
			
		||||
    # Update Chrome separately, as it has to be done with the force option. Otherwise the installation of other browsers will not be done if Chrome is already installed.
 | 
			
		||||
    /opt/browserless/node_modules/playwright-core/cli.js install --force chrome &>/dev/null
 | 
			
		||||
    /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit &>/dev/null
 | 
			
		||||
    npm run build --prefix /opt/browserless &>/dev/null
 | 
			
		||||
    npm run build:function --prefix /opt/browserless &>/dev/null
 | 
			
		||||
    npm prune production --prefix /opt/browserless &>/dev/null
 | 
			
		||||
    $STD /opt/browserless/node_modules/playwright-core/cli.js install --force chrome
 | 
			
		||||
    $STD /opt/browserless/node_modules/playwright-core/cli.js install chromium firefox webkit
 | 
			
		||||
    $STD npm run build --prefix /opt/browserless
 | 
			
		||||
    $STD npm run build:function --prefix /opt/browserless
 | 
			
		||||
    $STD npm prune production --prefix /opt/browserless
 | 
			
		||||
    systemctl restart browserless
 | 
			
		||||
    msg_ok "Updated Browserless"
 | 
			
		||||
  else
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://getchannels.com/dvr-server/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Channels"
 | 
			
		||||
var_tags="dvr"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="0"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -32,7 +27,7 @@ function update_script() {
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  msg_error "There is currently no update path available."
 | 
			
		||||
  msg_error "Currently we don't provide an update function for this ${APP}."
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,6 @@ var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -29,17 +27,17 @@ function update_script() {
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -fsSL https://api.github.com/repos/checkmk/checkmk/tags | grep "name" | awk '{print substr($2, 3, length($2)-4) }') 
 | 
			
		||||
  RELEASE=$(curl -fsSL https://api.github.com/repos/checkmk/checkmk/tags | grep "name" | awk '{print substr($2, 3, length($2)-4) }' | tr ' ' '\n' | grep -v '\-rc' | sort -V | tail -n 1) 
 | 
			
		||||
  if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
 | 
			
		||||
    msg_info "Updating ${APP} to v${RELEASE}"
 | 
			
		||||
    omd stop monitoring &>/dev/null
 | 
			
		||||
    omd cp monitoring monitoringbackup &>/dev/null
 | 
			
		||||
    $STD omd stop monitoring
 | 
			
		||||
    $STD omd cp monitoring monitoringbackup
 | 
			
		||||
    wget -q https://download.checkmk.com/checkmk/${RELEASE}/check-mk-raw-${RELEASE}_0.bookworm_amd64.deb -O /opt/checkmk.deb
 | 
			
		||||
    apt-get install -y /opt/checkmk.deb &>/dev/null
 | 
			
		||||
    omd --force -V ${RELEASE}.cre update --conflict=install monitoring &>/dev/null
 | 
			
		||||
    omd start monitoring &>/dev/null
 | 
			
		||||
    omd -f rm monitoringbackup  &>/dev/null
 | 
			
		||||
    omd cleanup &>/dev/null
 | 
			
		||||
    $STD apt-get install -y /opt/checkmk.deb
 | 
			
		||||
    $STD omd --force -V ${RELEASE}.cre update --conflict=install monitoring
 | 
			
		||||
    $STD omd start monitoring
 | 
			
		||||
    $STD omd -f rm monitoringbackup 
 | 
			
		||||
    $STD omd cleanup
 | 
			
		||||
    rm -rf /opt/checkmk.deb
 | 
			
		||||
    msg_ok "Updated ${APP} to v${RELEASE}"
 | 
			
		||||
  else
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.cloudflare.com/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Cloudflared"
 | 
			
		||||
var_tags="network;cloudflare"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
      exit
 | 
			
		||||
   fi
 | 
			
		||||
   msg_info "Updating $APP LXC"
 | 
			
		||||
   apt-get update &>/dev/null
 | 
			
		||||
   apt-get -y upgrade &>/dev/null
 | 
			
		||||
   $STD apt-get update
 | 
			
		||||
   $STD apt-get -y upgrade
 | 
			
		||||
   msg_ok "Updated $APP LXC"
 | 
			
		||||
   exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://cockpit-project.org/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Cockpit"
 | 
			
		||||
var_tags="monitoring;network"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -41,48 +36,48 @@ function update_script() {
 | 
			
		||||
 | 
			
		||||
  if [ "$UPD" == "1" ]; then
 | 
			
		||||
    msg_info "Updating ${APP} LXC"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get -y upgrade &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
    msg_ok "Updated ${APP} LXC"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$UPD" == "2" ]; then
 | 
			
		||||
    msg_info "Installing dependencies (patience)"
 | 
			
		||||
    apt-get install -y attr &>/dev/null
 | 
			
		||||
    apt-get install -y nfs-kernel-server &>/dev/null
 | 
			
		||||
    apt-get install -y samba &>/dev/null
 | 
			
		||||
    apt-get install -y samba-common-bin &>/dev/null
 | 
			
		||||
    apt-get install -y winbind &>/dev/null
 | 
			
		||||
    apt-get install -y gawk &>/dev/null
 | 
			
		||||
    $STD apt-get install -y attr
 | 
			
		||||
    $STD apt-get install -y nfs-kernel-server
 | 
			
		||||
    $STD apt-get install -y samba
 | 
			
		||||
    $STD apt-get install -y samba-common-bin
 | 
			
		||||
    $STD apt-get install -y winbind
 | 
			
		||||
    $STD apt-get install -y gawk
 | 
			
		||||
    msg_ok "Installed dependencies"
 | 
			
		||||
    msg_info "Installing Cockpit file sharing"
 | 
			
		||||
    wget -q $(curl -s https://api.github.com/repos/45Drives/cockpit-file-sharing/releases/latest | grep download | grep focal_all.deb | cut -d\" -f4)
 | 
			
		||||
    dpkg -i cockpit-file-sharing_*focal_all.deb &>/dev/null
 | 
			
		||||
    $STD dpkg -i cockpit-file-sharing_*focal_all.deb
 | 
			
		||||
    rm cockpit-file-sharing_*focal_all.deb
 | 
			
		||||
    msg_ok "Installed Cockpit file sharing"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$UPD" == "3" ]; then
 | 
			
		||||
    msg_info "Installing dependencies (patience)"
 | 
			
		||||
    apt-get install -y psmisc &>/dev/null
 | 
			
		||||
    apt-get install -y samba &>/dev/null
 | 
			
		||||
    apt-get install -y samba-common-bin &>/dev/null
 | 
			
		||||
    $STD apt-get install -y psmisc
 | 
			
		||||
    $STD apt-get install -y samba
 | 
			
		||||
    $STD apt-get install -y samba-common-bin
 | 
			
		||||
    msg_ok "Installed dependencies"
 | 
			
		||||
    msg_info "Installing Cockpit identities"
 | 
			
		||||
    wget -q $(curl -s https://api.github.com/repos/45Drives/cockpit-identities/releases/latest | grep download | grep focal_all.deb | cut -d\" -f4)
 | 
			
		||||
    dpkg -i cockpit-identities_*focal_all.deb &>/dev/null
 | 
			
		||||
    $STD dpkg -i cockpit-identities_*focal_all.deb
 | 
			
		||||
    rm cockpit-identities_*focal_all.deb
 | 
			
		||||
    msg_ok "Installed Cockpit identities"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$UPD" == "4" ]; then
 | 
			
		||||
    msg_info "Installing dependencies"
 | 
			
		||||
    apt-get install -y rsync &>/dev/null
 | 
			
		||||
    apt-get install -y zip &>/dev/null
 | 
			
		||||
    $STD apt-get install -y rsync
 | 
			
		||||
    $STD apt-get install -y zip
 | 
			
		||||
    msg_ok "Installed dependencies"
 | 
			
		||||
    msg_info "Installing Cockpit navigator"
 | 
			
		||||
    wget -q $(curl -s https://api.github.com/repos/45Drives/cockpit-navigator/releases/latest | grep download | grep focal_all.deb | cut -d\" -f4)
 | 
			
		||||
    dpkg -i cockpit-navigator_*focal_all.deb &>/dev/null
 | 
			
		||||
    $STD dpkg -i cockpit-navigator_*focal_all.deb
 | 
			
		||||
    rm cockpit-navigator_*focal_all.deb
 | 
			
		||||
    msg_ok "Installed Cockpit navigator"
 | 
			
		||||
    exit
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.commafeed.com/#/welcome
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="CommaFeed"
 | 
			
		||||
var_tags="rss-reader"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								ct/cosmos.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								ct/cosmos.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
#!/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: Michel Roegl-Brunner (michelroegl-brunner)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://https://cosmos-cloud.io/
 | 
			
		||||
 | 
			
		||||
APP="cosmos"
 | 
			
		||||
var_tags="os,docker"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="2048"
 | 
			
		||||
var_disk="8"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /opt/cosmos ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  msg_ok "${APP} updates itself automatically!"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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}"
 | 
			
		||||
							
								
								
									
										85
									
								
								ct/crafty-controller.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								ct/crafty-controller.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts
 | 
			
		||||
# Author: CrazyWolf13
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://gitlab.com/crafty-controller/crafty-4
 | 
			
		||||
 | 
			
		||||
APP="Crafty-Controller"
 | 
			
		||||
var_tags="gaming"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
var_ram="4096"
 | 
			
		||||
var_disk="16"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /opt/crafty-controller ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
   
 | 
			
		||||
    RELEASE=$(curl -s "https://gitlab.com/api/v4/projects/20430749/releases" | grep -o '"tag_name":"v[^"]*"' | head -n 1 | sed 's/"tag_name":"v//;s/"//')
 | 
			
		||||
    if [[ ! -f /opt/crafty-controller_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/crafty-controller_version.txt)" ]]; then
 | 
			
		||||
      
 | 
			
		||||
      msg_info "Stopping Crafty-Controller"
 | 
			
		||||
      systemctl stop crafty-controller
 | 
			
		||||
      msg_ok "Stopped Crafty-Controller"
 | 
			
		||||
 | 
			
		||||
      msg_info "Creating Backup of config"
 | 
			
		||||
      cp -a /opt/crafty-controller/crafty/crafty-4/app/config/. /opt/crafty-controller/backup
 | 
			
		||||
      rm /opt/crafty-controller/backup/version.json
 | 
			
		||||
      rm /opt/crafty-controller/backup/credits.json
 | 
			
		||||
      rm /opt/crafty-controller/backup/logging.json
 | 
			
		||||
      rm /opt/crafty-controller/backup/default.json.example
 | 
			
		||||
      rm /opt/crafty-controller/backup/motd_format.json
 | 
			
		||||
      msg_ok "Backup Created"
 | 
			
		||||
      
 | 
			
		||||
      msg_info "Updating Crafty-Controller to v${RELEASE}"
 | 
			
		||||
      wget -q "https://gitlab.com/crafty-controller/crafty-4/-/archive/v${RELEASE}/crafty-4-v${RELEASE}.zip"
 | 
			
		||||
      unzip -q crafty-4-v${RELEASE}.zip
 | 
			
		||||
      cp -a crafty-4-v${RELEASE}/. /opt/crafty-controller/crafty/crafty-4/
 | 
			
		||||
      rm -rf crafty-4-v${RELEASE}
 | 
			
		||||
      cd /opt/crafty-controller/crafty/crafty-4
 | 
			
		||||
      sudo -u crafty bash -c '
 | 
			
		||||
        source /opt/crafty-controller/crafty/.venv/bin/activate
 | 
			
		||||
        pip3 install --no-cache-dir -r requirements.txt
 | 
			
		||||
      ' &>/dev/null
 | 
			
		||||
      echo "${RELEASE}" >"/opt/crafty-controller_version.txt"
 | 
			
		||||
      msg_ok "Updated Crafty-Controller to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
      msg_info "Restoring Backup of config"
 | 
			
		||||
      cp -a /opt/crafty-controller/backup/. /opt/crafty-controller/crafty/crafty-4/app/config
 | 
			
		||||
      rm -rf /opt/crafty-controller/backup
 | 
			
		||||
      chown -R crafty:crafty /opt/crafty-controller/
 | 
			
		||||
      msg_ok "Backup Restored"
 | 
			
		||||
 | 
			
		||||
      msg_info "Starting Crafty-Controller"
 | 
			
		||||
      systemctl start crafty-controller
 | 
			
		||||
      msg_ok "Started Crafty-Controller"
 | 
			
		||||
 | 
			
		||||
      msg_ok "Updated Successfully"
 | 
			
		||||
      exit
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. Crafty-Controller is already at v${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}https://${IP}:8443${CL}"
 | 
			
		||||
							
								
								
									
										144
									
								
								ct/create_lxc.sh
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								ct/create_lxc.sh
									
									
									
									
									
								
							@@ -36,13 +36,14 @@ trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
 | 
			
		||||
# This function handles errors
 | 
			
		||||
function error_handler() {
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local exit_code="$?"
 | 
			
		||||
  local line_number="$1"
 | 
			
		||||
  local command="$2"
 | 
			
		||||
  local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
 | 
			
		||||
  echo -e "\n$error_message\n"
 | 
			
		||||
  exit 200
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function displays a spinner.
 | 
			
		||||
@@ -50,13 +51,13 @@ function spinner() {
 | 
			
		||||
  local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
 | 
			
		||||
  local spin_i=0
 | 
			
		||||
  local interval=0.1
 | 
			
		||||
  printf "\e[?25l" 
 | 
			
		||||
  printf "\e[?25l"
 | 
			
		||||
 | 
			
		||||
  local color="${YWB}"
 | 
			
		||||
 | 
			
		||||
  while true; do
 | 
			
		||||
    printf "\r ${color}%s${CL}" "${frames[spin_i]}"
 | 
			
		||||
    spin_i=$(( (spin_i + 1) % ${#frames[@]} ))
 | 
			
		||||
    spin_i=$(((spin_i + 1) % ${#frames[@]}))
 | 
			
		||||
    sleep "$interval"
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
@@ -69,9 +70,16 @@ function msg_info() {
 | 
			
		||||
  SPINNER_PID=$!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function msg_warn() {
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${INFO}${YWB}${msg}${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function displays a success message with a green color.
 | 
			
		||||
function msg_ok() {
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${CM}${GN}${msg}${CL}"
 | 
			
		||||
@@ -79,7 +87,7 @@ function msg_ok() {
 | 
			
		||||
 | 
			
		||||
# This function displays a error message with a red color.
 | 
			
		||||
function msg_error() {
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID > /dev/null; then kill $SPINNER_PID > /dev/null; fi
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
 | 
			
		||||
@@ -112,9 +120,12 @@ function select_storage() {
 | 
			
		||||
    CONTENT='vztmpl'
 | 
			
		||||
    CONTENT_LABEL='Container template'
 | 
			
		||||
    ;;
 | 
			
		||||
  *) false || exit "Invalid storage class." ;;
 | 
			
		||||
  *) false || {
 | 
			
		||||
    msg_error "Invalid storage class."
 | 
			
		||||
    exit 201
 | 
			
		||||
  } ;;
 | 
			
		||||
  esac
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  # This Queries all storage locations
 | 
			
		||||
  local -a MENU
 | 
			
		||||
  while read -r line; do
 | 
			
		||||
@@ -128,37 +139,64 @@ function select_storage() {
 | 
			
		||||
    fi
 | 
			
		||||
    MENU+=("$TAG" "$ITEM" "OFF")
 | 
			
		||||
  done < <(pvesm status -content $CONTENT | awk 'NR>1')
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  # Select storage location
 | 
			
		||||
  if [ $((${#MENU[@]}/3)) -eq 1 ]; then
 | 
			
		||||
  if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
    printf ${MENU[0]}
 | 
			
		||||
  else
 | 
			
		||||
    local STORAGE
 | 
			
		||||
    while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
      STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${MENU[@]}" 3>&1 1>&2 2>&3) || exit "Menu aborted."
 | 
			
		||||
        "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
        16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
        "${MENU[@]}" 3>&1 1>&2 2>&3) || {
 | 
			
		||||
        msg_error "Menu aborted."
 | 
			
		||||
        exit 202
 | 
			
		||||
      }
 | 
			
		||||
      if [ $? -ne 0 ]; then
 | 
			
		||||
        echo -e "${CROSS}${RD} Menu aborted by user.${CL}"
 | 
			
		||||
        exit 0 
 | 
			
		||||
        exit 0
 | 
			
		||||
      fi
 | 
			
		||||
    done
 | 
			
		||||
    printf "%s" "$STORAGE"
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
# Test if required variables are set
 | 
			
		||||
[[ "${CTID:-}" ]] || exit "You need to set 'CTID' variable."
 | 
			
		||||
[[ "${PCT_OSTYPE:-}" ]] || exit "You need to set 'PCT_OSTYPE' variable."
 | 
			
		||||
[[ "${CTID:-}" ]] || {
 | 
			
		||||
  msg_error "You need to set 'CTID' variable."
 | 
			
		||||
  exit 203
 | 
			
		||||
}
 | 
			
		||||
[[ "${PCT_OSTYPE:-}" ]] || {
 | 
			
		||||
  msg_error "You need to set 'PCT_OSTYPE' variable."
 | 
			
		||||
  exit 204
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Test if ID is valid
 | 
			
		||||
[ "$CTID" -ge "100" ] || exit "ID cannot be less than 100."
 | 
			
		||||
[ "$CTID" -ge "100" ] || {
 | 
			
		||||
  msg_error "ID cannot be less than 100."
 | 
			
		||||
  exit 205
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check for network connectivity (IPv4 & IPv6)
 | 
			
		||||
#function check_network() {
 | 
			
		||||
#  local CHECK_URLS=("8.8.8.8" "1.1.1.1" "9.9.9.9" "2606:4700:4700::1111" "2001:4860:4860::8888" "2620:fe::fe")
 | 
			
		||||
#
 | 
			
		||||
#  for url in "${CHECK_URLS[@]}"; do
 | 
			
		||||
#    if ping -c 1 -W 2 "$url" &>/dev/null; then
 | 
			
		||||
#      return 0 # Success: At least one connection works
 | 
			
		||||
#    fi
 | 
			
		||||
#  done
 | 
			
		||||
#
 | 
			
		||||
#  msg_error "No network connection detected. Check your internet connection."
 | 
			
		||||
#  exit 101
 | 
			
		||||
#}
 | 
			
		||||
 | 
			
		||||
# Test if ID is in use
 | 
			
		||||
if pct status $CTID &>/dev/null; then
 | 
			
		||||
if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
 | 
			
		||||
  echo -e "ID '$CTID' is already in use."
 | 
			
		||||
  unset CTID
 | 
			
		||||
  exit "Cannot use ID that is already in use."
 | 
			
		||||
  msg_error "Cannot use ID that is already in use."
 | 
			
		||||
  exit 206
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Get template storage
 | 
			
		||||
@@ -171,32 +209,74 @@ msg_ok "Using ${BL}$CONTAINER_STORAGE${CL} ${GN}for Container Storage."
 | 
			
		||||
 | 
			
		||||
# Update LXC template list
 | 
			
		||||
msg_info "Updating LXC Template List"
 | 
			
		||||
#check_network
 | 
			
		||||
pveam update >/dev/null
 | 
			
		||||
msg_ok "Updated LXC Template List"
 | 
			
		||||
 | 
			
		||||
# Get LXC template string
 | 
			
		||||
TEMPLATE_SEARCH=${PCT_OSTYPE}-${PCT_OSVERSION:-}
 | 
			
		||||
mapfile -t TEMPLATES < <(pveam available -section system | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
 | 
			
		||||
[ ${#TEMPLATES[@]} -gt 0 ] || exit "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
 | 
			
		||||
[ ${#TEMPLATES[@]} -gt 0 ] || {
 | 
			
		||||
  msg_error "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
 | 
			
		||||
  exit 207
 | 
			
		||||
}
 | 
			
		||||
TEMPLATE="${TEMPLATES[-1]}"
 | 
			
		||||
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE)"
 | 
			
		||||
# Without NAS/Mount: TEMPLATE_PATH="/var/lib/vz/template/cache/$TEMPLATE"
 | 
			
		||||
# Check if template exists, if corrupt remove and redownload
 | 
			
		||||
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE" || ! zstdcat "$TEMPLATE_PATH" | tar -tf - >/dev/null 2>&1; then
 | 
			
		||||
  msg_warn "Template $TEMPLATE not found in storage or seems to be corrupted. Redownloading."
 | 
			
		||||
  [[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
 | 
			
		||||
 | 
			
		||||
# Download LXC template if needed
 | 
			
		||||
if ! pveam list $TEMPLATE_STORAGE | grep -q $TEMPLATE; then
 | 
			
		||||
  msg_info "Downloading LXC Template"
 | 
			
		||||
  pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null ||
 | 
			
		||||
    exit "A problem occured while downloading the LXC template."
 | 
			
		||||
  msg_ok "Downloaded LXC Template"
 | 
			
		||||
  # Download with 3 attempts
 | 
			
		||||
  for attempt in {1..3}; do
 | 
			
		||||
    msg_info "Attempt $attempt: Downloading LXC template..."
 | 
			
		||||
 | 
			
		||||
    if timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then
 | 
			
		||||
      msg_ok "Template download successful."
 | 
			
		||||
      break
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if [ $attempt -eq 3 ]; then
 | 
			
		||||
      msg_error "Three failed attempts. Aborting."
 | 
			
		||||
      exit 208
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    sleep $((attempt * 5))
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
msg_ok "LXC Template is ready to use."
 | 
			
		||||
 | 
			
		||||
# Check and fix subuid/subgid
 | 
			
		||||
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
 | 
			
		||||
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
 | 
			
		||||
 | 
			
		||||
# Combine all options
 | 
			
		||||
DEFAULT_PCT_OPTIONS=(
 | 
			
		||||
  -arch $(dpkg --print-architecture))
 | 
			
		||||
 | 
			
		||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
 | 
			
		||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
 | 
			
		||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
 | 
			
		||||
 | 
			
		||||
# Create container
 | 
			
		||||
msg_info "Creating LXC Container"
 | 
			
		||||
pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[@]} >/dev/null ||
 | 
			
		||||
  exit "A problem occured while trying to create container."
 | 
			
		||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
 | 
			
		||||
  msg_error "Container creation failed. Checking if template is corrupted."
 | 
			
		||||
 | 
			
		||||
  if ! zstdcat "$TEMPLATE_PATH" | tar -tf - >/dev/null 2>&1; then
 | 
			
		||||
    msg_error "Template appears to be corrupted. Removing and re-downloading."
 | 
			
		||||
    rm -f "$TEMPLATE_PATH"
 | 
			
		||||
 | 
			
		||||
    if ! timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then
 | 
			
		||||
      msg_error "Failed to re-download template."
 | 
			
		||||
      exit 208
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    msg_ok "Re-downloaded LXC Template"
 | 
			
		||||
 | 
			
		||||
    if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
 | 
			
		||||
      msg_error "Container creation failed after re-downloading template."
 | 
			
		||||
      exit 200
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    msg_error "Container creation failed, but template is not corrupted."
 | 
			
		||||
    exit 209
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://cronicle.net/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Cronicle"
 | 
			
		||||
var_tags="task-scheduler"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -41,12 +36,12 @@ function update_script() {
 | 
			
		||||
    if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then
 | 
			
		||||
      if ! command -v npm >/dev/null 2>&1; then
 | 
			
		||||
        echo "Installing NPM..."
 | 
			
		||||
        apt-get install -y npm >/dev/null 2>&1
 | 
			
		||||
        $STD apt-get install -y npm
 | 
			
		||||
        echo "Installed NPM..."
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Updating ${APP}"
 | 
			
		||||
    /opt/cronicle/bin/control.sh upgrade &>/dev/null
 | 
			
		||||
    $STD /opt/cronicle/bin/control.sh upgrade
 | 
			
		||||
    msg_ok "Updated ${APP}"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
@@ -54,7 +49,7 @@ function update_script() {
 | 
			
		||||
    if [[ "$(node -v | cut -d 'v' -f 2)" == "18."* ]]; then
 | 
			
		||||
      if ! command -v npm >/dev/null 2>&1; then
 | 
			
		||||
        echo "Installing NPM..."
 | 
			
		||||
        apt-get install -y npm >/dev/null 2>&1
 | 
			
		||||
        $STD apt-get install -y npm
 | 
			
		||||
        echo "Installed NPM..."
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
@@ -62,36 +57,36 @@ function update_script() {
 | 
			
		||||
    IP=$(hostname -I | awk '{print $1}')
 | 
			
		||||
    msg_info "Installing Dependencies"
 | 
			
		||||
 | 
			
		||||
    apt-get install -y git &>/dev/null
 | 
			
		||||
    apt-get install -y make &>/dev/null
 | 
			
		||||
    apt-get install -y g++ &>/dev/null
 | 
			
		||||
    apt-get install -y gcc &>/dev/null
 | 
			
		||||
    apt-get install -y ca-certificates &>/dev/null
 | 
			
		||||
    apt-get install -y gnupg &>/dev/null
 | 
			
		||||
    $STD apt-get install -y git
 | 
			
		||||
    $STD apt-get install -y make
 | 
			
		||||
    $STD apt-get install -y g++
 | 
			
		||||
    $STD apt-get install -y gcc
 | 
			
		||||
    $STD apt-get install -y ca-certificates
 | 
			
		||||
    $STD apt-get install -y gnupg
 | 
			
		||||
    msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
    msg_info "Setting up Node.js Repository"
 | 
			
		||||
    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"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get install -y nodejs &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get install -y nodejs
 | 
			
		||||
    msg_ok "Installed Node.js"
 | 
			
		||||
 | 
			
		||||
    msg_info "Installing Cronicle Worker"
 | 
			
		||||
    mkdir -p /opt/cronicle
 | 
			
		||||
    cd /opt/cronicle
 | 
			
		||||
    tar zxvf <(curl -fsSL https://github.com/jhuckaby/Cronicle/archive/${LATEST}.tar.gz) --strip-components 1 &>/dev/null
 | 
			
		||||
    npm install &>/dev/null
 | 
			
		||||
    node bin/build.js dist &>/dev/null
 | 
			
		||||
    $STD tar zxvf <(curl -fsSL https://github.com/jhuckaby/Cronicle/archive/${LATEST}.tar.gz) --strip-components 1
 | 
			
		||||
    $STD npm install
 | 
			
		||||
    $STD node bin/build.js dist
 | 
			
		||||
    sed -i "s/localhost:3012/${IP}:3012/g" /opt/cronicle/conf/config.json
 | 
			
		||||
    /opt/cronicle/bin/control.sh start &>/dev/null
 | 
			
		||||
    cp /opt/cronicle/bin/cronicled.init /etc/init.d/cronicled &>/dev/null
 | 
			
		||||
    $STD /opt/cronicle/bin/control.sh start
 | 
			
		||||
    $STD cp /opt/cronicle/bin/cronicled.init /etc/init.d/cronicled
 | 
			
		||||
    chmod 775 /etc/init.d/cronicled
 | 
			
		||||
    update-rc.d cronicled defaults &>/dev/null
 | 
			
		||||
    $STD update-rc.d cronicled defaults
 | 
			
		||||
    msg_ok "Installed Cronicle Worker"
 | 
			
		||||
    echo -e "\n Add Masters secret key to /opt/cronicle/conf/config.json \n"
 | 
			
		||||
    exit
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								ct/cross-seed.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								ct/cross-seed.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
#!/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: Jakub Matraszek (jmatraszek)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.cross-seed.org
 | 
			
		||||
 | 
			
		||||
APP="cross-seed"
 | 
			
		||||
var_tags="arr"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="1024"
 | 
			
		||||
var_disk="2"
 | 
			
		||||
var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    if command -v cross-seed &> /dev/null; then
 | 
			
		||||
        current_version=$(cross-seed --version)
 | 
			
		||||
        latest_version=$(npm show cross-seed version)
 | 
			
		||||
        if [ "$current_version" != "$latest_version" ]; then
 | 
			
		||||
            msg_info "Updating ${APP} from version v${current_version} to v${latest_version}"
 | 
			
		||||
            $STD npm install -g cross-seed@latest
 | 
			
		||||
            systemctl restart cross-seed
 | 
			
		||||
            msg_ok "Updated Successfully"
 | 
			
		||||
        else
 | 
			
		||||
            msg_ok "${APP} is already at v${current_version}"
 | 
			
		||||
        fi
 | 
			
		||||
    else
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    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 cross-seed API using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:2468${CL}"
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://daemonsync.me/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Daemon Sync"
 | 
			
		||||
var_tags="sync"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Updating $APP LXC"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get -y upgrade &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
    msg_ok "Updated $APP LXC"
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://dashy.to/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Dashy"
 | 
			
		||||
var_tags="dashboard"
 | 
			
		||||
var_cpu="2"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/m
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://www.debian.org/
 | 
			
		||||
 | 
			
		||||
# App Default Values
 | 
			
		||||
APP="Debian"
 | 
			
		||||
var_tags="os"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
@@ -15,11 +14,7 @@ var_os="debian"
 | 
			
		||||
var_version="12"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 | 
			
		||||
# App Output & Base Settings
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
base_settings
 | 
			
		||||
 | 
			
		||||
# Core
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
@@ -33,8 +28,8 @@ function update_script() {
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    msg_info "Updating $APP LXC"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get -y upgrade &>/dev/null
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
    msg_ok "Updated $APP LXC"
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user