Skip to content

ตัวเลือกการตั้งค่า

CORS

คุณเปลี่ยนค่า CORS เริ่มต้นสำหรับการขอและแลก challenge ได้ด้วยการตั้งตัวแปรสภาพแวดล้อม CORS_ORIGIN ตอนรันเซิร์ฟเวอร์ ค่าเริ่มต้นคือ * ซึ่งอนุญาตทุก origin ถ้าต้องการหลาย origin ให้คั่นด้วยจุลภาค เช่น domain1.tld,domain2.tld,...

Asset server

Asset server ถูกปิดไว้โดยค่าเริ่มต้น เปิดใช้ได้โดยตั้งตัวแปรสภาพแวดล้อม ENABLE_ASSETS_SERVER เป็น true แล้วไฟล์จะถูกเสิร์ฟจาก endpoint /assets

จากนั้นอย่าลืมตั้ง WIDGET_VERSION และ WASM_VERSION ให้ตรงกับเวอร์ชันของไฟล์วิดเจ็ตและ WASM ที่คุณต้องการเสิร์ฟ ค่าเริ่มต้นคือ latest ซึ่งจะเสิร์ฟเวอร์ชันล่าสุด แต่ไม่แนะนำบนโปรดักชัน เพราะอาจได้การเปลี่ยนแปลงที่ทำให้ระบบพัง

เวอร์ชันที่ใช้ได้คือรีลีสบน npm ของ @cap.js/widget และ @cap.js/wasm ตัวอย่างเช่น:

env
ENABLE_ASSETS_SERVER=true
WIDGET_VERSION=0.1.56
WASM_VERSION=0.0.7

ไฟล์ของคุณจะถูกเสิร์ฟจากเส้นทางต่อไปนี้:

  • /assets/widget.js
  • /assets/floating.js
  • /assets/cap_wasm_bg.wasm
  • /assets/cap_wasm.js

นำไปใช้ในแอปของคุณได้โดยตั้ง src ของสคริปต์วิดเจ็ตให้ชี้ไปยังเส้นทางที่เหมาะสม เช่น:

html
<script src="https://<server url>/assets/widget.js"></script>

สำหรับโหมดลอย ให้ใช้:

html
<script src="https://<server url>/assets/floating.js"></script>

และตั้ง window.CAP_CUSTOM_WASM_URL ให้ชี้ไปยังไฟล์ cap_wasm_bg.wasm แบบนี้:

js
window.CAP_CUSTOM_WASM_URL = "https://<server url>/assets/cap_wasm_bg.wasm";

