Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ The script guides you through a simplified menu to perform the following:

| Action | Description |
| :--- | :--- |
| **Install Docker Engine** | Downloads the official installer to a temp file, then runs it (never `curl \| sh`) |
| **Install Docker Engine** | On Alpine, installs via `apk` from the community repo; elsewhere downloads the official installer to a temp file and runs it (never `curl \| sh`) |
| **User Configuration** | Creates a new user specifically for Docker or adds your current user |
| **Security Groups** | Adds the selected user to the `docker` group for non-root command execution |
| **Portainer Deployment** | Pulls and runs Portainer CE pinned to a verified image digest from the LTS release channel on port 9443 |
Expand Down
184 changes: 153 additions & 31 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,132 @@ execute_script() {
fi
}

# detect_distro_id returns the OS ID from /etc/os-release (e.g. alpine, ubuntu).
detect_distro_id() {
if [[ -f /etc/os-release ]]; then
awk -F= '/^ID=/{gsub(/"/, "", $2); print $2; exit}' /etc/os-release
else
printf '%s\n' "unknown"
fi
}

# enable_docker_service enables and starts the Docker daemon via systemd or OpenRC.
# Returns nonzero if enable/start fails or neither init system is available.
enable_docker_service() {
local SUDO="${1:-}"

if command -v systemctl >/dev/null 2>&1; then
if ! $SUDO systemctl enable docker; then
print_error "Failed to enable Docker service."
return 1
fi
if ! $SUDO systemctl start docker; then
print_error "Failed to start Docker service."
return 1
fi
print_success "Docker service enabled and started."
return 0
fi

if command -v rc-update >/dev/null 2>&1; then
if ! $SUDO rc-update add docker default; then
print_error "Failed to enable Docker service."
return 1
fi
if command -v rc-service >/dev/null 2>&1; then
if ! $SUDO rc-service docker start; then
print_error "Failed to start Docker service."
return 1
fi
elif command -v service >/dev/null 2>&1; then
if ! $SUDO service docker start; then
print_error "Failed to start Docker service."
return 1
fi
else
print_error "No OpenRC service command found to start Docker."
return 1
fi
print_success "Docker service enabled and started."
return 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
fi

print_error "Could not detect systemd or OpenRC; start Docker manually."
return 1
}

# install_docker_alpine installs Docker Engine and Compose from Alpine community packages.
install_docker_alpine() {
local SUDO="${1:-}"
local alpine_version repo_url exit_code

print_status "Alpine detected — using apk (get.docker.com does not support Alpine)."
print_line "-" "$BLUE"

if [[ ! -f /etc/alpine-release ]]; then
print_error "Alpine release file not found."
return 1
fi

alpine_version=$(cut -d'.' -f1,2 /etc/alpine-release)
repo_url="https://dl-cdn.alpinelinux.org/alpine/v${alpine_version}/community"

if ! grep -qE '/alpine/(v[^/]+|edge)/community' /etc/apk/repositories 2>/dev/null; then
print_status "Enabling Alpine community repository..."
echo "$repo_url" | $SUDO tee -a /etc/apk/repositories >/dev/null
fi

print_status "Installing Docker & Compose via apk..."
exit_code=0
$SUDO apk update || exit_code=$?
if [[ $exit_code -eq 0 ]]; then
$SUDO apk add docker docker-cli-compose || exit_code=$?
fi

if [[ $exit_code -ne 0 ]]; then
print_error "Docker installation failed."
return "$exit_code"
fi

print_success "Docker installed successfully!"
if ! enable_docker_service "$SUDO"; then
return 1
fi
return 0
}

# install_docker_official downloads get.docker.com to a temp file, then executes that file.
install_docker_official() {
local SUDO="${1:-}"
local installer_path exit_code download_status

print_status "Using official Docker installation script..."
print_line "-" "$BLUE"

installer_path=$(mktemp "${TMPDIR:-/tmp}/get-docker.XXXXXXXX.sh")
if curl -fsSL https://get.docker.com -o "$installer_path"; then
exit_code=0
$SUDO sh "$installer_path" || exit_code=$?
rm -f "$installer_path"

if [[ $exit_code -eq 0 ]]; then
print_success "Docker installed successfully!"
if ! enable_docker_service "$SUDO"; then
return 1
fi
return 0
fi

print_error "Docker installation failed."
return "$exit_code"
fi

download_status=$?
rm -f "$installer_path"
print_error "Failed to download Docker installation script."
return "$download_status"
}

