Skip to content

प्रोडक्शन सेटअप

Potato को प्रोडक्शन में gunicorn, nginx या Apache, TLS टर्मिनेशन, Docker, सत्र दृढ़ता और साझा सर्वर के लिए ज़रूरी पहुंच नियंत्रण के साथ तैनात करें।

एकाधिक उपयोगकर्ताओं, डेटा दृढ़ता और उचित सुरक्षा के साथ वास्तविक एनोटेशन कार्यों के लिए Potato तैनात करें।

सर्वर कॉन्फ़िगरेशन

बुनियादी प्रोडक्शन कॉन्फ़िग

yaml
server:
  host: 0.0.0.0
  port: 8000
  debug: false

server ब्लॉक केवल host, port और debug स्वीकार करता है, इसके अलावा कुछ नहीं। वर्कर की संख्या और टाइमआउट कॉन्फ़िग फ़ाइल में नहीं, बल्कि उस WSGI सर्वर में सेट होते हैं जो Potato को चलाता है। प्रोडक्शन में debug बंद रखें, क्योंकि डीबग मोड सर्वर की अपनी मशीन से आए अनुरोधों के लिए एडमिन पेज बिना कुंजी के खोल देता है, और डिप्लॉय किए गए होस्ट पर इनमें उसका रिवर्स प्रॉक्सी भी शामिल होता है।

HTTPS का उपयोग करना

Potato के कॉन्फ़िग में कोई TLS सेटिंग नहीं होती, इसलिए प्रमाणपत्र वहां कॉन्फ़िगर नहीं किए जाते। TLS को Potato के सामने वाले रिवर्स प्रॉक्सी पर टर्मिनेट करें, जो नीचे के nginx और Apache खंड सेट करते हैं, या प्रमाणपत्र सीधे gunicorn को दें, जैसा "SSL के साथ" में दिखाया गया है।

Gunicorn के साथ चलाना

Potato को gunicorn के तहत ठीक एक वर्कर के साथ चलाएं, और जब अधिक समवर्तिता चाहिए तो थ्रेड की संख्या बढ़ाएं:

bash
gunicorn "potato.flask_server:create_app('config.yaml')" \
  --workers 1 \
  --threads 8 \
  --bind 0.0.0.0:8000 \
  --timeout 120

एक वर्कर की शर्त प्रदर्शन-ट्यूनिंग का विकल्प नहीं, बल्कि सही व्यवहार की आवश्यकता है। Potato अपना आइटम पूल, असाइनमेंट कतार और हर एनोटेटर की स्थिति प्रोसेस के भीतर मेमोरी में रखता है। दूसरे वर्कर को इन तीनों की अपनी अलग प्रति मिलती है, इसलिए वह ऐसे इंस्टेंस बांट देता है जो पहला वर्कर पहले ही असाइन कर चुका है। और चूंकि user_state.json हर सेव पर पूरा दोबारा लिखा जाता है, जो वर्कर आखिर में सेव करता है वह दूसरे के एनोटेशन मिटा देता है। इस नुकसान की कोई रिपोर्ट नहीं होती, और एनोटेशन बस गायब हो जाते हैं। थ्रेड उस स्थिति की एक ही प्रति साझा करते हैं, इसलिए --threads समवर्तिता को सुरक्षित रूप से बढ़ाता है, जबकि --workers ऐसा नहीं करता।

SSL के साथ

bash
gunicorn "potato.flask_server:create_app('config.yaml')" \
  --workers 1 \
  --threads 8 \
  --bind 0.0.0.0:443 \
  --certfile /path/to/cert.pem \
  --keyfile /path/to/key.pem

रिवर्स प्रॉक्सी सेटअप

Nginx कॉन्फ़िगरेशन

nginx
upstream potato {
    server 127.0.0.1:8000;
}
 
server {
    listen 80;
    server_name annotation.example.com;
    return 301 https://$server_name$request_uri;
}
 
server {
    listen 443 ssl;
    server_name annotation.example.com;
 
    ssl_certificate /etc/letsencrypt/live/annotation.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/annotation.example.com/privkey.pem;
 
    location / {
        proxy_pass http://potato;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
 
        # Long annotation sessions
        proxy_read_timeout 300;
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
    }
}

Apache कॉन्फ़िगरेशन

apache
<VirtualHost *:443>
    ServerName annotation.example.com
 
    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem
 
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/
 
    <Proxy *>
        Order allow,deny
        Allow from all
    </Proxy>