โดยค่าเริ่มต้น ไฟล์เหล่านี้ถูกดึงมาจาก process.env.CACHE_HOST (ซึ่งมีค่าเริ่มต้นเป็น https://cdn.jsdelivr.net) เปลี่ยนได้โดยตั้งตัวแปร CACHE_HOST ตอนรันเซิร์ฟเวอร์

แก้ปัญหา

ไฟล์จะถูกดาวน์โหลดจาก CACHE_HOST เข้าไปใน Redis ตอนเริ่มระบบ แล้วรีเฟรชทุกชั่วโมง ถ้า endpoint ของไฟล์ตอบว่า Asset not cached yet แปลว่าการดาวน์โหลดยังไม่เกิดขึ้น ให้ตรวจสอบว่า:

  • ตั้ง ENABLE_ASSETS_SERVER=true ไว้ที่คอนเทนเนอร์ Cap จริงหรือไม่ ถ้าคุณแก้ในไฟล์ compose ให้สร้างคอนเทนเนอร์ใหม่ หากไม่ได้ตั้งค่านี้ endpoint /assets/* จะตอบ 404 พร้อมอธิบายว่า asset server ถูกปิดอยู่
  • คอนเทนเนอร์ออกอินเทอร์เน็ตไปยัง CACHE_HOST ได้หรือไม่ ถ้าดาวน์โหลดล้มเหลว เซิร์ฟเวอร์จะบันทึกบรรทัดที่มีข้อความ [asset server] failed to update assets cache ตอนเริ่มระบบ แล้วลองใหม่ทุกชั่วโมง
  • WIDGET_VERSION และ WASM_VERSION ชี้ไปยังเวอร์ชันที่มีอยู่จริงบน npm หรือไม่

การจำกัดอัตราคำขอ

endpoint ของ challenge ถูกจำกัดอัตราตาม IP ของไคลเอนต์ด้วยหน้าต่างเวลาแบบคงที่ ค่าเริ่มต้นคือ 30 คำขอทุก 5 วินาที คุณเปลี่ยนค่าจำกัดรวมได้ที่ Settings ในแดชบอร์ด (หรือผ่าน PUT /settings/ratelimit) และกำหนดทับรายคีย์ได้ในแท็บ Configuration ของคีย์นั้น เมื่อเกินขีดจำกัด คำขอจะได้รับการตอบกลับ 429 พร้อมเฮดเดอร์ X-RateLimit-Remaining: 0

endpoint /siteverify มีไว้ใช้แบบเซิร์ฟเวอร์ถึงเซิร์ฟเวอร์ จึงไม่ถูกจำกัดอัตราโดยค่าเริ่มต้น

IP ของไคลเอนต์เมื่ออยู่หลังพร็อกซี

Standalone ระบุตัวไคลเอนต์โดยดูเฮดเดอร์ X-Forwarded-For, X-Real-IP และ CF-Connecting-IP (ตามลำดับนี้) แล้วค่อยถอยไปใช้ที่อยู่ของซ็อกเก็ต ถ้าคุณอยู่หลัง reverse proxy ที่ใช้เฮดเดอร์อื่น ให้ตั้ง RATELIMIT_IP_HEADER ใน env ของคุณ (หรือกำหนดเฮดเดอร์ IP ที่ Settings > Headers ในแดชบอร์ด) เช่น ถ้าอยู่หลัง Cloudflare คุณอาจตั้งเป็น cf-connecting-ip

ตรวจให้แน่ใจว่าพร็อกซีของคุณส่งต่อ IP ของไคลเอนต์จริง ๆ สำหรับ nginx:

nginx
location / {
    proxy_pass http://localhost:3000;
    proxy_set_header X-Forwarded-For $remote_addr;
}

ถ้าไม่ทำแบบนี้ ทุกคำขอจะดูเหมือนมาจาก IP ของพร็อกซีเอง และไคลเอนต์ทั้งหมดจะใช้โควตาจำกัดอัตราร่วมกันถังเดียว อีกทั้งพึงทราบว่า X-Forwarded-For ถูกเชื่อถือตามที่ส่งมา เซิร์ฟเวอร์จึงต้องไม่เปิดให้เข้าถึงตรงจากอินเทอร์เน็ต ไม่เช่นนั้นไคลเอนต์จะปลอมเฮดเดอร์เพื่อเลี่ยงการจำกัดอัตราได้

Redis / Valkey

Cap Standalone ใช้ Redis (หรือ Valkey) สำหรับการเก็บข้อมูลทั้งหมด ให้ตั้งตัวแปรสภาพแวดล้อม REDIS_URL เป็นสตริงเชื่อมต่อ Redis ของคุณ ค่าเริ่มต้นคือ redis://localhost:6379

การตั้งค่าที่เราแนะนำใช้ Valkey (ที่เก็บข้อมูลซึ่งเข้ากันได้กับ Redis) ผ่านไฟล์ docker-compose ในคู่มือเริ่มต้นใช้งาน

ถ้าคุณใช้ Redis อินสแตนซ์เดียวร่วมกันหลาย Cap (หรือร่วมกับแอปอื่น) ให้ตั้ง REDIS_PREFIX เพื่อแยก namespace ของคีย์ทั้งหมด เช่น REDIS_PREFIX=cap: จะเก็บ session เป็น cap:session:... และเก็บ metric เป็น cap:metrics:... เป็นต้น ค่าเริ่มต้นคือว่าง ระบบที่ใช้งานอยู่แล้วจึงไม่ได้รับผลกระทบ

ข้อความแสดงข้อผิดพลาด

ข้อความแสดงข้อผิดพลาดจะถูกปิดบังโดยค่าเริ่มต้น และบันทึกลงคอนโซลแทน หากต้องการปิดการบันทึกข้อผิดพลาด ให้ตั้ง DISABLE_ERROR_LOGGING=true และหากต้องการปิดการปิดบังข้อความ ให้ตั้ง SHOW_ERRORS=true

ปริศนา time-lock แบบ RSW

Standalone รองรับปริศนา time-lock แบบ RSW ในฐานะทางเลือกที่ต้านทาน GPU แทน PoW แบบ SHA-256 โดยต้องเลือกเปิดเอง มันตั้งค่าแยกรายคีย์ ดังนั้นบางคีย์จะใช้ RSW ขณะที่คีย์อื่นยังใช้ challenge แบบ SHA-256 ตามค่าเริ่มต้นก็ได้

วิธีเปิดใช้คือเปิดแท็บ Configuration ของคีย์นั้น แล้วสลับ Challenge protocol เป็น "RSW time-lock puzzle" ครั้งแรกที่คุณเปิด RSW กับคีย์ใดก็ตาม Standalone จะสร้างมอดุลัสขนาด 2048 บิต (ราว 1-3 วินาที) แล้วเก็บไว้ใน Redis คู่กุญแจชุดเดียวกันจะถูกใช้ซ้ำกับทุกคีย์ที่เปิด RSW คุณจึงไม่ต้องจัดการเอง

ระดับความยากควบคุมด้วยแถบเลื่อน RSW squarings (พารามิเตอร์ t คือจำนวนครั้งที่ไคลเอนต์ต้องยกกำลังสองตามลำดับ) ค่าเริ่มต้นคือ 75_000 ซึ่งคิดเป็นงานฝั่งไคลเอนต์ราว 300-800 มิลลิวินาทีบนฮาร์ดแวร์สมัยใหม่ ลดลงถ้าอยากให้ challenge เบาลง เพิ่มขึ้นถ้าอยากหน่วงแรงขึ้น ช่วงที่ใช้ได้คือ 10_000-300_000

คุณกำหนดขนาดมอดุลัสทับได้ตอนบูตด้วย RSW_BITS=2048 (ค่าเริ่มต้น) ขนาดที่เล็กกว่านี้มีประโยชน์เฉพาะตอนทดสอบ

TIP

RSW เป็นแบบเลือกเปิดเองและยังอยู่ในขั้นทดลอง ไปป์ไลน์มาตรฐานของ Cap ยังใช้ PoW แบบ SHA-256 อยู่ ตัววิดเจ็ตตรวจจับ challenge แบบ RSW ได้เองจากรูปแบบข้อมูล การสลับสวิตช์จึงเป็นสิ่งเดียวที่คุณต้องทำ

challenge แบบ instrumentation

Cap Standalone รองรับ challenge แบบ JavaScript instrumentation เพื่อรับมือกับตัวแก้ proof-of-work พร้อมตัวเลือกสำหรับสกัดเบราว์เซอร์แบบ headless ไม่ให้แก้ผ่าน โดย challenge แบบ instrumentation จะเปิดใช้งานเป็นค่าเริ่มต้นเมื่อสร้าง site key ใหม่

คุณเปิดหรือปิด challenge แบบ instrumentation ได้ในหน้าตั้งค่าของ site key และหากต้องการสกัดเบราว์เซอร์ headless ให้เปิด "Attempt to block headless browsers" ในการตั้งค่าของคีย์

พึงทราบว่าระดับ instrumentation ที่สูงอาจลดอัตราการสร้างลงอย่างมาก เราแนะนำให้คงไว้ที่ระดับ 3 เว้นแต่คุณต้องการการทำให้อ่านยากที่เข้มขึ้น ถ้าพบว่าระดับ 3 ช้าเกินไป ระดับ 1 จะเร็วกว่ามากบนคอร์เดียว

ฐานข้อมูล IP

การค้นหาประเทศและ ASN เลือกใช้ผู้ให้บริการได้สามราย ตั้งค่าได้ที่ Settings > IP Data > Country & ASN data ในแดชบอร์ด ได้แก่ DB-IP Lite, MaxMind GeoLite2 และ API ของ IPInfo

สำหรับ DB-IP และ MaxMind ไฟล์ .mmdb จะถูกดาวน์โหลดไปไว้ที่ /usr/src/app/data/ ภายในคอนเทนเนอร์

สิทธิ์ของ Docker volume

คอนเทนเนอร์รันด้วยผู้ใช้ที่ไม่มีสิทธิ์พิเศษชื่อ bun (UID 1000) ถ้าคุณ bind-mount ไดเรกทอรีของเครื่องโฮสต์ไปที่ /usr/src/app/data ไดเรกทอรีนั้นต้องเขียนได้โดย UID 1000 ไม่เช่นนั้นการดาวน์โหลดจะล้มเหลวด้วย EACCES: permission denied

bash
mkdir -p ./cap-data
sudo chown 1000:1000 ./cap-data
yaml
services:
  cap:
    image: tiago2/cap:latest
    volumes:
      - ./cap-data:/usr/src/app/data
    # ...

ถ้าคุณเปลี่ยนเจ้าของไฟล์บนเครื่องโฮสต์ไม่ได้ (บางแพลตฟอร์มอย่าง Coolify ทำเรื่องนี้ได้ลำบาก) ทางเลือกที่ง่ายที่สุดคือ:

  • ไม่ต้อง bind mount เลย ปล่อยให้ Docker จัดการไดเรกทอรีข้อมูลเอง เพราะอิมเมจสร้างมันไว้ให้พร้อมสิทธิ์ที่ถูกต้องอยู่แล้ว
  • ใช้ named volume แทน bind mount
  • เปลี่ยนไปใช้ผู้ให้บริการข้อมูล IP ที่ไม่ต้องมีไฟล์ในเครื่อง

เผยแพร่ภายใต้สัญญาอนุญาต Apache 2.0