Bereid een kleine, gecontroleerde omgeving voor
Deze procedure is gericht op een Linux-systeem met systemd, een beheerdersaccount, een reeds geïnstalleerde Node.js 24 LTS-runtime, curl en Caddy's gepakte systeemservice. Bevestig eerst geïnstalleerde versies en pakketpaden; Node's releasepagina identificeert ondersteunde releaselijnen. Installatie en provisioning door de provider zijn afzonderlijke taken. Gebruik een machine die u beheert en houd een geteste SSH-sessie en herstelpad beschikbaar. De namen first-api en /opt/first-api moeten ongebruikt zijn voordat u dit voorbeeld maakt.
Voor HTTPS hebt u ook een domein nodig dat u beheert, correcte A/AAAA-records en toestemming om webverkeer bloot te stellen. api.example.com hieronder is een gereserveerd voorbeeld: vervang het door uw eigen hostnaam. Deze API bevat bewust geen database, authenticatie of klantgegevens. Het demonstreert een reproduceerbaar proces, niet een compleet product of een geteste OffVPS-deployment.
Verifieer de runtime en maak één release
command -v node &&
readlink -f "$(command -v node)" &&
node --version
De rest van het voorbeeld gaat ervan uit dat de geverifieerde gedeelde executable /usr/bin/nodeis. Als de uwe afwijkt, vervang dat pad dan in elke controle en in ExecStart. Een runtime in de privé-thuismap van uw login-gebruiker is niet automatisch beschikbaar voor een systeemservice. Maak het serviceaccount en een door root beheerde releasedirectory aan en stop als een onverwacht bestaand account of pad wordt gevonden.
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
Sla het volgende met uw editor met beheerderstoegang op als /opt/first-api/releases/001/server.mjs, eigendom van root en leesbaar voor de servicegebruiker. De release bevat alleen dit bestand; er zijn geen pakketafhankelijkheden of secrets.
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();
});
Het expliciete loopbackadres houdt de API-listener op de server zelf. Caddy wordt het openbare toegangspunt. De Node HTTP API documenteert verzoekafhandeling, time-outs en servershutdown. Controleer het bestand als het account dat het daadwerkelijk gaat uitvoeren:
sudo -u first-api /usr/bin/node --check /opt/first-api/releases/001/server.mjs
Geef het proces een servicedefinitie
Opslaan /etc/systemd/system/first-api.service met deze inhoud:
[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
De unit gebruikt één toegewijde gebruiker, een expliciete executable en een geversioneerde werkmap. Automatisch herstel is snelheidsbeperkt; een opzettelijke servicestop activeert Restart=on-failureniet. Zie systemd.service. De bestandssysteembeperkingen passen bij deze alleen-lezen API; een applicatie die gegevens schrijft, heeft bewust afgebakende beschrijfbare opslag nodig. Secrets horen niet in deze omgevingsregels. Zie systemd-uitvoeringsinstellingen.
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
Het && beveiligingen stoppen de geplakte reeks wanneer een opdracht mislukt. Los validatiewaarschuwingen op voordat u start en ga na een mislukte controle niet verder naar het volgende blok. Unitverificatie kan syntaxis- en executableproblemen opsporen, maar een geslaagde controle is geen bewijs van een werkende applicatie. De verwachte health-respons is {"status":"ok","release":"001"}. Als het mislukt, inspecteer sudo journalctl -u first-api.service -n 50 --no-pager voordat u herhaaldelijk herstart.
Voeg de HTTPS-route toe na de lokale controle
Maak een back-up van de bestaande Caddy-configuratie onder een ongebruikte bestandsnaam. Voeg dit blok toe aan /etc/caddy/Caddyfile zonder niet-gerelateerde sites te vervangen:
api.example.com {
reverse_proxy 127.0.0.1:3000
}
Voor de standaard openbare-domeinflow moet de hostnaam naar de server verwijzen, moeten poorten 80/443 Caddy bereiken en moet Caddy's certificaatopslag beschrijfbaar en persistent blijven. Controleer elke gepubliceerde A/AAAA-route. Laat SSH-toegang intact en houd poort 3000 privé. Deze vereisten komen uit Caddy automatische HTTPS; de upstream-syntaxis is gedocumenteerd in reverse_proxy.
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile &&
sudo systemctl reload caddy.service
Herlaad alleen na succesvolle validatie; caddy validate controleert de aangepaste configuratie. De workflow voor de pakketdienst wordt beschreven in Caddy's servicehandleiding. Vraag vanaf een aparte client https://api.example.com/healthz aan met uw echte hostnaam. Verwacht een vertrouwde TLS-verbinding en dezelfde release-respons, zonder certificaatcontroles te omzeilen. Verifieer vervolgens dat /api/message zijn bericht retourneert en een onbekend pad 404 retourneert.
Behoud een bekende release en een veilig stoppunt
Nadat beide controles werken, schakelt u de API in voor toekomstige boots met sudo systemctl enable first-api.service. Noteer de runtimeversie, het bronbestand, de unit en de Caddy-configuratie. Maak voor de volgende release een nieuwe genummerde directory, controleer de syntaxis als de servicegebruiker, werk beide unitpaden bij, herlaad systemd en herstart de API. Behoud de vorige directory tot de nieuwe release is geaccepteerd.
Gebruik om dit voorbeeld te stoppen sudo systemctl stop first-api.service. Caddy meldt een upstream-fout zolang die route geconfigureerd blijft; verwijder alleen deze route en valideer/herlaad Caddy wanneer u deze buiten gebruik stelt. Draai een mislukte coderelease terug door de vorige unitpaden te selecteren en de controles te herhalen. Een latere databasemigratie heeft zijn eigen herstelplan nodig. Ga verder met het DNS-naar-applicatie-verzoekpad of uitzoeken waarom een app stopte.
Gebruikte documentatie
Primaire referenties voor deze pagina. Controleer de documentatie voor de versie die in uw eigen omgeving is geïnstalleerd.