</VirtualHost>

URL पाथ के तहत माउंट करना

Potato को डोमेन रूट के बजाय https://host/app1/ पर सर्व करने के लिए एक अतिरिक्त कदम चाहिए। एनोटेशन पेज /static/... और /updateinstance को सार्वजनिक रूट के सापेक्ष अनुरोध करता है, इसलिए पाथ प्रीफ़िक्स के तहत एसेट 404 देते हैं और एनोटेशन सेव नहीं होते, जबकि पेज का ढांचा फिर भी दिखता रहता है।

Potato को उसका सार्वजनिक प्रीफ़िक्स बताएं। जब प्रॉक्सी आपके नियंत्रण में हो और वह फ़ॉरवर्डेड हेडर भेज सकता हो:

bash
export POTATO_PROXY_FIX=1
potato start config.yaml -p 8000
nginx
location /app1/ {
    proxy_pass         http://127.0.0.1:8000/;   # trailing slash strips /app1/
    proxy_set_header   Host              $host;
    proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_set_header   X-Forwarded-Prefix /app1;
}

POTATO_PROXY_FIX तभी सक्षम करें जब ऐप केवल उसी प्रॉक्सी के माध्यम से पहुंच योग्य हो। यह फ़ॉरवर्डेड हेडर पर भरोसा करता है, इसलिए जो क्लाइंट सीधे आंतरिक पोर्ट तक पहुंच सकता है, वह प्रीफ़िक्स को नकली बनाकर हर जनरेट किए गए URL को दूषित कर सकता है।

जब आप हेडर नहीं जोड़ सकते लेकिन माउंट पाथ जानते हैं, तो उसे सीधे सेट करें। प्रॉक्सी को फ़ॉरवर्ड करने से पहले प्रीफ़िक्स हटाना अब भी ज़रूरी है:

bash
export POTATO_URL_PREFIX=/app1
potato start config.yaml -p 8000

बिना सत्र वाले ब्राउज़र में साइन इन करके जांचें, क्योंकि प्रीफ़िक्स न होने पर सबसे पहले लॉगिन फ़ॉर्म वाला पेज ही टूटता है।

लाइव एजेंट और लाइव कोडिंग व्यूअर Server-Sent Events पर स्ट्रीम करते हैं, जिन्हें बफ़रिंग करने वाला प्रॉक्सी स्ट्रीम खत्म होने तक रोके रखता है। उन रूट पर बफ़रिंग बंद करें:

nginx
location /app1/api/ {
    proxy_pass            http://127.0.0.1:8000/api/;
    proxy_set_header      Host $host;
    proxy_buffering       off;
    proxy_read_timeout    3600s;
}

Docker तैनाती

Potato एक प्रीबिल्ट इमेज GitHub Container Registry पर प्रकाशित करता है, ghcr.io/davidjurgens/potato। इसमें Potato और उसकी डिपेंडेंसी हैं, और कुछ नहीं। आपका प्रोजेक्ट फ़ोल्डर, config.yaml और उसके डेटा के साथ, /app पर माउंट होता है, इसलिए एक ही इमेज हर कार्य के लिए काम करती है:

bash
docker run -p 8000:7860 \
  -v "$PWD/myproject:/app" \
  -e POTATO_SECRET_KEY="$(openssl rand -hex 32)" \
  ghcr.io/davidjurgens/potato:latest

latest टैग और रिलीज़ टैग, जैसे 2.12.1, में केवल मुख्य डिपेंडेंसी होती हैं। -all टैग (latest-all, 2.12.1-all) AI SDK, फ़ॉर्मेट रीडर, और एक्सपोर्ट तथा प्रमाणीकरण से जुड़े अतिरिक्त पैकेज जोड़ते हैं, और विज़न मॉडल शामिल नहीं करते।

कंटेनर कार्य को एक gunicorn वर्कर और आठ थ्रेड के साथ सर्व करता है, उसी कारण से जो ऊपर gunicorn खंड में दिया गया है। GUNICORN_WORKERS को 1 से ऊपर सेट करने पर कंटेनर स्टार्टअप पर ही रुक जाता है, जब तक कि POTATO_ALLOW_MULTIWORKER=1 भी सेट न हो, और ऐसा करने से वास्तविक अध्ययन में एनोटेशन खो जाते हैं। अधिक समवर्तिता के लिए GUNICORN_THREADS बढ़ाएं। POTATO_CONFIG config.yaml के अलावा किसी दूसरी कॉन्फ़िग फ़ाइल का नाम देता है, और PORT कंटेनर के भीतर पोर्ट को 7860 से बदल देता है।

