Prejsť na obsah
Aktuálny kupón:zľava 10 %Uplatniť v objednávke

Aplikácia 24/7 na VPS: služba systemd (Node.js, Python, Java)

Spustíte aplikáciu alebo bota na VPS ako službu systemd: beh na pozadí, automatický reštart po páde aj po reštarte VPS, logy v journale a tajné údaje mimo kódu.

  • pokročilý
  • ~20 min
  • Aktualizované 9. 10. 2026

Aplikácia spustená v termináli skončí, hneď ako zatvoríte SSH alebo VPS reštartujete. Nastavíme ju ako službu systemd: pobeží na pozadí, po páde sa sama reštartuje, spustí sa po štarte VPS a jej výpis nájdete v systémovom logu.

Čo budete potrebovať

  • VPS u StormHostu s Ubuntu 24.04 alebo Debianom 13
  • Pripojenie cez SSH ako root (návod)
  • Aplikáciu, ktorú viete spustiť z príkazového riadka (napríklad Discord bota v Node.js)
  • Približne 20 minút

Prečo systemd#

systemd je správca služieb, ktorý je súčasťou Ubuntu aj Debianu. Spúšťa všetky systémové služby (SSH, Nginx, databázy), takže nič ďalšie neinštalujete.

SpôsobReštart po pádeŠtart po reštarte VPSLogyPoznámka
Terminál, nohup, &NieNieIba do súboruVhodné iba na skúšku.
screen, tmuxNieNieIba v oknePraktické na ručnú prácu, nie na prevádzku.
pm2ÁnoÁno (po nastavení)VlastnéĎalší program navyše, iba pre Node.js.
systemdÁnoÁnojournalSúčasť systému, funguje pre akýkoľvek jazyk.

Používateľ pre aplikáciu#

Aplikácia nemá bežať ako root. Keď ju niekto napadne, získa iba práva jej používateľa. Vytvorte systémového používateľa s domovským priečinkom v /opt:

bash
useradd --system --create-home --home-dir /opt/mujbot --shell /usr/sbin/nologin mujbot
  • --system – systémový účet pre službu (nižšie číslo používateľa, bez hesla).
  • --create-home --home-dir /opt/mujbot – vytvorí priečinok /opt/mujbot, ktorý patrí používateľovi.
  • --shell /usr/sbin/nologin – pod používateľom sa nedá prihlásiť cez SSH ani terminál.
  • mujbot – meno používateľa (a zároveň rovnomennej skupiny). Zvoľte vlastné, v návode ho potom všade nahraďte.

Node.js LTS#

Repozitár Ubuntu 24.04 obsahuje Node.js 18 a Debian 13 Node.js 20. Obe verzie už autori Node.js nepodporujú (18 od 30. 4. 2025, 20 od 30. 4. 2026). Nainštalujte aktuálnu LTS verziu z oficiálnych balíkov na nodejs.org (otvorí sa v novom okne). V októbri 2026 je aktívna LTS Node.js 24 (koncom októbra 2026 sa LTS stáva Node.js 26).

Najprv archív stiahnite a overte:

