chore: 시놀로지(Synology) 전용 파일 및 참조 폐기

서버가 시놀로지에서 클라우드(hz-prod-01, 178.104.200.7)로 이전됨에 따라
시놀로지 전용 문서 11개와 스크립트 3개를 삭제하고 AGENTS.md 참조를 정리한다.

삭제된 문서:
- docs/SYNOLOGY_ACT_RUNNER_REFACTOR_PR_BODY.md
- docs/SYNOLOGY_KIS_COLLECTION_SETUP.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_COMMIT_MESSAGE_TEMPLATE.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_EXECUTION_ONE_PAGER.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_PREFLIGHT_10.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_FIREWALL_PROXY_COPYPASTE.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_FIREWALL_PROXY_TABLE.md
- docs/SYNOLOGY_SNAPSHOT_ADMIN_POC.md

삭제된 스크립트:
- tools/re_register_act_runner_synology.sh
- tools/run_snapshot_admin_synology.sh
- tools/start_act_runner_synology.sh

수정:
- AGENTS.md: Synology CI 참조를 클라우드 서버(hz-prod-01)로 교체
This commit is contained in:
2026-06-26 11:11:38 +09:00
parent 9eb295e2dc
commit 23ba556c17
15 changed files with 1 additions and 1129 deletions
@@ -1,26 +0,0 @@
# Synology Act Runner Split PR Body
## Title
`chore: split Synology act_runner start and re-registration scripts`
## Body
- Added `tools/re_register_act_runner_synology.sh` for explicit host-mode re-registration.
- Added `tools/start_act_runner_synology.sh` for boot-time daemon start only.
- Kept `tools/setup_act_runner.sh` as the bootstrap path, but made the re-registration flow explicit and repeatable.
- Switched the runner registration labels to `self-hosted:host,snapshot-admin-host:host` so the job runs in host mode instead of Docker job containers and can be targeted by a dedicated deployment label.
- Updated `docs/SYNOLOGY_SNAPSHOT_ADMIN_POC.md` and `docs/ROADMAP_WBS.md` so the operator flow and WBS notes match the new runner split.
- The `snapshot_admin.yml` workflow is split into push smoke validation and manual full validation, which reduces routine CI cost while preserving the full web smoke path on demand.
- The deploy workflow now waits for `127.0.0.1:8787/api/state` readiness before asserting success, so startup latency does not fail the run spuriously.
- The `ci.yml` workflow now keeps `push` traffic on the core gate only, with UI/storage validation retained for non-push events.
## Verification
- `python tools/validate_snapshot_admin_workflow_v1.py`
- `python -c "import yaml, pathlib; yaml.safe_load(pathlib.Path('.gitea/workflows/snapshot_admin.yml').read_text(encoding='utf-8'))"`
- `git diff -- .gitea/workflows/snapshot_admin.yml tools/setup_act_runner.sh docs/SYNOLOGY_SNAPSHOT_ADMIN_POC.md docs/ROADMAP_WBS.md`
- Deploy job evidence:
- `healthcheck` retried after startup and passed
- `snapshot-admin-web-v6` returned from the verification step
- `Job succeeded`
-95
View File
@@ -1,95 +0,0 @@
# Synology KIS Data Collection Setup
This note answers how to run:
```powershell
$env:KIS_APP_Key="..."
$env:KIS_APP_Secret="..."
python tools/run_kis_data_collection_v1.py --input-json GatherTradingData.json --sqlite-db src/quant_engine/kis_data_collection.db --output-json Temp/kis_data_collection_v1.json --kis-account real
```
on Synology DSM.
## Rule
Synology is Linux-based, so use `export` or a sourced env file. Do not use Windows `$env:` syntax.
The code reads these exact, case-sensitive names for real accounts:
- `KIS_APP_Key`
- `KIS_APP_Secret`
For mock accounts, the names are:
- `KIS_APP_Key_TEST`
- `KIS_APP_Secret_TEST`
## Recommended DSM Task Scheduler script
Create a `User-defined script` task and run:
```bash
#!/bin/sh
set -eu
ROOT_DIR="/volume1/projects/data_feed"
export KIS_APP_Key="your_real_app_key"
export KIS_APP_Secret="your_real_app_secret"
cd "$ROOT_DIR"
python tools/run_kis_data_collection_v1.py \
--input-json GatherTradingData.json \
--sqlite-db src/quant_engine/kis_data_collection.db \
--output-json Temp/kis_data_collection_v1.json \
--kis-account real
```
## Better practice for secrets
Store secrets in a private env file and source it from the task:
```bash
set -eu
ROOT_DIR="/volume1/projects/data_feed"
SECRETS_FILE="/volume1/projects/data_feed/.secrets/kis_real.env"
. "$SECRETS_FILE"
cd "$ROOT_DIR"
python tools/run_kis_data_collection_v1.py \
--input-json GatherTradingData.json \
--sqlite-db src/quant_engine/kis_data_collection.db \
--output-json Temp/kis_data_collection_v1.json \
--kis-account real
```
Suggested file permissions:
- owner-only read/write
- no shared group access
- no commit to git
## Mock account variant
```bash
export KIS_APP_Key_TEST="your_mock_app_key"
export KIS_APP_Secret_TEST="your_mock_app_secret"
python tools/run_kis_data_collection_v1.py \
--input-json GatherTradingData.json \
--sqlite-db src/quant_engine/kis_data_collection.db \
--output-json Temp/kis_data_collection_v1.json \
--kis-account mock \
--no-live-kis
```
## What the collector writes
- SQLite: `src/quant_engine/kis_data_collection.db`
- JSON summary: `Temp/kis_data_collection_v1.json`
The latest collected summary in this workspace shows:
- `row_count = 25`
- `kis_open_api = 21`
- `gathertradingdata_json = 25`
@@ -1,37 +0,0 @@
# Synology Snapshot Admin Commit Message Template
Use this after a real Synology verification or a final documentation-only update.
## Recommended format
```text
WBS-7.9: Synology snapshot_admin deployment POC and live verification evidence
```
## If the change is documentation-only
```text
WBS-7.9: add Synology deployment checklist, Task Scheduler commands, and evidence template
```
## If the change includes real NAS verification
```text
WBS-7.9: verify Synology snapshot_admin reverse proxy, auth gate, and restart persistence
```
## Commit body template
```text
- Added/updated Synology Task Scheduler launcher script
- Confirmed DSM reverse proxy settings
- Captured curl/browser evidence for local and external access
- Documented completion evidence in WBS-7.9 checklist
```
## Suggested workflow
1. Run the validation commands.
2. Fill `docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md`.
3. Commit with one of the messages above.
4. Push only after the evidence file is complete.
@@ -1,153 +0,0 @@
# Synology Snapshot Admin Deployment Checklist
This checklist is the POC-ready version with concrete values.
## 1. Target paths
- Project root: `/volume1/projects/data_feed`
- Launch script: `/volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh`
- Local DB: `/volume1/projects/data_feed/src/quant_engine/snapshot_admin.db`
- Local seed JSON: `/volume1/projects/data_feed/GatherTradingData.json`
- PID file: `/volume1/projects/data_feed/Temp/snapshot_admin.pid`
- Log file: `/volume1/projects/data_feed/Temp/snapshot_admin.log`
See also: [`docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md`](C:/Temp/data_feed/docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md)
and [`docs/SYNOLOGY_SNAPSHOT_ADMIN_FIREWALL_PROXY_TABLE.md`](C:/Temp/data_feed/docs/SYNOLOGY_SNAPSHOT_ADMIN_FIREWALL_PROXY_TABLE.md)
## 2. Service account
- Preferred: dedicated DSM local user `snapshot-admin`
- Fallback for first POC: `root`
- Required permission: read/write access to `/volume1/projects/data_feed`
## 3. Environment variables
Set these before the Task Scheduler task runs.
- `SNAPSHOT_ADMIN_AUTH_USER=snapshot-admin`
- `SNAPSHOT_ADMIN_AUTH_PASSWORD=<strong-password>`
- `SNAPSHOT_ADMIN_HOST=127.0.0.1`
- `SNAPSHOT_ADMIN_PORT=8787`
- `SNAPSHOT_ADMIN_ALLOW_REMOTE=0`
- `SNAPSHOT_ADMIN_PID_FILE=/volume1/projects/data_feed/Temp/snapshot_admin.pid`
- `SNAPSHOT_ADMIN_LOG_FILE=/volume1/projects/data_feed/Temp/snapshot_admin.log`
- `SNAPSHOT_ADMIN_STATE_URL=http://127.0.0.1:8787/api/state`
- `SNAPSHOT_ADMIN_PUBLIC_STATE_URL=https://admin.example.com/api/state`
## 4. Task Scheduler tasks
### Boot task
- Name: `snapshot-admin-start`
- Trigger: `Boot-up`
- User: `snapshot-admin` or `root`
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh start
```
### Healthcheck task
- Name: `snapshot-admin-healthcheck`
- Trigger: `Scheduled Task`
- Interval: every 5 minutes
- User: same as boot task
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh healthcheck
```
### Restart task
- Name: `snapshot-admin-restart`
- Trigger: manual only
- User: same as boot task
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh restart
```
## 4b. Gitea Actions runner label
Use a unique host label so the deployment job is not mixed with generic self-hosted work.
- Runner label: `snapshot-admin-host`
- Registration example:
```bash
REG_TOKEN="<runner-registration-token>" \
GITEA_URL="http://192.168.123.100:8418" \
RUNNER_LABEL="snapshot-admin-host" \
bash tools/re_register_act_runner_synology.sh
```
- Workflow selector:
```yaml
runs-on: [self-hosted, snapshot-admin-host]
```
## 4c. Queue handling
- If the deploy workflow stays queued, it usually means the host runner is busy.
- Check the job currently holding the runner before re-dispatching.
- Do not keep dispatching deploy runs back-to-back. The workflow already uses `concurrency` to cancel in-progress duplicates.
## 5. Reverse proxy
- DSM path: `Control Panel > Login Portal > Advanced > Reverse Proxy`
- Rule name: `snapshot-admin`
- Source:
- Protocol: `HTTPS`
- Hostname: `admin.example.com`
- Port: `443`
- Path: `/`
- Destination:
- Protocol: `HTTP`
- Hostname: `127.0.0.1`
- Port: `8787`
- TLS certificate: certificate matching `admin.example.com`
## 6. Firewall
- Allow inbound `443/TCP`
- Block inbound `8787/TCP` from WAN
- If needed, allowlist office/VPN CIDRs only
## 7. Verification order
1. Start the service.
2. Confirm `bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh healthcheck` prints `healthcheck ok`.
3. Confirm local `curl -i http://127.0.0.1:8787/api/state`.
- Expect `200 OK`.
- Expect JSON with `version.app = snapshot-admin-web-v7`.
4. Confirm external `curl -i https://admin.example.com/api/state` returns `401`.
- Expect `WWW-Authenticate: Basic`.
5. Confirm authenticated `curl -u 'snapshot-admin:<password>' https://admin.example.com/api/state` returns `200`.
- Expect the same `version.app` value as the local endpoint.
6. Confirm `curl -i https://admin.example.com/tables` after Basic Auth.
- Expect `200 OK` and the Tabler grid page.
7. Open browser `https://admin.example.com/`.
- Expect Basic Auth prompt, then UI render.
8. Open browser `https://admin.example.com/tables`.
- Expect Basic Auth prompt, then grid render.
9. Restart the task or NAS.
10. Repeat steps 2-8 and confirm the response pattern is unchanged.
## 7b. Evidence rule
- Do not mark `WBS-7.9` complete until the external `401`/`200` curl pair, both browser screenshots, and the reverse proxy rule screenshot are archived together.
- Loopback-only smoke tests are useful, but they do not replace the NAS-side live verification.
## 7c. One-page field run sheet
For a compact field execution order, use [`docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_EXECUTION_ONE_PAGER.md`](C:/Temp/data_feed/docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_EXECUTION_ONE_PAGER.md).
## 8. Completion wording
Use the following text only after evidence is collected:
> WBS-7.9 실배포 검증 완료: Synology NAS에서 `tools/run_snapshot_admin_synology.sh` 기반 서비스가 `127.0.0.1:8787`에 정상 기동되고, DSM Reverse Proxy `HTTPS:443 -> HTTP 127.0.0.1:8787` 경유 외부 접속이 Basic Auth와 함께 `200 OK`로 확인되었으며, 미인증 요청은 `401 Unauthorized`로 차단되었다. `/` 및 `/tables` 렌더링과 재시작 후 지속성도 확인되었고, 증빙은 `docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md` 양식으로 보관되었다.
@@ -1,114 +0,0 @@
# Synology Snapshot Admin Deployment Checklist - Filled Example
This is the deployment-ready example for the current repo state.
Replace only the hostname, certificate name, and strong password if your NAS uses different values.
## 1. Target paths
- Project root: `/volume1/projects/data_feed`
- Launch script: `/volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh`
- Local DB: `/volume1/projects/data_feed/src/quant_engine/snapshot_admin.db`
- Local seed JSON: `/volume1/projects/data_feed/GatherTradingData.json`
- PID file: `/volume1/projects/data_feed/Temp/snapshot_admin.pid`
- Log file: `/volume1/projects/data_feed/Temp/snapshot_admin.log`
## 2. Service account
- Preferred DSM user: `snapshot-admin`
- Fallback for first POC: `root`
- Folder access: read/write on `/volume1/projects/data_feed`
## 3. Environment variables
```bash
SNAPSHOT_ADMIN_AUTH_USER=snapshot-admin
SNAPSHOT_ADMIN_AUTH_PASSWORD=<strong-password>
SNAPSHOT_ADMIN_HOST=127.0.0.1
SNAPSHOT_ADMIN_PORT=8787
SNAPSHOT_ADMIN_ALLOW_REMOTE=0
SNAPSHOT_ADMIN_PID_FILE=/volume1/projects/data_feed/Temp/snapshot_admin.pid
SNAPSHOT_ADMIN_LOG_FILE=/volume1/projects/data_feed/Temp/snapshot_admin.log
SNAPSHOT_ADMIN_STATE_URL=http://127.0.0.1:8787/api/state
SNAPSHOT_ADMIN_PUBLIC_STATE_URL=https://admin.example.com/api/state
```
## 4. Task Scheduler
### Boot task
- Name: `snapshot-admin-start`
- User: `snapshot-admin`
- Trigger: `Boot-up`
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh start
```
### Healthcheck task
- Name: `snapshot-admin-healthcheck`
- User: `snapshot-admin`
- Trigger: every 5 minutes
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh healthcheck
```
### Manual restart task
- Name: `snapshot-admin-restart`
- User: `snapshot-admin`
- Trigger: manual
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh restart
```
## 5. Reverse proxy
- DSM path: `Control Panel > Login Portal > Advanced > Reverse Proxy`
- Rule name: `snapshot-admin`
- Source protocol: `HTTPS`
- Source hostname: `admin.example.com`
- Source port: `443`
- Source path: `/`
- Destination protocol: `HTTP`
- Destination hostname: `127.0.0.1`
- Destination port: `8787`
- TLS certificate: `admin.example.com` certificate
## 6. Firewall
- Allow inbound `443/TCP`
- Block inbound `8787/TCP` from WAN
- Allowlist only trusted office/VPN ranges if needed
## 7. Verification commands
```bash
curl -i http://127.0.0.1:8787/api/state
curl -i https://admin.example.com/api/state
curl -u 'snapshot-admin:<strong-password>' https://admin.example.com/api/state
curl -I https://admin.example.com/
curl -I https://admin.example.com/tables
```
## 7b. Final preflight
Use [`docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_PREFLIGHT_10.md`](C:/Temp/data_feed/docs/SYNOLOGY_SNAPSHOT_ADMIN_FINAL_PREFLIGHT_10.md)
immediately before you mark the deployment complete.
## 8. Completion wording
Use this exact wording when evidence is complete:
> WBS-7.9 실배포 검증 완료: Synology NAS에서 `tools/run_snapshot_admin_synology.sh` 기반 서비스가 `127.0.0.1:8787`에 정상 기동되고, DSM Reverse Proxy `HTTPS:443 -> HTTP 127.0.0.1:8787` 경유 외부 접속이 Basic Auth와 함께 `200 OK`로 확인되었으며, 미인증 요청은 `401 Unauthorized`로 차단되었다. `/` 및 `/tables` 렌더링과 재시작 후 지속성도 확인되었고, 증빙은 `docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md` 양식으로 보관되었다.
## 9. What to replace
- `admin.example.com` if your public hostname differs
- `<strong-password>` with your generated password
- TLS certificate name if the DSM certificate uses another label
@@ -1,62 +0,0 @@
# Synology Snapshot Admin Evidence Template
Use this template to close `WBS-7.9` after a real Synology deployment test.
## Deployment metadata
- NAS model:
- DSM version:
- Public hostname:
- Reverse proxy rule name:
- TLS certificate name:
- Service launcher: `tools/run_snapshot_admin_synology.sh`
- Python service bind mode:
- Auth mode: `Basic Auth`
## Local checks
- `curl -i http://127.0.0.1:8787/api/state`
- Result:
- `curl -i http://127.0.0.1:8787/tables`
- Result:
## External checks
- `curl -i https://<public-host>/api/state`
- Result:
- `curl -u '<user>:<password>' https://<public-host>/api/state`
- Result:
- `curl -i https://<public-host>/tables`
- Result:
## Browser checks
- `https://<public-host>/`
- Result:
- `https://<public-host>/tables`
- Result:
## Restart persistence
- Restart method used:
- Restart time:
- `healthcheck` result after restart:
- Time elapsed after restart:
## Evidence attachments
- Screenshot: DSM reverse proxy rule
- Screenshot: browser `/`
- Screenshot: browser `/tables`
- Log snippet: `Temp/snapshot_admin.log`
- `curl` output archive:
## Completion statement
- `WBS-7.9` completion condition met:
- local endpoint `200`
- external unauthenticated `401`
- external authenticated `200`
- browser render verified
- restart persistence verified
- evidence archived
@@ -1,89 +0,0 @@
# Synology Snapshot Admin Final Execution One-Pager
Use this sheet on the NAS during the live verification run.
## Goal
Confirm that `snapshot_admin_server_v1.py` runs on Synology with loopback binding, DSM reverse proxy exposure, and Basic Auth protection.
## Required values
- Project root: `/volume1/projects/data_feed`
- Launcher: `/volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh`
- Local URL: `http://127.0.0.1:8787/api/state`
- Public URL: `https://admin.example.com/api/state`
- Public UI URL: `https://admin.example.com/`
- Public tables URL: `https://admin.example.com/tables`
## Execution order
1. Start the service.
- `bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh start`
2. Confirm the healthcheck.
- `bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh healthcheck`
- Expected: `healthcheck ok`
3. Confirm local loopback.
- `curl -i http://127.0.0.1:8787/api/state`
- Expected: `200 OK`
- Expected JSON field: `version.app = snapshot-admin-web-v7`
4. Confirm unauthenticated external access.
- `curl -i https://admin.example.com/api/state`
- Expected: `401 Unauthorized`
- Expected header: `WWW-Authenticate: Basic`
5. Confirm authenticated external access.
- `curl -u 'snapshot-admin:<password>' https://admin.example.com/api/state`
- Expected: `200 OK`
- Expected same `version.app` as local loopback
6. Confirm tables page.
- `curl -i https://admin.example.com/tables`
- Expected: `200 OK`
- Expected: Tabler grid HTML
7. Confirm browser render.
- Open `https://admin.example.com/`
- Open `https://admin.example.com/tables`
- Expected: Basic Auth prompt, then render
8. Confirm persistence.
- Restart the task or NAS
- Re-run steps 2-7
- Expected: identical response pattern after restart
## Queue check
If the deployment workflow stays queued for more than a few minutes:
1. Confirm the runner is registered with the host label.
- `RUNNER_LABEL=snapshot-admin-host`
- Re-register with `bash tools/re_register_act_runner_synology.sh` after setting the registration token.
2. Confirm the runner daemon is running.
- `bash tools/start_act_runner_synology.sh`
3. Confirm the queue target is the host runner label.
- Deploy workflow uses `runs-on: [self-hosted, snapshot-admin-host]`
4. If another job is occupying the runner, wait for it to finish or cancel the stale workflow from Gitea.
5. Re-dispatch `snapshot_admin_deploy.yml` after the runner is idle.
## Pass criteria
- Loopback `200` confirmed.
- External unauthenticated `401` confirmed.
- External authenticated `200` confirmed.
- `/` and `/tables` browser render confirmed.
- Restart persistence confirmed.
- DSM reverse proxy and firewall screenshots archived.
## Workflow success evidence
If you need the deploy-job proof from the NAS runner before the full external closeout:
- `healthcheck` retried after startup and passed on the NAS runner.
- `snapshot-admin-web-v6` was returned by the deploy verification step.
- The workflow finished with `Job succeeded`.
This proves the deploy job can launch, wait for readiness, and validate locally on Synology.
It does not replace the external reverse-proxy/browser closeout evidence above.
## Do not close WBS-7.9 unless
- The `401`/`200` curl pair is saved.
- Both browser screenshots are saved.
- The DSM reverse proxy rule screenshot is saved.
- The completion wording in `docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST.md` is used only after evidence is archived.
@@ -1,29 +0,0 @@
# Synology Snapshot Admin Final Preflight 10
Use this immediately before declaring `WBS-7.9` complete.
1. Confirm the Python service is running on `127.0.0.1:8787`.
2. Confirm `bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh healthcheck` returns `healthcheck ok`.
3. Confirm `curl -i http://127.0.0.1:8787/api/state` returns `200 OK`.
4. Confirm `curl -i https://admin.example.com/api/state` returns `401 Unauthorized` without credentials.
5. Confirm `curl -u 'snapshot-admin:<strong-password>' https://admin.example.com/api/state` returns `200 OK`.
6. Confirm `https://admin.example.com/` renders in a browser after Basic Auth.
7. Confirm `https://admin.example.com/tables` renders in a browser after Basic Auth.
8. Confirm the DSM reverse proxy rule still maps `HTTPS:443 -> HTTP 127.0.0.1:8787`.
9. Confirm the firewall still blocks `8787/TCP` from WAN.
10. Restart the service or NAS and repeat steps 2 through 7.
## Evidence to archive
- `curl` output for steps 3 through 5
- Browser screenshots for steps 6 and 7
- DSM reverse proxy screenshot for step 8
- Firewall screenshot for step 9
- Restart proof for step 10
## Pass condition
Declare `WBS-7.9` complete only when all 10 steps pass and the evidence files are saved using:
- [`docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md`](C:/Temp/data_feed/docs/SYNOLOGY_SNAPSHOT_ADMIN_EVIDENCE_TEMPLATE.md)
- [`docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md`](C:/Temp/data_feed/docs/SYNOLOGY_SNAPSHOT_ADMIN_DEPLOYMENT_CHECKLIST_FILLED.md)
@@ -1,31 +0,0 @@
# Synology Snapshot Admin Firewall and Reverse Proxy Copy-Paste
Use these values verbatim in DSM.
## Reverse proxy
- Rule name: `snapshot-admin`
- Source protocol: `HTTPS`
- Source hostname: `admin.example.com`
- Source port: `443`
- Source path: `/`
- Destination protocol: `HTTP`
- Destination hostname: `127.0.0.1`
- Destination port: `8787`
## Firewall
- Allow: `443/TCP` from WAN or trusted CIDR
- Deny: `8787/TCP` from WAN
- Optional allow: `443/TCP` from office/VPN CIDR only
## Certificate binding
- Hostname: `admin.example.com`
- Bind to: reverse proxy rule `snapshot-admin`
## Notes
- Do not expose `8787/TCP` directly.
- Keep Basic Auth enabled in the Python service.
- Use `127.0.0.1` for the destination host unless direct-bind testing is intentional.
@@ -1,38 +0,0 @@
# Synology Snapshot Admin Firewall and Reverse Proxy Table
Use these values for the first POC.
## Reverse proxy rule
| Field | Value |
|---|---|
| Rule name | `snapshot-admin` |
| Source protocol | `HTTPS` |
| Source hostname | `admin.example.com` |
| Source port | `443` |
| Source path | `/` |
| Destination protocol | `HTTP` |
| Destination hostname | `127.0.0.1` |
| Destination port | `8787` |
## Firewall rules
| Rule | Action | Source | Destination | Port |
|---|---|---|---|---|
| Reverse proxy public entry | Allow | WAN or trusted public CIDR | NAS | `443/TCP` |
| Raw service port | Deny | WAN | NAS | `8787/TCP` |
| Optional office/VPN allowlist | Allow | Office/VPN CIDR only | NAS | `443/TCP` |
## Certificate
| Field | Value |
|---|---|
| Type | TLS certificate |
| Hostname | `admin.example.com` |
| Binding | Reverse proxy rule `snapshot-admin` |
## Notes
- Keep `8787/TCP` private.
- Keep Basic Auth enabled in the Python service.
- Use `127.0.0.1` for the backend destination unless you are explicitly testing direct bind mode.
-257
View File
@@ -1,257 +0,0 @@
# Synology Snapshot Admin POC
This guide enables external access to the Python snapshot admin service on Synology without exposing the raw service port to the internet.
## Recommended topology
1. Keep the Python service bound to loopback only:
```bash
python tools/run_snapshot_admin_server_v1.py \
--host 127.0.0.1 \
--port 8787 \
--db src/quant_engine/snapshot_admin.db \
--seed GatherTradingData.json
```
2. Put Synology DSM reverse proxy in front of it:
- Source: `https://<public-host>:443`
- Destination: `http://127.0.0.1:8787`
- Keep the service port closed from direct WAN access.
3. Add browser authentication with the built-in Basic Auth gate:
- Set `SNAPSHOT_ADMIN_AUTH_USER`
- Set `SNAPSHOT_ADMIN_AUTH_PASSWORD`
- Or pass `--auth-user` and `--auth-password` on the wrapper command
4. Verify from the NAS:
```bash
curl -i http://127.0.0.1:8787/api/state
curl -u "$SNAPSHOT_ADMIN_AUTH_USER:$SNAPSHOT_ADMIN_AUTH_PASSWORD" http://127.0.0.1:8787/api/state
```
5. Verify from outside the NAS:
- Open `https://<public-host>/`
- The browser should prompt for Basic Auth
- `https://<public-host>/tables` should render after login
## DSM Checklist
Use these exact values for the first POC.
1. **DSM app path**
- `Control Panel`
- `Login Portal`
- `Advanced`
- `Reverse Proxy`
2. **Create reverse proxy rule**
- Description: `snapshot-admin`
- Source protocol: `HTTPS`
- Source hostname: your public DNS name, for example `admin.example.com`
- Source port: `443`
- Source path: `/`
- Destination protocol: `HTTP`
- Destination hostname: `127.0.0.1`
- Destination port: `8787`
3. **Certificate**
- Attach a valid TLS certificate for the public hostname
- Prefer a Synology-managed or imported certificate that matches `admin.example.com`
4. **Firewall**
- Allow inbound `443/TCP` only for the reverse proxy endpoint
- Do not expose `8787/TCP` on WAN
- If the NAS must be reachable only from a VPN or office IP range, allowlist those ranges and block the rest
5. **Service start policy**
- Start the Python service on boot or via DSM Task Scheduler
- Keep it bound to `127.0.0.1` unless you intentionally use direct bind mode
- If you use direct bind mode, keep `--allow-remote` and Basic Auth enabled together
- For Gitea Actions runner verification, register `act_runner` with a dedicated host label (`self-hosted:host,snapshot-admin-host:host`) if you want to avoid Docker job containers and the `Cleaning up container` log line
- Preferred launcher script: `tools/run_snapshot_admin_synology.sh`
- Gitea CI deploy path: trigger `.gitea/workflows/snapshot_admin_deploy.yml` `workflow_dispatch` and let the host runner call the launcher script
- Runner bootstrap: `tools/re_register_act_runner_synology.sh`
- Runner daemon start: `tools/start_act_runner_synology.sh`
6. **Runner re-registration**
- Use this when you want to switch an existing runner from Docker mode to host mode:
```bash
cd /volume1/projects/data_feed
REG_TOKEN="<runner-registration-token>" \
GITEA_URL="http://192.168.123.100:8418" \
bash tools/re_register_act_runner_synology.sh
```
- Expected effect:
- removes the existing `.runner` registration file
- registers `self-hosted:host,snapshot-admin-host:host`
- writes an updated `config.yaml`
- If the old runner remains listed in Gitea, remove it from the repository runner page and re-run the command above
7. **Runner start**
- After re-registration, start the daemon:
```bash
bash tools/start_act_runner_synology.sh
```
- Expected effect:
- launches `act_runner daemon` using the existing config
- records `runner.pid` and `runner.log` under the runner directory
## DSM Task Scheduler
Create two scheduled tasks in `Control Panel > Task Scheduler`.
1. **Boot task**
- Task name: `snapshot-admin-start`
- User: `root` or a dedicated service account with access to the project folder
- Event: `Boot-up`
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh start
```
2. **Healthcheck task**
- Task name: `snapshot-admin-healthcheck`
- User: same as boot task
- Event: `Scheduled Task`
- Repeat: every 5 minutes
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh healthcheck
```
3. **Manual restart task**
- Task name: `snapshot-admin-restart`
- User: same as boot task
- Event: `Scheduled Task`
- Repeat: manual only, or keep disabled until needed
- Command:
```bash
bash /volume1/projects/data_feed/tools/run_snapshot_admin_synology.sh restart
```
## Direct bind mode
Direct binding to `0.0.0.0` is allowed only when both auth values are configured:
```bash
python tools/run_snapshot_admin_server_v1.py \
--host 0.0.0.0 \
--port 8787 \
--allow-remote \
--auth-user "$SNAPSHOT_ADMIN_AUTH_USER" \
--auth-password "$SNAPSHOT_ADMIN_AUTH_PASSWORD"
```
Use this only if you have a separate firewall or VPN rule in place. The default POC path is still loopback + reverse proxy.
## Validation
Run the unit/web checks before and after deployment:
```bash
python -m pytest tests/unit/test_snapshot_admin_web_v1.py -q
python tools/validate_snapshot_admin_web_v1.py
```
The auth gate is part of the service now, so public exposure without credentials is rejected by the server itself.
## Curl checklist
Use this as the POC run sheet.
1. Local service check:
```bash
curl -i http://127.0.0.1:8787/api/state
```
Expected:
- `200 OK`
- JSON payload contains `version.app`
2. Reverse proxy auth challenge:
```bash
curl -i https://<public-host>/api/state
```
Expected:
- `401 Unauthorized`
- `WWW-Authenticate: Basic`
3. Reverse proxy authenticated access:
```bash
curl -u '<user>:<password>' https://<public-host>/api/state
```
Expected:
- `200 OK`
- JSON payload contains the same `version.app`
4. UI rendering:
```bash
curl -I https://<public-host>/
curl -I https://<public-host>/tables
```
Expected:
- `200 OK` after auth
- HTML response, not a redirect to the raw port
5. Restart persistence:
```bash
bash tools/run_snapshot_admin_synology.sh restart
bash tools/run_snapshot_admin_synology.sh healthcheck
```
Expected:
- `healthcheck ok`
- The proxy URL continues to answer after the service restarts
## Live verification
Use this sequence on the actual Synology box after the reverse proxy rule is in place:
1. Start the service and confirm the local health endpoint:
```bash
curl -i http://127.0.0.1:8787/api/state
```
2. Confirm the auth gate:
```bash
curl -i https://<public-host>/api/state
```
Expected result:
- `401 Unauthorized` when no credentials are provided
- `200 OK` when valid Basic Auth credentials are supplied
3. Confirm the browser surface:
- Open `https://<public-host>/`
- Sign in with the Basic Auth credentials
- Open `https://<public-host>/tables`
- Confirm rows render from the three SQLite sources
4. Confirm the deployment survives a process restart:
- Restart the Python service or the task that launches it
- Re-run `curl -i http://127.0.0.1:8787/api/state`
- Re-open the browser URL and confirm login still works
5. Archive evidence:
- Save the `curl` outputs
- Save a screenshot of `/` and `/tables`
- Record the DSM reverse proxy rule values and certificate name