कंटेनर uid 1000 के रूप में चलता है और एनोटेशन आउटपुट, potato.log और अपने SQLite डेटाबेस /app में लिखता है। Linux पर, किसी दूसरे उपयोगकर्ता के स्वामित्व वाला बाइंड-माउंट किया गया प्रोजेक्ट फ़ोल्डर बूट के समय सर्वर को रोक देता है, और त्रुटि संदेश समस्या का नाम बताता है। sudo chown -R 1000:1000 myproject से फ़ोल्डर uid 1000 को सौंप दें। Mac पर Docker Desktop बाइंड-माउंट के स्वामित्व को अनदेखा करता है, इसलिए यह त्रुटि केवल Linux पर दिखती है।

इमेज के नाम के बाद दिए गए आर्गुमेंट सर्वर कमांड की जगह ले लेते हैं, जो एक बार की जांचों के लिए उपयोगी है:

bash
docker run -v "$PWD/myproject:/app" \
  ghcr.io/davidjurgens/potato:latest potato validate config.yaml --strict

Docker Compose

yaml
services:
  potato:
    image: ghcr.io/davidjurgens/potato:latest
    ports:
      - "8000:7860"
    volumes:
      - ./myproject:/app
    environment:
      - POTATO_SECRET_KEY=${POTATO_SECRET_KEY}
      - POTATO_ADMIN_API_KEY=${POTATO_ADMIN_API_KEY}
    restart: unless-stopped
 
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./certs:/etc/ssl/certs
    depends_on:
      - potato
    restart: unless-stopped

Compose नेटवर्क के भीतर, nginx Potato तक सर्विस के नाम और कंटेनर के पोर्ट से पहुंचता है, इसलिए ऊपर रिवर्स प्रॉक्सी खंड का upstream ब्लॉक server 127.0.0.1:8000; के बजाय server potato:7860; बन जाता है।

चूंकि प्रोजेक्ट फ़ोल्डर इमेज में कॉपी नहीं किया जाता बल्कि माउंट किया जाता है, Potato उसमें जो एनोटेशन लिखता है वे कंटेनर बदलने पर भी होस्ट पर बने रहते हैं।

पहुंच नियंत्रण

कौन रजिस्टर कर सकता है, इसे सीमित करना

Potato डिफ़ॉल्ट रूप से स्व-पंजीकरण की अनुमति देता है। सार्वजनिक सर्वर पर उन लोगों की सूची दें जो साइन अप कर सकते हैं:

yaml
user_config:
  allow_all_users: false
  users:
    - annotator1@example.com
    - annotator2@example.com

दोनों कुंजियां user_config के तहत आती हैं। शीर्ष स्तर पर लिखे जाने पर उन्हें अनदेखा कर दिया जाता है, और तब कॉन्फ़िग एक ऐसी पहुंच सूची जैसी दिखती है जो असल में सभी को प्रवेश देती है।

एडमिन पहुंच

admin_api_key एक साझा कुंजी है जो X-API-Key हेडर के रूप में भेजी जाती है। जब आप इसे सेट नहीं करते, तो Potato एक कुंजी जनरेट करके उसे {task_dir}/admin_api_key.txt में लिख देता है, इसलिए प्रोडक्शन होस्ट पर इसे खुद सेट करें और रिपॉज़िटरी से बाहर रखें:

yaml
admin_api_key: "your-shared-key"
 
rbac:
  enabled: true
  user_role_assignments:
    lead@example.com: admin

rbac कॉन्फ़िगर होने पर, नामित लोग साझा कुंजी इधर-उधर भेजने के बजाय सामान्य रूप से लॉग इन करके /admin तक पहुंचते हैं। पूरे अनुमति सेट के लिए उपयोगकर्ता प्रबंधन देखें।

सत्र

yaml
secret_key: "a-long-random-string"
session_timeout_minutes: 60
persist_sessions: true
session_lifetime_days: 7
max_session_seconds: 7200

secret_key सत्र कुकी पर हस्ताक्षर करती है और इसके बजाय POTATO_SECRET_KEY से भी आ सकती है। इसके बिना Potato हर स्टार्टअप पर एक नई कुंजी जनरेट करता है, इसलिए हर रीस्टार्ट कार्य के बीच में सभी को लॉग आउट कर देता है। जो सर्वर हर डिप्लॉय पर रीस्टार्ट होता है, उस पर यही सेटिंग सबसे अधिक बार एनोटेशन के नुकसान का कारण बनती है।

