Syncthing CLI –addresses가 저장되지 않을 때 version과 REST 결과를 확인하는 법

현재 version에서 같은 bug인지 먼저 확인한다

Syncthing issue 8503은 syncthing cli config devices add에서 --addresses를 함께 사용했을 때 reflect 오류가 발생한 과거 bug를 다룹니다. 해당 수정은 Syncthing 1.23.5 release에 포함됐습니다. 최신 설치에서 주소가 보이지 않는다고 해서 같은 bug라고 단정하면 다른 config home, 잘못된 device ID, REST 배열 교체 같은 현재 원인을 놓칠 수 있습니다.

진단 기준은 CLI의 성공 문구가 아니라 Syncthing이 실제로 보관한 device object입니다. 실행 중 instance가 어느 config directory와 GUI API를 사용하는지 기록하고, 그 instance의 REST API에서 주소 배열을 읽습니다.

변경 전에 고정할 값

항목확인 값오류 가능성
binary경로와 Syncthing version오래된 CLI 또는 다른 설치를 실행했습니다.
config homeconfig.xml과 database 경로service와 shell이 다른 instance를 봅니다.
device identity정확한 device ID다른 device object를 수정했습니다.
addresses 배열dynamic과 static URI 목록PATCH에서 기존 배열을 교체했습니다.
restart staterestart-required API저장됐지만 적용 대기 중입니다.
syncthing --version
syncthing paths
syncthing cli config devices add --device-id <DEVICE_ID> --name <NAME> --addresses tcp://192.0.2.42:22000

주소 URI에는 protocol prefix를 포함합니다. Syncthing config 문서는 TCP와 QUIC 주소, 기본 port, dynamic 값을 설명합니다. static 주소만 넣을지 discovery fallback을 위해 dynamic을 함께 둘지는 운영 의도에 따라 결정합니다.

REST API로 저장된 object를 확인한다

Linux/macOS Bash와 헤더 파일을 지원하는 curl에서 사용하는 예제입니다. API 키는 숨김 입력으로 받고 권한 제한 디렉터리의 헤더 파일에만 씁니다. 셸 명령에 키를 직접 넣거나 export하지 않으며, curl 인자에는 파일 경로만 전달합니다. 이 방식도 같은 사용자·관리자의 메모리나 파일 접근까지 차단하지는 않습니다. 디버그·세션 녹화가 없는 개인 터미널에서 실행하세요. 아래 GET과 다음 PATCH는 같은 스크립트 안에서 실행합니다. 종료 시 키 파일만 지우고 백업은 보호된 WORK 디렉터리에 남깁니다. API 전체 설정 응답은 공개하지 않습니다. TLS를 사용하는 GUI는 실제 HTTPS URL과 신뢰 가능한 인증서를 사용하며 -k로 검증을 끄지 않습니다.

# Bash on Linux/macOS; save as a script, do not enable xtrace.
set +x
set -euo pipefail
umask 077
WORK=$(mktemp -d "${TMPDIR:-/tmp}/syncthing-check.XXXXXXXX")
trap 'rm -f -- "$WORK/api-header"' EXIT
IFS= read -r -s -p 'Syncthing API key: ' ST_API_KEY
printf '
'
printf 'X-API-Key: %s
' "$ST_API_KEY" > "$WORK/api-header"
unset ST_API_KEY
DEVICE_ID='REPLACE_WITH_DEVICE_ID'
API='http://127.0.0.1:8384'
curl -q -fsS --header "@$WORK/api-header" \
  "$API/rest/config/devices/$DEVICE_ID" > "$WORK/device-before.json"
curl -q -fsS --header "@$WORK/api-header" "$API/rest/config/restart-required"

합성 키와 로컬 모의 HTTP 서버로 헤더 전달을 시험했습니다. 이 시험은 특정 Syncthing 빌드의 PATCH 동작 재현이 아닙니다.

PATCH 배열은 추가가 아니라 교체다

Syncthing REST 문서는 PATCH가 기존 object 위에 JSON을 덮지만 child array는 확장하지 않고 교체한다고 설명합니다. addresses에 새 값 하나만 보내면 기존 dynamic이나 다른 static 주소가 사라질 수 있습니다. 원하는 최종 배열 전체를 명시합니다.

curl -q -fsS -X PATCH \
  --header "@$WORK/api-header" \
  -H 'Content-Type: application/json' \
  --data '{"addresses":["tcp://192.0.2.42:22000","dynamic"]}' \
  "$API/rest/config/devices/$DEVICE_ID"
curl -q -fsS --header "@$WORK/api-header" "$API/rest/config/devices/$DEVICE_ID"
curl -q -fsS --header "@$WORK/api-header" "$API/rest/config/restart-required"

결과별 판단

  • version이 1.23.5보다 오래됨: issue 8503 범위에 들어갈 수 있습니다. 해당 release note와 현재 package channel을 확인하고 지원되는 version으로 업데이트한 뒤 다시 시험합니다.
  • CLI 뒤 REST object에 주소가 없음: CLI 인수, device ID, config home을 확인합니다. 다른 Syncthing instance의 CLI를 호출하지 않았는지 봅니다.
  • REST에는 있으나 연결에 사용되지 않음: 저장 문제는 아닙니다. URI 문법, destination listen address, firewall, device connection log를 다음 분기로 조사합니다.
  • PATCH 뒤 기존 주소가 사라짐: 배열 교체 동작입니다. backup의 addresses와 새 주소를 합친 최종 배열로 다시 PATCH합니다.
  • restart-required가 true: 현재 전송을 확인하고 planned restart를 수행합니다. config 저장과 즉시 연결 성공을 같은 것으로 취급하지 않습니다.

롤백과 검증

변경이 실패하면 $WORK/device-before.json에서 원래 addresses 배열을 추출해 PATCH로 복원합니다. 전체 device object를 PUT하면 조사 대상이 아닌 field까지 과거 값으로 돌아갈 수 있으므로 주소만 되돌리는 편이 안전합니다.

복원 뒤 REST GET과 connection log를 다시 확인합니다. API key는 shell에서 제거하고 backup 파일 권한을 제한합니다. static 주소가 실패해도 dynamic fallback을 남겼다면 discovery 경로로 연결될 수 있으므로 실제 사용 주소를 connection 정보에서 확인합니다.

공식 문서 및 확인 기준

이 글에 남아 있던 이전 검증 기록

검증 수준: 공식 문서 대조

과거 CLI bug의 수정 version과 현재 REST config 동작을 공식 issue, release, 문서로 대조했습니다. 특정 package build는 재현하지 않았으므로 현재 설치가 같은 bug라고 단정하지 않습니다.

작성 방식과 수정 정책 · 오류 제보