Node संस्करण संस्थापित करना
Node संस्करण एक स्थायी सेवा की तरह चलता है: एक प्रक्रिया, डिस्क पर एक SQLite डेटाबेस, और कुछ भी संस्थापित करने को नहीं — न बाहरी डेटाबेस, न कैश, न कतार। यह निर्देश ख़ाली फ़ोल्डर से लेकर उत्पादन में चलते प्रतिष्ठान तक जाता है, उन बातों सहित जिन्हें अधिकांश मार्गदर्शिकाएँ छोड़ देती हैं: तंत्र-सेवा, रिवर्स प्रॉक्सी, TLS, बैकअप और उन्नयन।
क्या चाहिए#
| तत्व | संस्करण | क्यों |
|---|---|---|
| Node.js | 22 या नया | उत्पाद अपने अंतर्निहित परीक्षण-चालक और नए इंटरफ़ेसों पर टिका है। |
| एक C संकलक | build-essential | better-sqlite3 संस्थापन के समय संकलित होता है, बशर्ते आपके मंच के लिए तैयार द्विआधारी फ़ाइल न हो। |
| स्थानीय डिस्क | — | SQLite और चढ़ाई गई फ़ाइलें। नेटवर्क साझा कभी नहीं: नीचे देखिए। |
एक कोर और 512 MB स्मृति वाली मशीन कुछ दर्जन लोगों के लिए काफ़ी है। जो मायने रखता है वह शक्ति नहीं, डिस्क है: वह स्थानीय हो और उसका बैकअप हो।
१. लाना और संस्थापित करना#
git clone <आपका-भंडार> /var/www/toutadmin
cd /var/www/toutadmin
npm ci --omit=dev
npm install नहीं, npm ci: यह ठीक वही संस्थापित करता है जो लॉक फ़ाइल
कहती है, और उसे कभी नहीं बदलता। सर्वर पर खिसका हुआ संस्करण वह ख़राबी है जो किसी की समझ में
नहीं आती।
better-sqlite3 ही एकमात्र निर्भरता है जो C संकलित करती है।
sudo apt install -y build-essential python3 लगभग सारे मामले सुलझा देता है।
२. विन्यास#
cp .env.example .env
सब कुछ पर्यावरण चरों से तय होता है — जो .env से पढ़े जाते हैं, या आपके सेवा-प्रबंधक
द्वारा रखे जाते हैं। कोई भी अनिवार्य नहीं: .env के बिना प्रतिष्ठान पोर्ट 3000 पर
चढ़ता है और आपको सहायक के पास भेज देता है।
| चर | पूर्वनिर्धारित | यह क्या करता है |
|---|---|---|
PORT | 3000 | सुनने का पोर्ट। |
NODE_ENV | — | उत्पादन में production: कड़े कुकी, बिना विस्तृत निशान। |
SESSION_SECRET | उत्पन्न | सत्रों पर मुहर लगाता है। ख़ाली छोड़ने पर data/session.key में बन जाता है। |
INSTALL_TOKEN | — | संस्थापन से पहले सहायक इसे माँगता है। खुले सर्वर पर अनुशंसित। |
TRUST_PROXY | — | भरोसेमंद प्रॉक्सी के पीछे 1 — और केवल वहीं। |
DB_PATH | data/app.sqlite | डेटाबेस। |
UPLOAD_DIR, CV_DIR, VAULT_DIR, SIGN_DIR, DOCS_DIR, BACKUP_DIR | data/ के भीतर | फ़ाइल-फ़ोल्डर: चित्र, बायोडेटा, तिजोरी, हस्ताक्षर-पत्र, प्राप्त दस्तावेज़, अभिलेख। |
LOGIN_RATE_LIMIT | 10 | प्रति पते, प्रति पंद्रह मिनट लॉगिन प्रयास। |
GLOBAL_RATE_LIMIT | 300 | प्रति पते, प्रति मिनट अनुरोध। |
API_RATE_LIMIT | — | प्रति टोकन, प्रति मिनट API पुकार। |
SESSION_IDLE_MINUTES | 60 | इतनी निष्क्रियता के बाद सत्र गिर जाता है। |
SESSION_MAX_HOURS | 12 | निरपेक्ष अवधि, जिसे कोई गतिविधि नहीं बढ़ाती। |
ADMIN_EMAIL, ADMIN_PASSWORD | — | बिना अंतरफलक संस्थापन: चालू होते ही प्रशासक बना देता है। |
SESSION_SECRET बदलना सबको एक साथ बाहर कर देता है। इसे एक बार रखिए, यादृच्छिक
बनाइए
(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"), और
बाकी के साथ सहेजिए। इसे कभी git भंडार में न छोड़िए।
संस्थापन-टोकन रखना#
पहले आरंभ और सहायक तक आपके पहुँचने के बीच प्रतिष्ठान जिसे मिल जाए उसका होता
है: जो पहले आया, वही प्रशासन-खाता बना लेता है। इसलिए पोर्ट खोलने से पहले
INSTALL_TOKEN रख दीजिए:
node -e "console.log(require('crypto').randomBytes(16).toString('hex'))"
# फिर .env में:
INSTALL_TOKEN=c3f1…
सहायक इसकी तुलना स्थिर समय में करता है — साधारण तुलना टोकन को अक्षर-दर-अक्षर ताड़ लेने देती — और हर अस्वीकृति को पंजी में लिखता है। प्रतिष्ठान बन जाने पर सहायक स्वयं बंद हो जाता है।
बिना अंतरफलक संस्थापन#
स्वचालित परिनियोजन के लिए ADMIN_EMAIL और ADMIN_PASSWORD सहायक को
लाँघकर, चालू होते ही प्रशासक बना देते हैं। बाद में इन्हें हटा दीजिए: किसी सेवा के परिवेश में
पड़ा पासवर्ड वही पढ़ लेता है जो उस सेवा को पढ़ता है।
३. अनुमतियाँ और डेटा कहाँ रहता है#
sudo useradd --system --home /var/www/toutadmin --shell /usr/sbin/nologin toutadmin
sudo chown -R toutadmin:toutadmin /var/www/toutadmin/data
sudo chmod 750 /var/www/toutadmin/data
sudo chmod 640 /var/www/toutadmin/.env
कोड केवल पढ़ने योग्य रह सकता है; लिखने योग्य केवल data/ होना चाहिए। SQLite पड़ोसी
फ़ाइलें लिखता है (-wal, -shm): मायने फ़ोल्डर रखता है, केवल
डेटाबेस नहीं।
NFS और SMB फ़ाइल-तालों के बारे में झूठ बोलते हैं। SQLite दो एक साथ लेखन रोकने के लिए उसी ताले पर भरोसा करता है: साझा पर डेटाबेस बिना चेतावनी भ्रष्ट हो जाता है। स्थानीय डिस्क, हमेशा — और बाहर जाती है बैकअप की प्रति, डेटाबेस नहीं।
४. सेवा#
हाथ से चलाया गया उत्पाद टर्मिनल बंद करते ही रुक जाता है। उसे systemd को सौंपिए:
# /etc/systemd/system/toutadmin.service
[Unit]
Description=Toutadmin
After=network.target
[Service]
Type=simple
User=toutadmin
WorkingDirectory=/var/www/toutadmin
EnvironmentFile=/var/www/toutadmin/.env
ExecStart=/usr/bin/node src/server.js
Restart=always
RestartSec=5
# सेवा को केवल data/ में लिखना है।
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/www/toutadmin/data
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now toutadmin
sudo systemctl status toutadmin
journalctl -u toutadmin -f
कठोरता की ये पाँच पंक्तियाँ सजावट नहीं हैं: ProtectSystem=strict पूरी फ़ाइल-प्रणाली
को अलेख्य बना देता है, और ReadWritePaths केवल उस एक फ़ोल्डर को फिर खोलता है जिसे
लेख्य होना ही है। मनमाने लेखन की कोई दरार तब data/ से आगे नहीं पहुँचती।
५. रिवर्स प्रॉक्सी#
पोर्ट 3000 को कभी सीधे इंटरनेट पर मत परोसिए: वह TLS नहीं करता, और उसे सीखने की कोई वजह नहीं।
server {
listen 443 ssl http2;
server_name intranet.udaharan.in;
ssl_certificate /etc/letsencrypt/live/intranet.udaharan.in/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/intranet.udaharan.in/privkey.pem;
client_max_body_size 20M; # तिजोरी में जमा, प्राप्त दस्तावेज़
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
}
server {
listen 80;
server_name intranet.udaharan.in;
return 301 https://$host$request_uri;
}
साथ ही सेवा को केवल लूपबैक पर सुनने दीजिए, ताकि पोर्ट 3000 तक केवल प्रॉक्सी पहुँच सके।
TLS#
sudo certbot --nginx -d intranet.udaharan.in
संपर्क गोपित होते ही उत्पाद Strict-Transport-Security शीर्षक लगा देता है, और खुले
में कभी नहीं: बिना गोपन वाले पृष्ठ से घोषित होने पर वह पढ़ा ही न जाता, और किसी स्थानीय परख को
छह महीने के लिए https में बंद कर देता।
TRUST_PROXY प्रॉक्सी के साथ जाता है — और केवल उसी के साथ
यह चर सर्वर को शीर्षक में घोषित मूल पते पर भरोसा करा देता है। nginx के पीछे यही चाहिए —
वरना सारे अनुरोध 127.0.0.1 से आते दिखते हैं और प्रति-पता सीमाएँ कुछ नहीं
बचातीं। सामने प्रॉक्सी न हो तो उलटा होता है: कोई भी अपनी पसंद का पता घोषित कर सीमाएँ लाँघ
जाता है।
६. सहायक#
अपना डोमेन खोलिए। जब तक कोई खाता नहीं, हर पता /installation पर भेज देता है। पाँच
चरण:
- प्रतिष्ठान की भाषा, 16 में से।
- पूर्वापेक्षाएँ, जाँची और दिखाई गईं।
- कंपनी: वह नाम जो हर जगह दिखेगा।
- हर नए ग़ैर-फ़्रीलांस कर्मचारी को मिलने वाला वार्षिक अवकाश।
- प्रशासन-खाता: पता और कम-से-कम बारह अक्षरों का पासवर्ड।
जैसे ही कोई खाता बनता है, /installation लॉगिन पृष्ठ पर भेजने लगता है: सहायक स्वयं
बंद हो चुका है, हाथ से हटाने को कोई फ़ाइल नहीं।
७. आवधिक फेरा#
PHP संस्करण से भिन्न, यहाँ निर्धारित करने को कुछ नहीं: सर्वर अपना अनुसूचक स्वयं रखता है, जो हर घंटे जागता है और आठ काम करता है।
| फेरा क्या करता है | प्रत्याभूति |
|---|---|
| जिनका अनुबंध पूरा हो चुका, उन खातों को बंद करता है | लॉगिन पर और पटल खुलते समय भी जाँचा जाता है |
| जिन सदस्यताओं की तिथि आ गई, उनके बीजक जारी करता है | एक अनन्य अनुक्रमणिका दो बार बीजक बनने नहीं देती |
| समय-सीमाओं को सूचनाओं में बदलता है | दोहराव मिटाने वाली कुंजी: एक समय-सीमा एक ही बार चेताती है |
| पढ़ी हुई सूचनाएँ और लेखा-पंजी साफ़ करता है | चुनी हुई संरक्षण-अवधि के अनुसार |
| लेखा-डाकपेटी (IMAP) से संदेश उठाता है | यदि उठाना विन्यस्त हो |
| वेबहुक की कतार, उसके पुनःप्रयासों सहित, ख़ाली करता है | पाँच प्रयास, फिर छोड़ देना |
| स्वचालित बैकअप बनाता है और बाहर भेजता है | जब निर्धारित अंतराल बीत चुका हो |
हर संक्रिया समघाती है: दोहराया गया फेरा दो बार बीजक नहीं बनाता और दो बार सूचित नहीं करता। इसी से सेवा को किसी भी क्षण बिना सोचे फिर चालू किया जा सकता है।
८. जाँचना कि सब चलता है#
# परीक्षण (ये आपके डेटाबेस में नहीं लिखते)
npm test
# घूमने के लिए एक प्रदर्शन-प्रतिष्ठान
node scripts/seed-demo.js
फिर अंतरफलक में: एक सदस्य बनाइए, उससे लॉग इन कीजिए, एक संलग्नक चढ़ाइए, हाथ से बैकअप चलाइए और बैकअप परदे से उसे जाँचिए। ये चार काम डेटाबेस, फ़ाइलों, अधिकारों और अभिलेख को छूते हैं।
९. उन्नयन#
# १. पहले बैकअप, हमेशा — बैकअप परदे से
# २. कोड
cd /var/www/toutadmin
git pull
npm ci --omit=dev
# ३. फिर चालू कीजिए; डेटाबेस आरंभ पर स्वयं अद्यतन हो जाता है
sudo systemctl restart toutadmin
journalctl -u toutadmin -n 30 --no-pager
ढाँचा समघाती प्रवासों से बदलता है: उन्नयन दोहराने से कुछ नहीं टूटता। data/ और
.env को कभी हाथ नहीं लगाया जाता।
पीछे लौटना#
कोड को पिछले संस्करण पर लाइए और फिर चालू कीजिए। प्रवास कोई स्तंभ नहीं मिटाते: प्रवासित डेटाबेस पिछले संस्करण से पढ़ा जा सकता है, बशर्ते परिवर्तन-सूची में स्पष्ट उल्लेख न हो। संदेह हो तो चरण १ में लिया अभिलेख पुनर्स्थापित कीजिए।
१०. सचमुच बैकअप लेना#
tar.gz अभिलेख डेटाबेस और पाँच फ़ाइल-फ़ोल्डर ले जाता है। डेटाबेस SQLite के ऑनलाइन
बैकअप से नक़ल होता है, जो लेखन के बीच भी संगत प्रति देता है — PHP संस्करण वही परिणाम
VACUUM INTO से पाता है। हर फ़ाइल अपनी SHA-256 छाप लिए चलती है, जो पुनर्स्थापन पर
जाँची जाती है।
जिस सर्वर की रक्षा करता है उसी पर पड़ा अभिलेख किसी की रक्षा नहीं करता: बैकअप परदे से
दूरस्थ गंतव्य (FTPS या Google Drive) सेट कीजिए, और sauvegarde.echec पर एक वेबहुक
जोड़िए ताकि बाहर भेजना विफल होने पर पता चल जाए। ब्योरा
बैकअप और पुनर्स्थापन पृष्ठ पर है।
पहले स्थानीय रूप से आज़माइए#
npm install
cp .env.example .env
npm run dev # हर बदलाव पर फिर चालू होता है
http://localhost:3000 खोलिए। स्थानीय रूप से NODE_ENV ख़ाली रहने
दीजिए: production में कुकी «सुरक्षित» चिह्नित होती हैं और बिना गोपन वाले संपर्क पर
सहेजी नहीं जातीं — आप लॉगिन पृष्ठ पर चक्कर काटते रह जाएँगे।
PHP संस्करण पर जाना, या वहाँ से आना#
दोनों संस्करणों का ढाँचा एक है — 142 तालिकाएँ, 1311 स्तंभ — और
पासवर्ड का प्रारूप भी। एक को रोकिए, app.sqlite और फ़ाइल-फ़ोल्डर नक़ल कीजिए, दूसरे
को चालू कीजिए: कोई रूपांतरण नहीं। देखिए दो संस्करण।
Toutadmin प्रलेखन — 2026-09-13 को बनाया गया। स्वतंत्र साइट, सॉफ़्टवेयर से अलग।