Use visible NAS upload storage and reconcile missing files

This commit is contained in:
2026-10-13 15:54:27 +09:00
parent 50e54bc4c5
commit 9e0f493228
26 changed files with 1075 additions and 119 deletions

View File

@@ -61,7 +61,7 @@ if [ ! -f .env ]; then
hop_session_secret=$(openssl rand -hex 32)
hop_discovery_secret=$(openssl rand -hex 32)
hop_env_tmp=$(mktemp .env.nas.XXXXXX)
awk '!/^(HOP_BIND_IP|HOP_HOST_PORT|HOP_CONTAINER_PORT|APP_URL|SESSION_SECRET|DISCOVERY_SECRET|RESEND_API_KEY|REGISTRATION_MODE)=/' .env.example > "$hop_env_tmp"
awk '!/^(HOP_BIND_IP|HOP_HOST_PORT|HOP_CONTAINER_PORT|HOP_RUN_UID|HOP_RUN_GID|APP_URL|SESSION_SECRET|DISCOVERY_SECRET|RESEND_API_KEY|REGISTRATION_MODE)=/' .env.example > "$hop_env_tmp"
{
printf 'HOP_BIND_IP=%s\n' "$hop_nas_ip"
printf 'HOP_HOST_PORT=50189\nHOP_CONTAINER_PORT=50189\n'
@@ -78,6 +78,24 @@ else
printf '%s\n' '기존 .env를 유지합니다. 비밀값을 다시 생성하지 않습니다.'
fi
# Match the NAS user so owner-only uploaded files remain readable in the NAS file manager.
hop_run_uid=${SUDO_UID:-$(id -u)}
hop_run_gid=${SUDO_GID:-$(id -g)}
if [ "$hop_run_uid" = 0 ]; then
printf '%s\n' 'NAS의 일반 사용자로 로그인한 뒤 sudo sh scripts/configure-nas.sh로 실행하세요.' >&2
exit 1
fi
for hop_identity_key in HOP_RUN_UID HOP_RUN_GID; do
if ! grep -Eq "^${hop_identity_key}=[0-9]+$" .env; then
hop_env_tmp=$(mktemp .env.nas.XXXXXX)
awk -v key="$hop_identity_key" 'index($0,key "=") != 1' .env > "$hop_env_tmp"
case "$hop_identity_key" in HOP_RUN_UID) hop_identity_value=$hop_run_uid ;; HOP_RUN_GID) hop_identity_value=$hop_run_gid ;; esac
printf '%s=%s\n' "$hop_identity_key" "$hop_identity_value" >> "$hop_env_tmp"
mv "$hop_env_tmp" .env
hop_env_tmp=''
fi
done
chmod 600 .env
if grep -Eq '^USER_STORAGE_LIMIT_MB=10240$' .env; then
hop_env_tmp=$(mktemp .env.nas.XXXXXX)
@@ -95,10 +113,15 @@ if ! grep -Eq '^PROXY_DIAGNOSTIC_TOKEN=.{32,}$' .env; then
hop_env_tmp=''
unset hop_diagnostic_token
fi
sh scripts/prepare-nas-storage.sh
hop_yaml_tmp=$(mktemp .compose.nas.XXXXXX)
docker compose --project-name hop --project-directory "$PWD" --env-file .env -f compose.yaml config --no-env-resolution > "$hop_yaml_tmp"
mv "$hop_yaml_tmp" compose.nas.yaml
hop_yaml_tmp=''
chmod 600 compose.nas.yaml
# sudo writes configuration as root; return it to the SSH user for Git/Docker app access.
if [ "$(id -u)" = 0 ]; then
chown "$hop_run_uid:$hop_run_gid" .env compose.nas.yaml
fi
printf '\n%s\n' '완료. Docker 앱에서 프로젝트 이름 hop으로 아래 YAML을 불러오세요.'
printf '%s/compose.nas.yaml\n' "$PWD"

View File

@@ -0,0 +1,38 @@
#!/bin/sh
# Prepare owner-only storage for the NAS user. Does not delete or reset any data.
set -eu
cd "$(dirname "$0")/.."
hop_storage_uid=$(sed -n 's/^HOP_RUN_UID=//p' .env)
hop_storage_gid=$(sed -n 's/^HOP_RUN_GID=//p' .env)
case "$hop_storage_uid:$hop_storage_gid" in
*[!0-9:]*|:*|*:) printf '%s\n' 'HOP_RUN_UID/GID를 확인하세요.' >&2; exit 1 ;;
esac
if [ "$hop_storage_uid" = 0 ]; then
printf '%s\n' '앱은 일반 NAS 사용자 UID로 실행해야 합니다.' >&2
exit 1
fi
if docker inspect hop >/dev/null 2>&1; then
if [ "$(docker inspect --format '{{.State.Running}}' hop)" = true ]; then
printf '%s\n' 'Docker 앱에서 hop 프로젝트를 먼저 중지한 뒤 다시 실행하세요.' >&2
exit 1
fi
if docker inspect --format '{{range .Mounts}}{{if eq .Destination "/data/uploads"}}{{.Type}}{{end}}{{end}}' hop | grep -qx volume; then
printf '%s\n' '기존 업로드 볼륨이 연결돼 있습니다. deploy.md의 저장소 전환 순서를 먼저 진행하세요.' >&2
exit 1
fi
fi
mkdir -p uploads
docker volume create --label com.docker.compose.project=hop --label com.docker.compose.volume=hop_database hop_hop_database >/dev/null
docker run --rm --network none --user 0:0 \
--mount type=volume,source=hop_hop_database,target=/database \
--mount "type=bind,source=$PWD/uploads,target=/uploads" \
alpine:3.22 sh -eu -c '
chown -R "$1:$2" /database /uploads
chmod 700 /database /uploads
for folder in originals temporary chunks; do
mkdir -p "/uploads/$folder"
chmod 700 "/uploads/$folder"
done
chown -R "$1:$2" /uploads
' sh "$hop_storage_uid" "$hop_storage_gid"
printf '%s\n' '파일 저장소 준비 완료: hop/uploads (NAS 사용자 소유, 기존 파일 유지)'