Skip to content

Commit 0b5767c

Browse files
authored
Merge branch 'main' into feature/ollama-openwebui
2 parents 6ffbc57 + ea1702a commit 0b5767c

8 files changed

Lines changed: 691 additions & 22 deletions

File tree

lib/constants.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,12 @@
112112
OLLAMA_PERMA_MOUNTS: List[str] = [
113113
"pseudohome",
114114
"projects",
115-
]
115+
]
116+
117+
# Firewall module:
118+
FIREWALL_SCRIPT_DEST: str = "/usr/local/bin/apply-firewall.sh"
119+
FIREWALL_SERVICE_NAME: str = "firewall.service"
120+
FIREWALL_CONF_DIR: str = "/etc/iptables"
121+
# iptables and ip6tables are standard, but we ensure iptables-persistent
122+
# directory structure exists for our own script's logic.
123+
FIREWALL_PACKAGES: List[str] = ["iptables", "curl"]

lib/installer_utils/module_docker.py

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import shutil
22
import platform
33
import os
4-
from typing import List, Optional, Union
4+
from typing import List, Optional, Union, Dict
55
import subprocess
66

77
from ..executor import Executor
@@ -10,6 +10,24 @@
1010
from .apt_tools import apt_install, ensure_apt_repo
1111
from .user_mgmt import add_user_to_group
1212

13+
def _get_os_release() -> Dict[str, str]:
14+
"""
15+
Parses /etc/os-release into a dictionary natively.
16+
Replaces brittle shell 'grep/cut/tr' with robust Python string matching.
17+
"""
18+
info = {}
19+
try:
20+
if os.path.exists("/etc/os-release"):
21+
with open("/etc/os-release") as f:
22+
for line in f:
23+
if "=" in line:
24+
key, value = line.rstrip().split("=", 1)
25+
# Remove surrounding quotes often found in these files
26+
info[key] = value.strip('"')
27+
except Exception as e:
28+
log.error(f"Failed to read /etc/os-release: {e}")
29+
return info
30+
1331
def _remove_old_docker(exec_obj: Executor) -> None:
1432
"""
1533
Removes old, conflicting, or manually installed Docker packages
@@ -48,7 +66,12 @@ def _remove_old_docker(exec_obj: Executor) -> None:
4866
def install_docker_and_add_users(exec_obj: Executor, *users_to_add: str) -> None:
4967
"""
5068
Installs Docker packages, starts the service, and adds users to the 'docker' group.
69+
Supports both Ubuntu and Debian automatically.
5170
"""
71+
# Safeguard for macOS
72+
if platform.system().lower() == "darwin":
73+
log.warning("Docker Engine installation is not supported on macOS via this orchestrator.")
74+
return
5275

5376
if shutil.which("docker"):
5477
log.success("Docker binary detected, skipping installation steps.")
@@ -62,32 +85,33 @@ def install_docker_and_add_users(exec_obj: Executor, *users_to_add: str) -> None
6285
# DOCKER_DEPS includes ca-certificates and lsb-release
6386
apt_install(exec_obj, DOCKER_DEPS)
6487

88+
# 1. Detect OS details using Python dictionary matching
89+
os_info = _get_os_release()
90+
os_id = os_info.get("ID") # e.g., 'ubuntu' or 'debian'
91+
codename = os_info.get("VERSION_CODENAME") # e.g., 'noble' or 'bookworm'
92+
93+
if not os_id or not codename:
94+
log.critical("Could not detect OS ID or Codename from /etc/os-release. Aborting Docker setup.")
95+
raise RuntimeError("Cannot proceed without distribution details.")
96+
97+
log.info(f"Detected OS: {os_id}, Codename: {codename}")
98+
6599
keyrings_dir = "/etc/apt/keyrings"
66-
docker_gpg_path = os.path.join(keyrings_dir, "docker.asc") # Official script uses docker.asc
100+
docker_gpg_path = os.path.join(keyrings_dir, "docker.gpg") # Modern standard uses .gpg binary
67101
list_file = "/etc/apt/sources.list.d/docker.list"
68102

69103
exec_obj.run(f"mkdir -p {keyrings_dir}", force_sudo=True)
70104

71105
if not os.path.exists(docker_gpg_path):
72-
log.info("Downloading and adding Docker GPG key.")
73-
# Note: We use docker.asc file name for consistency with Docker's script output
74-
curl_cmd = f"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o {docker_gpg_path}"
106+
log.info(f"Downloading and adding Docker GPG key for {os_id}.")
107+
# Note: We use gpg --dearmor to ensure a binary .gpg file for /etc/apt/keyrings compatibility
108+
curl_cmd = f"curl -fsSL https://download.docker.com/linux/{os_id}/gpg | gpg --dearmor -o {docker_gpg_path}"
75109
exec_obj.run(curl_cmd, force_sudo=True)
76110
# Ensure proper read permissions for apt
77111
exec_obj.run(f"chmod a+r {docker_gpg_path}", force_sudo=True)
78112
else:
79113
log.info("Docker GPG key already exists.")
80114

81-
# 1. Get Distribution Codename robustly
82-
try:
83-
result = exec_obj.run("lsb_release -cs", check=True, run_quiet=True)
84-
codename = result.stdout.strip()
85-
log.info(f"Detected distribution codename: {codename}")
86-
except Exception as e:
87-
log.critical("Failed to determine Linux distribution codename (lsb_release -cs failed). Aborting Docker setup.")
88-
log.debug(f"lsb_release error: {e}")
89-
raise RuntimeError("Cannot proceed without distribution codename.")
90-
91115
arch = platform.machine()
92116

93117
# --- FIX: Architecture Correction (aarch64 -> arm64) ---
@@ -96,11 +120,9 @@ def install_docker_and_add_users(exec_obj: Executor, *users_to_add: str) -> None
96120
display_arch = 'arm64'
97121
else:
98122
display_arch = arch
99-
100-
effective_codename = codename # Trust the detected codename
101123

102-
# 2. Interpolate the correct codename and arch into the repository line
103-
repo_line = f"deb [arch={display_arch} signed-by={docker_gpg_path}] https://download.docker.com/linux/ubuntu {effective_codename} stable"
124+
# 2. Interpolate the correct ID, codename and arch into the repository line
125+
repo_line = f"deb [arch={display_arch} signed-by={docker_gpg_path}] https://download.docker.com/linux/{os_id} {codename} stable"
104126

105127
log.info(f"Using APT repository line: {repo_line}")
106128
ensure_apt_repo(exec_obj, list_file, repo_line)

0 commit comments

Comments
 (0)