session_timeout_minutes उस सत्र को मिटा देता है जो इतनी देर से निष्क्रिय है, और हर अनुरोध पर घड़ी फिर से शुरू होती है। Potato 2.11 पहली रिलीज़ है जो इसे लागू करती है, और इसका डिफ़ॉल्ट 480 मिनट है। इस उदाहरण की तरह 60 पर, जो एनोटेटर एक घंटे के लिए उठकर चला जाता है, उसे लौटने पर फिर से लॉग इन करना पड़ता है।

एनोटेशन आउटपुट

yaml
output_annotation_dir: /var/potato/annotations/
export_annotation_format: [csv, jsonl]
auto_export_interval: 300

Potato output_annotation_dir के तहत हर एनोटेटर के लिए एक डायरेक्टरी लिखता है, जिसमें उस व्यक्ति की user_state.json होती है। export_annotation_format उन फ़ॉर्मेट के नाम देता है जिन्हें आवधिक एक्सपोर्ट लिखता है, और खाली मान का अर्थ है कि कोई ऑटो-एक्सपोर्ट नहीं होगा। auto_export_interval सेकंड में दो एक्सपोर्ट के बीच का अंतराल है, और इसका डिफ़ॉल्ट 60 है।

डेटाबेस बैकएंड

एनोटेशन डिफ़ॉल्ट रूप से डिस्क पर रहते हैं। जिन तैनातियों को डेटाबेस चाहिए, उनके लिए database.type mysql या file स्वीकार करता है:

yaml
database:
  type: mysql
  host: localhost
  port: 3306
  database: potato_db
  username: potato
  password: ${DB_PASSWORD}

कुंजियां database और username हैं, name और user नहीं। कनेक्शन स्ट्रिंग इसके बजाय POTATO_DB_CONNECTION से भी आ सकती है, जिससे क्रेडेंशियल कॉन्फ़िग फ़ाइल से बाहर रहता है।

ड्राइवर pip install 'potato-annotation[mysql]' से इंस्टॉल करें। 2.10.2 से पहले MySQL बैकएंड कभी चालू ही नहीं होता था, और जो कॉन्फ़िग उसे चुनता था वह बिना कोई सूचना दिए एनोटेशन डिस्क पर सहेजता था। 2.10.2 से ड्राइवर न होने पर या सर्वर तक न पहुँच पाने पर स्टार्टअप रुक जाता है, और एक्सपोर्ट, बैकअप और potato deploy pull डेटाबेस से पढ़ते हैं।

हेल्थ चेक और लॉगिंग

Potato हर तैनाती पर GET /health सर्व करता है, और इस रूट को प्रमाणीकरण की आवश्यकता नहीं होती, इसलिए यह लोड बैलेंसर या ऑर्केस्ट्रेटर के लिए रेडीनेस प्रोब के रूप में काम करता है:

bash
curl -sf https://annotation.example.com/health

लॉगिंग का विस्तार-स्तर किसी logging ब्लॉक में नहीं, बल्कि कॉन्फ़िग में या कमांड लाइन पर सेट होता है:

yaml
verbose: true
debug_log: server

debug_log all, ui, server या none लेता है। जब आप किसी एक सबसिस्टम की समस्या खोज रहे हों, तो POTATO_LOGGERS पर्यावरण चर आउटपुट को नामित लॉगर तक सीमित कर देता है।

स्केलिंग

Potato एक ही प्रोसेस के रूप में चलता है जो पूरा आइटम सेट मेमोरी में रखता है, इसलिए सर्वरों की संख्या नहीं, मशीन को बड़ा करें। लोड बैलेंसर के पीछे कई रेप्लिका चलाने से काम बंटता नहीं है। हर रेप्लिका असाइनमेंट कतार और एनोटेटर स्थिति की अपनी अलग प्रति रखती है, जिससे ठीक वही डेटा हानि होती है जो ऊपर gunicorn के तहत बताई गई है।

डेटासेट के साथ बढ़ने वाला संसाधन मेमोरी है। लगभग दस लाख आइटम पर पेलोड को SQLite कैश में ले जाया जा सकता है:

yaml
item_store:
  backend: paged      # default: memory
  cache_size: 2048