bash
apt -y install curl xz-utils
cd /tmp
NODE_SOUBOR=$(curl -fsSL https://nodejs.org/dist/latest-v24.x/SHASUMS256.txt | grep -o 'node-v[0-9.]*-linux-x64.tar.xz' | head -n 1)
curl -fsSLO "https://nodejs.org/dist/latest-v24.x/$NODE_SOUBOR"
curl -fsSL https://nodejs.org/dist/latest-v24.x/SHASUMS256.txt | grep " $NODE_SOUBOR\$" | sha256sum -c -
Výstuptext
node-v24.21.0-linux-x64.tar.xz: OK

Pokračujte, iba keď vidíte OK. Pri FAILED súbor zmažte (rm /tmp/node-v*.tar.xz) a stiahnutie zopakujte. Potom Node.js nainštalujte (v rovnakom okne terminálu, premenná NODE_SOUBOR musí zostať nastavená):

bash
mkdir -p /opt/nodejs
tar -xJf "$NODE_SOUBOR" -C /opt/nodejs --strip-components=1
ln -sf /opt/nodejs/bin/node /usr/local/bin/node
ln -sf /opt/nodejs/bin/npm /usr/local/bin/npm
ln -sf /opt/nodejs/bin/npx /usr/local/bin/npx
PríkazČo robí
apt -y install curl xz-utilsSťahovací program a rozbaľovanie formátu .tar.xz.
NODE_SOUBOR=$(… SHASUMS256.txt | grep -o … | head -n 1)Zo zoznamu kontrolných súčtov najnovšieho vydania radu 24 zistí názov súboru pre Linux x64, napríklad node-v24.21.0-linux-x64.tar.xz.
curl -fsSLO "…/$NODE_SOUBOR"Stiahne archív; -O ho uloží pod pôvodným názvom.
… | grep " $NODE_SOUBOR\$" | sha256sum -c -Overí kontrolný súčet stiahnutého súboru oproti oficiálnemu zoznamu. Chráni pred poškodeným alebo podvrhnutým súborom.
mkdir -p /opt/nodejsPriečinok pre Node.js.
tar -xJf … -C /opt/nodejs --strip-components=1Rozbalí archív (J = formát xz) do /opt/nodejs bez najvyššieho priečinka s číslom verzie.
ln -sf /opt/nodejs/bin/… /usr/local/bin/…Vytvorí odkazy na node, npm a npx v priečinku, kde ich systém hľadá. Cesta /usr/local/bin/node zostane rovnaká aj po aktualizácii.

Overenie: node -v vypíše v24.…, npm -v číslo verzie npm.

Pre iný rad nahraďte vo všetkých adresách latest-v24.x napríklad latest-v26.x. Aktualizácia Node.js = zastaviť službu, zmazať /opt/nodejs a postup zopakovať.

Prečo nie nvm

nvm (ponúka ho stránka sťahovania na nodejs.org) inštaluje Node.js do domovského priečinka používateľa do cesty s číslom verzie. Pre službu systemd je potrebná pevná absolútna cesta k programu, ktorá sa po aktualizácii nezmení. Preto tu používame oficiálny archív s odkazom v /usr/local/bin.

Aplikácia#

  1. Nahrajte kód aplikácie do /opt/mujbot/app (cez SFTP, návod, alebo git clone). Súbor .env s tokenom a priečinok node_modules nenahrávajte.

  2. Odovzdajte súbory používateľovi aplikácie:

    bash
    chown -R mujbot:mujbot /opt/mujbot
  3. Nainštalujte balíčky pod používateľom aplikácie:

    bash
    cd /opt/mujbot/app
    runuser -u mujbot -- npm ci --omit=dev
    • runuser -u mujbot -- – spustí príkaz pod používateľom mujbot (funguje aj bez balíka sudo).
    • npm ci – nainštaluje presne verzie zo súboru package-lock.json. Ak ho projekt nemá, použite npm install --omit=dev.
    • --omit=dev – vynechá balíčky potrebné iba na vývoj.
  4. Vyskúšajte aplikáciu ručne: runuser -u mujbot -- node index.js. Keď sa spustí bez chyby, ukončite ju Ctrl+C. (Ak potrebuje token, ručný test urobte až po kapitole Tajné údaje.)

Tajné údaje v EnvironmentFile#

Token a heslá nepatria do kódu ani do unit súboru. Uložte ich do súboru premenných, ktorý číta iba root, a systemd ich odovzdá aplikácii pri štarte.

  1. Vytvorte súbor nano /etc/mujbot.env:

    /etc/mujbot.envini
    DISCORD_TOKEN=<TOKEN_BOTA>
    NODE_ENV=production
    • Každý riadok je NAZEV=hodnota, bez export a bez medzier okolo =.
    • Riadky začínajúce # sú komentáre.
    • V aplikácii hodnotu prečítate ako process.env.DISCORD_TOKEN.
  2. Obmedzte práva:

    bash
    chown root:root /etc/mujbot.env
    chmod 600 /etc/mujbot.env
    • chmod 600 – súbor smie čítať a meniť iba root. systemd ho číta ešte pred prepnutím na používateľa aplikácie, premenné sa tak k aplikácii dostanú, ale súbor nikto iný neprečíta.

Unit súbor služby#

Vytvorte súbor nano /etc/systemd/system/mujbot.service:

/etc/systemd/system/mujbot.serviceini
[Unit]
Description=Môj Discord bot
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=mujbot
Group=mujbot
WorkingDirectory=/opt/mujbot/app
EnvironmentFile=/etc/mujbot.env
ExecStart=/usr/local/bin/node /opt/mujbot/app/index.js
Restart=on-failure
RestartSec=5
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target
DirektívaČo robíOdporúčaná hodnotaKedy zmeniť
Description=Opis služby vo výpisoch.Názov aplikácie–
After=network-online.targetSlužba štartuje až po nastavení siete.network-online.target–
Wants=network-online.targetPožiada systém, aby na sieť počkal (After samo nestačí).network-online.target–
Type=simpleProces z ExecStart je hlavný proces služby a beží v popredí.simpleIba keď aplikácia sama prechádza na pozadie (forking).
User=, Group=Pod akým používateľom aplikácia beží.používateľ aplikácieNikdy nie root.
WorkingDirectory=Pracovný priečinok; relatívne cesty v aplikácii sa počítajú od neho.priečinok aplikáciePri presune aplikácie.
EnvironmentFile=Súbor s premennými prostredia. Keď neexistuje, služba nenaštartuje (pomlčka pred cestou, -/etc/…, ho urobí nepovinným)./etc/mujbot.env–
ExecStart=Príkaz na spustenie. Program musí byť zadaný absolútnou cestou./usr/local/bin/node /opt/…/index.jsPodľa hlavného súboru aplikácie.
Restart=on-failureReštart, keď proces skončí nenulovým kódom alebo ho ukončí signál (okrem SIGTERM, SIGINT, SIGHUP a SIGPIPE, ktoré systemd berie ako riadne ukončenie). Ukončenie s kódom 0 reštart nespustí.on-failurealways, ak sa má spustiť znova aj po riadnom ukončení.
RestartSec=5Pauza 5 sekúnd pred reštartom (predvolené je 100 ms).5Dlhšia, ak aplikácia pri páde zaťažuje cudzie API.
NoNewPrivileges=trueAplikácia ani jej podprocesy nezískajú vyššie práva (napríklad cez programy s bitom setuid).true–
WantedBy=multi-user.targetPo enable sa služba spustí pri štarte VPS.multi-user.target–

Limit opakovaných štartov

systemd v predvolenom stave nepovolí viac než 5 štartov služby za 10 sekúnd. S RestartSec=5 sa tento limit nevyčerpá a padajúca služba sa bude skúšať spúšťať stále dokola každých 5 sekúnd. Ak chcete po sérii pádov skončiť, pridajte do časti [Unit] napríklad StartLimitIntervalSec=300 a StartLimitBurst=10 (najviac 10 štartov za 5 minút).

Spustenie služby#

bash
systemctl daemon-reload
systemctl enable --now mujbot
systemctl status mujbot
  • systemctl daemon-reload – načíta nové a zmenené unit súbory. Spúšťajte po každej úprave súboru .service.
  • systemctl enable --now mujbot – zapne spustenie po štarte VPS a službu hneď spustí.
  • systemctl status mujbot – stav služby a posledných pár riadkov logu.

Vo výpise status sledujte:

Výstuptext
● mujbot.service - Môj Discord bot
     Loaded: loaded (/etc/systemd/system/mujbot.service; enabled; preset: enabled)
     Active: active (running) since …
   Main PID: 12345 (node)
  • Loaded: … enabled – služba sa spustí po reštarte VPS.
  • Active: active (running) – beží. failed znamená, že spadla; activating (auto-restart), že čaká na reštart.
  • Main PID – číslo procesu aplikácie.

Ďalšie príkazy: systemctl restart mujbot (reštart), systemctl stop mujbot (zastavenie), systemctl disable mujbot (vypnutie spúšťania po štarte).

Logy#

Všetko, čo aplikácia vypíše (console.log, print, chyby), ukladá systemd do journalu.

PríkazČo ukáže
journalctl -u mujbot -fPriebežný výpis ako živá konzola; ukončíte Ctrl+C.
journalctl -u mujbot -n 100Posledných 100 riadkov.
journalctl -u mujbot --since "1 hour ago"Výpis za poslednú hodinu.
journalctl -u mujbot -bVýpis od posledného štartu VPS.
journalctl --disk-usageKoľko miesta journal zaberá.

Journal sa premazáva sám: v predvolenom stave zaberie najviac 10 % veľkosti súborového systému, maximálne 4 GB.

Python a Java#

Postup je rovnaký, líši sa iba inštalácia prostredia a riadok ExecStart.

Python

Python 3 je v systéme. Pre aplikáciu vytvorte virtuálne prostredie, aby sa balíčky nemiešali so systémovými:

bash
apt -y install python3-venv
runuser -u mujbot -- python3 -m venv /opt/mujbot/venv
runuser -u mujbot -- /opt/mujbot/venv/bin/pip install -r /opt/mujbot/app/requirements.txt
  • python3 -m venv /opt/mujbot/venv – vytvorí samostatné prostredie Pythonu v priečinku venv.
  • /opt/mujbot/venv/bin/pip install -r … – nainštaluje balíčky zo súboru requirements.txt do tohto prostredia.

V unit súbore použite Python z prostredia a vypnite bufferovanie výstupu (inak sa logy v journale objavujú s oneskorením):

ini
Environment=PYTHONUNBUFFERED=1
ExecStart=/opt/mujbot/venv/bin/python /opt/mujbot/app/bot.py

Java

Nainštalujte behové prostredie Javy vo verzii, ktorú aplikácia vyžaduje. Pre Javu 21:

bash
apt -y install openjdk-21-jre-headless

Pre Javu 25 nainštalujte namiesto toho balík openjdk-25-jre-headless. Oba sú v repozitári Ubuntu 24.04 aj Debianu 13. Verziu overíte príkazom java -version.

V unit súbore:

ini
ExecStart=/usr/bin/java -Xms512M -Xmx1G -jar /opt/mujbot/app/aplikace.jar
SuccessExitStatus=143
  • -Xms512M -Xmx1G – počiatočná a maximálna veľkosť pamäte Javy. Maximum nastavte s rezervou pod voľnú RAM VPS.
  • SuccessExitStatus=143 – Java pri riadnom zastavení (signál SIGTERM) končí kódom 143. Bez tohto riadka by systemd po každom systemctl stop hlásil službu ako failed.

Aktualizácia aplikácie#

bash
systemctl stop mujbot
cd /opt/mujbot/app
runuser -u mujbot -- git pull
runuser -u mujbot -- npm ci --omit=dev
systemctl start mujbot
  • git pull – stiahne novú verziu kódu (ak aplikáciu máte v Gite; inak nahrajte súbory cez SFTP a spustite chown -R mujbot:mujbot /opt/mujbot).
  • npm ci --omit=dev – doinštaluje zmenené balíčky.

Ak sa zmenili iba súbory kódu, stačí systemctl restart mujbot.

Overenie#

  • systemctl is-enabled mujbot vypíše enabled, systemctl is-active mujbot vypíše active.
  • Po reštarte VPS (reboot) aplikácia beží bez vášho zásahu.
  • Skúška automatického reštartu: systemctl kill -s SIGKILL mujbot (násilne ukončí proces, ako keby spadol). O 5 sekúnd systemctl status mujbot znova ukáže active (running) s iným Main PID. Obyčajné systemctl kill bez -s SIGKILL posiela SIGTERM, ktorý systemd berie ako riadne ukončenie, a s Restart=on-failure sa služba nespustí znova.

Keď niečo nefunguje#

status=203/EXEC#

Systemd nedokázal spustiť program z ExecStart. Cesta k programu neexistuje, nie je absolútna, alebo súbor sa nedá spustiť. Overte cestu (ls -l /usr/local/bin/node) a pri skriptoch prvý riadok (#!/usr/bin/env …) a právo spustenia.

status=217/USER#

Používateľ z User= neexistuje. Skontrolujte meno (id mujbot), alebo používateľa vytvorte podľa kapitoly Používateľ pre aplikáciu.

status=200/CHDIR#

Priečinok z WorkingDirectory= neexistuje alebo doň používateľ nesmie. Skontrolujte cestu a vlastníka (ls -ld /opt/mujbot/app).

Failed to load environment files: No such file or directory#

Súbor z EnvironmentFile= neexistuje. Skontrolujte cestu, alebo pred ňu pridajte -, ak je súbor nepovinný.

Start request repeated too quickly. (start-limit-hit)#

Služba padala príliš rýchlo za sebou a systemd ju prestal spúšťať. Príčinu nájdete v logu (journalctl -u mujbot -n 50). Po oprave vynulujte počítadlo a spustite službu:

bash
systemctl reset-failed mujbot
systemctl start mujbot

Warning: The unit file … changed on disk. Run 'systemctl daemon-reload' to reload units.#

Upravili ste unit súbor a nevykonali systemctl daemon-reload. Spustite ho a službu reštartujte.

Aplikácia hlási EACCES alebo permission denied#

Používateľ aplikácie nesmie čítať alebo zapisovať súbory. Typicky po nahraní súborov ako root. Opravte vlastníka: chown -R mujbot:mujbot /opt/mujbot. Port pod 1024 (napríklad 80) bežný používateľ otvoriť nesmie; nechajte aplikáciu počúvať na vyššom porte a pred ňu dajte Nginx (návod).

Aplikácia nevidí premennú z .env#

Systemd súbor .env v adresári aplikácie sám nenačítava. Premenné dajte do súboru z EnvironmentFile=, alebo ich v aplikácii načítajte knižnicou (napríklad dotenv). Po zmene súboru premenných službu reštartujte.

Zhrnutie

  • Aplikácia beží pod vlastným používateľom, nie ako root.
  • Unit súbor v /etc/systemd/system/ určuje používateľa, priečinok, príkaz s absolútnou cestou a reštart po páde.
  • Tajné údaje sú v súbore z EnvironmentFile= s právami 600.
  • Po úprave unit súboru: systemctl daemon-reload; zapnutie a štart: systemctl enable --now.
  • Logy: journalctl -u <NAZEV_SLUZBY> -f.

Hľadanie v návodoch