Skip to content

sonozaki7/kyc

Repository files navigation

KYC Manager Uploader App

Self-hosted KYC link + upload application with:

  • Admin + manager RBAC
  • Public client upload flow with consent
  • Storage backend switch:
    • local filesystem (demo mode)
    • WebDAV (one-cloud.org / Nextcloud / NAS)
  • Per-manager folder contract under KYC_vault/managers/<manager_code>/INBOX/S_<session_uuid>

Quick start

  1. Install dependencies:
npm install
  1. Create .env from .env.example and set values. For local demo mode (default):

    • STORAGE_BACKEND=local
    • LOCAL_STORAGE_ROOT=local_vault
    • Files are saved under: <LOCAL_STORAGE_ROOT>/<VAULT_ROOT>/managers/<manager_code>/INBOX/S_<session_uuid>/...

    To switch back to one-cloud / NAS:

    • STORAGE_BACKEND=webdav
    • Nextcloud:
      • WEBDAV_MODE=nextcloud
      • WEBDAV_BASE_URL=https://one-cloud.org (or full DAV root URL)
      • Upload path: https://one-cloud.org/remote.php/dav/files/<username>/<VAULT_ROOT>/...
    • Generic NAS (UGREEN / standard WebDAV):
      • WEBDAV_MODE=generic
      • WEBDAV_BASE_URL=https://<nas-host>:5006
      • VAULT_ROOT=<actual top-level folder exposed by NAS account> (example: KYC)
      • Upload path: https://<nas-host>:5006/<VAULT_ROOT>/...
      • If NAS cert is self-signed (local/dev only):
        • WEBDAV_ALLOW_SELF_SIGNED_TLS=true Public KYC upload UI is mobile-first by default (PUBLIC_UPLOAD_MOBILE_ONLY=true). For local phone handoff via QR code:
    • Preferred: set MOBILE_PUBLIC_BASE_URL=http://<your-lan-ip>:3000
    • Or keep it empty and use AUTO_LAN_BASE_URL=true for auto LAN IP detection
    • Do not leave QR handoff on localhost if the client scans from another device
    • Ensure laptop and phone are on the same Wi-Fi/hotspot network
    • If multiple network adapters are active, set MOBILE_PUBLIC_BASE_URL explicitly
    • For the best in-browser camera quality (custom recorder), use HTTPS or localhost. On plain http://<lan-ip>:3000, mobile browsers fall back to native camera capture.
    • Install ffmpeg to enable automatic high-quality video compression on upload:
      • macOS: brew install ffmpeg
  2. Initialize database schema:

npm run db:init
  1. Seed first admin:
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD='change-me' npm run db:seed-admin
  1. Start app:
npm run dev
  1. Open http://localhost:3000.

Production deployment (shared VPS + existing reverse proxy)

This repo's production path is intentionally simple:

  • Dockerfile for the Node app with ffmpeg
  • deploy/docker-compose.prod.yml for app + Postgres
  • deploy/.env.prod.example as the production env template
  • deploy/deploy-vps.sh to build/start the stack
  • deploy/backup-db.sh for database backups
  • deploy/generate-secrets.sh for strong secrets
  • deploy/nginx-site.example.conf as an example reverse-proxy site

The app does not manage TLS or port 80/443 itself anymore. It listens only on 127.0.0.1:<APP_PORT>, and your VPS reverse proxy should forward your domain to it.

1) DNS and VPS prep

  1. Create a DNS A record for your domain (example: taviaverify.com) to your VPS IP.
  2. SSH into the VPS and install Docker + Docker Compose plugin.
  3. Make sure your existing reverse proxy can add a new site for your domain.
  4. Ensure the reverse proxy allows uploads of at least 300M.

2) Upload project and configure env

On VPS:

git clone <your-repo-url> kyc
cd kyc
cp deploy/.env.prod.example deploy/.env.prod

Edit deploy/.env.prod:

  • Set APP_PORT to a free localhost port, for example 3100
  • Set APP_DATA_DIR to a persistent host path, for example /home/newuser/taviaverify-data
  • Set strong POSTGRES_PASSWORD, JWT_SECRET, ADMIN_PASSWORD
  • Set PUBLIC_BASE_URL and MOBILE_PUBLIC_BASE_URL to https://<your-domain>
  • Keep STORAGE_BACKEND=local for VPS-local storage, or switch to webdav for NAS/Nextcloud

Optional helper to generate strong secrets:

./deploy/generate-secrets.sh

3) Launch the app stack