install_docker() {
echo ""
print_status "Installing Docker Engine..."
Expand Down Expand Up @@ -479,37 +605,19 @@ install_docker() {
SUDO="sudo"
fi

print_status "Using official Docker installation script..."
print_line "-" "$BLUE"
local distro_id exit_code
distro_id=$(detect_distro_id)
exit_code=0

# Download the installer to a temp file, then execute that file.
local installer_path exit_code download_status
installer_path=$(mktemp "${TMPDIR:-/tmp}/get-docker.XXXXXXXX.sh")
if curl -fsSL https://get.docker.com -o "$installer_path"; then
exit_code=0
$SUDO sh "$installer_path" || exit_code=$?
rm -f "$installer_path"

if [[ $exit_code -eq 0 ]]; then
print_success "Docker installed successfully!"

# Enable and start Docker
if command -v systemctl >/dev/null 2>&1; then
$SUDO systemctl enable docker 2>/dev/null || true
$SUDO systemctl start docker 2>/dev/null || true
print_success "Docker service enabled and started."
fi
else
print_error "Docker installation failed."
pause
return "$exit_code"
fi
if [[ "$distro_id" == "alpine" ]]; then
install_docker_alpine "$SUDO" || exit_code=$?
else
download_status=$?
rm -f "$installer_path"
print_error "Failed to download Docker installation script."
install_docker_official "$SUDO" || exit_code=$?
fi

if [[ $exit_code -ne 0 ]]; then
pause
return "$download_status"
return "$exit_code"
fi

pause
Expand Down Expand Up @@ -555,14 +663,28 @@ add_user_to_docker_group() {
local SUDO=""
fi

local distro_id
distro_id=$(detect_distro_id)

# Ensure docker group exists
if ! getent group docker >/dev/null 2>&1; then
print_status "Creating docker group..."
$SUDO groupadd docker
if [[ "$distro_id" == "alpine" ]]; then
$SUDO addgroup docker
else
$SUDO groupadd docker
fi
fi

# Add user to group (Alpine uses addgroup; others use usermod)
local group_ok=0
if [[ "$distro_id" == "alpine" ]]; then
$SUDO addgroup "$current_user" docker && group_ok=1
else
$SUDO usermod -aG docker "$current_user" && group_ok=1
fi

# Add user to group
if $SUDO usermod -aG docker "$current_user"; then
if [[ $group_ok -eq 1 ]]; then
print_success "User '$current_user' added to docker group."
echo ""
print_warn "You must log out and back in for this to take effect."
Expand Down
16 changes: 16 additions & 0 deletions tests/security-checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ if ! grep -Eq '^VERSION="2\.[0-9]+\.[0-9]+"' install.sh; then
exit 1
fi

if ! grep -q 'apk add docker docker-cli-compose' install.sh; then
echo "install.sh Alpine path must install docker and docker-cli-compose via apk." >&2
exit 1
fi

# Alpine / non-Alpine branches must call the matching installer (not merely define it).
if ! rg -U -q '\[\[ "\$distro_id" == "alpine" \]\]; then[[:space:]]+install_docker_alpine "\$SUDO"' install.sh; then
echo 'Alpine distro_id branch must call install_docker_alpine "$SUDO".' >&2
exit 1
fi

if ! rg -U --multiline-dotall -q '\[\[ "\$distro_id" == "alpine" \]\]; then[[:space:]]+install_docker_alpine "\$SUDO".*else[[:space:]]+install_docker_official "\$SUDO"' install.sh; then
echo 'Non-Alpine distro_id branch must call install_docker_official "$SUDO".' >&2
exit 1
fi

if rg -n 'git clean[[:space:]]+-[^[:space:]]*f' install.sh; then
echo "Broad destructive git clean is forbidden." >&2
exit 1
Expand Down
Loading