OffVPSVPS OFFSHOREAssistance

Déployer une application

Donnez à votre première API une version reproductible.

Faites fonctionner une petite API localement, rendez son processus récupérable, et connectez seulement ensuite son nom d’hôte et HTTPS. Gardez le chemin de publication et le chemin de retour explicites.

guide pratique OffVPS · Révisé · 5 min de lecture

Préparez un petit environnement contrôlé

Cette procédure cible un système Linux avec systemd, un compte administrateur, un runtime Node.js 24 LTS déjà installé, curl et le service système empaqueté de Caddy. Confirmez d’abord les versions installées et les chemins des paquets ; Page de publication de Node identifie les lignes de version prises en charge. L'installation et le provisionnement du fournisseur sont des tâches distinctes. Utilisez une machine que vous contrôlez et gardez une session SSH testée et un chemin de récupération disponibles. Les noms first-api et /opt/first-api doivent être inutilisés avant de créer cet exemple.

Pour HTTPS, vous avez également besoin d'un domaine que vous contrôlez, d'enregistrements A/AAAA corrects et de l'autorisation d'exposer le trafic web. api.example.com ci-dessous est un exemple réservé : remplacez-le par votre propre nom d'hôte. Cette API ne contient délibérément aucune base de données, authentification ou donnée client. Elle démontre un processus reproductible, pas un produit complet ni un déploiement OffVPS testé.

Vérifiez le runtime et créez une version

command -v node &&
readlink -f "$(command -v node)" &&
node --version

Le reste de l'exemple suppose que l'exécutable partagé vérifié est /usr/bin/node. Si le vôtre diffère, remplacez ce chemin dans chaque vérification et dans ExecStart. Un runtime dans le répertoire personnel privé de votre utilisateur de connexion n'est pas automatiquement disponible pour un service système. Créez le compte de service et un répertoire de version appartenant à root, en vous arrêtant si un compte ou un chemin existant inattendu est détecté.

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

Avec votre éditeur disposant d'un accès administratif, enregistrez ce qui suit sous /opt/first-api/releases/001/server.mjs, appartenant à root et lisible par l'utilisateur du service. La version ne contient que ce fichier ; il n'y a aucune dépendance de paquet ni secret.

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'adresse loopback explicite maintient l'écouteur de l'API sur le serveur lui-même. Caddy sera son point d'entrée public. Le Node HTTP API documente la gestion des requêtes, les délais d'attente et l'arrêt du serveur. Vérifiez le fichier en tant que compte qui l'exécutera réellement :

sudo -u first-api /usr/bin/node --check /opt/first-api/releases/001/server.mjs

Donnez au processus une définition de service

Enregistrez /etc/systemd/system/first-api.service avec ce contenu :

[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é utilise un utilisateur dédié, un exécutable explicite et un répertoire de travail versionné. La récupération automatique est limitée en débit ; un arrêt intentionnel du service ne déclenche pas Restart=on-failure. Voir systemd.service. Les restrictions du système de fichiers conviennent à cette API en lecture seule ; une application qui écrit des données nécessite un stockage inscriptible délibérément délimité. Les secrets n'ont pas leur place dans ces lignes d'environnement. Voir systemd execution settings.

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

Le && les gardes arrêtent la séquence collée lorsqu'une commande échoue. Résolvez les avertissements de validation avant de démarrer, et ne passez pas au bloc suivant après une vérification échouée. Vérification de l'unité peut détecter les problèmes de syntaxe et d'exécutable, mais une vérification réussie ne prouve pas que l'application fonctionne. La réponse de santé attendue est {"status":"ok","release":"001"}. En cas d'échec, inspectez sudo journalctl -u first-api.service -n 50 --no-pager avant de redémarrer de façon répétée.

Ajoutez la route HTTPS après la vérification locale

Sauvegardez la configuration Caddy existante sous un nom de fichier inutilisé. Ajoutez ce bloc à /etc/caddy/Caddyfile sans remplacer les sites sans rapport :

api.example.com {
    reverse_proxy 127.0.0.1:3000
}

Pour le flux standard de domaine public, le nom d'hôte doit résoudre vers le serveur, les ports 80/443 doivent atteindre Caddy, et le stockage des certificats de Caddy doit rester inscriptible et persistant. Vérifiez chaque route A/AAAA publiée. Laissez l'accès SSH intact et gardez le port 3000 privé. Ces exigences proviennent de HTTPS automatique Caddy; la syntaxe amont est documentée dans reverse_proxy.

sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile &&
sudo systemctl reload caddy.service

Ne rechargez qu'après une validation réussie ; caddy validate vérifie la configuration adaptée. Le workflow du service packagé est décrit dans le guide de service de Caddy. Depuis un client séparé, demandez https://api.example.com/healthz en utilisant votre nom d’hôte réel. Attendez-vous à une connexion TLS approuvée et à la même réponse de version, sans contourner les vérifications de certificat. Vérifiez ensuite /api/message renvoie son message et un chemin inconnu renvoie 404.

Conservez une version connue et un point d’arrêt sûr

Une fois les deux vérifications effectuées, activez l’API pour les prochains démarrages avec sudo systemctl enable first-api.service. Notez la version d’exécution, le fichier source, l’unité et la configuration Caddy. Pour la prochaine version, créez un nouveau répertoire numéroté, vérifiez sa syntaxe en tant qu’utilisateur du service, mettez à jour les deux chemins d’unité, rechargez systemd et redémarrez l’API. Conservez le répertoire précédent jusqu’à ce que la nouvelle version soit acceptée.

Pour arrêter cet exemple, utilisez sudo systemctl stop first-api.service. Caddy signalera une défaillance d’amont tant que cette route reste configurée ; supprimez uniquement cette route et validez/rechargez Caddy lors de son retrait. Revenez à une version de code défaillante en sélectionnant les chemins d’unité précédents et en répétant les vérifications. Une migration de base de données ultérieure nécessite son propre plan de reprise. Continuez avec le chemin de requête DNS-vers-application ou déterminer pourquoi une application s’est arrêtée.

Documentation utilisée

Références principales pour cette page. Consultez la documentation de la version installée dans votre propre environnement.