इसे चालू करने से पहले मापें। पेजिंग विज़न आइटम पर लगभग 28% और टेक्स्ट पर 51% बचाती है, यानी दस गुना जैसी बचत नहीं होती, और इससे कॉर्पस लोड होना लगभग 2.5 गुना धीमा हो जाता है। यह फ़ाइल एक कैश है, जो हर बूट पर डेटा फ़ाइलों से दोबारा बनाई जाती है, इसलिए इसे हटाना सुरक्षित है।

बड़े प्रोजेक्ट के लिए कारगर उपाय हैं per_annotator_quota से किसी एक एनोटेटर को असाइन होने वाले काम की सीमा तय करना, batch_assignment से कॉर्पस को समूहों में बांटना, और स्टार्टअप पर सब कुछ लोड करने के बजाय data_directory से समय के साथ डेटा फ़ाइलें जोड़ना।

बैकअप रणनीति

बैकअप में एनोटेशन आउटपुट डायरेक्टरी से ज़्यादा चीज़ें शामिल होनी चाहिए। टास्क डायरेक्टरी में तीन तक SQLite डेटाबेस भी होते हैं, और इनमें से किसी को भी डेटा फ़ाइलों से दोबारा नहीं बनाया जा सकता: project.sqlite (मेमो, कोडबुक, समीक्षा वर्कफ़्लो), datasets.sqlite, और लेबलिंग इंजन इस्तेमाल होने पर engine.sqlite। साइन-अप फ़ॉर्म से बने खातों को Potato user_config.json में रखता है। जब सर्वर डेटाबेस में लिखता है, तब वे WAL मोड में चलते हैं, इसलिए किसी डेटाबेस फ़ाइल का tar या cp ऐसी प्रति बना सकता है जो खराब हो या जिसमें हाल का काम न हो, और दोनों में से कोई भी कमांड आपको चेतावनी नहीं देती।

बिल्ट-इन बैकअप

संस्करण 2.10 से, Potato का backup ब्लॉक एनोटेशन आउटपुट और डेटाबेस के .backup स्नैपशॉट को सर्वर से बाहर कॉपी करता है, और जब सर्वर खाली डिस्क के साथ शुरू होता है तो उन्हें रीस्टोर करता है। रीस्टोर एनोटेशन के साथ खातों की सूची भी वापस लाता है, और यह डिस्क पर पहले से मौजूद एनोटेशन को कभी ओवरराइट नहीं करता। नीचे का ब्लॉक हर पाँच मिनट में, जो डिफ़ॉल्ट अंतराल है, प्रति को एक S3 बकेट में भेजता है, इसलिए डिस्क खो जाने पर एनोटेटरों का अधिकतम पाँच मिनट का काम जाता है:

yaml
backup:
  schedule_minutes: 5
  restore_on_boot: true
  sinks:
    - type: s3
      bucket: lab-potato-backups
      prefix: pilot-study
      endpoint_url: https://s3.example.edu   # leave out for AWS S3

endpoint_url sink को S3 API समझने वाली किसी भी सेवा की ओर मोड़ता है, जैसे किसी विश्वविद्यालय का ऑब्जेक्ट स्टोर, MinIO, Cloudflare R2 या Backblaze B2। क्रेडेंशियल सर्वर के एनवायरनमेंट में POTATO_S3_ACCESS_KEY_ID और POTATO_S3_SECRET_ACCESS_KEY से, या boto3 की सामान्य क्रेडेंशियल शृंखला से आते हैं। केवल उसी एक बकेट तक सीमित कुंजी यह सीमित करती है कि सर्वर किन चीज़ों तक पहुँच सकता है। repo_id वाला type: huggingface sink इसके बजाय प्रति को एक निजी Hugging Face डेटासेट में भेजता है, और इसके लिए HF_TOKEN इस्तेमाल करता है। दोनों sinks को hosting extra चाहिए, pip install 'potato-annotation[hosting]'।

आपके अपने स्टोरेज पर रहने वाली प्रति

जब कोई डेटा-उपयोग समझौता डेटा को सर्वर पर ही रखने की शर्त रखता है, तो एक रात्रिकालीन job उसे लोकल या माउंट किए गए स्टोरेज पर कॉपी कर सकता है। नीचे की स्क्रिप्ट आउटपुट डायरेक्टरी को आर्काइव करती है, हर डेटाबेस की फ़ाइल कॉपी करने के बजाय SQLite के .backup कमांड से उसका स्नैपशॉट लेती है, और सात दिनों की प्रतियाँ रखती है। इसके लिए sqlite3 कमांड-लाइन टूल चाहिए:

