mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 10:22:50 +00:00 
			
		
		
		
	Compare commits
	
		
			39 Commits
		
	
	
		
			2025-01-24
			...
			2025-01-27
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					84b982ffa8 | ||
| 
						 | 
					53c7ab19f8 | ||
| 
						 | 
					d13c1e5722 | ||
| 
						 | 
					be92f947cd | ||
| 
						 | 
					452012529c | ||
| 
						 | 
					661654987d | ||
| 
						 | 
					c3a21069d2 | ||
| 
						 | 
					4de8c1c358 | ||
| 
						 | 
					cd86921467 | ||
| 
						 | 
					38a540b87a | ||
| 
						 | 
					8cd3669edb | ||
| 
						 | 
					adfbff63bc | ||
| 
						 | 
					47bf8e6f86 | ||
| 
						 | 
					43f05b3aba | ||
| 
						 | 
					b17befec88 | ||
| 
						 | 
					719da560d1 | ||
| 
						 | 
					ac25b5a702 | ||
| 
						 | 
					ce1a38eb50 | ||
| 
						 | 
					030174f508 | ||
| 
						 | 
					7e1fb858d7 | ||
| 
						 | 
					5dc1a7d219 | ||
| 
						 | 
					14247ac5a9 | ||
| 
						 | 
					4911a7918a | ||
| 
						 | 
					b06ad8bde8 | ||
| 
						 | 
					8a6364902e | ||
| 
						 | 
					dfd56aebf2 | ||
| 
						 | 
					78e6e12c8a | ||
| 
						 | 
					88c3f56157 | ||
| 
						 | 
					92057c4ea7 | ||
| 
						 | 
					0af7a5adbf | ||
| 
						 | 
					ba6edcdcaf | ||
| 
						 | 
					de80e95d69 | ||
| 
						 | 
					796275d175 | ||
| 
						 | 
					9ff56caafd | ||
| 
						 | 
					d596f4a3e0 | ||
| 
						 | 
					b9cdfc26d0 | ||
| 
						 | 
					ae726129b1 | ||
| 
						 | 
					bd3f823b86 | ||
| 
						 | 
					eddacd786d | 
							
								
								
									
										35
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -17,6 +17,41 @@ All LXC instances created using this repository come pre-installed with Midnight
 | 
			
		||||
Do not break established syntax in this file, as it is automatically updated by a Github Workflow
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 2025-01-27
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### ✨ New Scripts
 | 
			
		||||
 | 
			
		||||
