Bereiten Sie eine kleine, kontrollierte Umgebung vor
Dieses Verfahren zielt auf ein Linux-System mit systemd, einem Administratorkonto, einer bereits installierten Node.js 24 LTS-Laufzeit, curl und Caddys paketiertem Systemdienst ab. Bestätigen Sie zuerst die installierten Versionen und Paketpfade; Nodes Release-Seite identifiziert unterstützte Release-Zweige. Installation und Anbieterbereitstellung sind separate Aufgaben. Verwenden Sie eine Maschine, die Sie kontrollieren, und halten Sie eine getestete SSH-Sitzung und einen Wiederherstellungspfad verfügbar. Die Namen first-api und /opt/first-api müssen vor dem Erstellen dieses Beispiels unbenutzt sein.
Für HTTPS benötigen Sie außerdem eine Domain, die Sie kontrollieren, korrekte A/AAAA-Einträge und die Berechtigung, Webverkehr zu exponieren. api.example.com unten ist ein reserviertes Beispiel: Ersetzen Sie es durch Ihren eigenen Hostnamen. Diese API enthält absichtlich keine Datenbank, Authentifizierung oder Kundendaten. Sie demonstriert einen wiederholbaren Prozess, kein vollständiges Produkt oder eine getestete OffVPS-Bereitstellung.
Überprüfen Sie die Laufzeit und erstellen Sie ein Release
command -v node &&
readlink -f "$(command -v node)" &&
node --version
Der Rest des Beispiels setzt voraus, dass die verifizierte gemeinsam genutzte ausführbare Datei /usr/bin/nodeist. Wenn Ihre abweicht, ersetzen Sie diesen Pfad in jeder Prüfung und in ExecStart. Eine Laufzeit im privaten Home-Verzeichnis Ihres Anmeldebenutzers ist nicht automatisch für einen Systemdienst verfügbar. Erstellen Sie das Dienstkonto und ein root-eigenes Release-Verzeichnis und stoppen Sie, wenn ein unerwartetes bestehendes Konto oder ein unerwarteter Pfad gefunden wird.
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
Speichern Sie mit Ihrem Editor mit administrativem Zugriff Folgendes als /opt/first-api/releases/001/server.mjs, im Besitz von root und lesbar für den Dienstbenutzer. Das Release enthält nur diese Datei; es gibt keine Paketabhängigkeiten oder Geheimnisse.
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();
});
Die explizite Loopback-Adresse hält den API-Listener auf dem Server selbst. Caddy wird sein öffentlicher Einstiegspunkt sein. Die Node HTTP-API dokumentiert Anforderungsverarbeitung, Timeouts und Server-Shutdown. Prüfen Sie die Datei als das Konto, das sie tatsächlich ausführen wird:
sudo -u first-api /usr/bin/node --check /opt/first-api/releases/001/server.mjs
Geben Sie dem Prozess eine Dienstdefinition
Speichern /etc/systemd/system/first-api.service mit diesem Inhalt:
[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
Die Unit verwendet einen dedizierten Benutzer, eine explizite ausführbare Datei und ein versioniertes Arbeitsverzeichnis. Die automatische Wiederherstellung ist ratenbegrenzt; ein absichtlicher Dienststopp löst nicht aus Restart=on-failure. Siehe systemd.service. Die Dateisystembeschränkungen passen zu dieser schreibgeschützten API; eine Anwendung, die Daten schreibt, benötigt bewusst abgegrenzten beschreibbaren Speicher. Geheimnisse gehören nicht in diese Umgebungszeilen. Siehe systemd-Ausführungseinstellungen.
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
Das && Wächter stoppen die eingefügte Sequenz, wenn ein Befehl fehlschlägt. Klären Sie Validierungswarnungen vor dem Start und fahren Sie nach einer fehlgeschlagenen Prüfung nicht mit dem nächsten Block fort. Unit-Verifikation kann Syntax- und Ausführbarkeitsprobleme erkennen, aber eine erfolgreiche Prüfung ist kein Beweis für eine funktionierende Anwendung. Die erwartete Health-Antwort ist {"status":"ok","release":"001"}. Wenn sie fehlschlägt, untersuchen Sie sudo journalctl -u first-api.service -n 50 --no-pager , bevor Sie wiederholt neu starten.
Fügen Sie die HTTPS-Route nach der lokalen Prüfung hinzu
Sichern Sie die bestehende Caddy-Konfiguration unter einem unbenutzten Dateinamen. Fügen Sie diesen Block zu /etc/caddy/Caddyfile hinzu, ohne unabhängige Sites zu ersetzen:
api.example.com {
reverse_proxy 127.0.0.1:3000
}
Für den standardmäßigen Public-Domain-Flow muss der Hostname zum Server auflösen, die Ports 80/443 Caddy erreichen und Caddys Zertifikatsspeicher beschreibbar und persistent bleiben. Prüfen Sie jede veröffentlichte A/AAAA-Route. Lassen Sie SSH-Zugriff intakt und halten Sie Port 3000 privat. Diese Anforderungen stammen aus Caddy automatisches HTTPS; die Upstream-Syntax ist dokumentiert in reverse_proxy.
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile &&
sudo systemctl reload caddy.service
Laden Sie nur nach erfolgreicher Validierung neu; caddy validate prüft die angepasste Konfiguration. Der Workflow des paketierten Dienstes ist beschrieben in Caddys Diensthandbuch. Fordern Sie von einem separaten Client https://api.example.com/healthz mit Ihrem echten Hostnamen an. Erwarten Sie eine vertrauenswürdige TLS-Verbindung und dieselbe Release-Antwort, ohne Zertifikatsprüfungen zu umgehen. Überprüfen Sie dann, ob /api/message seine Meldung zurückgibt und ein unbekannter Pfad 404 zurückgibt.
Behalten Sie ein bekanntes Release und einen sicheren Stopppunkt bei
Nachdem beide Prüfungen funktionieren, aktivieren Sie die API für zukünftige Starts mit sudo systemctl enable first-api.service. Notieren Sie die Laufzeitversion, die Quelldatei, die Unit und die Caddy-Konfiguration. Erstellen Sie für das nächste Release ein neues nummeriertes Verzeichnis, prüfen Sie es als Dienstbenutzer auf Syntax, aktualisieren Sie beide Unit-Pfade, laden Sie systemd neu und starten Sie die API neu. Behalten Sie das vorherige Verzeichnis, bis das neue Release akzeptiert ist.
Um dieses Beispiel zu stoppen, verwenden Sie sudo systemctl stop first-api.service. Caddy meldet einen Upstream-Fehler, solange diese Route konfiguriert bleibt; entfernen Sie nur diese Route und validieren/laden Sie Caddy neu, wenn Sie sie außer Betrieb nehmen. Setzen Sie ein fehlgeschlagenes Code-Release zurück, indem Sie die vorherigen Unit-Pfade auswählen und die Prüfungen wiederholen. Eine spätere Datenbankmigration benötigt ihren eigenen Wiederherstellungsplan. Fahren Sie fort mit dem DNS-zu-Anwendungs-Anfragepfad oder herausfinden, warum eine App gestoppt wurde.
Verwendete Dokumentation
Primäre Referenzen für diese Seite. Überprüfen Sie die Dokumentation für die in Ihrer eigenen Umgebung installierte Version.