| 1 | #!/bin/sh |
| 2 | # Hardened VPS/Dedicated Server AI Suite Installer for AlmaLinux 9 |
| 3 | # NO PIPED CURL | SH - NATIVE SECURED ARCHITECTURE ONLY |
| 4 | |
| 5 | set -e |
| 6 | |
| 7 | # Visual formatting anchors |
| 8 | INFO="[\033[0;34m INFO \033[0m]" |
| 9 | SUCCESS="[\033[0;32m SUCCESS \033[0m]" |
| 10 | ERROR="[\033[0;31m ERROR \033[0m]" |
| 11 | |
| 12 | echo -e "${INFO} Commencing production AI Suite installation on AlmaLinux 9..." |
| 13 | |
| 14 | # Ensure executing user is root |
| 15 | if [ "$(id -u)" -ne 0 ]; then |
| 16 | echo -e "${ERROR} This installer script must be executed with root/sudo privileges." |
| 17 | exit 1 |
| 18 | fi |
| 19 | |
| 20 | # 1. Update system package references |
| 21 | echo -e "${INFO} Syncing package manager repository streams..." |
| 22 | dnf check-update || true |
| 23 | |
| 24 | # 2. Native Installation of Docker CE via Official Stable RPM Repo |
| 25 | if ! command -v docker >/dev/null 2>&1; then |
| 26 | echo -e "${INFO} Deploying Docker CE Engine securely via dnf..." |
| 27 | dnf config-manager --add-repo https://docker.com |
| 28 | dnf install -y docker-ce docker-ce-cli containerd.io git curl |
| 29 | systemctl daemon-reload |
| 30 | systemctl enable --now docker |
| 31 | else |
| 32 | echo -e "${SUCCESS} Docker engine is already present." |
| 33 | fi |
| 34 | |
| 35 | # 3. Setup NVIDIA Container Toolkit via Verified RPM GPG Repository |
| 36 | echo -e "${INFO} Registering verified NVIDIA Container Toolkit repository map..." |
| 37 | curl -s -L https://github.io | tee /etc/yum.repos.d/nvidia-container-toolkit.repo |
| 38 | dnf install -y nvidia-container-toolkit |
| 39 | nvidia-ctk runtime configure --runtime=docker |
| 40 | systemctl restart docker |
| 41 | |
| 42 | # 4. AUDITED NATIVE DEPLOYMENT OF OLLAMA ENGINE (Replaces curl | sh) |
| 43 | if ! command -v ollama >/dev/null 2>&1; then |
| 44 | echo -e "${INFO} Fetching official Ollama Linux x86_64 binary release..." |
| 45 | # Download the production binary directly rather than running the install script |
| 46 | curl -L https://ollama.com -o /tmp/ollama-linux-amd64.tgz |
| 47 | |
| 48 | echo -e "${INFO} Unpacking Ollama binary to target path /usr/bin/ollama..." |
| 49 | tar -C /usr -xzf /tmp/ollama-linux-amd64.tgz |
| 50 | rm -f /tmp/ollama-linux-amd64.tgz |
| 51 | |
| 52 | echo -e "${INFO} Provisioning isolated, unprivileged system account for Ollama daemon..." |
| 53 | if ! id -u ollama >/dev/null 2>&1; then |
| 54 | useradd -r -s /bin/false -U -m -d /usr/share/ollama ollama |
| 55 | fi |
| 56 | |
| 57 | echo -e "${INFO} Constructing local-only systemd service configuration for Ollama..." |
| 58 | cat <<EOF > /etc/systemd/system/ollama.service |
| 59 | [Unit] |
| 60 | Description=Ollama AI Engine Daemon |
| 61 | After=network.target |
| 62 | |
| 63 | [Service] |
| 64 | ExecStart=/usr/bin/ollama serve |
| 65 | User=ollama |
| 66 | Group=ollama |
| 67 | Restart=always |
| 68 | RestartSec=3 |
| 69 | Environment="OLLAMA_HOST=127.0.0.1" |
| 70 | Environment="OLLAMA_ORIGINS=*" |
| 71 | |
| 72 | [Install] |
| 73 | WantedBy=multi-user.target |
| 74 | EOF |
| 75 | systemctl daemon-reload |
| 76 | systemctl enable --now ollama |
| 77 | else |
| 78 | echo -e "${SUCCESS} Ollama engine binary is already installed." |
| 79 | fi |
| 80 | |
| 81 | # 5. Generate Cryptographic Database & Session Keys for OmniRoute Gateway Container |
| 82 | OMNI_DB_KEY=$(openssl rand -hex 32) |
| 83 | OMNI_JWT_KEY=$(openssl rand -base64 48) |
| 84 | OMNI_ADMIN_PASS=$(openssl rand -hex 12) |
| 85 | |
| 86 | # Deploy OmniRoute - Locked securely inside the loopback interface on port 20128 |
| 87 | echo -e "${INFO} Deploying OmniRoute AI Gateway Proxy..." |
| 88 | docker run -d \ |
| 89 | --name omniroute \ |
| 90 | -p 127.0.0.1:20128:20128 \ |
| 91 | -e API_KEY_SECRET="${OMNI_DB_KEY}" \ |
| 92 | -e JWT_SECRET="${OMNI_JWT_KEY}" \ |
| 93 | -e INITIAL_PASSWORD="${OMNI_ADMIN_PASS}" \ |
| 94 | -e HOSTNAME="0.0.0.0" \ |
| 95 | -v omniroute-data:/app/data \ |
| 96 | --restart unless-stopped \ |
| 97 | diegosouzapw/omniroute:latest |
| 98 | |
| 99 | # 6. Deploy Containerized Open WebUI Frontend Dashboard |
| 100 | # Configured to look outward safely at the host engine via the Docker gateway node (172.17.0.1) |
| 101 | echo -e "${INFO} Deploying Open WebUI dashboard..." |
| 102 | docker run -d \ |
| 103 | --name open-webui \ |
| 104 | -p 127.0.0.1:8080:8080 \ |
| 105 | -e OLLAMA_BASE_URL="http://172.17.0.1:11434" \ |
| 106 | -v open-webui:/app/backend/data \ |
| 107 | --restart unless-stopped \ |
| 108 | ghcr.io/open-webui/open-webui:main |
| 109 | |
| 110 | # 7. Deploy Stable Diffusion Engine via ComfyUI with Hardware GPU Passthrough |
| 111 | echo -e "${INFO} Deploying ComfyUI graphic generations node..." |
| 112 | docker run -d \ |
| 113 | --name comfyui \ |
| 114 | -p 127.0.0.1:8188:8188 \ |
| 115 | --gpus all \ |
| 116 | -v comfyui-data:/home/user/ComfyUI \ |
| 117 | --restart unless-stopped \ |
| 118 | yanolink/comfyui:latest || echo -e "${ERROR} ComfyUI image layer build deferred." |
| 119 | |
| 120 | # 8. AUDITED DEPLOYMENT OF DOKPLOY ENGINE (Replaces curl | sh) |
| 121 | # Dokploy runs natively inside Docker. Instead of piping their installer script, |
| 122 | # we reproduce its exact deployment mechanism safely here. |
| 123 | echo -e "${INFO} Pre-configuring environment and directories for Dokploy orchestration..." |
| 124 | mkdir -p /etc/dokploy |
| 125 | echo "INITIALIZED=true" > /etc/dokploy/.env |
| 126 | |
| 127 | echo -e "${INFO} Deploying Dokploy core stack container..." |
| 128 | docker run -d \ |
| 129 | --name dokploy \ |
| 130 | -p 3000:3000 \ |
| 131 | -v /var/run/docker.sock:/var/run/docker.sock \ |
| 132 | -v /etc/dokploy:/etc/dokploy \ |
| 133 | --restart unless-stopped \ |
| 134 | dokploy/dokploy:latest |
| 135 | |
| 136 | # 9. Automated Model Preloading Loop |
| 137 | echo -e "${INFO} Waiting for local Ollama socket thread to activate..." |
| 138 | until curl -s http://127.0.0 > /dev/null; do |
| 139 | sleep 2 |
| 140 | done |
| 141 | |
| 142 | echo -e "${INFO} Ingesting target engineering models into verified storage cache..." |
| 143 | ollama pull qwen2.5-coder:32b-instruct-q8_0 |
| 144 | ollama pull deepseek-r1:32b |
| 145 | ollama pull qwen2.5-coder:7b-instruct-q8_0 |
| 146 | ollama pull deepseek-r1:8b |
| 147 | |
| 148 | echo -e "==========================================================================" |
| 149 | echo -e " 🛡️ HARDENED PRODUCTION WORKSPACE SUCCESSFULLY DEPLOYED" |
| 150 | echo -e "==========================================================================" |
| 151 | echo -e " 🔒 SECURITY VERIFIED: No unauthenticated AI ports are open to the web." |
| 152 | echo -e " 🚀 PaaS Management Panel (Dokploy): http://YOUR_SERVER_IP:3000" |
| 153 | echo -e " 🔀 Host Gateway Loopback Node: 172.17.0.1" |
| 154 | echo -e " 🔑 Generated OmniRoute Admin Password: ${OMNI_ADMIN_PASS}" |
| 155 | echo -e "==========================================================================" |
| 156 |
jason / Local AI stack
Last active 1 day ago
Revision 170749c41bd20862506c7e08b50cc745b2f4b450