mkdir -p /home/newuser/taviaverify-data
./deploy/deploy-vps.sh

The app becomes reachable only on:

http://127.0.0.1:<APP_PORT>

Health check:

curl http://127.0.0.1:<APP_PORT>/api/healthz

4) Point your reverse proxy to the app

If your VPS uses Nginx, start with deploy/nginx-site.example.conf and forward your domain to:

127.0.0.1:<APP_PORT>

If you use another reverse proxy, the rule is the same:

  • terminate HTTPS there
  • forward traffic to 127.0.0.1:<APP_PORT>
  • preserve Host and X-Forwarded-* headers

Then open:

  • https://<your-domain>
  • https://<your-domain>/api/healthz

5) Operations

  • View logs:
docker compose --env-file deploy/.env.prod -f deploy/docker-compose.prod.yml logs -f app
  • Pull/rebuild after changes:
git pull
./deploy/deploy-vps.sh
  • DB backup:
./deploy/backup-db.sh

6) CI/CD

This repo includes deploy-production.yml for GitHub Actions.

Required GitHub Secrets:

  • VPS_HOST
  • VPS_USER
  • VPS_APP_PATH
  • VPS_SSH_KEY

The workflow:

  • syncs the repository to your VPS path
  • keeps deploy/.env.prod on the server
  • runs ./deploy/deploy-vps.sh
  • checks https://taviaverify.com/api/healthz

Core paths

  • Public upload: /s/:token
  • Manager sessions: /app/sessions
  • Manager settings: /app/settings
  • Admin dashboard: /admin

API overview

  • Auth:
    • POST /api/auth/login
    • POST /api/auth/logout
    • GET /api/auth/me
  • Manager:
    • POST /api/manager/sessions
    • GET /api/manager/sessions
    • GET /api/manager/sessions/:id
    • GET /api/manager/settings
  • Admin:
    • PATCH /api/admin/account/password
    • POST /api/admin/managers
    • GET /api/admin/managers
    • PATCH /api/admin/managers/:id/disable
    • POST /api/admin/managers/:id/provision-folders
    • GET /api/admin/sessions
    • GET /api/admin/audit
    • GET /api/admin/system-limits
    • PATCH /api/admin/system-limits
    • GET /api/admin/health
  • Public:
    • GET /api/public/session/:token
    • GET /api/public/session/:token/qr.svg
    • POST /api/public/session/:token/consent
    • POST /api/public/session/:token/upload

Security notes

  • Session token stored hashed in DB (sha256).
  • Public endpoints are rate-limited.
  • Request logs avoid token/body logging.
  • Public upload endpoint can enforce mobile-only clients (PUBLIC_UPLOAD_MOBILE_ONLY=true).
  • API should run on a DNS-only (grey-clouded) subdomain in production for large uploads.
  • Uploaded verification videos are re-encoded server-side (when ffmpeg is available) using visually-lossless defaults and only kept when the output is smaller than the original.

Demo storage note

  • In local mode, uploaded files are written on your MacBook to LOCAL_STORAGE_ROOT.
  • The app still records logical vault paths (for easy future switch to WebDAV).

Manual Nextcloud setup (one-time)

  1. Create dedicated uploader user and app password.
  2. Ensure vault structure exists:
    • KYC_vault/managers/<manager_code>/INBOX
  3. Share each KYC_vault/managers/<manager_code>/ to the matching manager in Nextcloud.
  4. Keep manager re-share disabled unless explicitly needed.

Manual UGREEN NAS setup (one-time)

  1. In UGOS Pro, open File Service and enable WebDAV.
  2. Enable HTTPS WebDAV and confirm port (default commonly 5006; HTTP usually 5005).
  3. Create a dedicated uploader account and grant only the required shared folder permissions.
  4. Create or select the vault shared folder (for example KYC_vault).
  5. Set in .env:
    • STORAGE_BACKEND=webdav
    • VAULT_ROOT=<folder exposed at WebDAV root> (for example KYC)
    • WEBDAV_MODE=generic
    • WEBDAV_BASE_URL=https://<nas-host>:5006
    • WEBDAV_USERNAME=<uploader-user>
    • WEBDAV_APP_PASSWORD=<uploader-password>
  6. If the NAS certificate is self-signed:
    • Local testing only: set WEBDAV_ALLOW_SELF_SIGNED_TLS=true
    • Production: use a trusted certificate and keep WEBDAV_ALLOW_SELF_SIGNED_TLS=false

About

KYC system for ID and face verification

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors