Prepara un ambiente piccolo e controllato
Questa procedura è destinata a un sistema Linux con systemd, un account amministratore, un runtime Node.js 24 LTS già installato, curl e il servizio system pacchettizzato di Caddy. Conferma prima le versioni installate e i percorsi dei pacchetti; la pagina dei rilasci di Node identifica le linee di rilascio supportate. Installazione e provisioning del provider sono attività separate. Usa una macchina che controlli e mantieni disponibile una sessione SSH testata e un percorso di ripristino. I nomi first-api y /opt/first-api devono essere inutilizzati prima di creare questo esempio.
Per HTTPS hai anche bisogno di un dominio che controlli, record A/AAAA corretti e permesso di esporre il traffico web. api.example.com sotto è un esempio riservato: sostituiscilo con il tuo nome host. Questa API deliberatamente non contiene database, autenticazione o dati dei clienti. Dimostra un processo ripetibile, non un prodotto completo o una distribuzione OffVPS testata.
Verifica il runtime e crea un rilascio
command -v node &&
readlink -f "$(command -v node)" &&
node --version
Il resto dell'esempio presuppone che l'eseguibile condiviso verificato sia /usr/bin/node. Se il tuo differisce, sostituisci quel percorso in ogni controllo e in ExecStart. Un runtime nella home privata del tuo utente di login non è automaticamente disponibile per un servizio di sistema. Crea l'account di servizio e una directory di rilascio di proprietà di root, fermandoti se viene trovato un account o percorso esistente inatteso.
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
Usando il tuo editor con accesso amministrativo, salva quanto segue come /opt/first-api/releases/001/server.mjs, di proprietà di root e leggibile dall'utente del servizio. Il rilascio contiene solo questo file; non ci sono dipendenze di pacchetto o segreti.
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();
});
L'indirizzo di loopback esplicito mantiene il listener dell'API sul server stesso. Caddy sarà il suo punto di ingresso pubblico. Il API HTTP Node documenta la gestione delle richieste, i timeout e lo spegnimento del server. Controlla il file come l'account che lo eseguirà effettivamente:
sudo -u first-api /usr/bin/node --check /opt/first-api/releases/001/server.mjs
Assegna al processo una definizione di servizio
Salva /etc/systemd/system/first-api.service con questo contenuto:
[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
L'unità usa un utente dedicato, un eseguibile esplicito e una directory di lavoro con versione. Il ripristino automatico è limitato in frequenza; un arresto intenzionale del servizio non attiva Restart=on-failure. Vedi systemd.service. Le restrizioni del filesystem si adattano a questa API di sola lettura; un'applicazione che scrive dati necessita di archiviazione scrivibile con ambito deliberato. I segreti non appartengono a queste righe di ambiente. Vedi impostazioni di esecuzione di 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
El && le protezioni fermano la sequenza incollata quando un comando fallisce. Risolvi gli avvisi di validazione prima di avviare, e non continuare al blocco successivo dopo un controllo fallito. Verifica dell'unità può individuare problemi di sintassi ed eseguibile, ma un controllo riuscito non è prova di un'applicazione funzionante. La risposta di health prevista è {"status":"ok","release":"001"}. Se fallisce, ispeziona sudo journalctl -u first-api.service -n 50 --no-pager prima di riavviare ripetutamente.
Aggiungi la rotta HTTPS dopo il controllo locale
Esegui il backup della configurazione Caddy esistente con un nome file inutilizzato. Aggiungi questo blocco a /etc/caddy/Caddyfile senza sostituire siti non correlati:
api.example.com {
reverse_proxy 127.0.0.1:3000
}
Per il flusso standard con dominio pubblico, il nome host deve risolvere al server, le porte 80/443 devono raggiungere Caddy, e l'archiviazione dei certificati di Caddy deve rimanere scrivibile e persistente. Controlla ogni rotta A/AAAA pubblicata. Lascia intatto l'accesso SSH e mantieni privata la porta 3000. Questi requisiti provengono da HTTPS automatico di Caddy; la sintassi upstream è documentata in reverse_proxy.
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile &&
sudo systemctl reload caddy.service
Ricarica solo dopo una validazione riuscita; caddy validate controlla la configurazione adattata. Il flusso di lavoro del servizio pacchettizzato è descritto in guida al servizio di Caddy. Da un client separato, richiedi https://api.example.com/healthz usando il tuo nome host reale. Aspettati una connessione TLS affidabile e la stessa risposta di rilascio, senza aggirare i controlli del certificato. Poi verifica /api/message restituisce il suo messaggio e un percorso sconosciuto restituisce 404.
Conserva un rilascio noto e un punto di arresto sicuro
Dopo che entrambi i controlli funzionano, abilita l'API per i prossimi avvii con sudo systemctl enable first-api.service. Registra la versione del runtime, il file sorgente, l'unità e la configurazione di Caddy. Per il rilascio successivo, crea una nuova directory numerata, controllane la sintassi come utente del servizio, aggiorna entrambi i percorsi dell'unità, ricarica systemd e riavvia l'API. Mantieni la directory precedente fino a quando il nuovo rilascio è accettato.
Per fermare questo esempio, usa sudo systemctl stop first-api.service. Caddy segnalerà un errore upstream finché quella rotta rimane configurata; rimuovi solo questa rotta e valida/ricarica Caddy quando la ritiri. Esegui il rollback di un rilascio di codice fallito selezionando i percorsi dell'unità precedenti e ripetendo i controlli. Una successiva migrazione del database necessita del proprio piano di ripristino. Continua con il percorso di richiesta dal DNS all'applicazione или trovare perché un'app si è fermata.
使用的文档
本页的主要参考。请核对您自己环境中安装版本对应的文档。