Teach the installer to detect and configure Docker or Podman.
Release rolling / release (push) Successful in 7m55s
Release rolling / release (push) Successful in 7m55s
Auto-select the engine, set socket group permissions (including Debian podman.socket drop-ins), write PEARDOCK_ENGINE into .env, and generate a matching systemd unit for the chosen runtime.
This commit is contained in:
@@ -34,8 +34,10 @@ curl -fsSL https://install.peardock.boats | bash
|
||||
Non-interactive:
|
||||
|
||||
```bash
|
||||
# Server (Linux → /opt/peardock + peardock.service + docker group)
|
||||
# Server (Linux → /opt/peardock + peardock.service; auto-detects Docker or Podman)
|
||||
curl -fsSL https://install.peardock.boats | bash -s -- --server --yes
|
||||
# Force Podman (rootful socket + group permissions):
|
||||
# curl -fsSL https://install.peardock.boats | bash -s -- --server --yes --engine podman
|
||||
|
||||
# Desktop client (Linux or macOS)
|
||||
curl -fsSL https://install.peardock.boats | bash -s -- --client --yes
|
||||
|
||||
+13
-8
@@ -1,11 +1,12 @@
|
||||
[Unit]
|
||||
Description=peardock HyperDHT Docker control plane
|
||||
Description=peardock HyperDHT container control plane
|
||||
Documentation=https://git.ssh.surf/snxraven/peardock
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
# Soft-depend on Docker / Podman (either socket is enough)
|
||||
# Soft-depend on Docker and/or Podman (installer rewrites After=/Wants= for the selected engine)
|
||||
Wants=docker.service
|
||||
# Rootful Podman API (optional; ignore if unit missing)
|
||||
# Rootful Podman API — uncomment or let install.sh set this when PEARDOCK_ENGINE=podman:
|
||||
# After=podman.socket
|
||||
# Wants=podman.socket
|
||||
|
||||
[Service]
|
||||
@@ -24,22 +25,26 @@ NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
|
||||
User=peardock
|
||||
# install.sh sets Group/SupplementaryGroups to the socket group (docker or podman)
|
||||
Group=docker
|
||||
SupplementaryGroups=docker
|
||||
|
||||
Environment=NODE_ENV=production
|
||||
EnvironmentFile=-/opt/peardock/.env
|
||||
# Installer also writes PEARDOCK_ENGINE / DOCKER_HOST into .env and may set:
|
||||
# Environment=PEARDOCK_ENGINE=podman
|
||||
# Environment=DOCKER_HOST=unix:///run/podman/podman.sock
|
||||
# Environment=CONTAINER_HOST=unix:///run/podman/podman.sock
|
||||
# Environment=DOCKER_API_VERSION=v1.41
|
||||
#
|
||||
# Example production knobs (prefer .env):
|
||||
# Environment=PEARDOCK_DEFAULT_ROLE=operator
|
||||
# Environment=PEARDOCK_PEER_ALLOWLIST=1
|
||||
# Environment=PEARDOCK_ENGINE=podman
|
||||
# Environment=DOCKER_HOST=unix:///run/podman/podman.sock
|
||||
# Swarm + Holesail are on by default (Docker); Swarm is always off on Podman
|
||||
# Environment=ENABLE_SWARM=0
|
||||
# Environment=ENABLE_HOLESAIL=0
|
||||
# Environment=DOCKER_API_VERSION=v1.41
|
||||
|
||||
ReadWritePaths=/opt/peardock
|
||||
# State dir + common engine sockets (Docker + Podman rootful)
|
||||
ReadWritePaths=/opt/peardock /var/run/docker.sock /run/docker.sock /run/podman/podman.sock /var/run/podman/podman.sock
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
+52
-6
@@ -6,19 +6,52 @@ Architecture and code docs: [README.md](./README.md) (hub) · [ARCHITECTURE.md](
|
||||
|
||||
## Recommended: one-line installer
|
||||
|
||||
On a Linux host with Docker already installed:
|
||||
On a Linux host with **Docker and/or Podman**:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://install.peardock.boats | bash -s -- --server --yes
|
||||
```
|
||||
|
||||
This downloads the Bare server binary from the **`rolling`** release, creates user `peardock`, adds it to the **docker** group, writes `/etc/systemd/system/peardock.service`, and can enable the service.
|
||||
The installer:
|
||||
|
||||
1. Downloads the Bare server binary from the **`rolling`** release
|
||||
2. Creates system user `peardock`
|
||||
3. **Detects** Docker and Podman sockets (and can enable `docker` / `podman.socket`)
|
||||
4. Configures **socket group permissions** (docker or podman) for Debian/Ubuntu, RHEL/Fedora, etc.
|
||||
5. Writes `/opt/peardock/.env` with `PEARDOCK_ENGINE` + `DOCKER_HOST`
|
||||
6. Installs `/etc/systemd/system/peardock.service` with the correct group and socket paths
|
||||
7. Optionally enables and starts the service
|
||||
|
||||
```bash
|
||||
# Prefer Docker (default auto order: Docker → Podman)
|
||||
curl -fsSL https://install.peardock.boats | bash -s -- --server --yes --engine docker
|
||||
|
||||
# Prefer / force Podman (rootful socket + group drop-in)
|
||||
curl -fsSL https://install.peardock.boats | bash -s -- --server --yes --engine podman
|
||||
# or: PEARDOCK_ENGINE=podman bash … --server --yes
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl status peardock
|
||||
sudo journalctl -u peardock -f
|
||||
```
|
||||
|
||||
### Debian / Ubuntu notes
|
||||
|
||||
| Engine | Packages / enable | Installer behavior |
|
||||
|--------|-------------------|--------------------|
|
||||
| Docker | `sudo apt install docker.io` then `sudo systemctl enable --now docker` | Adds `peardock` to group **`docker`**, socket usually `/var/run/docker.sock` |
|
||||
| Podman | `sudo apt install podman` then socket unit available | Enables **`podman.socket`**, creates group **`podman`**, installs drop-in `SocketGroup=podman` + `SocketMode=0660` under `/etc/systemd/system/podman.socket.d/peardock.conf`, adds `peardock` to `podman` |
|
||||
|
||||
Without the drop-in, rootful Podman sockets are often `root:root` mode `660` and the `peardock` user cannot connect.
|
||||
|
||||
```bash
|
||||
sudo systemctl status peardock
|
||||
sudo journalctl -u peardock -f
|
||||
# Engine wiring:
|
||||
sudo grep -E '^(PEARDOCK_ENGINE|DOCKER_HOST)=' /opt/peardock/.env
|
||||
```
|
||||
|
||||
### Keys: check `/opt/peardock/.env`
|
||||
|
||||
On first successful start the server writes identity into the env file (mode 600):
|
||||
@@ -54,16 +87,29 @@ Flags and Windows notes: [peardock.boats/download](https://peardock.boats/downlo
|
||||
|
||||
Unit source of truth: [`deploy/peardock.service`](../deploy/peardock.service).
|
||||
|
||||
## Docker group / socket access
|
||||
## Engine group / socket access
|
||||
|
||||
Engine sockets are typically `root:docker` mode `660`. The service **must** run as a user in group `docker` (or the socket’s group).
|
||||
Engine sockets are typically mode `660` and owned by a dedicated group. The service **must** run as a user in that group.
|
||||
|
||||
| Engine | Typical socket | Typical group |
|
||||
|--------|----------------|---------------|
|
||||
| Docker | `/var/run/docker.sock` | `docker` |
|
||||
| Podman (rootful) | `/run/podman/podman.sock` | `podman` (installer drop-in) |
|
||||
|
||||
```bash
|
||||
# Installer does this; manual recovery:
|
||||
# Installer does this; manual recovery — Docker:
|
||||
sudo usermod -aG docker peardock
|
||||
# if docker group was just created, restart Docker once
|
||||
sudo systemctl restart docker
|
||||
sudo systemctl restart peardock
|
||||
|
||||
# Manual recovery — Podman (rootful):
|
||||
sudo groupadd --system podman 2>/dev/null || true
|
||||
sudo usermod -aG podman peardock
|
||||
sudo mkdir -p /etc/systemd/system/podman.socket.d
|
||||
# SocketGroup=podman + SocketMode=0660 (see install.sh)
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now podman.socket
|
||||
sudo systemctl restart peardock
|
||||
```
|
||||
|
||||
Symptoms of a missing group: empty container lists, start failures, “permission denied” on the socket.
|
||||
|
||||
+587
-80
@@ -17,6 +17,7 @@
|
||||
# PEARDOCK_SERVER_DIR=/opt/peardock
|
||||
# PEARDOCK_CLIENT_DIR=... (default: ~/.local/share/peardock or ~/Applications)
|
||||
# PEARDOCK_YES=1 — assume defaults / non-interactive where possible
|
||||
# PEARDOCK_ENGINE=auto|docker|podman — container engine preference (server)
|
||||
#
|
||||
# Canonical install host: https://install.peardock.boats (serves this script)
|
||||
# Site: https://peardock.boats
|
||||
@@ -35,6 +36,15 @@ SERVER_DIR="${PEARDOCK_SERVER_DIR:-/opt/peardock}"
|
||||
TMPDIR_ROOT="${TMPDIR:-/tmp}"
|
||||
INSTALL_TMP=""
|
||||
CHANNEL="${PEARDOCK_CHANNEL:-stable}" # reserved
|
||||
# auto | docker | podman — resolved during server install
|
||||
ENGINE_PREF="${PEARDOCK_ENGINE:-auto}"
|
||||
# Filled by detect_container_engines / ensure_container_engine_access
|
||||
PEARDOCK_ENGINE_KIND=""
|
||||
PEARDOCK_ENGINE_SOCK=""
|
||||
PEARDOCK_ENGINE_GROUP=""
|
||||
PEARDOCK_ENGINE_LABEL=""
|
||||
PEARDOCK_DISTRO=""
|
||||
PEARDOCK_DISTRO_LIKE=""
|
||||
|
||||
# ─── colors / UI ────────────────────────────────────────────────────────────
|
||||
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1 && [[ $(tput colors 2>/dev/null || echo 0) -ge 8 ]]; then
|
||||
@@ -114,6 +124,10 @@ parse_args() {
|
||||
--tag) TAG="${2:-}"; shift 2 ;;
|
||||
--version) VERSION="${2:-}"; shift 2 ;;
|
||||
--server-dir) SERVER_DIR="${2:-}"; shift 2 ;;
|
||||
--engine)
|
||||
ENGINE_PREF="${2:-auto}"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
cat <<EOF
|
||||
Usage: install.sh [options]
|
||||
@@ -125,8 +139,13 @@ Usage: install.sh [options]
|
||||
--tag TAG Release tag (default: rolling)
|
||||
--version VER Pin asset version (default: auto from release)
|
||||
--server-dir DIR Server install path (default: /opt/peardock)
|
||||
--engine KIND Container engine: auto (default), docker, or podman
|
||||
--help This help
|
||||
|
||||
Env:
|
||||
PEARDOCK_ENGINE=auto|docker|podman
|
||||
PEARDOCK_YES=1 non-interactive
|
||||
|
||||
One-liner:
|
||||
curl -fsSL https://install.peardock.boats | bash
|
||||
EOF
|
||||
@@ -263,48 +282,274 @@ asset_url() {
|
||||
echo "${GITEA_URL}/${OWNER}/${REPO}/releases/download/${TAG}/${name}"
|
||||
}
|
||||
|
||||
# ─── docker group / socket access ───────────────────────────────────────────
|
||||
# Engine socket is typically root:docker mode 660. peardock.service runs as
|
||||
# User=peardock and must be a docker group member (SupplementaryGroups=docker).
|
||||
ensure_peardock_docker_group() {
|
||||
local sock="${DOCKER_HOST:-}"
|
||||
local grp="docker"
|
||||
|
||||
# Normalize DOCKER_HOST=unix:///var/run/docker.sock → path
|
||||
if [[ -z "$sock" || "$sock" == unix://* || "$sock" == /* ]]; then
|
||||
sock="${sock#unix://}"
|
||||
sock="${sock:-/var/run/docker.sock}"
|
||||
else
|
||||
# tcp://… — group membership not required for local socket, but still useful
|
||||
sock="/var/run/docker.sock"
|
||||
# ─── distro / container engine detection ─────────────────────────────────────
|
||||
detect_distro() {
|
||||
PEARDOCK_DISTRO="unknown"
|
||||
PEARDOCK_DISTRO_LIKE=""
|
||||
if [[ -r /etc/os-release ]]; then
|
||||
# shellcheck disable=SC1091
|
||||
. /etc/os-release
|
||||
PEARDOCK_DISTRO="${ID:-unknown}"
|
||||
PEARDOCK_DISTRO_LIKE="${ID_LIKE:-}"
|
||||
elif [[ -r /etc/debian_version ]]; then
|
||||
PEARDOCK_DISTRO="debian"
|
||||
PEARDOCK_DISTRO_LIKE="debian"
|
||||
fi
|
||||
export PEARDOCK_DISTRO PEARDOCK_DISTRO_LIKE
|
||||
}
|
||||
|
||||
if [[ ! -S "$sock" ]]; then
|
||||
warn "Docker socket not found at ${sock}"
|
||||
warn "Install/start Docker, then re-run: sudo usermod -aG docker peardock && sudo systemctl restart peardock"
|
||||
is_debian_family() {
|
||||
case "${PEARDOCK_DISTRO}" in
|
||||
debian|ubuntu|raspbian|linuxmint|pop|elementary|zorin|kali|parrot) return 0 ;;
|
||||
esac
|
||||
case " ${PEARDOCK_DISTRO_LIKE} " in
|
||||
*" debian "*|*" ubuntu "*) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
is_rhel_family() {
|
||||
case "${PEARDOCK_DISTRO}" in
|
||||
rhel|centos|fedora|rocky|almalinux|ol|amzn|nobara) return 0 ;;
|
||||
esac
|
||||
case " ${PEARDOCK_DISTRO_LIKE} " in
|
||||
*" rhel "*|*" fedora "*|*" centos "*) return 0 ;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
nologin_shell() {
|
||||
for s in /usr/sbin/nologin /sbin/nologin /bin/false /usr/bin/nologin; do
|
||||
if [[ -x "$s" ]]; then
|
||||
echo "$s"
|
||||
return
|
||||
fi
|
||||
done
|
||||
echo /bin/false
|
||||
}
|
||||
|
||||
# Normalize DOCKER_HOST / path to a bare unix path (or empty).
|
||||
normalize_unix_sock() {
|
||||
local raw="${1:-}"
|
||||
raw="${raw#unix://}"
|
||||
if [[ -z "$raw" ]]; then
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
if [[ "$raw" == /* || "$raw" == //./pipe/* ]]; then
|
||||
echo "$raw"
|
||||
return
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
socket_exists() {
|
||||
local p="$1"
|
||||
[[ -n "$p" && -S "$p" ]]
|
||||
}
|
||||
|
||||
# Populate candidate Docker socket paths (existing first later).
|
||||
list_docker_sock_candidates() {
|
||||
local -a c=()
|
||||
local n
|
||||
n="$(normalize_unix_sock "${DOCKER_HOST:-}")"
|
||||
[[ -n "$n" ]] && c+=("$n")
|
||||
n="$(normalize_unix_sock "${DOCKER_SOCK:-}")"
|
||||
[[ -n "$n" ]] && c+=("$n")
|
||||
c+=(
|
||||
/var/run/docker.sock
|
||||
/run/docker.sock
|
||||
)
|
||||
if [[ -n "${XDG_RUNTIME_DIR:-}" ]]; then
|
||||
c+=("${XDG_RUNTIME_DIR}/docker.sock")
|
||||
fi
|
||||
if [[ -n "${HOME:-}" ]]; then
|
||||
c+=("${HOME}/.docker/run/docker.sock")
|
||||
fi
|
||||
printf '%s\n' "${c[@]}" | awk 'NF && !seen[$0]++'
|
||||
}
|
||||
|
||||
list_podman_sock_candidates() {
|
||||
local -a c=()
|
||||
local n uid
|
||||
n="$(normalize_unix_sock "${CONTAINER_HOST:-}")"
|
||||
[[ -n "$n" && "$n" == *podman* ]] && c+=("$n")
|
||||
n="$(normalize_unix_sock "${PODMAN_SOCK:-}")"
|
||||
[[ -n "$n" ]] && c+=("$n")
|
||||
c+=(
|
||||
/run/podman/podman.sock
|
||||
/var/run/podman/podman.sock
|
||||
)
|
||||
if [[ -n "${XDG_RUNTIME_DIR:-}" ]]; then
|
||||
c+=("${XDG_RUNTIME_DIR}/podman/podman.sock")
|
||||
fi
|
||||
uid="$(id -u 2>/dev/null || true)"
|
||||
if [[ -n "$uid" ]]; then
|
||||
c+=("/run/user/${uid}/podman/podman.sock")
|
||||
fi
|
||||
if [[ -n "${HOME:-}" ]]; then
|
||||
c+=(
|
||||
"${HOME}/.local/share/containers/podman/machine/podman.sock"
|
||||
"${HOME}/.local/share/containers/podman/machine/podman-machine-default/podman.sock"
|
||||
)
|
||||
fi
|
||||
printf '%s\n' "${c[@]}" | awk 'NF && !seen[$0]++'
|
||||
}
|
||||
|
||||
find_first_socket() {
|
||||
local p
|
||||
while IFS= read -r p; do
|
||||
[[ -z "$p" ]] && continue
|
||||
if socket_exists "$p"; then
|
||||
echo "$p"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# Prefer the socket's group when it is not root
|
||||
local sock_grp
|
||||
sock_grp="$(stat -c '%G' "$sock" 2>/dev/null || stat -f '%Sg' "$sock" 2>/dev/null || echo docker)"
|
||||
if [[ -n "$sock_grp" && "$sock_grp" != "root" ]]; then
|
||||
grp="$sock_grp"
|
||||
have_cmd() { command -v "$1" >/dev/null 2>&1; }
|
||||
|
||||
# Try to enable rootful Podman API socket (system unit).
|
||||
try_enable_podman_system_socket() {
|
||||
if ! have_cmd systemctl; then
|
||||
return 1
|
||||
fi
|
||||
# Prefer system (rootful) socket for the peardock system service user
|
||||
if systemctl list-unit-files podman.socket >/dev/null 2>&1 \
|
||||
|| [[ -f /lib/systemd/system/podman.socket || -f /usr/lib/systemd/system/podman.socket ]]; then
|
||||
log "Enabling system podman.socket (rootful API)…"
|
||||
run_root systemctl enable --now podman.socket 2>/dev/null || \
|
||||
run_root systemctl start podman.socket 2>/dev/null || true
|
||||
# Give systemd a moment to create the socket
|
||||
sleep 0.5
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
if ! getent group "$grp" >/dev/null 2>&1; then
|
||||
log "Creating group '${grp}' for Docker socket access…"
|
||||
if command -v groupadd >/dev/null 2>&1; then
|
||||
try_enable_docker() {
|
||||
if ! have_cmd systemctl; then
|
||||
return 1
|
||||
fi
|
||||
if systemctl list-unit-files docker.service >/dev/null 2>&1 \
|
||||
|| [[ -f /lib/systemd/system/docker.service || -f /usr/lib/systemd/system/docker.service ]]; then
|
||||
log "Ensuring docker.service is running…"
|
||||
run_root systemctl enable --now docker.service 2>/dev/null || \
|
||||
run_root systemctl start docker.service 2>/dev/null || true
|
||||
sleep 0.5
|
||||
return 0
|
||||
fi
|
||||
# Debian docker.io sometimes uses docker.socket
|
||||
if systemctl list-unit-files docker.socket >/dev/null 2>&1; then
|
||||
run_root systemctl enable --now docker.socket 2>/dev/null || true
|
||||
sleep 0.5
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
ensure_group_exists() {
|
||||
local grp="$1"
|
||||
if getent group "$grp" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
log "Creating group '${grp}'…"
|
||||
if have_cmd groupadd; then
|
||||
# Debian: --system is fine; some older systems reject flags
|
||||
run_root groupadd --system "$grp" 2>/dev/null || run_root groupadd "$grp"
|
||||
elif command -v addgroup >/dev/null 2>&1; then
|
||||
elif have_cmd addgroup; then
|
||||
# Debian addgroup --system
|
||||
run_root addgroup --system "$grp" 2>/dev/null || run_root addgroup "$grp"
|
||||
else
|
||||
die "Cannot create group '${grp}' (need groupadd/addgroup)"
|
||||
fi
|
||||
}
|
||||
|
||||
add_user_to_group() {
|
||||
local user="$1" grp="$2"
|
||||
log "Adding user ${user} to group '${grp}'…"
|
||||
if have_cmd usermod; then
|
||||
run_root usermod -aG "$grp" "$user"
|
||||
elif have_cmd gpasswd; then
|
||||
run_root gpasswd -a "$user" "$grp"
|
||||
elif have_cmd adduser; then
|
||||
# Debian: adduser USER GROUP
|
||||
run_root adduser "$user" "$grp" 2>/dev/null || run_root adduser "$user" "$grp"
|
||||
else
|
||||
die "Cannot add ${user} to ${grp} (need usermod/gpasswd/adduser)"
|
||||
fi
|
||||
|
||||
if getent group "$grp" | grep -qE "(^|,)${user}(,|$)"; then
|
||||
ok "${user} is a member of group '${grp}'"
|
||||
return 0
|
||||
fi
|
||||
if run_root id -nG "$user" 2>/dev/null | tr ' ' '\n' | grep -qx "$grp"; then
|
||||
ok "${user} is a member of group '${grp}'"
|
||||
return 0
|
||||
fi
|
||||
die "Failed to add ${user} to group '${grp}'. Run: sudo usermod -aG ${grp} ${user}"
|
||||
}
|
||||
|
||||
# Configure rootful Podman socket group access for peardock (Debian/RHEL/etc.).
|
||||
# Stock podman.socket is often root:root 660 — peardock cannot use it without a drop-in.
|
||||
configure_podman_socket_permissions() {
|
||||
local sock="$1"
|
||||
local grp="${2:-podman}"
|
||||
|
||||
ensure_group_exists "$grp"
|
||||
|
||||
# systemd drop-in so the socket keeps group + mode across restarts
|
||||
if have_cmd systemctl && {
|
||||
[[ -f /lib/systemd/system/podman.socket ]] \
|
||||
|| [[ -f /usr/lib/systemd/system/podman.socket ]] \
|
||||
|| systemctl list-unit-files podman.socket >/dev/null 2>&1
|
||||
}; then
|
||||
local drop_dir="/etc/systemd/system/podman.socket.d"
|
||||
log "Installing podman.socket drop-in (SocketGroup=${grp}, mode 0660)…"
|
||||
run_root mkdir -p "$drop_dir"
|
||||
run_root tee "${drop_dir}/peardock.conf" >/dev/null <<EOF
|
||||
# Managed by peardock installer — allow group '${grp}' to use the rootful API
|
||||
[Socket]
|
||||
SocketMode=0660
|
||||
SocketGroup=${grp}
|
||||
EOF
|
||||
run_root systemctl daemon-reload
|
||||
run_root systemctl restart podman.socket 2>/dev/null || \
|
||||
run_root systemctl start podman.socket 2>/dev/null || true
|
||||
sleep 0.5
|
||||
fi
|
||||
|
||||
# Live socket: chgrp/chmod even if not managed by our drop-in yet
|
||||
if socket_exists "$sock"; then
|
||||
run_root chgrp "$grp" "$sock" 2>/dev/null || true
|
||||
run_root chmod 660 "$sock" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Debian/Ubuntu sometimes use /var/run → /run symlink; touch both names
|
||||
if [[ "$sock" == /run/podman/podman.sock && -S /var/run/podman/podman.sock ]]; then
|
||||
run_root chgrp "$grp" /var/run/podman/podman.sock 2>/dev/null || true
|
||||
run_root chmod 660 /var/run/podman/podman.sock 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
configure_docker_socket_permissions() {
|
||||
local sock="$1"
|
||||
local grp="${2:-docker}"
|
||||
|
||||
ensure_group_exists "$grp"
|
||||
|
||||
local sock_grp mode
|
||||
sock_grp="$(stat -c '%G' "$sock" 2>/dev/null || stat -f '%Sg' "$sock" 2>/dev/null || echo "$grp")"
|
||||
if [[ -n "$sock_grp" && "$sock_grp" != "root" ]]; then
|
||||
grp="$sock_grp"
|
||||
fi
|
||||
|
||||
# Prefer socket's actual group if non-root
|
||||
if [[ "$sock_grp" != "root" && -n "$sock_grp" ]]; then
|
||||
ensure_group_exists "$sock_grp"
|
||||
grp="$sock_grp"
|
||||
fi
|
||||
|
||||
# Ensure socket is group-accessible when possible
|
||||
local mode
|
||||
mode="$(stat -c '%a' "$sock" 2>/dev/null || echo "")"
|
||||
if [[ -n "$mode" && "$mode" != "666" && "$mode" != "660" && "$mode" != "620" ]]; then
|
||||
log "Setting ${sock} group to ${grp}, mode 660…"
|
||||
@@ -314,48 +559,247 @@ ensure_peardock_docker_group() {
|
||||
run_root chgrp "$grp" "$sock" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
log "Adding user peardock to group '${grp}'…"
|
||||
if command -v usermod >/dev/null 2>&1; then
|
||||
run_root usermod -aG "$grp" peardock
|
||||
elif command -v gpasswd >/dev/null 2>&1; then
|
||||
run_root gpasswd -a peardock "$grp"
|
||||
elif command -v adduser >/dev/null 2>&1; then
|
||||
run_root adduser peardock "$grp" 2>/dev/null || run_root adduser peardock "$grp"
|
||||
else
|
||||
die "Cannot add peardock to ${grp} (need usermod/gpasswd/adduser)"
|
||||
# Export resolved group
|
||||
PEARDOCK_ENGINE_GROUP="$grp"
|
||||
}
|
||||
|
||||
verify_socket_access() {
|
||||
local sock="$1" grp="$2" label="$3"
|
||||
if ! socket_exists "$sock"; then
|
||||
warn "${label} socket missing at ${sock}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verify membership (id may need a moment; read /etc/group directly)
|
||||
if getent group "$grp" | grep -qE '(^|,)peardock(,|$)'; then
|
||||
ok "peardock is a member of group '${grp}'"
|
||||
else
|
||||
# usermod sometimes succeeds but getent lag — check id -nG as root
|
||||
if run_root id -nG peardock 2>/dev/null | tr ' ' '\n' | grep -qx "$grp"; then
|
||||
ok "peardock is a member of group '${grp}'"
|
||||
else
|
||||
die "Failed to add peardock to group '${grp}'. Run: sudo usermod -aG ${grp} peardock"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prove socket is reachable as peardock (sg runs with supplementary group)
|
||||
if command -v sg >/dev/null 2>&1; then
|
||||
# Prefer testing with the group active (new membership not always in current session)
|
||||
if have_cmd sg; then
|
||||
if run_root sg "$grp" -c "runuser -u peardock -- test -r '$sock' -a -w '$sock'" 2>/dev/null \
|
||||
|| run_root runuser -u peardock -- sg "$grp" -c "test -r '$sock' -a -w '$sock'" 2>/dev/null; then
|
||||
ok "Docker socket ${sock} is read/write for peardock (via ${grp})"
|
||||
else
|
||||
# fallback: test as peardock with full group list after usermod
|
||||
|| run_root runuser -u peardock -- sg "$grp" -c "test -r '$sock' -a -w '$sock'" 2>/dev/null \
|
||||
|| run_root su -s /bin/sh peardock -c "sg $grp -c \"test -r '$sock' -a -w '$sock'\"" 2>/dev/null; then
|
||||
ok "${label} socket ${sock} is read/write for peardock (via ${grp})"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if run_root su -s /bin/sh peardock -c "test -r '$sock' -a -w '$sock'" 2>/dev/null; then
|
||||
ok "Docker socket ${sock} is accessible to peardock"
|
||||
ok "${label} socket ${sock} is accessible to peardock"
|
||||
return 0
|
||||
fi
|
||||
warn "Could not verify ${label} socket RW as peardock yet"
|
||||
warn " After install: sudo systemctl restart peardock"
|
||||
if [[ "$label" == "Docker" ]]; then
|
||||
warn " sudo systemctl restart docker"
|
||||
else
|
||||
warn "Could not verify socket RW as peardock yet — restart Docker after group change if needed"
|
||||
warn " sudo systemctl restart docker && sudo systemctl restart peardock"
|
||||
warn " sudo systemctl restart podman.socket"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Merge PEARDOCK_ENGINE / DOCKER_HOST into server .env without clobbering secrets.
|
||||
write_engine_env() {
|
||||
local env_file="${SERVER_DIR}/.env"
|
||||
local kind="$1" sock="$2"
|
||||
local unix="unix://${sock}"
|
||||
local tmp keep
|
||||
|
||||
run_root touch "$env_file"
|
||||
run_root chmod 600 "$env_file"
|
||||
|
||||
tmp="$(mktemp)"
|
||||
keep="$(mktemp)"
|
||||
# Preserve existing lines except engine-related keys we manage
|
||||
if run_root cat "$env_file" 2>/dev/null >"$keep"; then
|
||||
grep -vE '^(PEARDOCK_ENGINE|DOCKER_HOST|CONTAINER_HOST|DOCKER_API_VERSION)=' "$keep" >"$tmp" || true
|
||||
else
|
||||
: >"$tmp"
|
||||
fi
|
||||
rm -f "$keep"
|
||||
{
|
||||
echo "PEARDOCK_ENGINE=${kind}"
|
||||
echo "DOCKER_HOST=${unix}"
|
||||
echo "CONTAINER_HOST=${unix}"
|
||||
if [[ "$kind" == "podman" ]]; then
|
||||
echo "DOCKER_API_VERSION=v1.41"
|
||||
fi
|
||||
} >>"$tmp"
|
||||
run_root cp "$tmp" "$env_file"
|
||||
run_root chmod 600 "$env_file"
|
||||
run_root chown peardock:peardock "$env_file" 2>/dev/null || run_root chown peardock "$env_file" || true
|
||||
rm -f "$tmp"
|
||||
ok "Wrote engine settings to ${env_file} (PEARDOCK_ENGINE=${kind})"
|
||||
}
|
||||
|
||||
# Detect Docker and/or Podman; pick engine from PEARDOCK_ENGINE / --engine / auto.
|
||||
detect_container_engines() {
|
||||
detect_distro
|
||||
log "Distro: ${PEARDOCK_DISTRO}${PEARDOCK_DISTRO_LIKE:+ (like ${PEARDOCK_DISTRO_LIKE})}"
|
||||
|
||||
local docker_sock="" podman_sock=""
|
||||
local has_docker_bin=0 has_podman_bin=0
|
||||
|
||||
have_cmd docker && has_docker_bin=1
|
||||
have_cmd podman && has_podman_bin=1
|
||||
|
||||
docker_sock="$(list_docker_sock_candidates | find_first_socket || true)"
|
||||
podman_sock="$(list_podman_sock_candidates | find_first_socket || true)"
|
||||
|
||||
# Soft-start engines when binaries exist but sockets are down
|
||||
if [[ -z "$docker_sock" && "$has_docker_bin" -eq 1 ]]; then
|
||||
try_enable_docker || true
|
||||
docker_sock="$(list_docker_sock_candidates | find_first_socket || true)"
|
||||
fi
|
||||
if [[ -z "$podman_sock" && "$has_podman_bin" -eq 1 ]]; then
|
||||
try_enable_podman_system_socket || true
|
||||
podman_sock="$(list_podman_sock_candidates | find_first_socket || true)"
|
||||
fi
|
||||
|
||||
# Explicit DOCKER_HOST from environment wins as preferred path for classification
|
||||
local env_host
|
||||
env_host="$(normalize_unix_sock "${DOCKER_HOST:-${CONTAINER_HOST:-}}")"
|
||||
if [[ -n "$env_host" && -S "$env_host" ]]; then
|
||||
if [[ "$env_host" == *podman* ]]; then
|
||||
podman_sock="$env_host"
|
||||
else
|
||||
docker_sock="$env_host"
|
||||
fi
|
||||
fi
|
||||
|
||||
local pref
|
||||
pref="$(echo "${ENGINE_PREF:-auto}" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')"
|
||||
case "$pref" in
|
||||
docker|podman|auto) ;;
|
||||
*)
|
||||
warn "Unknown PEARDOCK_ENGINE='${ENGINE_PREF}', using auto"
|
||||
pref=auto
|
||||
;;
|
||||
esac
|
||||
|
||||
local kind="" sock="" label=""
|
||||
|
||||
if [[ "$pref" == "docker" ]]; then
|
||||
if [[ -n "$docker_sock" ]]; then
|
||||
kind=docker; sock="$docker_sock"; label=Docker
|
||||
else
|
||||
die "PEARDOCK_ENGINE=docker but no Docker socket found. Install Docker (e.g. docker.io on Debian) and start it."
|
||||
fi
|
||||
elif [[ "$pref" == "podman" ]]; then
|
||||
if [[ -z "$podman_sock" && "$has_podman_bin" -eq 1 ]]; then
|
||||
try_enable_podman_system_socket || true
|
||||
podman_sock="$(list_podman_sock_candidates | find_first_socket || true)"
|
||||
fi
|
||||
if [[ -n "$podman_sock" ]]; then
|
||||
kind=podman; sock="$podman_sock"; label=Podman
|
||||
elif [[ "$has_podman_bin" -eq 1 ]]; then
|
||||
# Default path even if not up yet — configure for it
|
||||
kind=podman
|
||||
sock="/run/podman/podman.sock"
|
||||
label=Podman
|
||||
warn "Podman binary found but socket not up — will enable podman.socket and configure ${sock}"
|
||||
else
|
||||
die "PEARDOCK_ENGINE=podman but Podman is not installed. On Debian: sudo apt install podman"
|
||||
fi
|
||||
else
|
||||
# auto: Docker first, then Podman (matches server runtime)
|
||||
if [[ -n "$docker_sock" ]]; then
|
||||
kind=docker; sock="$docker_sock"; label=Docker
|
||||
elif [[ -n "$podman_sock" ]]; then
|
||||
kind=podman; sock="$podman_sock"; label=Podman
|
||||
elif [[ "$has_docker_bin" -eq 1 ]]; then
|
||||
kind=docker; sock="/var/run/docker.sock"; label=Docker
|
||||
warn "Docker CLI found but socket missing — install/start Docker and re-run if peardock cannot connect"
|
||||
elif [[ "$has_podman_bin" -eq 1 ]]; then
|
||||
kind=podman; sock="/run/podman/podman.sock"; label=Podman
|
||||
warn "Podman CLI found but socket missing — enabling podman.socket"
|
||||
try_enable_podman_system_socket || true
|
||||
podman_sock="$(list_podman_sock_candidates | find_first_socket || true)"
|
||||
[[ -n "$podman_sock" ]] && sock="$podman_sock"
|
||||
else
|
||||
warn "Neither Docker nor Podman socket detected."
|
||||
if is_debian_family; then
|
||||
warn "Debian/Ubuntu: sudo apt install docker.io OR sudo apt install podman"
|
||||
warn " Docker: sudo systemctl enable --now docker"
|
||||
warn " Podman: sudo systemctl enable --now podman.socket"
|
||||
elif is_rhel_family; then
|
||||
warn "RHEL/Fedora: install moby-engine/docker-ce or podman; enable docker or podman.socket"
|
||||
else
|
||||
warn "Install Docker or Podman, then re-run the installer or set PEARDOCK_ENGINE."
|
||||
fi
|
||||
# Default unit to docker group so a later Docker install works
|
||||
kind=docker
|
||||
sock="/var/run/docker.sock"
|
||||
label=Docker
|
||||
fi
|
||||
fi
|
||||
|
||||
PEARDOCK_ENGINE_KIND="$kind"
|
||||
PEARDOCK_ENGINE_SOCK="$sock"
|
||||
PEARDOCK_ENGINE_LABEL="$label"
|
||||
export PEARDOCK_ENGINE_KIND PEARDOCK_ENGINE_SOCK PEARDOCK_ENGINE_LABEL
|
||||
|
||||
log "Selected engine: ${C_BOLD}${label}${C_RESET} socket=${sock}"
|
||||
if [[ -n "$docker_sock" ]]; then ok "Docker socket: ${docker_sock}"; else log "Docker socket: (none)"; fi
|
||||
if [[ -n "$podman_sock" ]]; then ok "Podman socket: ${podman_sock}"; else log "Podman socket: (none)"; fi
|
||||
}
|
||||
|
||||
# Full permission + group setup for the selected engine.
|
||||
ensure_container_engine_access() {
|
||||
detect_container_engines
|
||||
|
||||
local kind="$PEARDOCK_ENGINE_KIND"
|
||||
local sock="$PEARDOCK_ENGINE_SOCK"
|
||||
local label="$PEARDOCK_ENGINE_LABEL"
|
||||
local grp
|
||||
|
||||
if [[ "$kind" == "podman" ]]; then
|
||||
grp="podman"
|
||||
# If socket already has a non-root group (e.g. some distros use podman), prefer it
|
||||
if socket_exists "$sock"; then
|
||||
local sg
|
||||
sg="$(stat -c '%G' "$sock" 2>/dev/null || true)"
|
||||
if [[ -n "$sg" && "$sg" != "root" ]]; then
|
||||
grp="$sg"
|
||||
fi
|
||||
fi
|
||||
try_enable_podman_system_socket || true
|
||||
# Re-resolve after enable
|
||||
local found
|
||||
found="$(list_podman_sock_candidates | find_first_socket || true)"
|
||||
if [[ -n "$found" ]]; then
|
||||
sock="$found"
|
||||
PEARDOCK_ENGINE_SOCK="$sock"
|
||||
fi
|
||||
configure_podman_socket_permissions "$sock" "$grp"
|
||||
PEARDOCK_ENGINE_GROUP="$grp"
|
||||
add_user_to_group peardock "$grp"
|
||||
verify_socket_access "$sock" "$grp" "Podman" || true
|
||||
else
|
||||
grp="docker"
|
||||
if socket_exists "$sock"; then
|
||||
configure_docker_socket_permissions "$sock" "$grp"
|
||||
grp="${PEARDOCK_ENGINE_GROUP:-docker}"
|
||||
else
|
||||
ensure_group_exists docker
|
||||
PEARDOCK_ENGINE_GROUP=docker
|
||||
grp=docker
|
||||
fi
|
||||
add_user_to_group peardock "$grp"
|
||||
if socket_exists "$sock"; then
|
||||
verify_socket_access "$sock" "$grp" "Docker" || true
|
||||
else
|
||||
warn "Docker socket not found at ${sock}"
|
||||
if is_debian_family; then
|
||||
warn "Debian/Ubuntu: sudo apt install docker.io && sudo systemctl enable --now docker"
|
||||
warn "Then: sudo usermod -aG docker peardock && sudo systemctl restart peardock"
|
||||
else
|
||||
warn "Install/start Docker, then: sudo usermod -aG docker peardock && sudo systemctl restart peardock"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Export for unit file generation
|
||||
PEARDOCK_DOCKER_GROUP="$grp"
|
||||
export PEARDOCK_ENGINE_GROUP
|
||||
# Back-compat for older variable name used in unit snippets
|
||||
PEARDOCK_DOCKER_GROUP="${PEARDOCK_ENGINE_GROUP}"
|
||||
export PEARDOCK_DOCKER_GROUP
|
||||
|
||||
write_engine_env "$kind" "$sock"
|
||||
}
|
||||
|
||||
# ─── server install ─────────────────────────────────────────────────────────
|
||||
@@ -403,36 +847,61 @@ install_server() {
|
||||
run_root chmod 600 "${SERVER_DIR}/.env"
|
||||
fi
|
||||
|
||||
# system user
|
||||
# system user (Debian: nologin path + adduser --system; RHEL: useradd --system)
|
||||
local shell_nologin
|
||||
shell_nologin="$(nologin_shell)"
|
||||
if ! id peardock >/dev/null 2>&1; then
|
||||
log "Creating system user peardock…"
|
||||
if command -v useradd >/dev/null 2>&1; then
|
||||
run_root useradd --system --home "$SERVER_DIR" --shell /usr/sbin/nologin peardock 2>/dev/null \
|
||||
if have_cmd useradd; then
|
||||
run_root useradd --system --home-dir "$SERVER_DIR" --shell "$shell_nologin" --user-group peardock 2>/dev/null \
|
||||
|| run_root useradd --system --home "$SERVER_DIR" --shell "$shell_nologin" peardock 2>/dev/null \
|
||||
|| run_root useradd --system --home "$SERVER_DIR" --shell /bin/false peardock
|
||||
elif command -v adduser >/dev/null 2>&1; then
|
||||
run_root adduser --system --home "$SERVER_DIR" --shell /usr/sbin/nologin --no-create-home peardock || true
|
||||
elif have_cmd adduser; then
|
||||
# Debian/Ubuntu adduser
|
||||
run_root adduser --system --group --home "$SERVER_DIR" --shell "$shell_nologin" --no-create-home peardock 2>/dev/null \
|
||||
|| run_root adduser --system --home "$SERVER_DIR" --shell "$shell_nologin" --no-create-home peardock || true
|
||||
else
|
||||
die "Cannot create peardock user (need useradd or adduser)"
|
||||
fi
|
||||
fi
|
||||
id peardock >/dev/null 2>&1 || die "peardock user was not created"
|
||||
|
||||
# Docker socket access: peardock must be in the docker group (mode 660 root:docker).
|
||||
ensure_peardock_docker_group
|
||||
# Docker and/or Podman: detect engine, groups, socket mode, .env PEARDOCK_ENGINE
|
||||
ensure_container_engine_access
|
||||
|
||||
run_root chown -R peardock:peardock "$SERVER_DIR" 2>/dev/null || run_root chown -R peardock "$SERVER_DIR"
|
||||
|
||||
local eng_kind eng_sock eng_grp eng_label unit_after unit_wants read_paths
|
||||
eng_kind="${PEARDOCK_ENGINE_KIND:-docker}"
|
||||
eng_sock="${PEARDOCK_ENGINE_SOCK:-/var/run/docker.sock}"
|
||||
eng_grp="${PEARDOCK_ENGINE_GROUP:-docker}"
|
||||
eng_label="${PEARDOCK_ENGINE_LABEL:-Docker}"
|
||||
|
||||
unit_after="network-online.target"
|
||||
unit_wants="network-online.target"
|
||||
if [[ "$eng_kind" == "podman" ]]; then
|
||||
unit_after="${unit_after} podman.socket"
|
||||
unit_wants="${unit_wants} podman.socket"
|
||||
else
|
||||
unit_after="${unit_after} docker.service"
|
||||
unit_wants="${unit_wants} docker.service"
|
||||
fi
|
||||
|
||||
# Allow access to both common sockets so auto-fallback still works after install
|
||||
read_paths="${SERVER_DIR} /var/run/docker.sock /run/docker.sock /run/podman/podman.sock /var/run/podman/podman.sock"
|
||||
if [[ -n "$eng_sock" && "$read_paths" != *"$eng_sock"* ]]; then
|
||||
read_paths="${read_paths} ${eng_sock}"
|
||||
fi
|
||||
|
||||
# systemd unit
|
||||
unit_path="/etc/systemd/system/peardock.service"
|
||||
log "Writing ${unit_path}…"
|
||||
log "Writing ${unit_path} (engine=${eng_kind}, group=${eng_grp})…"
|
||||
run_root tee "$unit_path" >/dev/null <<EOF
|
||||
[Unit]
|
||||
Description=peardock HyperDHT Docker control plane
|
||||
Description=peardock HyperDHT container control plane (${eng_label})
|
||||
Documentation=${GITEA_URL}/${OWNER}/${REPO}
|
||||
After=docker.service network-online.target
|
||||
Wants=network-online.target
|
||||
# docker.service may be missing on rootless setups — soft dependency
|
||||
Wants=docker.service
|
||||
After=${unit_after}
|
||||
Wants=${unit_wants}
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@@ -443,21 +912,24 @@ RestartSec=5
|
||||
TimeoutStartSec=30
|
||||
TimeoutStopSec=30
|
||||
User=peardock
|
||||
# Primary + supplementary docker group so /var/run/docker.sock (root:docker 660) works
|
||||
Group=${PEARDOCK_DOCKER_GROUP:-docker}
|
||||
SupplementaryGroups=${PEARDOCK_DOCKER_GROUP:-docker}
|
||||
# Socket group (docker or podman) so the Engine API socket is accessible
|
||||
Group=${eng_grp}
|
||||
SupplementaryGroups=${eng_grp}
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
Environment=NODE_ENV=production
|
||||
Environment=PEARDOCK_ENGINE=${eng_kind}
|
||||
Environment=DOCKER_HOST=unix://${eng_sock}
|
||||
Environment=CONTAINER_HOST=unix://${eng_sock}
|
||||
EnvironmentFile=-${SERVER_DIR}/.env
|
||||
# Docker socket + state
|
||||
ReadWritePaths=${SERVER_DIR} /var/run/docker.sock /run/docker.sock
|
||||
# State + engine sockets (Docker and/or Podman)
|
||||
ReadWritePaths=${read_paths}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
if have_cmd systemctl; then
|
||||
run_root systemctl daemon-reload
|
||||
if confirm "Enable and start peardock.service now?" "y"; then
|
||||
run_root systemctl enable --now peardock.service
|
||||
@@ -485,6 +957,7 @@ ${C_BOLD}Server installed${C_RESET}
|
||||
Binary: ${SERVER_DIR}/peardock-server
|
||||
Config: ${SERVER_DIR}/.env ${C_BOLD}← check this file for your keys${C_RESET}
|
||||
Service: peardock.service
|
||||
Engine: ${eng_label} (${eng_kind}) socket=${eng_sock} group=${eng_grp}
|
||||
|
||||
${C_BOLD}Keys (written on first successful start)${C_RESET}
|
||||
After peardock has started once, open the env file:
|
||||
@@ -527,6 +1000,18 @@ ${C_BOLD}Connect from the desktop client → Add peer${C_RESET}
|
||||
Docs: https://peardock.boats/docs/quickstart
|
||||
|
||||
EOF
|
||||
|
||||
if [[ "$eng_kind" == "podman" ]]; then
|
||||
cat <<EOF
|
||||
${C_BOLD}Podman notes${C_RESET}
|
||||
· Rootful API: systemctl status podman.socket
|
||||
· Socket group: ${eng_grp} (drop-in in /etc/systemd/system/podman.socket.d/)
|
||||
· peardock is in group ${eng_grp}; unit sets PEARDOCK_ENGINE=podman
|
||||
· Swarm is not available on Podman (UI hides it); use Pods / Stacks instead
|
||||
· Prefer Registry Vault for private pulls (auth.json differs from Docker)
|
||||
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# ─── client install ─────────────────────────────────────────────────────────
|
||||
@@ -713,7 +1198,7 @@ main() {
|
||||
|
||||
if [[ -z "$ROLE" ]]; then
|
||||
echo "What do you want to install?"
|
||||
echo " ${C_BOLD}1${C_RESET}) Server — HyperDHT control plane (Docker host, Linux systemd)"
|
||||
echo " ${C_BOLD}1${C_RESET}) Server — HyperDHT control plane (Docker or Podman host, Linux systemd)"
|
||||
echo " ${C_BOLD}2${C_RESET}) Client — Desktop GUI (connect with a public key)"
|
||||
echo " ${C_BOLD}3${C_RESET}) Both"
|
||||
echo
|
||||
@@ -727,6 +1212,28 @@ main() {
|
||||
esac
|
||||
fi
|
||||
|
||||
# Optional interactive engine pick for server installs when not forced
|
||||
if [[ "$ROLE" == "server" || "$ROLE" == "both" ]]; then
|
||||
local ep
|
||||
ep="$(echo "${ENGINE_PREF}" | tr '[:upper:]' '[:lower:]')"
|
||||
if [[ "$ASSUME_YES" != "1" && ( "$ep" == "auto" || -z "$ep" ) ]]; then
|
||||
echo
|
||||
echo "Container engine for the server:"
|
||||
echo " ${C_BOLD}1${C_RESET}) Auto — Docker if present, else Podman (recommended)"
|
||||
echo " ${C_BOLD}2${C_RESET}) Docker"
|
||||
echo " ${C_BOLD}3${C_RESET}) Podman"
|
||||
echo
|
||||
local eng_choice
|
||||
eng_choice="$(ask_choice "Choose 1/2/3" "1")"
|
||||
case "$eng_choice" in
|
||||
1|a|auto) ENGINE_PREF=auto ;;
|
||||
2|d|docker) ENGINE_PREF=docker ;;
|
||||
3|p|podman) ENGINE_PREF=podman ;;
|
||||
*) ENGINE_PREF=auto ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
INSTALL_TMP="$(mktemp -d "${TMPDIR_ROOT}/peardock-install.XXXXXX")"
|
||||
|
||||
case "$ROLE" in
|
||||
|
||||
Reference in New Issue
Block a user