ci(deploy): switch from rsync to lftp mirror (SFTP-only hosting)
All checks were successful
ci / build-test (push) Successful in 3m55s
All checks were successful
ci / build-test (push) Successful in 3m55s
Hetzner Webhosting accepts SSH for file transfer but refuses remote command exec, failing rsync with: exec request failed on channel 0 rsync error: error in rsync protocol data stream (code 12) rsync over SSH requires spawning a remote rsync binary, which isn't possible on SFTP-only tiers. Switch the mirror to lftp, which speaks SFTP end-to-end. Same semantics (upload + delete removed files), same key + known_hosts pinning via sftp:connect-program. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -96,27 +96,35 @@ jobs:
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
printf '%s\n' "$SFTP_KNOWN_HOSTS" > ~/.ssh/known_hosts
|
||||
chmod 644 ~/.ssh/known_hosts
|
||||
# Ensure rsync + openssh are present even on a minimal runner image.
|
||||
if ! command -v rsync >/dev/null 2>&1 || ! command -v ssh >/dev/null 2>&1; then
|
||||
# Hetzner Webhosting accounts are SFTP-only — they accept SSH for file
|
||||
# transfer but refuse remote command exec ("exec request failed on
|
||||
# channel 0"). rsync over SSH needs to spawn a remote rsync binary,
|
||||
# so it cannot work here. Use lftp's mirror instead, which speaks
|
||||
# SFTP end-to-end with the same key + known_hosts pinning.
|
||||
if ! command -v lftp >/dev/null 2>&1 || ! command -v ssh >/dev/null 2>&1; then
|
||||
if command -v sudo >/dev/null 2>&1; then SUDO=sudo; else SUDO=; fi
|
||||
$SUDO apt-get update -qq
|
||||
$SUDO apt-get install -y --no-install-recommends rsync openssh-client
|
||||
$SUDO apt-get install -y --no-install-recommends lftp openssh-client
|
||||
fi
|
||||
|
||||
- name: Deploy via rsync
|
||||
- name: Deploy via lftp (mirror over SFTP)
|
||||
env:
|
||||
SFTP_USER: ${{ secrets.SFTP_USER }}
|
||||
SFTP_HOST: ${{ secrets.SFTP_HOST }}
|
||||
SFTP_PATH: ${{ secrets.SFTP_PATH }}
|
||||
run: |
|
||||
# Fail loudly if any secret is missing — otherwise rsync --delete
|
||||
# Fail loudly if any secret is missing — otherwise mirror --delete
|
||||
# could be directed at the SSH user's home root.
|
||||
: "${SFTP_USER:?SFTP_USER secret must be set}"
|
||||
: "${SFTP_HOST:?SFTP_HOST secret must be set}"
|
||||
: "${SFTP_PATH:?SFTP_PATH secret must be set}"
|
||||
rsync -avz --delete \
|
||||
-e "ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=yes -o UserKnownHostsFile=~/.ssh/known_hosts" \
|
||||
dist/ "$SFTP_USER@$SFTP_HOST:$SFTP_PATH/"
|
||||
lftp <<LFTP
|
||||
set cmd:fail-exit yes
|
||||
set sftp:connect-program 'ssh -a -x -i $HOME/.ssh/id_ed25519 -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$HOME/.ssh/known_hosts'
|
||||
open sftp://$SFTP_USER@$SFTP_HOST
|
||||
mirror --reverse --delete --verbose --parallel=4 dist/ $SFTP_PATH/
|
||||
bye
|
||||
LFTP
|
||||
|
||||
- name: Post-deploy smoke test
|
||||
run: |
|
||||
|
||||
Reference in New Issue
Block a user