Siapkan lingkungan kecil yang terkendali
Prosedur ini menargetkan sistem Linux dengan systemd, akun administrator, runtime Node.js 24 LTS yang sudah terpasang, curl, dan layanan sistem terpaket Caddy. Konfirmasi versi dan jalur paket yang terpasang terlebih dahulu; Halaman rilis Node mengidentifikasi jalur rilis yang didukung. Instalasi dan penyediaan penyedia adalah tugas terpisah. Gunakan mesin yang Anda kendalikan dan sediakan sesi SSH serta jalur pemulihan yang teruji. Nama first-api dan /opt/first-api harus belum digunakan sebelum membuat contoh ini.
Untuk HTTPS Anda juga memerlukan domain yang Anda kendalikan, rekaman A/AAAA yang benar, dan izin untuk mengekspos lalu lintas web. api.example.com di bawah ini adalah contoh yang dicadangkan: ganti dengan nama host Anda sendiri. API ini sengaja tidak berisi basis data, autentikasi, atau data pelanggan. Ini menunjukkan proses yang dapat diulang, bukan produk lengkap atau penyebaran OffVPS yang teruji.
Verifikasi runtime dan buat satu rilis
command -v node &&
readlink -f "$(command -v node)" &&
node --version
Sisa contoh mengasumsikan executable bersama yang terverifikasi adalah /usr/bin/node. Jika milik Anda berbeda, ganti jalur itu di setiap pemeriksaan dan di ExecStart. Runtime di dalam home pribadi pengguna login Anda tidak otomatis tersedia untuk layanan sistem. Buat akun layanan dan direktori rilis milik root, berhenti jika menemukan akun atau jalur yang ada yang tidak terduga.
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
Dengan editor Anda yang memiliki akses administratif, simpan berikut sebagai /opt/first-api/releases/001/server.mjs, dimiliki oleh root dan dapat dibaca oleh pengguna layanan. Rilis hanya berisi file ini; tidak ada dependensi paket atau rahasia.
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();
});
Alamat loopback eksplisit menjaga pendengar API tetap di server itu sendiri. Caddy akan menjadi titik masuk publiknya. API HTTP Node mendokumentasikan penanganan permintaan, batas waktu, dan penghentian server. Periksa file sebagai akun yang benar-benar akan menjalankannya:
sudo -u first-api /usr/bin/node --check /opt/first-api/releases/001/server.mjs
Beri proses definisi layanan
Simpan /etc/systemd/system/first-api.service dengan konten ini:
[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
Unit menggunakan satu pengguna khusus, executable eksplisit, dan direktori kerja berversi. Pemulihan otomatis dibatasi lajunya; penghentian layanan yang disengaja tidak memicu Restart=on-failure. Lihat systemd.service. Pembatasan sistem file cocok untuk API hanya-baca ini; aplikasi yang menulis data memerlukan penyimpanan yang dapat ditulis dengan cakupan yang disengaja. Rahasia tidak termasuk dalam baris lingkungan ini. Lihat pengaturan eksekusi 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
Skenario && penjaga menghentikan urutan yang ditempel saat perintah gagal. Selesaikan peringatan validasi sebelum memulai, dan jangan lanjut ke blok berikutnya setelah pemeriksaan gagal. Verifikasi unit dapat menangkap masalah sintaks dan executable, tetapi pemeriksaan yang berhasil bukan bukti aplikasi yang berfungsi. Respons kesehatan yang diharapkan adalah {"status":"ok","release":"001"}. Jika gagal, periksa sudo journalctl -u first-api.service -n 50 --no-pager sebelum berulang kali memulai ulang.
Tambahkan rute HTTPS setelah pemeriksaan lokal
Cadangkan konfigurasi Caddy yang ada dengan nama file yang belum digunakan. Tambahkan blok ini ke /etc/caddy/Caddyfile tanpa mengganti situs yang tidak terkait:
api.example.com {
reverse_proxy 127.0.0.1:3000
}
Untuk alur domain publik standar, nama host harus mengarah ke server, port 80/443 harus mencapai Caddy, dan penyimpanan sertifikat Caddy harus tetap dapat ditulis dan persisten. Periksa setiap rute A/AAAA yang diterbitkan. Biarkan akses SSH tetap utuh dan jaga port 3000 tetap privat. Persyaratan ini berasal dari HTTPS otomatis Caddy; sintaks hulu didokumentasikan di reverse_proxy.
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile &&
sudo systemctl reload caddy.service
Muat ulang hanya setelah validasi berhasil; caddy validate memeriksa konfigurasi yang diadaptasi. Alur kerja layanan terpaket dijelaskan di panduan layanan Caddy. Dari klien terpisah, minta https://api.example.com/healthz menggunakan nama host asli Anda. Harapkan koneksi TLS tepercaya dan respons rilis yang sama, tanpa melewati pemeriksaan sertifikat. Lalu verifikasi /api/message mengembalikan pesannya dan jalur yang tidak dikenal mengembalikan 404.
Pertahankan rilis yang diketahui dan titik penghentian yang aman
Setelah kedua pemeriksaan berhasil, aktifkan API untuk boot mendatang dengan sudo systemctl enable first-api.service. Catat versi runtime, file sumber, unit, dan konfigurasi Caddy. Untuk rilis berikutnya, buat direktori bernomor baru, periksa sintaksnya sebagai pengguna layanan, perbarui kedua jalur unit, muat ulang systemd, dan mulai ulang API. Pertahankan direktori sebelumnya hingga rilis baru diterima.
Untuk menghentikan contoh ini, gunakan sudo systemctl stop first-api.service. Caddy akan melaporkan kegagalan hulu selama rute itu tetap dikonfigurasi; hapus hanya rute ini dan validasi/muat ulang Caddy saat menghentikannya. Kembalikan rilis kode yang gagal dengan memilih jalur unit sebelumnya dan mengulangi pemeriksaan. Migrasi basis data selanjutnya memerlukan rencana pemulihannya sendiri. Lanjutkan dengan jalur permintaan DNS-ke-aplikasi atau menemukan mengapa aplikasi berhenti.
Dokumentasi yang digunakan
Referensi utama untuk halaman ini. Periksa dokumentasi untuk versi yang terpasang di lingkungan Anda sendiri.