Pregătiți un mediu mic și controlat
Această procedură vizează un sistem Linux cu systemd, un cont de administrator, un runtime Node.js 24 LTS deja instalat, curl și serviciul de sistem Caddy din pachet. Confirmați mai întâi versiunile instalate și căile pachetelor; Pagina de lansări a Node identifică liniile de lansare acceptate. Instalarea și provizionarea de către furnizor sunt sarcini separate. Folosiți o mașină pe care o controlați și păstrați disponibile o sesiune SSH testată și o cale de recuperare. Numele first-api și /opt/first-api trebuie să fie neutilizate înainte de a crea acest exemplu.
Pentru HTTPS aveți nevoie și de un domeniu pe care îl controlați, înregistrări A/AAAA corecte și permisiunea de a expune trafic web. api.example.com de mai jos este un exemplu rezervat: înlocuiți-l cu propriul nume de gazdă. Acest API nu conține în mod deliberat bază de date, autentificare sau date ale clienților. Demonstrează un proces repetabil, nu un produs complet sau o implementare OffVPS testată.
Verificați runtime-ul și creați o lansare
command -v node &&
readlink -f "$(command -v node)" &&
node --version
Restul exemplului presupune că executabilul partajat verificat este /usr/bin/node. Dacă al dvs. diferă, înlocuiți acea cale în fiecare verificare și în ExecStart. Un runtime din directorul home privat al utilizatorului dvs. de autentificare nu este disponibil automat pentru un serviciu de sistem. Creați contul de serviciu și un director de lansare deținut de root, oprindu-vă dacă se găsește un cont sau o cale existentă neașteptată.
sudo useradd --system --user-group --home-dir /opt/first-api \
--shell /usr/sbin/nologin first-api &&
sudo install -d -o root -g root -m 0755 /opt/first-api/releases/001
Folosind editorul dvs. cu acces administrativ, salvați următoarele ca /opt/first-api/releases/001/server.mjs, deținut de root și lizibil de utilizatorul serviciului. Lansarea conține doar acest fișier; nu există dependențe de pachete sau secrete.
import http from 'node:http';
const port = Number(process.env.PORT || 3000);
if (!Number.isInteger(port) || port < 1024 || port > 65535) {
throw new Error('PORT must be an integer from 1024 to 65535');
}
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
res.setHeader('Cache-Control', 'no-store');
if (req.method !== 'GET') {
res.writeHead(405, { Allow: 'GET' });
res.end(JSON.stringify({ error: 'method_not_allowed' }));
return;
}
if (req.url === '/healthz') {
res.writeHead(200);
res.end(JSON.stringify({ status: 'ok', release: '001' }));
} else if (req.url === '/api/message') {
res.writeHead(200);
res.end(JSON.stringify({ message: 'A small app, running clearly.' }));
} else {
res.writeHead(404);
res.end(JSON.stringify({ error: 'not_found' }));
}
});
server.requestTimeout = 10000;
server.headersTimeout = 10000;
server.keepAliveTimeout = 5000;
server.listen(port, '127.0.0.1');
process.on('SIGTERM', () => {
server.close(() => process.exit(0));
setTimeout(() => process.exit(1), 10000).unref();
});
Adresa explicită de loopback menține procesul în ascultare al API-ului pe serverul însuși. Caddy va fi punctul său de intrare public. API-ul HTTP Node documentează gestionarea cererilor, timeout-urile și oprirea serverului. Verificați fișierul ca fiind contul care îl va executa efectiv:
sudo -u first-api /usr/bin/node --check /opt/first-api/releases/001/server.mjs
Dați procesului o definiție de serviciu
Salvați /etc/systemd/system/first-api.service cu acest conținut:
[Unit]
Description=First API learning release
After=network.target
StartLimitIntervalSec=60
StartLimitBurst=5
[Service]
Type=simple
User=first-api
Group=first-api
WorkingDirectory=/opt/first-api/releases/001
ExecStart=/usr/bin/node /opt/first-api/releases/001/server.mjs
Environment=NODE_ENV=production
Environment=PORT=3000
Restart=on-failure
RestartSec=5
TimeoutStopSec=15
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
Unitatea folosește un singur utilizator dedicat, un executabil explicit și un director de lucru versionat. Recuperarea automată este limitată ca rată; o oprire intenționată a serviciului nu declanșează Restart=on-failure. Consultați systemd.service. Restricțiile sistemului de fișiere se potrivesc acestui API doar-citire; o aplicație care scrie date are nevoie de stocare inscriptibilă cu scop delimitat în mod deliberat. Secretele nu aparțin acestor linii de mediu. Consultați setările de execuție systemd.
sudo systemd-analyze verify /etc/systemd/system/first-api.service &&
sudo systemctl daemon-reload &&
sudo systemctl start first-api.service &&
sudo systemctl status first-api.service --no-pager &&
curl --fail --show-error http://127.0.0.1:3000/healthz
The && Gărzile opresc secvența lipită când o comandă eșuează. Rezolvați avertismentele de validare înainte de pornire și nu continuați la următorul bloc după o verificare eșuată. Verificarea unității poate prinde probleme de sintaxă și de executabil, dar o verificare reușită nu este dovada unei aplicații funcționale. Răspunsul de sănătate așteptat este {"status":"ok","release":"001"}. Dacă eșuează, inspectați sudo journalctl -u first-api.service -n 50 --no-pager înainte de a reporni în mod repetat.
Adăugați ruta HTTPS după verificarea locală
Faceți o copie de siguranță a configurației Caddy existente sub un nume de fișier neutilizat. Adăugați acest bloc la /etc/caddy/Caddyfile fără a înlocui site-uri nelegate:
api.example.com {
reverse_proxy 127.0.0.1:3000
}
Pentru fluxul standard cu domeniu public, numele de gazdă trebuie să se rezolve la server, porturile 80/443 trebuie să ajungă la Caddy, iar stocarea certificatelor Caddy trebuie să rămână inscriptibilă și persistentă. Verificați fiecare rută A/AAAA publicată. Lăsați accesul SSH intact și păstrați portul 3000 privat. Aceste cerințe provin din HTTPS automat Caddy; sintaxa upstream este documentată în reverse_proxy.
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile &&
sudo systemctl reload caddy.service
Reîncărcați numai după validare reușită; caddy validate verifică configurația adaptată. Fluxul de lucru al serviciului din pachet este descris în ghidul de serviciu al Caddy. De la un client separat, solicitați https://api.example.com/healthz folosind numele dvs. real de gazdă. Așteptați-vă la o conexiune TLS de încredere și la același răspuns de lansare, fără a ocoli verificările certificatului. Apoi verificați că /api/message returnează mesajul său și o cale necunoscută returnează 404.
Păstrați o lansare cunoscută și un punct de oprire sigur
După ce ambele verificări funcționează, activați API-ul pentru pornirile viitoare cu sudo systemctl enable first-api.service. Înregistrați versiunea runtime-ului, fișierul sursă, unitatea și configurația Caddy. Pentru următoarea lansare, creați un director nou numerotat, verificați sintaxa ca utilizator al serviciului, actualizați ambele căi ale unității, reîncărcați systemd și reporniți API-ul. Păstrați directorul anterior până când noua lansare este acceptată.
Pentru a opri acest exemplu, folosiți sudo systemctl stop first-api.service. Caddy va raporta o eroare upstream cât timp acea rută rămâne configurată; eliminați doar această rută și validați/reîncărcați Caddy când o retrageți. Reveniți asupra unei lansări de cod eșuate selectând căile anterioare ale unității și repetând verificările. O migrare ulterioară a bazei de date are nevoie de propriul plan de recuperare. Continuați cu calea cererii de la DNS la aplicație sau găsirea motivului pentru care o aplicație s-a oprit.
Documentație utilizată
Referințe primare pentru această pagină. Verificați documentația pentru versiunea instalată în propriul mediu.