bash
#!/bin/bash
# backup.sh
set -e
TASK_DIR=/var/potato
DEST=/var/backups/potato/$(date +%Y%m%d_%H%M%S)
mkdir -p "$DEST"
 
tar -czf "$DEST/annotations.tar.gz" -C "$TASK_DIR" annotations
for db in project.sqlite datasets.sqlite engine.sqlite; do
  if [ -f "$TASK_DIR/$db" ]; then
    sqlite3 "$TASK_DIR/$db" ".backup '$DEST/$db'"
  fi
done
cp "$TASK_DIR/config.yaml" "$DEST/"
if [ -f "$TASK_DIR/user_config.json" ]; then cp "$TASK_DIR/user_config.json" "$DEST/"; fi
 
find /var/backups/potato -mindepth 1 -maxdepth 1 -mtime +7 -exec rm -rf {} +

इसे हर रात 2 बजे cron से चलाएँ:

bash
0 2 * * * /var/potato/backup.sh

रात में एक बार बनने वाली प्रति में एक दिन तक का काम खो सकता है, इसलिए कई एनोटेटरों वाले अध्ययन के दौरान इसे ज़्यादा बार चलाएँ। अध्ययन शुरू होने से पहले एक प्रति को किसी टेस्ट सर्वर पर रीस्टोर करें और जाँचें कि आख़िरी एनोटेशन उसमें है।

सुरक्षा चेकलिस्ट

  • वैध प्रमाणपत्र के साथ प्रॉक्सी पर TLS टर्मिनेट करें
  • secret_key या POTATO_SECRET_KEY सेट करें, ताकि सत्र रीस्टार्ट के बाद भी बने रहें
  • जनरेट की गई फ़ाइल भेजने के बजाय admin_api_key सेट करें
  • user_config.users से पंजीकरण सीमित करें
  • debug बंद रखें, क्योंकि डीबग मोड में रिवर्स प्रॉक्सी के अनुरोध बिना कुंजी के एडमिन पेज तक पहुँच जाते हैं
  • gunicorn को एक ही वर्कर के साथ चलाएं
  • क्रेडेंशियल कॉन्फ़िग में नहीं, पर्यावरण चर में रखें
  • POTATO_PROXY_FIX केवल भरोसेमंद प्रॉक्सी के पीछे सक्षम करें
  • आउटपुट डायरेक्टरी, खातों की फ़ाइल और डेटाबेस का बैकअप लें, और रीस्टोर की जाँच करें
  • समीक्षा करें कि एडमिन भूमिका किसके पास है

पर्यावरण चर

bash
# .env file
POTATO_SECRET_KEY=your-super-secret-key
POTATO_ADMIN_API_KEY=your-admin-key
POTATO_DB_CONNECTION=mysql://potato:password@localhost:3306/potato_db

इस कमांड से साइनिंग कुंजी जनरेट करें:

bash
python3 -c 'import secrets; print(secrets.token_hex(32))'

Docker Compose में लोड करें:

yaml
services:
  potato:
    env_file:
      - .env

समस्या निवारण

लॉग जांचें

bash
# Gunicorn logs
journalctl -u potato -f
 
# Docker logs
docker-compose logs -f potato

सामान्य समस्याएं

502 Bad Gateway: जांचें कि Potato चल रहा है और उसी पोर्ट से बाउंड है जिस पर प्रॉक्सी फ़ॉरवर्ड करता है।

डिप्लॉय के बाद सभी लॉग आउट हो गए: secret_key सेट नहीं है, इसलिए स्टार्टअप पर एक नई साइनिंग कुंजी जनरेट हुई।

एनोटेशन गायब हैं: वर्कर की संख्या जांचें। एक से अधिक gunicorn वर्कर बिना कोई रिपोर्ट दिए एनोटेशन मिटा देते हैं।

पाथ प्रीफ़िक्स के तहत एसेट 404 देते हैं: POTATO_PROXY_FIX या POTATO_URL_PREFIX सेट करें, और पुष्टि करें कि प्रॉक्सी फ़ॉरवर्ड करने से पहले प्रीफ़िक्स हटाता है।

बड़े कॉर्पस के साथ धीमा: सर्वर जोड़ने से पहले मेमोरी बढ़ाएं, और लगभग दस लाख आइटम से आगे item_store.backend: paged पर विचार करें।

अगले कदम

कार्यान्वयन के विवरण के लिए रिवर्स प्रॉक्सी गाइड और स्केलिंग गाइड देखें।