mirror of
https://github.com/shenxn/protonmail-bridge-docker.git
synced 2026-03-26 21:35:58 +00:00
refactor: replace faketty with headless --noninteractive daemon + PTY_TOOL switcher
- Drop faketty named pipe and screen; daemon runs via exec protonmail-bridge --noninteractive
so stdout/stderr reach docker logs natively and SIGTERM lands directly on the bridge
- Add PTY_TOOL build ARG/ENV (dtach default, abduco, reptyr) for interactive sessions only
- Split commands: init (first-time setup), run (daemon), manage (interactive CLI), attach (reattach)
- PTY machinery isolated to manage/attach; restart loop and log forwarding hacks removed
- Fix $1 unbound variable with ${1:-}, set -ex replaced with set -euo pipefail
- chmod +x consolidated into install RUN layer; healthcheck -exc fixed to -c
- CMD switched to exec form to ensure signals reach entrypoint directly
This commit is contained in:
parent
97014ae98c
commit
be89ba8662
@ -9,20 +9,37 @@ RUN apt-get update && apt-get install -y wget binutils
|
|||||||
# Repack deb (removes unnecessary dependencies and produces /protonmail.deb)
|
# Repack deb (removes unnecessary dependencies and produces /protonmail.deb)
|
||||||
RUN bash /install.sh
|
RUN bash /install.sh
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
FROM debian:sid-slim
|
FROM debian:sid-slim
|
||||||
LABEL maintainer="Simon Felding <sife@adm.ku.dk>"
|
LABEL maintainer="Simon Felding <sife@adm.ku.dk>"
|
||||||
|
|
||||||
|
# Select PTY tool for manage/attach commands: dtach (default), abduco, reptyr
|
||||||
|
ARG PTY_TOOL=dtach
|
||||||
|
ENV PTY_TOOL=${PTY_TOOL}
|
||||||
|
|
||||||
EXPOSE 25/tcp
|
EXPOSE 25/tcp
|
||||||
EXPOSE 143/tcp
|
EXPOSE 143/tcp
|
||||||
|
|
||||||
WORKDIR /protonmail
|
WORKDIR /protonmail
|
||||||
|
|
||||||
# Copy bash scripts
|
# PACKAGE is only needed in the build stage; don't copy it into the final image
|
||||||
COPY gpgparams entrypoint.sh PACKAGE /protonmail/
|
COPY gpgparams entrypoint.sh /protonmail/
|
||||||
COPY --from=build /protonmail.deb /tmp/protonmail.deb
|
COPY --from=build /protonmail.deb /tmp/protonmail.deb
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends /tmp/protonmail.deb socat pass libsecret-1-0 ca-certificates procps \
|
&& apt-get install -y --no-install-recommends \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
/tmp/protonmail.deb \
|
||||||
|
socat pass libsecret-1-0 libfido2-1 ca-certificates procps \
|
||||||
|
&& case "${PTY_TOOL}" in \
|
||||||
|
dtach) apt-get install -y --no-install-recommends dtach ;; \
|
||||||
|
abduco) apt-get install -y --no-install-recommends abduco ;; \
|
||||||
|
reptyr) apt-get install -y --no-install-recommends reptyr ;; \
|
||||||
|
esac \
|
||||||
|
&& chmod +x /protonmail/entrypoint.sh \
|
||||||
|
&& rm -rf /tmp/protonmail.deb /var/lib/apt/lists/*
|
||||||
|
|
||||||
CMD ["bash", "/protonmail/entrypoint.sh"]
|
HEALTHCHECK --interval=30s --timeout=5s --retries=3 --start-period=120s \
|
||||||
|
CMD /bin/bash -c "true < /dev/tcp/localhost/25"
|
||||||
|
|
||||||
|
CMD ["/protonmail/entrypoint.sh", "run"]
|
||||||
|
|||||||
@ -1,49 +1,151 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -ex
|
set -euo pipefail
|
||||||
|
|
||||||
# Initialize
|
PTY_TOOL="${PTY_TOOL:-dtach}"
|
||||||
if [[ $1 == init ]]; then
|
BRIDGE_SOCK=/protonmail/bridge.sock
|
||||||
|
BRIDGE_PID_FILE=/protonmail/bridge.pid
|
||||||
|
|
||||||
# # Parse parameters
|
# Clean stale gpg-agent sockets left from a previous run
|
||||||
# TFP="" # Default empty two factor passcode
|
rm -f /root/.gnupg/S.gpg-agent* 2>/dev/null || true
|
||||||
# shift # skip `init`
|
|
||||||
# while [[ $# -gt 0 ]]; do
|
|
||||||
# key="$1"
|
|
||||||
# case $key in
|
|
||||||
# -u|--username)
|
|
||||||
# USERNAME="$2"
|
|
||||||
# ;;
|
|
||||||
# -p|--password)
|
|
||||||
# PASSWORD="$2"
|
|
||||||
# ;;
|
|
||||||
# -t|--twofactor)
|
|
||||||
# TWOFACTOR="$2"
|
|
||||||
# ;;
|
|
||||||
# esac
|
|
||||||
# shift
|
|
||||||
# shift
|
|
||||||
# done
|
|
||||||
|
|
||||||
# Initialize pass
|
# --- PTY helpers (only used by: init, manage, attach) ---
|
||||||
|
|
||||||
|
pty_start() {
|
||||||
|
case "${PTY_TOOL}" in
|
||||||
|
dtach) dtach -n "${BRIDGE_SOCK}" "$@" ;;
|
||||||
|
abduco) abduco -n bridge "$@" ;;
|
||||||
|
# reptyr re-attaches existing PIDs; use nohup+setsid to launch headlessly instead
|
||||||
|
reptyr) setsid "$@" </dev/null &>/dev/null & echo $! > "${BRIDGE_PID_FILE}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
pty_attach() {
|
||||||
|
case "${PTY_TOOL}" in
|
||||||
|
dtach) exec dtach -a "${BRIDGE_SOCK}" -e '^\' ;;
|
||||||
|
abduco) exec abduco -a bridge ;;
|
||||||
|
reptyr) exec reptyr "$(cat "${BRIDGE_PID_FILE}")" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
detach_hint() {
|
||||||
|
case "${PTY_TOOL}" in
|
||||||
|
dtach|abduco) echo "Ctrl+\\" ;;
|
||||||
|
reptyr) echo "Ctrl+C" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait up to $1 seconds for the bridge socket (or PID file) to appear
|
||||||
|
wait_for_session() {
|
||||||
|
local timeout="${1:-10}"
|
||||||
|
local elapsed=0
|
||||||
|
while [[ "${elapsed}" -lt "${timeout}" ]]; do
|
||||||
|
case "${PTY_TOOL}" in
|
||||||
|
dtach|abduco) [[ -S "${BRIDGE_SOCK}" ]] && return 0 ;;
|
||||||
|
reptyr) [[ -f "${BRIDGE_PID_FILE}" ]] && return 0 ;;
|
||||||
|
esac
|
||||||
|
sleep 1
|
||||||
|
(( elapsed++ )) || true
|
||||||
|
done
|
||||||
|
echo "ERROR: bridge session did not start within ${timeout}s." >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Commands ---
|
||||||
|
|
||||||
|
CMD="${1:-run}"
|
||||||
|
|
||||||
|
case "${CMD}" in
|
||||||
|
|
||||||
|
init)
|
||||||
|
# One-time setup: generate GPG key, init password store, interactive login.
|
||||||
|
# Run as: docker run -it <image> init
|
||||||
gpg --generate-key --batch /protonmail/gpgparams
|
gpg --generate-key --batch /protonmail/gpgparams
|
||||||
pass init pass-key
|
pass init pass-key
|
||||||
|
exec protonmail-bridge --cli
|
||||||
|
;;
|
||||||
|
|
||||||
# Login
|
manage)
|
||||||
protonmail-bridge --cli
|
# Open an interactive --cli session for account management (add/remove accounts etc).
|
||||||
|
# Run as: docker run -it --rm -v <data-volume> <image> manage
|
||||||
|
# NOTE: Stop the running daemon container first to avoid port/lock conflicts.
|
||||||
|
CONTAINER_ID=$(hostname)
|
||||||
|
echo " Starting management session... [PTY_TOOL=${PTY_TOOL}]"
|
||||||
|
pty_start protonmail-bridge --cli
|
||||||
|
|
||||||
else
|
# Wait for the session socket/pid to appear before printing attach instructions
|
||||||
|
wait_for_session 10
|
||||||
|
|
||||||
# socat will make the conn appear to come from 127.0.0.1
|
echo " Management session ready."
|
||||||
# ProtonMail Bridge currently expects that.
|
echo " Attach: docker exec -it ${CONTAINER_ID} /protonmail/entrypoint.sh attach"
|
||||||
# It also allows us to bind to the real ports :)
|
echo " Detach: $(detach_hint)"
|
||||||
socat TCP-LISTEN:25,fork TCP:127.0.0.1:1025 &
|
;;
|
||||||
socat TCP-LISTEN:143,fork TCP:127.0.0.1:1143 &
|
|
||||||
|
|
||||||
# Start protonmail
|
|
||||||
# Fake a terminal, so it does not quit because of EOF...
|
|
||||||
rm -f faketty
|
|
||||||
mkfifo faketty
|
|
||||||
cat faketty | protonmail-bridge --cli
|
|
||||||
|
|
||||||
|
attach)
|
||||||
|
# Reattach to a running manage session.
|
||||||
|
case "${PTY_TOOL}" in
|
||||||
|
dtach|abduco)
|
||||||
|
if [[ ! -S "${BRIDGE_SOCK}" ]]; then
|
||||||
|
echo "ERROR: No active session found (${BRIDGE_SOCK} does not exist)." >&2
|
||||||
|
echo " Start one first: docker exec -it \$(hostname) /protonmail/entrypoint.sh manage" >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
reptyr)
|
||||||
|
if [[ ! -f "${BRIDGE_PID_FILE}" ]]; then
|
||||||
|
echo "ERROR: No active session found (${BRIDGE_PID_FILE} does not exist)." >&2
|
||||||
|
echo " Start one first: docker exec -it \$(hostname) /protonmail/entrypoint.sh manage" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
pty_attach
|
||||||
|
;;
|
||||||
|
|
||||||
|
run)
|
||||||
|
# Daemon mode: --noninteractive runs headless, output goes directly to docker logs.
|
||||||
|
CONTAINER_ID=$(hostname)
|
||||||
|
echo "========================================"
|
||||||
|
echo " ProtonMail Bridge daemon starting..."
|
||||||
|
echo " Container: ${CONTAINER_ID}"
|
||||||
|
echo ""
|
||||||
|
echo " Available commands:"
|
||||||
|
echo " First-time setup:"
|
||||||
|
echo " docker run -it <image> init"
|
||||||
|
echo ""
|
||||||
|
echo " Manage accounts (stop daemon first):"
|
||||||
|
echo " docker run -it --rm -v <data-volume> <image> manage"
|
||||||
|
echo ""
|
||||||
|
echo " Attach to a running manage session:"
|
||||||
|
echo " docker exec -it ${CONTAINER_ID} /protonmail/entrypoint.sh attach"
|
||||||
|
echo ""
|
||||||
|
echo " View logs:"
|
||||||
|
echo " docker logs -f ${CONTAINER_ID}"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
# socat forwards standard ports to bridge's localhost-only listener ports.
|
||||||
|
socat TCP-LISTEN:25,fork,reuseaddr TCP:127.0.0.1:1025,nodelay &
|
||||||
|
SOCAT_SMTP_PID=$!
|
||||||
|
socat TCP-LISTEN:143,fork,reuseaddr TCP:127.0.0.1:1143,nodelay &
|
||||||
|
SOCAT_IMAP_PID=$!
|
||||||
|
|
||||||
|
# Verify both socat processes started successfully
|
||||||
|
sleep 1
|
||||||
|
for pid in "${SOCAT_SMTP_PID}" "${SOCAT_IMAP_PID}"; do
|
||||||
|
if ! kill -0 "${pid}" 2>/dev/null; then
|
||||||
|
echo "ERROR: socat port-forward (pid ${pid}) failed to start." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# exec replaces the shell so the bridge becomes the waited-on process.
|
||||||
|
# docker stop sends SIGTERM directly to it. socat processes are reaped on exit.
|
||||||
|
exec protonmail-bridge --noninteractive
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: entrypoint.sh [init|manage|attach|run]" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user