Linux – E1W
Postupy rozbehania Linuxu pre E1W
Tieto kroky boli odskúšané na Ubuntu 24.04.
Ako vytvoriť SSH kľúč
V PowerShell, CMD alebo v Linux termináli spusti:
ssh-keygen -t ed25519 -C "tvoje.meno@tvojafirma.sk"
Potom sa ťa to opýta:
Enter file in which to save the key (/home/pavol/.ssh/id_ed25519):
Stlač ENTER (uloží sa do default .ssh priečinka), alebo zadaj vlastnú cestu.
Následne:
Enter passphrase (empty for no passphrase):
Odporúčané: nechaj prázdne → ENTER.
Kde sa vytvorený kľúč uloží?
Windows:
C:\Users\<tvoje_meno>\.ssh\
id_ed25519 ← PRIVÁTNÝ KĽÚČ
id_ed25519.pub ← PUBLIC KĽÚČ
Linux/macOS:
~/.ssh/
id_ed25519
id_ed25519.pub
Prenesenie PUBLIC KEY na VPS
Privátny kľúč nikdy nahrávať na VPS!
Na VPS sa nahráva iba .pub.
Zobrazíš si public key:
cat ~/.ssh/id_ed25519.pub
Výstup bude napríklad:
ssh-ed25519 AAAAC3Nza.... tvoje.meno@tvojafirma.sk
Pridaj ho na VPS
Pripoj sa na VPS:
ssh root@IP_SERVERA
Vytvor súbor:
mkdir -p ~/.ssh
nano ~/.ssh/authorized_keys
Vlož tam celý obsah .pub kľúča.
Nastav práva:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Hotovo. Od teraz VPS prijíma tvoj SSH public key.
Otestuj prihlásenie pomocou SSH kľúča
Na Windows:
ssh -i C:\Users\<meno>\.ssh\id_ed25519 root@IP_SERVERA
Na Linux/macOS (automaticky nájde kľúč):
ssh root@IP_SERVERA
Ak sa prihlásiš bez hesla → OK.
Výpis private kľúča
cat ~/.ssh/id_ed25519
Použitie SSH Private Key v Azure DevOps – SSH service connection
V Azure DevOps:
- Project Settings
- Service connections
- New service connection
- Typ: SSH
- Vyplň:
- Host: IP VPS
- Username: root
- Private Key: vlož obsah
id_ed25519(súkromný kľúč) - Passphrase: prázdne (ak si nechal prázdne)
Private Key → musí byť v čisto OpenSSH formáte a musí vyzerať takto:
-----BEGIN OPENSSH PRIVATE KEY-----
<base64>
-----END OPENSSH PRIVATE KEY-----
Stane sa, že sa nevie prihlásiť, kvôli validácii host key. Podarilo sa mi to rozbehať tak, že pipeline sa mi spúšťa na agentovi, ktorého mám nainštalované na Windows ako službu, ktorá beží pod NetworkService. Vytvoril som adresár
C:\Windows\ServiceProfiles\NetworkService\.ssh\
a do neho súbor known_hosts. AI radí urobiť ho skriptom
ssh-keyscan -t ed25519 194.146.13.157 >> C:\Users\pavol\.ssh\known_hosts
Mne to na Windows nešlo, musel som pustiť na macos toto:
ssh-keyscan -t ed25519 194.146.13.157
Výstup bol niečo ako:
# XXX.XXX.XXX.XXX:22 SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.14 XXX.XXX.XXX.XXX ssh-ed25519 AAAAC3NzaC...
a to som nakopíroval do súboru known_hosts a potom sa to rozbehlo
Nastavenie VPS, Docker, Nginx reverse proxy a 2 kontajnery (e1w + e1w-dev)
VPS bude hostovať 2 Docker kontajnery:
- e1w → produkcia
- e1w-dev → development
Proxy (Nginx) obslúži 2 domény:
webl1.erpio.app→ kontajner e1wweb9.erpio.app→ kontajner e1w-dev
Použije sa wildcard certifikát (*.erpio.app)
Inštalácia Docker + Compose
apt update && apt upgrade -y
apt install ca-certificates curl gnupg -y
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
Pridaj repozitár:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null
Nainštaluj docker:
apt update
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
Tu mi to skončilo chybou – … GPG error… AI poradila pustiť tento skript a potom to už išlo spustiť
# 1) Odstráň prípadné staré záznamy, ktoré môžu kolidovať
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo rm -f /etc/apt/keyrings/docker.gpg
# 2) Vytvor adresár na keyring a nastav práva
sudo install -m 0755 -d /etc/apt/keyrings
# 3) Stiahni GPG kľúč a ulož ho v binárnej (dearmored) podobe
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 4) Povolenia, aby k nemu vedel APT pristupovať
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 5) Zapíš Docker repozitár s korektným 'signed-by=' a správnym codename (noble)
sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable" \
> /etc/apt/sources.list.d/docker.list'
# 6) Update balíčkov
sudo apt update
Príprava adresárovej štruktúry pre oba kontajnery
mkdir -p /var/www/e1w
mkdir -p /var/www/e1w-dev
mkdir -p /etc/nginx/ssl
Sem nahráš certifikáty:
/etc/nginx/ssl/fullchain.pem
/etc/nginx/ssl/privkey.pem
Nastavíš oprávnenia:
chmod 600 /etc/nginx/ssl/privkey.pem
chmod 644 /etc/nginx/ssl/fullchain.pem
Tieto pem súbory som si vyrobil z pfx, ktoré som dával na windows mašiny:
openssl pkcs12 -in cert.pfx -clcerts -nokeys -out fullchain.pem
openssl pkcs12 -in cert.pfx -nocerts -nodes -out privkey.pem
Docker Compose súbory
Pre každý kontajner som vytvoril príslušný siteconfig.json, kvôli zobrazovaniu informácie (pri čísle verzie), že ktorý server aktuálne mi zobrazuje webového klienta. V docker-compose.yml je potom tento súbor namapovaný namiesto toho, ktorý je súčasťou buildu.
# DEV
mkdir -p /var/www/e1w-dev/config/siteconfig
printf '{\n "SiteIdent": "DEVL1"\n}\n' > /var/www/e1w-dev/config/siteconfig/erpiositeconfig.json
# PROD
mkdir -p /var/www/e1w/config/siteconfig
printf '{\n "SiteIdent": "W1"\n}\n' > /var/www/e1w/config/siteconfig/erpiositeconfig.json
docker-compose.yml pre PRODUKCIU – /var/www/e1w/docker-compose.yml
services:
e1w:
image: e1w:latest
build:
context: . # koreň repozitára
dockerfile: E1Wserver/Dockerfile
container_name: e1w
restart: always
ports:
- "5001:8080"
environment:
- ASPNETCORE_URLS=http://+:8080
volumes:
- /var/www/e1w/config/siteconfig/erpiositeconfig.json:/app/wwwroot/siteconfig/erpiositeconfig.json:ro
docker-compose.yml pre DEV – /var/www/e1w-dev/docker-compose.yml
services:
e1w-dev:
image: e1w-dev:latest
build:
context: . # koreň repozitára
dockerfile: E1Wserver/Dockerfile
container_name: e1w-dev
restart: always
ports:
- "5002:8080"
environment:
- ASPNETCORE_URLS=http://+:8080
volumes:
- /var/www/e1w-dev/config/siteconfig/erpiositeconfig.json:/app/wwwroot/siteconfig/erpiositeconfig.json:ro
Nastavenie Nginx reverse proxy
Inštalácia Nginx (Ubuntu 24.04)
apt update
apt install -y nginx
Over, že beží:
systemctl status nginx --no-pager
# prípadne:
systemctl enable --now nginx
Pozn.: Balík nginx štandardne vytvorí štruktúru /etc/nginx/sites-available a /etc/nginx/sites-enabled.
Vytvor config pre produkciu:
nano /etc/nginx/sites-available/e1w
Vlož:
server {
listen 80;
server_name webl1.erpio.app;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name webl1.erpio.app;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
proxy_pass http://localhost:5001;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Vytvor config pre DEV
nano /etc/nginx/sites-available/e1w-dev
Vlož:
server {
listen 80;
server_name web9.erpio.app;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name web9.erpio.app;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
proxy_pass http://localhost:5002;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Aktivácia:
ln -s /etc/nginx/sites-available/e1w /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/e1w-dev /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx
V tomto kroku som kontajnery nespúšťal, nechal som to až po rozbehnutí DevOps pipelines, keď ich buildli a následne spustili.
Azure DevOps – CI/CD pipeline pre e1w a e1w-dev
- e1w-dev pipeline → automatický deploy po každom commite
- e1w pipeline → ručný deploy (prod release)
- Obe používajú to isté Git repo
- Deployment = upload súborov z repo na VPS +
docker compose build -> up -d - Predpokladá sa vytvorená SSH service connection podľ iného bodu
Pipeline pre DEV (automatická)
V repo vytvor azure-pipelines-e1w-dev.yml, deploy po každom push do master
trigger:
- master # auto-trigger je push do master
pool: WinNEOKrabica
steps:
- checkout: self
- task: CopyFilesOverSSH@0
displayName: 'Copy repo → VPS (/var/www/e1w-dev)'
inputs:
sshEndpoint: 'Contabo docker web client'
sourceFolder: '$(System.DefaultWorkingDirectory)'
targetFolder: '/var/www/e1w-dev'
cleanTargetFolder: false
- task: SSH@0
displayName: 'Docker compose build & up (e1w-dev)'
inputs:
sshEndpoint: 'Contabo docker web client'
runOptions: 'commands'
failOnStdErr: false
commands: |
set -e
cd /var/www/e1w-dev && docker compose -f ./docker-compose.yml config >/dev/null 2>&1 && docker compose -f ./docker-compose.yml build --progress=plain 2>&1 && docker compose -f ./docker-compose.yml up -d 2>&1
Pipeline pre PRODUKCIU (ručne spúšťaná) azure-pipelines-e1w.yml:
trigger: none # žiadny auto-trigger, spúšťaš manuálne
pool: WinNEOKrabica
steps:
- checkout: self
- task: CopyFilesOverSSH@0
displayName: 'Copy repo → VPS (/var/www/e1w)'
inputs:
sshEndpoint: 'Contabo docker web client'
sourceFolder: '$(System.DefaultWorkingDirectory)'
targetFolder: '/var/www/e1w'
cleanTargetFolder: false
- task: SSH@0
displayName: 'Docker compose build & up (e1w)'
inputs:
sshEndpoint: 'Contabo docker web client'
runOptions: 'commands'
failOnStdErr: false
commands: |
set -e
cd /var/www/e1w && docker compose -f ./docker-compose.yml config >/dev/null 2>&1 && docker compose -f ./docker-compose.yml build --progress=plain 2>&1 && docker compose -f ./docker-compose.yml up -d 2>&1
Následne dvakrát pre dev a prod:
- Pipelines
- New pipeline
- Azure repos Git (YAML)
- Vybrať repository
- Existing Azure Pipelines YAML file
- vybrať branch a súbor yml podľa návodu vyššie
Skúsiť spusťiť pipeline
“Load balancer” HAProxy
HAProxy bude:
- terminovať HTTPS cez wildcard cert
- rozdeľovať traffic medzi web1/web2/web3
- používať cookie sticky session (ako ARRAffinity)
- podporovať WebSockets (SignalR)
- mať admin štatistiky na porte
8404
DNS – treba upraviť A záznam pre web.erpio.app a nasmerovať ho na IP kde je HAProxy
Nainštalovanie HAProxy na VPS:
sudo apt update
sudo apt install -y haproxy
Overenie či beží:
systemctl status haproxy
Pripravenie wildcard certifikátu pre HAProxy:
openssl pkcs12 -in ErpioApp2026.pfx -out wildcard.erpio.app.pem -nodes
Táto varianta niekedy končí chybou SEC_ERROR_UNKNOWN_ISSUER. Vyzerá to, že lepšia varianta je zobrať pem, ktorý prišiel od autority a doplniť tam private key. Vraj by pem mal obsahovať toto:
-----BEGIN CERTIFICATE-----
(tvoj wildcard cert)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(RapidSSL intermediate)
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
(tvoj key)
-----END PRIVATE KEY-----
Overenie sa dá urobiť na adrese: https://www.ssllabs.com/ssltest/analyze.html?d=web.erpio.app
Nakopírovať ho do cieľa a nastavenie práv:
sudo mkdir -p /etc/haproxy/certs
sudo mv wildcard.erpio.app.pem /etc/haproxy/certs/wildcard.erpio.app.pem
sudo chmod 600 /etc/haproxy/certs/wildcard.erpio.app.pem
Kompletná konfigurácia HAProxy (HTTPS → 3 backendy s sticky cookie)
Uprav súbor:
nano /etc/haproxy/haproxy.cfg
a dať tam tento obsah:
global
log /dev/log local0
log /dev/log local1 notice
maxconn 20000
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option dontlognull
timeout connect 5s
timeout client 2h
timeout server 2h
timeout http-request 10s
timeout http-keep-alive 1m
option forwardfor
# ADMIN ŠTATISTIKY
listen stats
bind *:8404
mode http
stats enable
stats uri /haproxy?stats
stats refresh 5s
stats auth admin:NejakeSilneHeslo12345
# FRONTEND – HTTPS
frontend fe_https
bind *:443 ssl crt /etc/haproxy/certs/wildcard.erpio.app.pem
http-request set-header X-Forwarded-Proto https
http-request set-header X-Forwarded-Host %[req.hdr(Host)]
default_backend be_app
# BACKEND – 3 IIS servery
backend be_app
balance roundrobin
# sticky sessions pre Blazor/SignalR
cookie SRV_ID insert indirect nocache secure httponly
# DOČASNE: SSL/TCP health-check (bez HTTP GET /health)
# - kontroluje sa, že server prijme TLS
# - žiadny problém s Host header / SNI pre health-check
default-server check check-ssl inter 3s fall 3 rise 2 verify none
# per-server SNI pre istotu (väčšinou netreba, ale neuškodí)
server web1 web1.erpio.app:443 ssl sni str(web1.erpio.app) cookie w1
server web2 web2.erpio.app:443 ssl sni str(web2.erpio.app) cookie w2
server web3 web3.erpio.app:443 ssl sni str(web3.erpio.app) cookie w3
Syntax check:
sudo haproxy -c -f /etc/haproxy/haproxy.cfg
ak ok:
sudo systemctl restart haproxy
Otestovanie balancera – otvoriť stránku web.erpio.app, ak sa zobrazí, je to nádejné. Test:
- vypni jeden node (dočasne stop IIS) → HAProxy ho vyradí
- otvor v Chrome Incognito 3× za sebou → zobrazia sa requesty na rovnaký server (sticky cookie)
- skús reload → cookie drží server (affinity)
Admin štatistiky
http://IP_TVOJEHO_VPS:8404/haproxy?stats
naše sa dajú nájsť na http://erpio.link/balancerstats
Tu uvidíš:
- online/offline nody
- počet spojení
- aktuálna záťaž
- health-check status
TO DO : verzia s dvomi HAProxy (high-availability)
- automatický failover do 2 sekúnd
- 2× HAProxy
- keepalived + VRRP → virtuálna IP
Doriešiť s AI