- New Script: Arch Linux VM [@MickLesk](https://github.com/MickLesk) ([#1780](https://github.com/community-scripts/ProxmoxVE/pull/1780))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Increase alpine-vaultwarden default var_disk size [@nayzm](https://github.com/nayzm) ([#1788](https://github.com/community-scripts/ProxmoxVE/pull/1788))
 | 
			
		||||
- Added change of the mobile GUI to disable nag request [@GarryG](https://github.com/GarryG) ([#1785](https://github.com/community-scripts/ProxmoxVE/pull/1785))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- Update frontend alpine-vaultwarden hdd size and OS version [@nayzm](https://github.com/nayzm) ([#1789](https://github.com/community-scripts/ProxmoxVE/pull/1789))
 | 
			
		||||
- Website: Add Description for Metadata Categories [@MickLesk](https://github.com/MickLesk) ([#1783](https://github.com/community-scripts/ProxmoxVE/pull/1783))
 | 
			
		||||
- [Fix] Double "VM" on website (Arch Linux) [@lasharor](https://github.com/lasharor) ([#1782](https://github.com/community-scripts/ProxmoxVE/pull/1782))
 | 
			
		||||
 | 
			
		||||
## 2025-01-26
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
- Fix jellyfin update command [@jcisio](https://github.com/jcisio) ([#1771](https://github.com/community-scripts/ProxmoxVE/pull/1771))
 | 
			
		||||
- openHAB - Use https and include doc url [@moodyblue](https://github.com/moodyblue) ([#1766](https://github.com/community-scripts/ProxmoxVE/pull/1766))
 | 
			
		||||
- Jellyfin: Fix default logging level [@tremor021](https://github.com/tremor021) ([#1768](https://github.com/community-scripts/ProxmoxVE/pull/1768))
 | 
			
		||||
- Calibre-Web: added installation of calibre binaries [@tremor021](https://github.com/tremor021) ([#1763](https://github.com/community-scripts/ProxmoxVE/pull/1763))
 | 
			
		||||
- Added environment variable to accept EULA for SQLServer2022 [@tremor021](https://github.com/tremor021) ([#1755](https://github.com/community-scripts/ProxmoxVE/pull/1755))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
- The Lounge: Fix the command to create new users [@tremor021](https://github.com/tremor021) ([#1762](https://github.com/community-scripts/ProxmoxVE/pull/1762))
 | 
			
		||||
 | 
			
		||||
## 2025-01-24
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,7 @@ function update_script() {
 | 
			
		||||
        mkdir -p /opt/actualbudget/
 | 
			
		||||
        tar -xzf v${RELEASE}.tar.gz >/dev/null 2>&1
 | 
			
		||||
        mv *ctual-server-*/* /opt/actualbudget
 | 
			
		||||
        rm -rf /opt/actualbudget/.env
 | 
			
		||||
        mv /opt/actualbudget_bak/.env /opt/actualbudget
 | 
			
		||||
        mv /opt/actualbudget_bak/server-files /opt/actualbudget/server-files
 | 
			
		||||
        cd /opt/actualbudget
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ APP="Alpine-Vaultwarden"
 | 
			
		||||
var_tags="alpine;vault"
 | 
			
		||||
var_cpu="1"
 | 
			
		||||
var_ram="256"
 | 
			
		||||
var_disk="0.3"
 | 
			
		||||
var_disk="0.5"
 | 
			
		||||
var_os="alpine"
 | 
			
		||||
var_version="3.20"
 | 
			
		||||
var_unprivileged="1"
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ function update_script() {
 | 
			
		||||
     msg_info "Updating ${APP} LXC"
 | 
			
		||||
     apt-get update &>/dev/null
 | 
			
		||||
     apt-get -y upgrade &>/dev/null
 | 
			
		||||
     apt-get --with-new-pkgs upgrade jellyfin jellyfin-server &>/dev/null
 | 
			
		||||
     apt-get -y --with-new-pkgs upgrade jellyfin jellyfin-server &>/dev/null
 | 
			
		||||
     msg_ok "Updated ${APP} LXC"
 | 
			
		||||
     exit
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -45,5 +45,6 @@ description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL} or ${TAB}${GATEWAY}${BGN}https://${IP}:8443${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using one of the following URLs:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}https://${IP}:8443${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:8080${CL}"
 | 
			
		||||
 
 | 
			
		||||
@@ -4,15 +4,33 @@ import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useRouter } from "next/navigation";
 | 
			
		||||
import { Card, CardContent } from "@/components/ui/card";
 | 
			
		||||
import { Button } from "@/components/ui/button";
 | 
			
		||||
import { Badge } from "@/components/ui/badge";
 | 
			
		||||
import { ChevronLeft, ChevronRight } from "lucide-react";
 | 
			
		||||
import { Category } from "@/lib/types";
 | 
			
		||||
 | 
			
		||||
const defaultLogo = "/default-logo.png"; // Fallback logo path
 | 
			
		||||
 | 
			
		||||
const MAX_DESCRIPTION_LENGTH = 100; // Set max length for description
 | 
			
		||||
const MAX_LOGOS = 5; // Max logos to display at once
 | 
			
		||||
 | 
			
		||||
const formattedBadge = (type: string) => {
 | 
			
		||||
  switch (type) {
 | 
			
		||||
    case "vm":
 | 
			
		||||
      return <Badge className="text-blue-500/75 border-blue-500/75 badge">VM</Badge>;
 | 
			
		||||
    case "ct":
 | 
			
		||||
      return (
 | 
			
		||||
        <Badge className="text-yellow-500/75 border-yellow-500/75 badge">LXC</Badge>
 | 
			
		||||
      );
 | 
			
		||||
    case "misc":
 | 
			
		||||
      return <Badge className="text-green-500/75 border-green-500/75 badge">MISC</Badge>;
 | 
			
		||||
  }
 | 
			
		||||
  return null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CategoryView = () => {
 | 
			
		||||
  const [categories, setCategories] = useState<Category[]>([]);
 | 
			
		||||
  const [selectedCategory, setSelectedCategory] = useState<Category | null>(null);
 | 
			
		||||
  const [selectedCategoryIndex, setSelectedCategoryIndex] = useState<number | null>(null);
 | 
			
		||||
  const [currentScripts, setCurrentScripts] = useState<any[]>([]);
 | 
			
		||||
  const [logoIndices, setLogoIndices] = useState<{ [key: string]: number }>({});
 | 
			
		||||
  const router = useRouter();
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
@@ -24,8 +42,14 @@ const CategoryView = () => {
 | 
			
		||||
          throw new Error("Failed to fetch categories");
 | 
			
		||||
        }
 | 
			
		||||
        const data = await response.json();
 | 
			
		||||
        console.log("Fetched categories:", data); // Debugging
 | 
			
		||||
        setCategories(data);
 | 
			
		||||
 | 
			
		||||
        // Initialize logo indices
 | 
			
		||||
        const initialLogoIndices: { [key: string]: number } = {};
 | 
			
		||||
        data.forEach((category: any) => {
 | 
			
		||||
          initialLogoIndices[category.name] = 0;
 | 
			
		||||
        });
 | 
			
		||||
        setLogoIndices(initialLogoIndices);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error("Error fetching categories:", error);
 | 
			
		||||
      }
 | 
			
		||||
@@ -34,91 +58,209 @@ const CategoryView = () => {
 | 
			
		||||
    fetchCategories();
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const handleCategoryClick = (category: Category) => {
 | 
			
		||||
    setSelectedCategory(category);
 | 
			
		||||
  const handleCategoryClick = (index: number) => {
 | 
			
		||||
    setSelectedCategoryIndex(index);
 | 
			
		||||
    setCurrentScripts(categories[index]?.scripts || []); // Update scripts for the selected category
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleBackClick = () => {
 | 
			
		||||
    setSelectedCategory(null);
 | 
			
		||||
    setSelectedCategoryIndex(null);
 | 
			
		||||
    setCurrentScripts([]); // Clear scripts when going back
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleScriptClick = (scriptSlug: string) => {
 | 
			
		||||
    router.push(`/scripts?id=${scriptSlug}`);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const navigateCategory = (direction: "prev" | "next") => {
 | 
			
		||||
    if (selectedCategoryIndex !== null) {
 | 
			
		||||
      const newIndex =
 | 
			
		||||
        direction === "prev"
 | 
			
		||||
          ? (selectedCategoryIndex - 1 + categories.length) % categories.length
 | 
			
		||||
          : (selectedCategoryIndex + 1) % categories.length;
 | 
			
		||||
      setSelectedCategoryIndex(newIndex);
 | 
			
		||||
      setCurrentScripts(categories[newIndex]?.scripts || []); // Update scripts for the new category
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const switchLogos = (categoryName: string, direction: "prev" | "next") => {
 | 
			
		||||
    setLogoIndices((prev) => {
 | 
			
		||||
      const currentIndex = prev[categoryName] || 0;
 | 
			
		||||
      const category = categories.find((cat) => cat.name === categoryName);
 | 
			
		||||
      if (!category || !category.scripts) return prev;
 | 
			
		||||
 | 
			
		||||
      const totalLogos = category.scripts.length;
 | 
			
		||||
      const newIndex =
 | 
			
		||||
        direction === "prev"
 | 
			
		||||
          ? (currentIndex - MAX_LOGOS + totalLogos) % totalLogos
 | 
			
		||||
          : (currentIndex + MAX_LOGOS) % totalLogos;
 | 
			
		||||
 | 
			
		||||
      return { ...prev, [categoryName]: newIndex };
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const truncateDescription = (text: string) => {
 | 
			
		||||
    return text.length > MAX_DESCRIPTION_LENGTH
 | 
			
		||||
      ? `${text.slice(0, MAX_DESCRIPTION_LENGTH)}...`
 | 
			
		||||
      : text;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const renderResources = (script: any) => {
 | 
			
		||||
    const cpu = script.install_methods[0]?.resources.cpu;
 | 
			
		||||
    const ram = script.install_methods[0]?.resources.ram;
 | 
			
		||||
    const hdd = script.install_methods[0]?.resources.hdd;
 | 
			
		||||
 | 
			
		||||
    const resourceParts = [];
 | 
			
		||||
    if (cpu) resourceParts.push(<span key="cpu"><b>CPU:</b> {cpu}vCPU</span>);
 | 
			
		||||
    if (ram) resourceParts.push(<span key="ram"><b>RAM:</b> {ram}MB</span>);
 | 
			
		||||
    if (hdd) resourceParts.push(<span key="hdd"><b>HDD:</b> {hdd}GB</span>);
 | 
			
		||||
 | 
			
		||||
    return resourceParts.length > 0 ? (
 | 
			
		||||
      <div className="text-sm text-gray-400">
 | 
			
		||||
        {resourceParts.map((part, index) => (
 | 
			
		||||
          <React.Fragment key={index}>
 | 
			
		||||
            {part}
 | 
			
		||||
            {index < resourceParts.length - 1 && " | "}
 | 
			
		||||
          </React.Fragment>
 | 
			
		||||
        ))}
 | 
			
		||||
      </div>
 | 
			
		||||
    ) : null;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="p-4 mt-20">
 | 
			
		||||
    <div className="p-6 mt-20">
 | 
			
		||||
      {categories.length === 0 && (
 | 
			
		||||
        <p className="text-center text-gray-500">No categories available. Please check the API endpoint.</p>
 | 
			
		||||
      )}
 | 
			
		||||
      {selectedCategory ? (
 | 
			
		||||
      {selectedCategoryIndex !== null ? (
 | 
			
		||||
        <div>
 | 
			
		||||
          <Button variant="default" onClick={handleBackClick} className="mb-4">
 | 
			
		||||
            Back to Categories
 | 
			
		||||
          </Button>
 | 
			
		||||
          <h2 className="text-xl font-semibold mb-4">{selectedCategory.name}</h2>
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
 | 
			
		||||
            {selectedCategory.scripts
 | 
			
		||||
          {/* Header with Navigation */}
 | 
			
		||||
          <div className="flex items-center justify-between mb-6">
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="ghost"
 | 
			
		||||
              onClick={() => navigateCategory("prev")}
 | 
			
		||||
              className="p-2 transition-transform duration-300 hover:scale-105"
 | 
			
		||||
            >
 | 
			
		||||
              <ChevronLeft className="h-6 w-6" />
 | 
			
		||||
            </Button>
 | 
			
		||||
            <h2 className="text-3xl font-semibold transition-opacity duration-300 hover:opacity-90">
 | 
			
		||||
              {categories[selectedCategoryIndex].name}
 | 
			
		||||
            </h2>
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="ghost"
 | 
			
		||||
              onClick={() => navigateCategory("next")}
 | 
			
		||||
              className="p-2 transition-transform duration-300 hover:scale-105"
 | 
			
		||||
            >
 | 
			
		||||
              <ChevronRight className="h-6 w-6" />
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          {/* Scripts Grid */}
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
 | 
			
		||||
            {currentScripts
 | 
			
		||||
              .sort((a, b) => a.name.localeCompare(b.name))
 | 
			
		||||
              .map((script) => (
 | 
			
		||||
                <Card key={script.name} className="p-4 cursor-pointer" onClick={() => handleScriptClick(script.slug)}>
 | 
			
		||||
                <Card
 | 
			
		||||
                  key={script.name}
 | 
			
		||||
                  className="p-4 cursor-pointer hover:shadow-md transition-shadow duration-300"
 | 
			
		||||
                  onClick={() => handleScriptClick(script.slug)}
 | 
			
		||||
                >
 | 
			
		||||
                  <CardContent className="flex flex-col gap-4">
 | 
			
		||||
                    <div className="flex items-center gap-4">
 | 
			
		||||
                      <img
 | 
			
		||||
                        src={script.logo || defaultLogo}
 | 
			
		||||
                        alt={script.name}
 | 
			
		||||
                        className="h-12 w-12 object-contain"
 | 
			
		||||
                      />
 | 
			
		||||
                      <div>
 | 
			
		||||
                        <h3 className="text-lg font-bold">{script.name}</h3>
 | 
			
		||||
                        <p className="text-sm text-gray-500"><b>Created at:</b> {script.date_created || "No date available"}</p>
 | 
			
		||||
                        <p className="text-sm text-gray-700">
 | 
			
		||||
                          {truncateDescription(script.description || "No description available.")}
 | 
			
		||||
                        </p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="text-sm text-gray-600">
 | 
			
		||||
                      <b>CPU:</b> {script.install_methods[0]?.resources.cpu || "N/A"}vCPU | <b>RAM:</b> {script.install_methods[0]?.resources.ram || "N/A"}MB | <b>HDD:</b> {script.install_methods[0]?.resources.hdd || "N/A"}GB
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <h3 className="text-lg font-bold script-text text-center hover:text-blue-600 transition-colors duration-300">
 | 
			
		||||
                      {script.name}
 | 
			
		||||
                    </h3>
 | 
			
		||||
                    <img
 | 
			
		||||
                      src={script.logo || defaultLogo}
 | 
			
		||||
                      alt={script.name || "Script logo"}
 | 
			
		||||
                      className="h-12 w-12 object-contain mx-auto"
 | 
			
		||||
                    />
 | 
			
		||||
                    <p className="text-sm text-gray-500 text-center">
 | 
			
		||||
                      <b>Created at:</b> {script.date_created || "No date available"}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p
 | 
			
		||||
                      className="text-sm text-gray-700 hover:text-gray-900 text-center transition-colors duration-300"
 | 
			
		||||
                      title={script.description || "No description available."}
 | 
			
		||||
                    >
 | 
			
		||||
                      {truncateDescription(script.description || "No description available.")}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    {renderResources(script)}
 | 
			
		||||
                  </CardContent>
 | 
			
		||||
                </Card>
 | 
			
		||||
              ))}
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          {/* Back to Categories Button */}
 | 
			
		||||
          <div className="mt-8 text-center">
 | 
			
		||||
            <Button
 | 
			
		||||
              variant="default"
 | 
			
		||||
              onClick={handleBackClick}
 | 
			
		||||
              className="px-6 py-2 text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow-md transition-transform duration-300 hover:scale-105"
 | 
			
		||||
            >
 | 
			
		||||
              Back to Categories
 | 
			
		||||
            </Button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      ) : (
 | 
			
		||||
        <div>
 | 
			
		||||
          <div className="flex justify-between items-center mb-6">
 | 
			
		||||
            <h1 className="text-2xl font-bold">Categories</h1>
 | 
			
		||||
          {/* Categories Grid */}
 | 
			
		||||
          <div className="flex justify-between items-center mb-8">
 | 
			
		||||
            <h1 className="text-3xl font-semibold mb-4">Categories</h1>
 | 
			
		||||
            <p className="text-sm text-gray-500">
 | 
			
		||||
              {categories.reduce((acc, cat) => acc + (cat.scripts?.length || 0), 0)} Total scripts
 | 
			
		||||
              {categories.reduce((total, category) => total + (category.scripts?.length || 0), 0)} Total scripts
 | 
			
		||||
            </p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
 | 
			
		||||
            {categories.map((category) => (
 | 
			
		||||
          <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8">
 | 
			
		||||
            {categories.map((category, index) => (
 | 
			
		||||
              <Card
 | 
			
		||||
                key={category.name}
 | 
			
		||||
                onClick={() => handleCategoryClick(category)}
 | 
			
		||||
                className="cursor-pointer hover:shadow-lg flex flex-col items-center justify-center"
 | 
			
		||||
                onClick={() => handleCategoryClick(index)}
 | 
			
		||||
                className="cursor-pointer hover:shadow-lg flex flex-col items-center justify-center py-6 transition-shadow duration-300"
 | 
			
		||||
              >
 | 
			
		||||
                <CardContent className="flex flex-col items-center">
 | 
			
		||||
                  <div className="flex flex-wrap justify-center gap-1 mb-2">
 | 
			
		||||
                    {category.scripts && category.scripts.slice(0, 4).map((script, index) => (
 | 
			
		||||
                      <img
 | 
			
		||||
                        key={index}
 | 
			
		||||
                        src={script.logo || defaultLogo}
 | 
			
		||||
                        alt={script.name || "Script logo"}
 | 
			
		||||
                        className="h-6 w-6 object-contain"
 | 
			
		||||
                      />
 | 
			
		||||
                    ))}
 | 
			
		||||
                  <h3 className="text-xl font-bold mb-4 category-title transition-colors duration-300 hover:text-blue-600">
 | 
			
		||||
                    {category.name}
 | 
			
		||||
                  </h3>
 | 
			
		||||
                  <div className="flex justify-center items-center gap-2 mb-4">
 | 
			
		||||
                    <Button
 | 
			
		||||
                      variant="ghost"
 | 
			
		||||
                      onClick={(e) => {
 | 
			
		||||
                        e.stopPropagation();
 | 
			
		||||
                        switchLogos(category.name, "prev");
 | 
			
		||||
                      }}
 | 
			
		||||
                      className="p-1 transition-transform duration-300 hover:scale-110"
 | 
			
		||||
                    >
 | 
			
		||||
                      <ChevronLeft className="h-4 w-4" />
 | 
			
		||||
                    </Button>
 | 
			
		||||
                    {category.scripts &&
 | 
			
		||||
                      category.scripts
 | 
			
		||||
                        .slice(logoIndices[category.name] || 0, (logoIndices[category.name] || 0) + MAX_LOGOS)
 | 
			
		||||
                        .map((script, i) => (
 | 
			
		||||
                          <div key={i} className="flex flex-col items-center">
 | 
			
		||||
                            <img
 | 
			
		||||
                              src={script.logo || defaultLogo}
 | 
			
		||||
                              alt={script.name || "Script logo"}
 | 
			
		||||
                              title={script.name}
 | 
			
		||||
                              className="h-8 w-8 object-contain cursor-pointer"
 | 
			
		||||
                              onClick={(e) => {
 | 
			
		||||
                                e.stopPropagation();
 | 
			
		||||
                                handleScriptClick(script.slug);
 | 
			
		||||
                              }}
 | 
			
		||||
                            />
 | 
			
		||||
                            {formattedBadge(script.type)}
 | 
			
		||||
                          </div>
 | 
			
		||||
                        ))}
 | 
			
		||||
                    <Button
 | 
			
		||||
                      variant="ghost"
 | 
			
		||||
                      onClick={(e) => {
 | 
			
		||||
                        e.stopPropagation();
 | 
			
		||||
                        switchLogos(category.name, "next");
 | 
			
		||||
                      }}
 | 
			
		||||
                      className="p-1 transition-transform duration-300 hover:scale-110"
 | 
			
		||||
                    >
 | 
			
		||||
                      <ChevronRight className="h-4 w-4" />
 | 
			
		||||
                    </Button>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <h3 className="text-lg font-bold mb-1">{category.name}</h3>
 | 
			
		||||
                  <p className="text-sm text-gray-500 text-center">
 | 
			
		||||
                  <p className="text-sm text-gray-400 text-center">
 | 
			
		||||
                    {(category as any).description || "No description available."}
 | 
			
		||||
                  </p>
 | 
			
		||||
                </CardContent>
 | 
			
		||||
@@ -131,4 +273,4 @@ const CategoryView = () => {
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default CategoryView;
 | 
			
		||||
export default CategoryView;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,7 @@ msg_ok "Installed Kepubify"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Calibre-Web"
 | 
			
		||||
mkdir -p /opt/calibre-web
 | 
			
		||||
$STD apt-get install -y calibre
 | 
			
		||||
$STD wget https://github.com/janeczku/calibre-web/raw/master/library/metadata.db -P /opt/calibre-web
 | 
			
		||||
$STD pip install calibreweb
 | 
			
		||||
$STD pip install jsonschema
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,7 @@ EOF
 | 
			
		||||
# Install Jellyfin using the metapackage (which will fetch jellyfin-server, jellyfin-web, and jellyfin-ffmpeg5)
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
$STD apt-get install -y jellyfin
 | 
			
		||||
sed -i 's/"MinimumLevel": "Information"/"MinimumLevel": "Error"/g' /etc/jellyfin/logging.json
 | 
			
		||||
chown -R jellyfin:adm /etc/jellyfin
 | 
			
		||||
sleep 10
 | 
			
		||||
systemctl restart jellyfin
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ msg_ok "Setup Server 2022"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing SQL Server Tools"
 | 
			
		||||
export DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
export ACCEPT_EULA=Y
 | 
			
		||||
curl https://packages.microsoft.com/keys/microsoft.asc | tee /etc/apt/trusted.gpg.d/microsoft.asc
 | 
			
		||||
curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list | tee /etc/apt/sources.list.d/mssql-release.list
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								json/archlinux-vm.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								json/archlinux-vm.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Arch Linux",
 | 
			
		||||
  "slug": "archlinux-vm",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    2
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-01-27",
 | 
			
		||||
  "type": "vm",
 | 
			
		||||
  "updateable": false,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": null,
 | 
			
		||||
  "documentation": null,
 | 
			
		||||
  "website": null,
 | 
			
		||||
  "logo": "https://raw.githubusercontent.com/ArchLinuxStudio/ArchLinuxTutorial/refs/heads/master/docs/arch_seo.png",
 | 
			
		||||
  "description": "Arch Linux is a highly customizable, independent Linux distribution that gives users complete control over their system. Known for its rolling release model, Arch Linux is always up-to-date with the latest software. It's favored by experienced users who appreciate its minimalist approach, demanding a hands-on installation and configuration process. This level of control and flexibility makes it a popular choice for those who want to tailor their Linux system to their exact needs.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "vm/archlinux-vm.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 1,
 | 
			
		||||
        "ram": 1024,
 | 
			
		||||
        "hdd": 4,
 | 
			
		||||
        "os": null,
 | 
			
		||||
        "version": null
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "doesnt work with lvm and lvmthin disks!",
 | 
			
		||||
      "type": "warning"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,30 +1,30 @@
 | 
			
		||||
{
 | 
			
		||||
	"categories": [
 | 
			
		||||
		{ "name": "Proxmox & Virtualization", "id": 1, "sort_order": 1.0 },
 | 
			
		||||
		{ "name": "Operating Systems", "id": 2, "sort_order": 2.0 },
 | 
			
		||||
		{ "name": "Containers & Docker", "id": 3, "sort_order": 3.0 },
 | 
			
		||||
		{ "name": "Network & Firewall", "id": 4, "sort_order": 4.0 },
 | 
			
		||||
		{ "name": "Adblock & DNS", "id": 5, "sort_order": 5.0 },
 | 
			
		||||
		{ "name": "Authentication & Security", "id": 6, "sort_order": 6.0 },
 | 
			
		||||
		{ "name": "Backup & Recovery", "id": 7, "sort_order": 7.0 },
 | 
			
		||||
		{ "name": "Databases", "id": 8, "sort_order": 8.0 },
 | 
			
		||||
		{ "name": "Monitoring & Analytics", "id": 9, "sort_order": 9.0 },
 | 
			
		||||
		{ "name": "Dashboards & Frontends", "id": 10, "sort_order": 10.0 },
 | 
			
		||||
		{ "name": "Files & Downloads", "id": 11, "sort_order": 11.0 },
 | 
			
		||||
		{ "name": "Documents & Notes", "id": 12, "sort_order": 12.0 },
 | 
			
		||||
		{ "name": "Media & Streaming", "id": 13, "sort_order": 13.0 },
 | 
			
		||||
		{ "name": "*Arr Suite", "id": 14, "sort_order": 14.0 },
 | 
			
		||||
		{ "name": "NVR & Cameras", "id": 15, "sort_order": 15.0 },
 | 
			
		||||
		{ "name": "IoT & Smart Home", "id": 16, "sort_order": 16.0 },
 | 
			
		||||
		{ "name": "ZigBee, Z-Wave & Matter", "id": 17, "sort_order": 17.0 },
 | 
			
		||||
		{ "name": "MQTT & Messaging", "id": 18, "sort_order": 18.0 },
 | 
			
		||||
		{ "name": "Automation & Scheduling", "id": 19, "sort_order": 19.0 },
 | 
			
		||||
		{ "name": "AI / Coding & Dev-Tools", "id": 20, "sort_order": 20.0 },
 | 
			
		||||
		{ "name": "Webservers & Proxies", "id": 21, "sort_order": 21.0 },
 | 
			
		||||
		{ "name": "Bots & ChatOps", "id": 22, "sort_order": 22.0 },
 | 
			
		||||
		{ "name": "Finance & Budgeting", "id": 23, "sort_order": 23.0 },
 | 
			
		||||
		{ "name": "Gaming & Leisure", "id": 24, "sort_order": 24.0 },
 | 
			
		||||
		{ "name": "Business & ERP", "id": 25, "sort_order": 25.0 },
 | 
			
		||||
		{ "name": "Miscellaneous", "id": 0, "sort_order": 99.0 }
 | 
			
		||||
		{ "name": "Proxmox & Virtualization", "id": 1, "sort_order": 1.0, "description": "Tools and scripts to manage Proxmox VE and virtualization platforms effectively." },
 | 
			
		||||
		{ "name": "Operating Systems", "id": 2, "sort_order": 2.0, "description": "Scripts for deploying and managing various operating systems." },
 | 
			
		||||
		{ "name": "Containers & Docker", "id": 3, "sort_order": 3.0, "description": "Solutions for containerization using Docker and related technologies." },
 | 
			
		||||
		{ "name": "Network & Firewall", "id": 4, "sort_order": 4.0, "description": "Enhance network security and configure firewalls with ease." },
 | 
			
		||||
		{ "name": "Adblock & DNS", "id": 5, "sort_order": 5.0, "description": "Optimize your network with DNS and ad-blocking solutions." },
 | 
			
		||||
		{ "name": "Authentication & Security", "id": 6, "sort_order": 6.0, "description": "Secure your infrastructure with authentication and security tools." },
 | 
			
		||||
		{ "name": "Backup & Recovery", "id": 7, "sort_order": 7.0, "description": "Reliable backup and recovery scripts to protect your data." },
 | 
			
		||||
		{ "name": "Databases", "id": 8, "sort_order": 8.0, "description": "Deploy and manage robust database systems with ease." },
 | 
			
		||||
		{ "name": "Monitoring & Analytics", "id": 9, "sort_order": 9.0, "description": "Monitor system performance and analyze data seamlessly." },
 | 
			
		||||
		{ "name": "Dashboards & Frontends", "id": 10, "sort_order": 10.0, "description": "Create interactive dashboards and user-friendly frontends." },
 | 
			
		||||
		{ "name": "Files & Downloads", "id": 11, "sort_order": 11.0, "description": "Manage file sharing and downloading solutions efficiently." },
 | 
			
		||||
		{ "name": "Documents & Notes", "id": 12, "sort_order": 12.0, "description": "Organize and manage documents and note-taking tools." },
 | 
			
		||||
		{ "name": "Media & Streaming", "id": 13, "sort_order": 13.0, "description": "Stream and manage media effortlessly across devices." },
 | 
			
		||||
		{ "name": "*Arr Suite", "id": 14, "sort_order": 14.0, "description": "Automated media management with the popular *Arr suite tools." },
 | 
			
		||||
		{ "name": "NVR & Cameras", "id": 15, "sort_order": 15.0, "description": "Manage network video recorders and camera setups." },
 | 
			
		||||
		{ "name": "IoT & Smart Home", "id": 16, "sort_order": 16.0, "description": "Control and automate IoT devices and smart home systems." },
 | 
			
		||||
		{ "name": "ZigBee, Z-Wave & Matter", "id": 17, "sort_order": 17.0, "description": "Solutions for ZigBee, Z-Wave, and Matter-based device management." },
 | 
			
		||||
		{ "name": "MQTT & Messaging", "id": 18, "sort_order": 18.0, "description": "Set up reliable messaging and MQTT-based communication systems." },
 | 
			
		||||
		{ "name": "Automation & Scheduling", "id": 19, "sort_order": 19.0, "description": "Automate tasks and manage scheduling with powerful tools." },
 | 
			
		||||
		{ "name": "AI / Coding & Dev-Tools", "id": 20, "sort_order": 20.0, "description": "Leverage AI and developer tools for smarter coding workflows." },
 | 
			
		||||
		{ "name": "Webservers & Proxies", "id": 21, "sort_order": 21.0, "description": "Deploy and configure web servers and proxy solutions." },
 | 
			
		||||
		{ "name": "Bots & ChatOps", "id": 22, "sort_order": 22.0, "description": "Enhance collaboration with bots and ChatOps integrations." },
 | 
			
		||||
		{ "name": "Finance & Budgeting", "id": 23, "sort_order": 23.0, "description": "Track expenses and manage budgets efficiently." },
 | 
			
		||||
		{ "name": "Gaming & Leisure", "id": 24, "sort_order": 24.0, "description": "Scripts for gaming servers and leisure-related tools." },
 | 
			
		||||
		{ "name": "Business & ERP", "id": 25, "sort_order": 25.0, "description": "Streamline business operations with ERP and management tools." },
 | 
			
		||||
		{ "name": "Miscellaneous", "id": 0, "sort_order": 99.0, "description": "General scripts and tools that don't fit into other categories." }
 | 
			
		||||
	]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,8 @@
 | 
			
		||||
    "type": "ct",
 | 
			
		||||
    "updateable": false,
 | 
			
		||||
    "privileged": false,
 | 
			
		||||
    "interface_port": 8080,
 | 
			
		||||
    "documentation": null,
 | 
			
		||||
    "interface_port": 8443,
 | 
			
		||||
    "documentation": "https://www.openhab.org/docs/",
 | 
			
		||||
    "website": "https://www.openhab.org/",
 | 
			
		||||
    "logo": "https://www.coxprod.org/domotique/wp-content/uploads/2019/01/openhab-logo-square.png",
 | 
			
		||||
    "description": "openHAB is a popular open-source home automation platform that provides a vendor and technology agnostic solution for integrating and automating various smart home devices and services. It supports a wide range of devices and protocols, making it easy to bring together different systems and devices into a unified smart home ecosystem. With its user-friendly interface and powerful automation capabilities, openHAB makes it easy to create custom automations and monitor and control your smart home devices and systems, all from a single interface.",
 | 
			
		||||
@@ -31,4 +31,4 @@
 | 
			
		||||
        "password": null
 | 
			
		||||
    },
 | 
			
		||||
    "notes": []
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "notes": [
 | 
			
		||||
      {
 | 
			
		||||
        "text": "The Lounge is running in private mode. Use `sudo -u thelounge thelounge add name` to create users.",
 | 
			
		||||
        "text": "The Lounge is running in private mode. Use `runuser -u thelounge -- thelounge add usernamehere` to create users.",
 | 
			
		||||
        "type": "info"
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -31,9 +31,9 @@
 | 
			
		||||
            "resources": {
 | 
			
		||||
                "cpu": 1,
 | 
			
		||||
                "ram": 256,
 | 
			
		||||
                "hdd": 0.3,
 | 
			
		||||
                "hdd": 0.5,
 | 
			
		||||
                "os": "alpine",
 | 
			
		||||
                "version": "3.19"
 | 
			
		||||
                "version": "3.20"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
 
 | 
			
		||||
@@ -120,8 +120,11 @@ EOF
 | 
			
		||||
    yes)
 | 
			
		||||
      whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Support Subscriptions" "Supporting the software's development team is essential. Check their official website's Support Subscriptions for pricing. Without their dedicated work, we wouldn't have this exceptional software." 10 58
 | 
			
		||||
      msg_info "Disabling subscription nag"
 | 
			
		||||
      # Normal GUI:
 | 
			
		||||
      echo "DPkg::Post-Invoke { \"dpkg -V proxmox-widget-toolkit | grep -q '/proxmoxlib\.js$'; if [ \$? -eq 1 ]; then { echo 'Removing subscription nag from UI...'; sed -i '/data\.status.*{/{s/\!//;s/active/NoMoreNagging/}' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; }; fi\"; };" >/etc/apt/apt.conf.d/no-nag-script
 | 
			
		||||
      apt --reinstall install proxmox-widget-toolkit &>/dev/null
 | 
			
		||||
      # JS-Library used when accessing via mobile device browser
 | 
			
		||||
      echo "DPkg::Post-Invoke { \"dpkg -V pmg-gui | grep -q '/pmgmanagerlib-mobile\.js$'; if [ \$? -eq 1 ]; then { echo 'Removing subscription nag from Mobile UI...'; sed -i '/data\.status.*{/{s/\!//;s/active/NoMoreNagging/}' /usr/share/javascript/pmg-gui/js/pmgmanagerlib-mobile.js; }; fi\"; };" >/etc/apt/apt.conf.d/no-nag-script
 | 
			
		||||
      apt --reinstall install proxmox-widget-toolkit pmg-gui &>/dev/null
 | 
			
		||||
      msg_ok "Disabled subscription nag (Delete browser cache)"
 | 
			
		||||
      ;;
 | 
			
		||||
    no)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										497
									
								
								vm/archlinux-vm.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										497
									
								
								vm/archlinux-vm.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,497 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: MickLesk (CanbiZ)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
 | 
			
		||||
function header_info {
 | 
			
		||||
  clear
 | 
			
		||||
  cat <<"EOF"
 | 
			
		||||
    ___              __       __    _                     _    ____  ___
 | 
			
		||||
   /   |  __________/ /_     / /   (_)___  __  ___  __   | |  / /  |/  /
 | 
			
		||||
  / /| | / ___/ ___/ __ \   / /   / / __ \/ / / / |/_/   | | / / /|_/ / 
 | 
			
		||||
 / ___ |/ /  / /__/ / / /  / /___/ / / / / /_/ />  <     | |/ / /  / /  
 | 
			
		||||
/_/  |_/_/   \___/_/ /_/  /_____/_/_/ /_/\__,_/_/|_|     |___/_/  /_/   
 | 
			
		||||
                                                                        
 | 
			
		||||
EOF
 | 
			
		||||
}
 | 
			
		||||
header_info
 | 
			
		||||
echo -e "\n Loading..."
 | 
			
		||||
GEN_MAC=02:$(openssl rand -hex 5 | awk '{print toupper($0)}' | sed 's/\(..\)/\1:/g; s/.$//')
 | 
			
		||||
NEXTID=$(pvesh get /cluster/nextid)
 | 
			
		||||
 | 
			
		||||
YW=$(echo "\033[33m")
 | 
			
		||||
BL=$(echo "\033[36m")
 | 
			
		||||
RD=$(echo "\033[01;31m")
 | 
			
		||||
BGN=$(echo "\033[4;92m")
 | 
			
		||||
GN=$(echo "\033[1;92m")
 | 
			
		||||
DGN=$(echo "\033[32m")
 | 
			
		||||
CL=$(echo "\033[m")
 | 
			
		||||
 | 
			
		||||
CL=$(echo "\033[m")
 | 
			
		||||
BOLD=$(echo "\033[1m")
 | 
			
		||||
BFR="\\r\\033[K"
 | 
			
		||||
HOLD=" "
 | 
			
		||||
TAB="  "
 | 
			
		||||
 | 
			
		||||
CM="${TAB}✔️${TAB}${CL}"
 | 
			
		||||
CROSS="${TAB}✖️${TAB}${CL}"
 | 
			
		||||
INFO="${TAB}💡${TAB}${CL}"
 | 
			
		||||
OS="${TAB}🖥️${TAB}${CL}"
 | 
			
		||||
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
 | 
			
		||||
DISKSIZE="${TAB}💾${TAB}${CL}"
 | 
			
		||||
CPUCORE="${TAB}🧠${TAB}${CL}"
 | 
			
		||||
RAMSIZE="${TAB}🛠️${TAB}${CL}"
 | 
			
		||||
CONTAINERID="${TAB}🆔${TAB}${CL}"
 | 
			
		||||
HOSTNAME="${TAB}🏠${TAB}${CL}"
 | 
			
		||||
BRIDGE="${TAB}🌉${TAB}${CL}"
 | 
			
		||||
GATEWAY="${TAB}🌐${TAB}${CL}"
 | 
			
		||||
DEFAULT="${TAB}⚙️${TAB}${CL}"
 | 
			
		||||
MACADDRESS="${TAB}🔗${TAB}${CL}"
 | 
			
		||||
VLANTAG="${TAB}🏷️${TAB}${CL}"
 | 
			
		||||
CREATING="${TAB}🚀${TAB}${CL}"
 | 
			
		||||
ADVANCED="${TAB}🧩${TAB}${CL}"
 | 
			
		||||
 | 
			
		||||
THIN="discard=on,ssd=1,"
 | 
			
		||||
set -e
 | 
			
		||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
trap cleanup EXIT
 | 
			
		||||
function error_handler() {
 | 
			
		||||
  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"
 | 
			
		||||
  cleanup_vmid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function cleanup_vmid() {
 | 
			
		||||
  if qm status $VMID &>/dev/null; then
 | 
			
		||||
    qm stop $VMID &>/dev/null
 | 
			
		||||
    qm destroy $VMID &>/dev/null
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function cleanup() {
 | 
			
		||||
  popd >/dev/null
 | 
			
		||||
  rm -rf $TEMP_DIR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEMP_DIR=$(mktemp -d)
 | 
			
		||||
pushd $TEMP_DIR >/dev/null
 | 
			
		||||
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "Arch Linux VM" --yesno "This will create a New Arch Linux VM. Proceed?" 10 58; then
 | 
			
		||||
  :
 | 
			
		||||
else
 | 
			
		||||
  header_info &&   echo -e "${CROSS}${RD}User exited script${CL}\n" && exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
function msg_info() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function msg_ok() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${CM}${GN}${msg}${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function msg_error() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function check_root() {
 | 
			
		||||
  if [[ "$(id -u)" -ne 0 || $(ps -o comm= -p $PPID) == "sudo" ]]; then
 | 
			
		||||
    clear
 | 
			
		||||
    msg_error "Please run this script as root."
 | 
			
		||||
    echo -e "\nExiting..."
 | 
			
		||||
    sleep 2
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function pve_check() {
 | 
			
		||||
  if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
 | 
			
		||||
    msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
 | 
			
		||||
    echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
 | 
			
		||||
    echo -e "Exiting..."
 | 
			
		||||
    sleep 2
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function arch_check() {
 | 
			
		||||
  if [ "$(dpkg --print-architecture)" != "amd64" ]; then
 | 
			
		||||
    echo -e "\n ${INFO}${YWB}This script will not work with PiMox! \n"
 | 
			
		||||
    echo -e "\n ${YWB}Visit https://github.com/asylumexp/Proxmox for ARM64 support. \n"
 | 
			
		||||
    echo -e "Exiting..."
 | 
			
		||||
    sleep 2
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ssh_check() {
 | 
			
		||||
  if command -v pveversion >/dev/null 2>&1; then
 | 
			
		||||
    if [ -n "${SSH_CLIENT:+x}" ]; then
 | 
			
		||||
      if whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH DETECTED" --yesno "It's suggested to use the Proxmox shell instead of SSH, since SSH can create issues while gathering variables. Would you like to proceed with using SSH?" 10 62; then
 | 
			
		||||
        echo "you've been warned"
 | 
			
		||||
      else
 | 
			
		||||
        clear
 | 
			
		||||
        exit
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function exit-script() {
 | 
			
		||||
  clear
 | 
			
		||||
  echo -e "\n${CROSS}${RD}User exited script${CL}\n"
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function default_settings() {
 | 
			
		||||
  VMID="$NEXTID"
 | 
			
		||||
  FORMAT=",efitype=4m"
 | 
			
		||||
  MACHINE=""
 | 
			
		||||
  DISK_SIZE="4G"
 | 
			
		||||
  DISK_CACHE=""
 | 
			
		||||
  HN="arch-linux"
 | 
			
		||||
  CPU_TYPE=""
 | 
			
		||||
  CORE_COUNT="1"
 | 
			
		||||
  RAM_SIZE="1024"
 | 
			
		||||
  BRG="vmbr0"
 | 
			
		||||
  MAC="$GEN_MAC"
 | 
			
		||||
  VLAN=""
 | 
			
		||||
  MTU=""
 | 
			
		||||
  START_VM="yes"
 | 
			
		||||
  echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
 | 
			
		||||
  echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
 | 
			
		||||
  echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE}${CL}"
 | 
			
		||||
  echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
 | 
			
		||||
  echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
 | 
			
		||||
  echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
 | 
			
		||||
  echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
 | 
			
		||||
  echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE}${CL}"
 | 
			
		||||
  echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
 | 
			
		||||
  echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
 | 
			
		||||
  echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
 | 
			
		||||
  echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
 | 
			
		||||
  echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
 | 
			
		||||
  echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above default settings${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function advanced_settings() {
 | 
			
		||||
  while true; do
 | 
			
		||||
    if VMID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Virtual Machine ID" 8 58 $NEXTID --title "VIRTUAL MACHINE ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
      if [ -z "$VMID" ]; then
 | 
			
		||||
        VMID="$NEXTID"
 | 
			
		||||
      fi
 | 
			
		||||
      if pct status "$VMID" &>/dev/null || qm status "$VMID" &>/dev/null; then
 | 
			
		||||
        echo -e "${CROSS}${RD} ID $VMID is already in use${CL}"
 | 
			
		||||
        sleep 2
 | 
			
		||||
        continue
 | 
			
		||||
      fi
 | 
			
		||||
      echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}$VMID${CL}"
 | 
			
		||||
      break
 | 
			
		||||
    else
 | 
			
		||||
      exit-script
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  if MACH=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "MACHINE TYPE" --radiolist --cancel-button Exit-Script "Choose Type" 10 58 2 \
 | 
			
		||||
    "i440fx" "Machine i440fx" ON \
 | 
			
		||||
    "q35" "Machine q35" OFF \
 | 
			
		||||
    3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ $MACH = q35 ]; then
 | 
			
		||||
      echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
 | 
			
		||||
      FORMAT=""
 | 
			
		||||
      MACHINE=" -machine q35"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}$MACH${CL}"
 | 
			
		||||
      FORMAT=",efitype=4m"
 | 
			
		||||
      MACHINE=""
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
  
 | 
			
		||||
  if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GiB (e.g., 10, 20)" 8 58 "$DISK_SIZE" --title "DISK SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    DISK_SIZE=$(echo "$DISK_SIZE" | tr -d ' ')
 | 
			
		||||
    if [[ "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
 | 
			
		||||
      DISK_SIZE="${DISK_SIZE}G"
 | 
			
		||||
      echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
 | 
			
		||||
    elif [[ "$DISK_SIZE" =~ ^[0-9]+G$ ]]; then
 | 
			
		||||
      echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}$DISK_SIZE${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${DISKSIZE}${BOLD}${RD}Invalid Disk Size. Please use a number (e.g., 10 or 10G).${CL}"
 | 
			
		||||
      exit-script
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
  
 | 
			
		||||
  if DISK_CACHE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISK CACHE" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
 | 
			
		||||
    "0" "None (Default)" ON \
 | 
			
		||||
    "1" "Write Through" OFF \
 | 
			
		||||
    3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ $DISK_CACHE = "1" ]; then
 | 
			
		||||
      echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}Write Through${CL}"
 | 
			
		||||
      DISK_CACHE="cache=writethrough,"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${DISKSIZE}${BOLD}${DGN}Disk Cache: ${BGN}None${CL}"
 | 
			
		||||
      DISK_CACHE=""
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if VM_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 arch-linux --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $VM_NAME ]; then
 | 
			
		||||
      HN="arch-linux"
 | 
			
		||||
      echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      HN=$(echo ${VM_NAME,,} | tr -d ' ')
 | 
			
		||||
      echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if CPU_TYPE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CPU MODEL" --radiolist "Choose" --cancel-button Exit-Script 10 58 2 \
 | 
			
		||||
    "0" "KVM64 (Default)" ON \
 | 
			
		||||
    "1" "Host" OFF \
 | 
			
		||||
    3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ $CPU_TYPE1 = "1" ]; then
 | 
			
		||||
      echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}Host${CL}"
 | 
			
		||||
      CPU_TYPE=" -cpu host"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${OS}${BOLD}${DGN}CPU Model: ${BGN}KVM64${CL}"
 | 
			
		||||
      CPU_TYPE=""
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 2 --title "CORE COUNT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $CORE_COUNT ]; then
 | 
			
		||||
      CORE_COUNT="2"
 | 
			
		||||
      echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 2048 --title "RAM" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $RAM_SIZE ]; then
 | 
			
		||||
      RAM_SIZE="2048"
 | 
			
		||||
      echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}$RAM_SIZE${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $BRG ]; then
 | 
			
		||||
      BRG="vmbr0"
 | 
			
		||||
      echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address" 8 58 $GEN_MAC --title "MAC ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $MAC1 ]; then
 | 
			
		||||
      MAC="$GEN_MAC"
 | 
			
		||||
      echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      MAC="$MAC1"
 | 
			
		||||
      echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for default)" 8 58 --title "VLAN" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $VLAN1 ]; then
 | 
			
		||||
      VLAN1="Default"
 | 
			
		||||
      VLAN=""
 | 
			
		||||
      echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      VLAN=",tag=$VLAN1"
 | 
			
		||||
      echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}$VLAN1${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default)" 8 58 --title "MTU SIZE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
 | 
			
		||||
    if [ -z $MTU1 ]; then
 | 
			
		||||
      MTU1="Default"
 | 
			
		||||
      MTU=""
 | 
			
		||||
      echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
 | 
			
		||||
    else
 | 
			
		||||
      MTU=",mtu=$MTU1"
 | 
			
		||||
      echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
 | 
			
		||||
    fi
 | 
			
		||||
  else
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
 | 
			
		||||
    echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
 | 
			
		||||
    START_VM="yes"
 | 
			
		||||
  else
 | 
			
		||||
    echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}no${CL}"
 | 
			
		||||
    START_VM="no"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS COMPLETE" --yesno "Ready to create a Arch Linux VM?" --no-button Do-Over 10 58); then
 | 
			
		||||
    echo -e "${CREATING}${BOLD}${DGN}Creating a Arch Linux VM using the above advanced settings${CL}"
 | 
			
		||||
  else
 | 
			
		||||
    header_info
 | 
			
		||||
    echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
 | 
			
		||||
    advanced_settings
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function start_script() {
 | 
			
		||||
  if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58); then
 | 
			
		||||
    header_info
 | 
			
		||||
    echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings${CL}"
 | 
			
		||||
    default_settings
 | 
			
		||||
  else
 | 
			
		||||
    header_info
 | 
			
		||||
    echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
 | 
			
		||||
    advanced_settings
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check_root
 | 
			
		||||
arch_check
 | 
			
		||||
pve_check
 | 
			
		||||
ssh_check
 | 
			
		||||
start_script
 | 
			
		||||
 | 
			
		||||
msg_info "Validating Storage"
 | 
			
		||||
while read -r line; do
 | 
			
		||||
  TAG=$(echo $line | awk '{print $1}')
 | 
			
		||||
  TYPE=$(echo $line | awk '{printf "%-10s", $2}')
 | 
			
		||||
  FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
 | 
			
		||||
  ITEM="  Type: $TYPE Free: $FREE "
 | 
			
		||||
  OFFSET=2
 | 
			
		||||
  if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
 | 
			
		||||
    MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
 | 
			
		||||
  fi
 | 
			
		||||
  STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
 | 
			
		||||
done < <(pvesm status -content images | awk 'NR>1')
 | 
			
		||||
VALID=$(pvesm status -content images | awk 'NR>1')
 | 
			
		||||
if [ -z "$VALID" ]; then
 | 
			
		||||
  msg_error "Unable to detect a valid storage location."
 | 
			
		||||
  exit
 | 
			
		||||
elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
  STORAGE=${STORAGE_MENU[0]}
 | 
			
		||||
else
 | 
			
		||||
  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 ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit
 | 
			
		||||
  done
 | 
			
		||||
fi
 | 
			
		||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
 | 
			
		||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
 | 
			
		||||
msg_info "Retrieving the URL for the Arch Linux .iso File"
 | 
			
		||||
URL=https://geo.mirror.pkgbuild.com/iso/latest/archlinux-x86_64.iso
 | 
			
		||||
sleep 2
 | 
			
		||||
msg_ok "${CL}${BL}${URL}${CL}"
 | 
			
		||||
wget -q --show-progress $URL
 | 
			
		||||
echo -en "\e[1A\e[0K"
 | 
			
		||||
FILE=$(basename $URL)
 | 
			
		||||
msg_ok "Downloaded ${CL}${BL}${FILE}${CL}"
 | 
			
		||||
 | 
			
		||||
STORAGE_TYPE=$(pvesm status -storage $STORAGE | awk 'NR>1 {print $2}')
 | 
			
		||||
case $STORAGE_TYPE in
 | 
			
		||||
nfs | dir | cifs)
 | 
			
		||||
  DISK_EXT=".qcow2"
 | 
			
		||||
  DISK_REF="$VMID/"
 | 
			
		||||
  DISK_IMPORT="-format qcow2"
 | 
			
		||||
  THIN=""
 | 
			
		||||
  ;;
 | 
			
		||||
btrfs)
 | 
			
		||||
  DISK_EXT=".raw"
 | 
			
		||||
  DISK_REF="$VMID/"
 | 
			
		||||
  DISK_IMPORT="-format raw"
 | 
			
		||||
  FORMAT=",efitype=4m"
 | 
			
		||||
  THIN=""
 | 
			
		||||
  ;;
 | 
			
		||||
esac
 | 
			
		||||
for i in {0,1}; do
 | 
			
		||||
  disk="DISK$i"
 | 
			
		||||
  eval DISK${i}=vm-${VMID}-disk-${i}${DISK_EXT:-}
 | 
			
		||||
  eval DISK${i}_REF=${STORAGE}:${DISK_REF:-}${!disk}
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
msg_info "Creating a Arch Linux VM"
 | 
			
		||||
qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE} -cores $CORE_COUNT -memory $RAM_SIZE \
 | 
			
		||||
  -name $HN -tags community-scripts -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
 | 
			
		||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
 | 
			
		||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
 | 
			
		||||
qm set $VMID \
 | 
			
		||||
  -efidisk0 ${DISK0_REF}${FORMAT} \
 | 
			
		||||
  -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
 | 
			
		||||
  -ide2 ${STORAGE}:cloudinit \
 | 
			
		||||
  -boot order=scsi0 \
 | 
			
		||||
  -serial0 socket >/dev/null
 | 
			
		||||
DESCRIPTION=$(
 | 
			
		||||
  cat <<EOF
 | 
			
		||||
<div align='center'>
 | 
			
		||||
  <a href='https://Helper-Scripts.com' target='_blank' rel='noopener noreferrer'>
 | 
			
		||||
    <img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
 | 
			
		||||
  </a>
 | 
			
		||||
 | 
			
		||||
  <h2 style='font-size: 24px; margin: 20px 0;'>Arch Linux VM</h2>
 | 
			
		||||
 | 
			
		||||
  <p style='margin: 16px 0;'>
 | 
			
		||||
    <a href='https://ko-fi.com/community_scripts' target='_blank' rel='noopener noreferrer'>
 | 
			
		||||
      <img src='https://img.shields.io/badge/☕-Buy us a coffee-blue' alt='spend Coffee' />
 | 
			
		||||
    </a>
 | 
			
		||||
  </p>
 | 
			
		||||
  
 | 
			
		||||
  <span style='margin: 0 10px;'>
 | 
			
		||||
    <i class="fa fa-github fa-fw" style="color: #f5f5f5;"></i>
 | 
			
		||||
    <a href='https://github.com/community-scripts/ProxmoxVE' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>GitHub</a>
 | 
			
		||||
  </span>
 | 
			
		||||
  <span style='margin: 0 10px;'>
 | 
			
		||||
    <i class="fa fa-comments fa-fw" style="color: #f5f5f5;"></i>
 | 
			
		||||
    <a href='https://github.com/community-scripts/ProxmoxVE/discussions' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Discussions</a>
 | 
			
		||||
  </span>
 | 
			
		||||
  <span style='margin: 0 10px;'>
 | 
			
		||||
    <i class="fa fa-exclamation-circle fa-fw" style="color: #f5f5f5;"></i>
 | 
			
		||||
    <a href='https://github.com/community-scripts/ProxmoxVE/issues' target='_blank' rel='noopener noreferrer' style='text-decoration: none; color: #00617f;'>Issues</a>
 | 
			
		||||
  </span>
 | 
			
		||||
</div>
 | 
			
		||||
EOF
 | 
			
		||||
)
 | 
			
		||||
qm set "$VMID" -description "$DESCRIPTION" >/dev/null
 | 
			
		||||
if [ -n "$DISK_SIZE" ]; then
 | 
			
		||||
    msg_info "Resizing disk to $DISK_SIZE GB"
 | 
			
		||||
    qm resize $VMID scsi0 ${DISK_SIZE} >/dev/null
 | 
			
		||||
else
 | 
			
		||||
    msg_info "Using default disk size of $DEFAULT_DISK_SIZE GB"
 | 
			
		||||
    qm resize $VMID scsi0 ${DEFAULT_DISK_SIZE} >/dev/null
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
msg_ok "Created a Arch Linux VM ${CL}${BL}(${HN})"
 | 
			
		||||
if [ "$START_VM" == "yes" ]; then
 | 
			
		||||
  msg_info "Starting Arch Linux VM"
 | 
			
		||||
  qm start $VMID
 | 
			
		||||
  msg_ok "Started Arch Linux VM"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
		Reference in New Issue
	
	Block a user