1. sslinks 403: Cloudflare blocks server IP. Add fetcher.proxy_url config
so subscription/flow requests can route through an HTTP proxy.
2. Egress probe: Docker image lacked sing-box. Install sing-box v1.11.4
in the Alpine runtime stage.
3. Collection rename: group by display baseName instead of internal
groupKey, format index as -N instead of %02d. Fixes double-suffix
issue where EnsureUniqueProxyNames appended -2/-3 onto existing 02.
- Dockerfile: 3-stage build (frontend npm build → backend go build → alpine runtime)
- Frontend dist files served from disk at /app/frontend/dist
- server.go: catch-all GET handler serves static files with SPA fallback to index.html
- config.go: new server.frontend_dir option (env: SUB_STORE_SERVER_FRONTEND_DIR)
- API routes (/api/*), download routes, and /health take priority over static serving