Ubuntu 26.04 LTS Desktop ako šablóna pre vRealize Automation (resp. VMware Aria Automation) je základný stavebný kameň pre automatizované nasadzovanie linuxových desktopov v podnikovom vSphere prostredí — typicky pre VDI, vývojárske pracovné stanice alebo lab stroje. Tento návod pokrýva kompletnú prípravu Ubuntu 26.04 Desktop šablóny — od nastavenia VMware VM, cez optimalizáciu OS pre klonovanie, konfiguráciu cloud-init, automatické aktualizácie pomocou unattended-upgrades, až po sealing skript a verifikáciu po deploye z VRA blueprintu.
Cieľ je dosiahnuť šablónu, ktorá po klonovaní spoľahlivo regeneruje machine-ID, SSH host kľúče a sieťové parametre, automaticky preberá konfiguráciu z VRA blueprintu (cez VMwareGuestInfo datasource alebo manuálnu customizáciu) a sama si drží OS bezpečnostné záplaty bez ručného zásahu. Pre serverovú variantu šablóny (bez GUI) pozri samostatný návod VRA Ubuntu 26.04 Server Template.
Poznámka: v tejto verzii článku je obsah totožný so Server variantom — Desktop-špecifické sekcie (inštalácia GUI, autologin, screen saver, xRDP self-healing setup a watchdog timer) sa do návodu doplnia v ďalšej revízii.
1. VMware VM custom attributes
Pred inštaláciou OS nastav vo vSphere na novej VM tieto Advanced Configuration parametre (Edit Settings → VM Options → Advanced → Edit Configuration). Robíme to pred bootom, niektoré z nich sa po prvom štarte už ťažšie menia.
sched.swap.vmxSwapEnabled false
disk.EnableUUID true
tools.guest.desktop.autolock false
- sched.swap.vmxSwapEnabled = false — vypína vmx swap súbor v datastore (.vswp). Pri šablónach kde je dostatok RAM sa zbytočne spotrebúva diskový priestor a IO na hostiteľovi.
- disk.EnableUUID = true — exponuje stabilné disk UUID do guest OS. Bez toho Ubuntu LVM/initramfs môže pri klonoch pomenúvať disky nekonzistentne.
- tools.guest.desktop.autolock = false — vypína auto-lock VMware Tools session (relevantné aj pre headless server kvôli vmtoolsd timeoutom).
2. Update + base balíčky
Po inštalácii Ubuntu 26.04 Desktop sa najprv pripoj cez SSH (alebo otvor terminál v GNOME) ako sudo používateľ a ako prvé urob plný update systému plus inštaláciu základných nástrojov.
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
sudo apt install -y mc htop ssh ntpsec net-tools util-linux-extra curl wget gnupg
sudo systemctl enable ssh ntpsec
Poznámka k vyradeným balíčkom: Oproti starším verziám tohto návodu zámerne nepridávame xinetd ani ifupdown — na Ubuntu 26.04 sú obe obsolete. Sieť rieši Netplan + systemd-networkd, super-server inetd takmer nikto reálne nepoužíva. Ak ich aplikačne potrebuješ, doinštaluješ ich neskôr.
Poznámka k chrony → ntpsec swap-u: Ubuntu 26.04 Desktop má ako default time daemon chrony. Inštalácia ntpsec ho automaticky odstráni (konflikt — oba poskytujú virtual package time-daemon). Apt pri tom zobrazí varovanie typu „ubuntu-desktop-minimal depends on chrony | time-daemon“ — je to transient dpkg warning počas swap-u, závislosť meta-packagu sa korektne splní keď ntpsec dokončí setup (sám poskytuje time-daemon). Stačí nechať dobehnúť, výsledný stav je v poriadku.
3. Reset machine-ID parametra
Klony šablóny by zdieľali rovnaký /etc/machine-id, čo láme DHCP DUID-LL (všetky VM by žiadali rovnakú IP), systemd journal cieľovanie a prípadne licenčnú väzbu. Tu nastavíme symlink a vynulujeme — finálny reset urobí sealing skript (sekcia 14).
sudo rm /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
echo "" | sudo tee /etc/machine-id
4. Cloud-init s VMwareGuestInfo datasource
Cloud-init zostáva nainštalovaný, ale presunieme ho na VMwareGuestInfo datasource. Vďaka tomu VRA blueprint dokáže pri prvom boote injektovať hostname, SSH kľúče, prvotné users, alebo run-once user-data skripty cez vmx guestinfo properties.
# obmedziť datasource_list iba na VMware (poradie = priorita)
sudo tee /etc/cloud/cloud.cfg.d/99-vmware-guestinfo.cfg >/dev/null <<'EOF'
datasource_list: [ VMwareGuestInfo, NoCloud, ConfigDrive, OVF, None ]
EOF
# vyčistiť stav z install image — povinné pred sealingom
sudo cloud-init clean --logs
Rozšírenie root partície pri prvom boote — nepridávame cloud-initramfs-growroot. Cloud-init má vlastné moduly growpart + resizefs ktoré robia presne to isté natívne počas init fázy (nie z initramfs hooku). Sú v default cloud-init konfigurácii zapnuté, takže žiadny extra balíček netreba. Naviac sa tým vyhneme problémovému swap-u na Ubuntu 26.04: cloud-initramfs-growroot má hard dependency na initramfs-tools, ale Ubuntu 26.04 má ako default initramfs generator dracut — apt by ho preto pri inštalácii odstránil a nahradil initramfs-tools. Riskantná operácia na už-nainštalovanom systéme bez reálneho benefitu.
Ak chceš overiť že growpart modul cloud-initu je aktívny:
grep -E "growpart|resizefs" /etc/cloud/cloud.cfg
# malo by ukázať tieto moduly v cloud_init_modules: alebo cloud_config_modules: sekcii
Pri tomto prístupe vo VRA blueprinte definuješ cloudConfig sekciu (YAML) ktorá sa pri klonovaní zapíše do guestinfo.userdata — cloud-init si ju pri prvom boote prečíta a aplikuje.
5. Sieť a DNS
Šablóna by nemala niesť žiadnu fixnú sieťovú konfiguráciu — tú dodá VRA blueprint alebo cloud-init pri prvom boote. Odstránime preto default netplan súbor a hardcoded fallback nameservery.
# Odstrániť default netplan config
sudo rm -f /etc/netplan/*.yaml
# Hardcoded resolv.conf (fallback ak systemd-resolved zlyhá)
sudo unlink /etc/resolv.conf 2>/dev/null || true
printf '%s\n' 'nameserver 192.168.3.2' 'nameserver 192.168.16.16' 'nameserver 8.8.8.8' | sudo tee /etc/resolv.conf >/dev/null
systemd-resolved nechaj zapnutý — cloud-init s ním štandardne počíta a v kombinácii s VMwareGuestInfo datasourceom správne aplikuje DNS prepisy doručené z VRA blueprintu.
6. Optimalizácia OpenVMtools
Default open-vm-tools.service sa štartuje pred cloud-init-local.service a pred dbus.service, čo na bootu spôsobuje race condition — vmtoolsd občas zatuhne na 30–60 sekundách. Patch posunie štart za dbus a zakomentuje konfliktný tmpfiles entry.
sudo sed -i 's|Before=cloud-init-local.service|After=dbus.service|g' \
/lib/systemd/system/open-vm-tools.service
sudo sed -i 's|^D /tmp 1777 root root -|#D /tmp 1777 root root -|g' \
/usr/lib/tmpfiles.d/tmp.conf
sudo systemctl daemon-reload
7. Časová zóna a NTP
Časová zóna sa nastaví na Europe/Bratislava. Primárny NTP server je ntp.tuke.sk (označený modifikátorom prefer), ako záloha sú pridané verejné pooly sk.pool.ntp.org a europe.pool.ntp.org. Tri zdroje stačia na detekciu falseticker-a (NTP majority voting).
sudo timedatectl set-timezone Europe/Bratislava
sudo tee /etc/ntpsec/ntp.conf >/dev/null <<'EOL'
driftfile /var/lib/ntpsec/ntp.drift
leapfile /usr/share/zoneinfo/leap-seconds.list
statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable
# Primárny NTP server
pool ntp.tuke.sk prefer iburst
# Záložné verejné pooly
pool 0.sk.pool.ntp.org iburst
pool 1.europe.pool.ntp.org iburst
restrict default kod nomodify notrap nopeer noquery limited
restrict 127.0.0.1
restrict ::1
EOL
sudo systemctl restart ntpsec
ntpq -p
Príkaz ntpq -p by mal po pár sekundách ukázať vybrané peer-y so synchronizovaným stavom — pri ntp.tuke.sk by mal byť znak * (vybraný ako system peer), pri ostatných + (kandidát). Ak ostane všade x alebo prázdno, skontroluj firewall na port 123/UDP.
8. SSH server setup
SSH host kľúče sa musia regenerovať pri prvom boote každého klonu. Toto rieši kombinácia rc.local (regenerácia ak chýbajú) plus finálne zmazanie kľúčov v sealing skripte (sekcia 14).
sudo tee /etc/rc.local >/dev/null <<'EOL'
#!/bin/sh -e
test -f /etc/ssh/ssh_host_rsa_key || dpkg-reconfigure openssh-server
exit 0
EOL
sudo chmod +x /etc/rc.local
sudo tee /etc/systemd/system/rc-local.service >/dev/null <<'EOL'
[Unit]
Description=/etc/rc.local Compatibility
ConditionPathExists=/etc/rc.local
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target
EOL
sudo systemctl daemon-reload
sudo systemctl enable rc-local
SSH konfigurácia — povolenie root loginu (interný admin prístup) a zákaz default vmware účtu zo subiquity inštalátora:
sudo sed -i '/^#PermitRootLogin/c\PermitRootLogin yes' /etc/ssh/sshd_config
echo 'DenyUsers vmware' | sudo tee -a /etc/ssh/sshd_config
sudo systemctl restart ssh
Bezpečnostná poznámka: PermitRootLogin yes je vhodné kombinovať s PasswordAuthentication no + povinnými SSH kľúčmi. Pre VRA-deployovanú VM kde root prístup tečie cez VPN/jump host to akceptujeme; pre exposed hosty zvážiť aj limit cez AllowUsers alebo presne túto sekciu prerobiť na key-only.
9. Automatické aktualizácie — unattended-upgrades
Automatické bezpečnostné záplaty sú pre šablóny must-have — bez nich VM po deploy-i niekoľko mesiacov visí so zraniteľnosťami kým sa k nej niekto neprihlási. Predtým sme to v starších verziách šablóny riešili custom first-boot-update.sh skriptom s reboot counterom; pre Ubuntu 26.04 odporúčam unattended-upgrades — je to štandardná Canonical cesta s lepšou integráciou (ESM, kernel cleanup, proper reboot scheduling).
sudo apt install -y unattended-upgrades apt-listchanges
Hlavný enable — /etc/apt/apt.conf.d/20auto-upgrades:
printf '%s\n' \
'APT::Periodic::Update-Package-Lists "1";' \
'APT::Periodic::Unattended-Upgrade "1";' \
'APT::Periodic::AutocleanInterval "7";' \
'APT::Periodic::Verbose "1";' \
| sudo tee /etc/apt/apt.conf.d/20auto-upgrades >/dev/null
Allowlist a reboot policy — /etc/apt/apt.conf.d/50unattended-upgrades (prepíše default, ktorý povoľuje iba -security). Heredoc s uvozovkovaným terminátorom <<'EOL' — apostrofy zaisťujú že znaky ${...} sa neexpandnú v shelle (apt parser si ich rieši sám) a zároveň prežije copy-paste z prehliadača bez mangling-u.
sudo tee /etc/apt/apt.conf.d/50unattended-upgrades >/dev/null <<'EOL'
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
"${distro_id}:${distro_codename}-updates";
};
Unattended-Upgrade::Package-Blacklist {
// sem dať balíčky ktoré nikdy nechceš auto-aktualizovať
// napr.: "linux-image-generic";
};
Unattended-Upgrade::DevRelease "auto";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
Unattended-Upgrade::Remove-Unused-Dependencies "false";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
Unattended-Upgrade::SyslogEnable "true";
Unattended-Upgrade::SyslogFacility "daemon";
EOL
Validácia a sledovanie — overenie že timer-y sú aktívne, dry-run čo by sa nainštalovalo, a kde čítať logy:
# dry-run - vypíše čo by upgrade urobil
sudo unattended-upgrade --dry-run -d
# stav timer-ov
systemctl list-timers apt-daily apt-daily-upgrade
# log z dnešného behu
sudo journalctl -u unattended-upgrades --since today
# detailnejší apt log
sudo cat /var/log/unattended-upgrades/unattended-upgrades.log
Po aplikácii bude šablóna pri každom deploye automaticky:
- denne sťahovať balíčkové listy a aplikovať
-securityaj-updatesrepá - autoremove-ovať staré kernely a nepoužívané závislosti
- reštartovať sa o 04:00 ráno keď je potrebný reboot (typicky kernel update)
- logovať do journalctl +
/var/log/unattended-upgrades/
10. Optimalizácie pre vSphere a mass-deployment
Šablóna z ktorej sa môže klonovať aj 150 VM zaslúži pár optimalizácií navyše — vypnutie nepotrebných služieb, rozumné limity pre logy, virtual-guest tuning a randomizácia automatických aktualizácií aby ti 150 strojov nezačalo súčasne sťahovať balíčky.
Vypnutie multipathd (default voľba pre vSphere VM)
Pre čisté vSphere VM bez in-guest iSCSI/FC initiátora je multipathd v hostiteľskom OS nadbytočný — vSphere rieši cesty k storage na úrovni ESXi hosta (Round Robin, Fixed, MRU policy), guest vidí jeden virtuálny disk a žiadne alternatívne cesty. Spustený multipathd v guest OS:
- Zbytočne spotrebúva pamäť a CPU pri každom boote (mapping pokus)
- Občas konfliktuje s LVM/initramfs počas
update-initramfs - Spomaľuje boot o niekoľko sekúnd kým detekuje že nemá čo mapovať
# Zastaviť, vypnúť a odstrániť (typicky nie je nainštalovaný, kontrola pre istotu)
sudo systemctl disable --now multipathd multipathd.socket 2>/dev/null || true
sudo apt purge -y multipath-tools 2>/dev/null || true
Výnimka — keď multipathd potrebuješ: ak v guest VM bežia in-guest iSCSI alebo FC initiátory (typicky Veeam Hardened Repository, databázový server s direct LUN cez open-iscsi, alebo SAP HANA s ASM diskmi), multipathd doinštalovať s blacklist regex pre sda/nvme/hd*. To je ale špeciálny prípad — pre default VRA šablónu vypneme.
Tuned profile virtual-guest
Tuned je daemon ktorý aplikuje pripravené ladiace profily — pre VMware/KVM guest má virtual-guest profil ktorý nastaví správny I/O scheduler (mq-deadline pre virtio/pvscsi), vm.dirty_ratio, transparent hugepages a CPU governor. Bez tuned-u zostávajú defaulty navrhnuté pre desktop, ktoré pre serverové VM nie sú optimálne.
sudo apt install -y tuned
sudo systemctl enable --now tuned
sudo tuned-adm profile virtual-guest
tuned-adm active
Vypnutie motd-news (zbytočný network call pri každom logine)
Default Ubuntu posiela pri každom SSH logine HTTP request na motd.ubuntu.com aby zobrazil "What's new" reklamy a Pro upgrade lure. Pri 150 VM je to 150 zbytočných HTTPS requestov pri každom prihlásení.
sudo sed -i 's/^ENABLED=1/ENABLED=0/' /etc/default/motd-news
sudo systemctl disable --now motd-news.timer motd-news.service 2>/dev/null || true
Limit veľkosti journald
Pre šablónu z ktorej sa generujú efemérne VM (priemerná životnosť dní/týždňov, nie roky) drž žurnál malý — default 4 GB cap je pre takéto stroje plytvanie. 200 MB pokrýva niekoľko týždňov histórie pre debug.
sudo mkdir -p /etc/systemd/journald.conf.d
printf '%s\n' \
'[Journal]' \
'SystemMaxUse=200M' \
'SystemMaxFileSize=20M' \
'ForwardToSyslog=no' \
| sudo tee /etc/systemd/journald.conf.d/00-template.conf >/dev/null
sudo systemctl restart systemd-journald
systemctl status systemd-journald
Pozn. Time-based MaxRetentionSec sme zo configu vynechali zámerne — pri šablóne je storage cap (SystemMaxUse=200M) jediná zmysluplná retencia. Storage rotuje staré záznamy keď sa naplní 200 MB, čo je spoľahlivejšie ako čas-based retention pri VM s nedeterministickými boot časmi.
Randomizácia apt-daily timer-ov pre 150 VM cluster
Default systemd apt-daily.timer a apt-daily-upgrade.timer majú už zabudovanú náhodnú odchýlku (RandomizedDelaySec 12h pre apt-daily, 60min pre apt-daily-upgrade). Pre 150 VM klonovaných z rovnakého template to znamená, že bezpečnostné aktualizácie sa rozložia v čase — bez randomizácie by všetky stroje začali ťahať balíčky súčasne v ten istý moment a tvoj apt mirror, NTP server a uplink by to nepekne pocítili.
# overenie randomizácie (default je už zapnutá)
systemctl cat apt-daily.timer | grep -i Randomized
systemctl cat apt-daily-upgrade.timer | grep -i Randomized
# ak chceš ešte väčší rozptyl pre veľký cluster (napr. 4h pre apt-daily-upgrade):
sudo mkdir -p /etc/systemd/system/apt-daily-upgrade.timer.d
printf '%s\n' '[Timer]' 'RandomizedDelaySec=4h' \
| sudo tee /etc/systemd/system/apt-daily-upgrade.timer.d/override.conf >/dev/null
sudo systemctl daemon-reload
Pri default 60-min jitteri sa 150 VM rozloží približne na ~2.5 stroja za minútu — pre väčšinu prostredí akceptovateľné. Pri širšom 4h okne je to ~0.6 stroja za minútu, čo apt mirror prakticky nezacíti.
11. Vypnutie screensaver a sleep
VM klonovaná zo šablóny nikdy nesmie ísť do suspend ani zamknúť obrazovku počas prvého boota — cloud-init aplikuje guestinfo properties (hostname, user, SSH kľúče) a administrátor si typicky pripája RDP/console session na vyriešenie issue. Default Ubuntu Desktop ale po 5 minútach nečinnosti zhasne obrazovku, po 15 zamkne a po 20 minútach môže ísť do suspend. Pre VRA šablónu to celé vypneme — radšej deterministicky vždy beží, koncový VDI policy si firma definuje per-user cez GPO/dconf neskôr.
Mask systemd sleep targets
Najradikálnejšia úroveň — zamaskovanie všetkých systemd targets ktoré realizujú suspend/hibernate. Po tomto je systemctl suspend neúčinný (skončí s "Failed to start sleep.target: Unit sleep.target is masked"). Pre headless VDI ideálne; ak by si v budúcnosti chcel suspend povoliť, stačí systemctl unmask.
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
GNOME dconf system-wide override
Per-user gsettings nepostačuje — pri klonovaní šablóny ešte nemusí existovať žiadny user (cloud-init ho vytvorí pri prvom boote), takže nastavenie aplikujeme cez system-wide dconf database. Override sa aktivuje pre všetkých budúcich userov (vrátane gdm session) ihneď po ich vytvorení.
# 1. dconf profile - povie dconf-u, ktorú system-db má načítať okrem user-db
sudo mkdir -p /etc/dconf/profile /etc/dconf/db/local.d /etc/dconf/db/local.d/locks
sudo tee /etc/dconf/profile/user >/dev/null <<'EOL'
user-db:user
system-db:local
EOL
# 2. Default values pre screensaver + power
sudo tee /etc/dconf/db/local.d/00-vra-template >/dev/null <<'EOL'
[org/gnome/desktop/session]
idle-delay=uint32 0
[org/gnome/desktop/screensaver]
lock-enabled=false
idle-activation-enabled=false
[org/gnome/settings-daemon/plugins/power]
sleep-inactive-ac-type='nothing'
sleep-inactive-ac-timeout=0
sleep-inactive-battery-type='nothing'
sleep-inactive-battery-timeout=0
idle-dim=false
power-button-action='nothing'
EOL
# 3. Locks - zakáže userovi tieto kľúče prepnúť v Settings UI (toggle bude šedý)
sudo tee /etc/dconf/db/local.d/locks/00-vra-template >/dev/null <<'EOL'
/org/gnome/desktop/session/idle-delay
/org/gnome/desktop/screensaver/lock-enabled
/org/gnome/desktop/screensaver/idle-activation-enabled
/org/gnome/settings-daemon/plugins/power/sleep-inactive-ac-type
/org/gnome/settings-daemon/plugins/power/sleep-inactive-battery-type
/org/gnome/settings-daemon/plugins/power/power-button-action
EOL
# 4. Apply
sudo dconf update
Pozn. k locks: Locks sú silnejšie ako default values — užívateľ ich nemôže prepnúť cez GNOME Settings GUI. Ak naopak chceš, aby si user mohol screensaver zapnúť keď chce, vynechaj locks/00-vra-template — defaultná hodnota sa aplikuje len pri vytvorení nového usera a ten ju môže následne meniť.
GDM login screen (pred prihlásením)
GDM má vlastný dconf profile s vlastnou login-time obrazovkou. Aby ani tá nešla po pár minútach do screen blank, treba override aj pre gdm profile:
sudo mkdir -p /etc/dconf/db/gdm.d
sudo tee /etc/dconf/db/gdm.d/00-vra-template >/dev/null <<'EOL'
[org/gnome/desktop/session]
idle-delay=uint32 0
[org/gnome/settings-daemon/plugins/power]
sleep-inactive-ac-type='nothing'
sleep-inactive-ac-timeout=0
idle-dim=false
EOL
sudo dconf update
Verifikácia
# Systemd targets sú masked
systemctl is-active sleep.target suspend.target hibernate.target
systemctl status sleep.target | grep -i masked
# dconf default values aplikované (čítam ako nobody pre systémový defalut)
sudo -u nobody dconf read /org/gnome/desktop/session/idle-delay
sudo -u nobody dconf read /org/gnome/desktop/screensaver/lock-enabled
# má vrátiť uint32 0 a false
# Na aktívnej user session-i overiť že settings sú locked (read-only):
gsettings get org.gnome.desktop.session idle-delay
gsettings get org.gnome.desktop.screensaver lock-enabled
gsettings get org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type
Po deploye z VRA blueprintu by VM mala bežať indefinitne bez čierneho screen-u alebo prerušenia session. Power-management timer-y by nemali byť v top položkách systemd-analyze blame.
12. Optimalizácie pre VMware Desktop VM
Predošlé sekcie boli zdielané so Server variantom. Tu pridávame tweaks ktoré sú špecifické pre Ubuntu Desktop bežiaci ako VMware VM — od skipu welcome wizarda cez performance tweaks pre VDI až po vypnutie HW služieb ktoré v guest VM nemajú zmysel.
Skip Welcome wizard a Apport crash reporter
Pri prvom prihlásení nového usera GNOME otvorí gnome-initial-setup wizard ("Welcome to Ubuntu" + privacy options + Ubuntu Pro setup) — irelevantný pre VDI deployment, tučí kontrolu adminovi. Predmarkujeme ho ako "done" v skeletone, takže každý nový user ho preskočí. Apport crash reporter na zdielanom VDI je iba noise — pri pádoch aplikácií zaplaví usera dialógom "Send report" ktorý nikto nečíta.
# Skip gnome-initial-setup pre všetkých budúcich userov (cloud-init users tiež)
sudo mkdir -p /etc/skel/.config
echo "yes" | sudo tee /etc/skel/.config/gnome-initial-setup-done >/dev/null
# Apport off
sudo sed -i 's/^enabled=1/enabled=0/' /etc/default/apport
sudo systemctl disable --now apport.service 2>/dev/null || true
Performance tweaks pre VDI
Pri 150 paralelne bežiacich GUI session-ach sa GNOME animácie, Tracker search indexer a defaultná swappiness rýchlo prejavia na CPU/IO ESXi hosta. Animácie a Tracker vypneme system-wide; vm.swappiness znížime z linuxového defaultu 60 (server profile) na desktop-friendly 10 — desktop user nenávidí swap-in latency keď otvára okno.
# 1. Vypnúť GNOME animácie - apenduje sa do existujúceho dconf override-u (sekcia 11)
sudo tee -a /etc/dconf/db/local.d/00-vra-template >/dev/null <<'EOL'
[org/gnome/desktop/interface]
enable-animations=false
EOL
# 2. Lock animations off (užívateľ ich nemôže zapnúť cez GUI)
echo '/org/gnome/desktop/interface/enable-animations' | \
sudo tee -a /etc/dconf/db/local.d/locks/00-vra-template >/dev/null
# 3. vm.swappiness=10 - desktop responsiveness
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-desktop-swap.conf >/dev/null
sudo sysctl --system >/dev/null
# 4. Tracker3 indexer mask (per-user services) - šetrí disk IO
sudo systemctl --global mask tracker-miner-fs-3.service \
tracker-extract-3.service \
tracker-miner-rss-3.service \
tracker-writeback-3.service 2>/dev/null || true
# 5. Apply dconf
sudo dconf update
Wayland off, force Xorg session
Ubuntu 26.04 GNOME defaultne púšťa Wayland session, ale viaceré VDI/remote-access nástroje vyžadujú Xorg: VMware Horizon Blast Extreme, xRDP, x11vnc, niektoré screen-recorder a screen-sharing utility. Force-neme Xorg v GDM. Ak Horizon/xRDP nepoužívaš, túto sekciu preskočiť — Wayland defaultne má lepšie izolácie pre HiDPI a fractional scaling.
# Odkomentovať existujúci WaylandEnable=false riadok ak je tam zakomentovaný
sudo sed -i 's/^#WaylandEnable=false/WaylandEnable=false/' /etc/gdm3/custom.conf
# Ak riadok ešte nie je tam (custom.conf bol upravovaný), pridať do [daemon] sekcie
grep -q '^WaylandEnable=false' /etc/gdm3/custom.conf || \
sudo sed -i '/^\[daemon\]/a WaylandEnable=false' /etc/gdm3/custom.conf
# Verify
grep -E '^(Wayland|\[daemon\])' /etc/gdm3/custom.conf
# Reštart GDM (pozn: odhlási GUI session - radšej cez SSH alebo po reboote)
# sudo systemctl restart gdm3
Boot speed
V VM nikto nepozerá Plymouth splash screen ani GRUB countdown — vypnutie ušetrí ~3 sekundy boot času. Snap refresh timer (default 4×/deň) throttle-neme na nightly window, aby pri kernel-class snapoch (Firefox, Chromium) neprerušoval user prácu počas dňa.
# 1. Plymouth splash off + rýchly GRUB timeout
sudo sed -i 's/quiet splash/quiet nosplash/g' /etc/default/grub
sudo sed -i 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=1/' /etc/default/grub
sudo update-grub
# 2. Snap refresh timer - len 02:00-04:00 ráno (nie počas pracovného dňa)
sudo snap set system refresh.timer=02:00-04:00
# Verify
sudo snap refresh --time
grep -E '^GRUB_(TIMEOUT|CMDLINE_LINUX_DEFAULT)=' /etc/default/grub
Vypnutie nepotrebných HW služieb
VMware VM nemá fyzický bluetooth, modem, ani thermal-throttling capable CPU — služby ktoré tento HW riadia bežia naprázdno a spotrebúvajú pamäť (typicky 5–30 MB každá). Pri 150 desktop VM × 4 daemony to robí ~10–18 GB RAM nasmrad.
# Bluetooth - VMware VM nemá BT HW
sudo systemctl disable --now bluetooth.service 2>/dev/null || true
sudo apt purge -y bluez bluez-cups 2>/dev/null || true
# ModemManager - 3G/4G modem support, irrelevant v VM
sudo systemctl disable --now ModemManager.service 2>/dev/null || true
# thermald - thermal throttling, virtual CPU nemá thermal sensor
sudo systemctl disable --now thermald.service 2>/dev/null || true
# fwupd - firmware updates, VMware HW emuluje cez vCenter
sudo systemctl disable --now fwupd.service fwupd-refresh.timer 2>/dev/null || true
# Verify - po cleanup-e by tam nemala byť žiadna z týchto služieb
systemctl list-unit-files --state=enabled | grep -iE "bluetooth|modem|thermal|fwupd" || \
echo "OK: všetky HW služby vypnuté"
fstab noatime, nodiratime
Default Linux ext4 mount aktualizuje atime (access time) pri každom čítaní súboru — pre VMware VM nad iSCSI/NFS datastore to znamená zbytočné random write IO. noatime tieto writes potlačí (kernel zapisuje atime iba ak je súčasne menené mtime). nodiratime je redundantné s noatime (noatime ho zahŕňa), pridávame ho len pre explicit dokumentáciu.
# Pridať noatime,nodiratime k existujúcim mount options pre / a /home
sudo sed -i -E 's|(\s+/\s+ext4\s+)([^[:space:]]+)|\1noatime,nodiratime,\2|' /etc/fstab
sudo sed -i -E 's|(\s+/home\s+ext4\s+)([^[:space:]]+)|\1noatime,nodiratime,\2|' /etc/fstab
# Verify
grep -E '\s+/(home)?\s+ext4' /etc/fstab
# Remount immediately (bez reboota)
sudo mount -o remount /
sudo mount -o remount /home 2>/dev/null || true
# Confirm
mount | grep -E '\son /(home)?\s' | grep -o 'noatime'
Pozn. Ak má systém samostatný /var alebo /srv mount, pridaj `noatime` aj tam. Ak používaš LVM s logical volumes pre rôzne mount-pointy, prejdi cez všetky relevantné riadky fstab. Sealing skript v sekcii 14 sa fstab nedotýka — tieto mount options prežijú konverziu na šablónu.
Vypnutie nepotrebných daemonov a autostartov
Ubuntu Desktop default obsahuje balík služieb ktoré majú zmysel na fyzickom notebooku/desktope (printing, mDNS service discovery, telemetria, GNOME Online Accounts, alternatívny update daemon), ale na VDI cez Horizon/RDP sú redundantné alebo proti firemnej policy. Vypneme ich — typicky 5–30 MB RAM každá, pri 150 VM × 6 daemonov to robí ~10–25 GB nasmrad na ESXi.
# CUPS print server - VDI cez Horizon/RDP má vlastné print redirect
sudo systemctl disable --now cups cups-browsed 2>/dev/null || true
sudo apt purge -y cups cups-browsed 2>/dev/null || true
# Avahi mDNS - link-local discovery, na VDI v korporátnej sieti nepotrebné
sudo systemctl disable --now avahi-daemon avahi-daemon.socket 2>/dev/null || true
# whoopsie - Ubuntu error telemetria do Canonical
sudo systemctl disable --now whoopsie.service 2>/dev/null || true
sudo apt purge -y whoopsie 2>/dev/null || true
# packagekit - alternatívny update daemon, duplikuje apt + unattended-upgrades
sudo systemctl disable --now packagekit.service 2>/dev/null || true
# GNOME Online Accounts - Google/Microsoft/Nextcloud auth integration
sudo systemctl --global mask goa-daemon.service 2>/dev/null || true
# GNOME Software autostart - duplikuje update prompts s unattended-upgrades
if [ -f /etc/xdg/autostart/gnome-software-service.desktop ]; then
sudo sed -i 's/^Exec=/Hidden=true\nExec=/' /etc/xdg/autostart/gnome-software-service.desktop
fi
# rsyslog - máme journald centralizovaný, rsyslog duplikuje IO
sudo systemctl disable --now rsyslog 2>/dev/null || true
sudo apt purge -y rsyslog 2>/dev/null || true
# Verify - po cleanup-e by tam nemala byť žiadna z týchto služieb
systemctl list-unit-files --state=enabled | \
grep -iE "cups|avahi|whoopsie|packagekit|rsyslog|goa-daemon" || \
echo "OK: všetky VDI-redundant služby vypnuté"
Pozn. k GNOME Online Accounts: --global mask zakáže službu pre všetky user session-y. Ak chceš ísť radikálnejšie, môžeš odstrániť aj balíčky (apt purge gnome-online-accounts gnome-online-accounts-common), ale potom prestane fungovať Evolution mail integration a podobne. Pre čistú VDI šablónu kde users nemajú spustený email klient v guest VM je purge OK.
systemd-coredump a /tmp ako tmpfs
systemd-coredump defaultne ukladá core dumps do /var/lib/systemd/coredump/ — pri pádoch Chrome/Firefox môže každý dump mať 200 MB+. Na efemérnej VDI VM nikto core dumpy nečíta, ale dokážu naplniť disk. Vypneme ich storage. /tmp ako tmpfs presunie temp súbory do RAM — rýchlejšie IO, žiadna disk write amplification, pri rebote sa automaticky vyčistia. 512 MB limit je rozumný (default by bolo 50% RAM, čo je veľa pre VDI).
# systemd-coredump - Storage=none znamená "iba forward do journald, nepiš na disk"
sudo mkdir -p /etc/systemd/coredump.conf.d
sudo tee /etc/systemd/coredump.conf.d/disable.conf >/dev/null <<'EOL'
[Coredump]
Storage=none
ProcessSizeMax=0
EOL
# Reload systemd config
sudo systemctl daemon-reexec
# /tmp ako tmpfs - 512 MB limit, neperzistuje (cisty po rebote)
# Skontroluj že fstab ešte nemá explicit /tmp riadok
if ! grep -qE '^[^#].*\s/tmp\s' /etc/fstab; then
echo 'tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,size=512M 0 0' | \
sudo tee -a /etc/fstab >/dev/null
fi
# Apply (vyžaduje že /tmp je prázdny - typicky áno po inštalácii)
sudo systemctl daemon-reload
sudo mount /tmp 2>/dev/null || echo "Pozn: /tmp mount sa aplikuje po reboote ak je busy"
# Verify
mount | grep '/tmp\s' || echo "Po reboote skontroluj: mount | grep /tmp"
grep '/tmp' /etc/fstab
Caveats k /tmp tmpfs: Niektoré apps (npr. niektoré databázové migrácie, veľké video editory, decompress veľkých archívov) môžu potrebovať /tmp väčší než 512 MB. Ak typický workload na tomto VDI áno, zväčši na 1G alebo vypni úplne (nechaj default disk-based). Pri klone z template-u Ubuntu vie /tmp znova naformátovať na tmpfs pri prvom boote — funguje pre všetky budúce klony bez extra setupu.
13. Vzdialený prístup cez xRDP (so self-healing watchdog)
Pre VDI deployment kde users pristupujú z thin-clientov alebo Windows pracovných staníc cez RDP klient (mstsc, Remmina, FreeRDP) postavíme stabilný xRDP server priamo v šablóne. Setup pokrýva všetky známe gotchas Ubuntu 26.04 GNOME + xRDP kombinácie: GNOME Xorg session force (sekcia 12.3 už spravila Wayland off, tu doplníme session-env), polkit rules ktoré eliminujú "Authentication required to create managed color device" popup loop pri každom logine, a self-healing watchdog ktorý automaticky reštartuje xrdp ak spadne service alebo prestane počúvať na porte.
Inštalácia + GNOME session konfigurácia
xRDP balíček + pridanie xrdp usera do ssl-cert skupiny (potrebuje čítať /etc/ssl/private/ssl-cert-snakeoil.key pre TLS-encrypted RDP session). Default /etc/xrdp/startwm.sh spúšťa /etc/X11/Xsession ktoré bez session-env premenných nahádza prázdnu/zlomenú GNOME session. Prepíšeme ho explicitne na GNOME Xorg mode.
sudo apt install -y xrdp
sudo adduser xrdp ssl-cert
# Backup originálneho startwm.sh
sudo cp /etc/xrdp/startwm.sh /etc/xrdp/startwm.sh.orig
# Nový startwm.sh s GNOME Xorg session env premennými
sudo tee /etc/xrdp/startwm.sh >/dev/null <<'EOL'
#!/bin/sh
# Load shell profiles
if test -r /etc/profile; then
. /etc/profile
fi
if test -r ~/.profile; then
. ~/.profile
fi
# === xRDP: force GNOME Xorg session ===
unset DBUS_SESSION_BUS_ADDRESS
unset XDG_RUNTIME_DIR
export XDG_SESSION_TYPE=x11
export XDG_CURRENT_DESKTOP=ubuntu:GNOME
export GNOME_SHELL_SESSION_MODE=ubuntu
# Start session
test -x /etc/X11/Xsession && exec /etc/X11/Xsession
exec /bin/sh /etc/X11/Xsession
EOL
sudo chmod +x /etc/xrdp/startwm.sh
Polkit rules — fix "Authentication required" popup loop
Klasický xRDP gotcha: po prvom prihlásení sa userovi zobrazí dialóg "Authentication is required to create managed color devices", ktorý po zatvorení ihneď otvorí druhý a tretí. Príčina: GNOME colord service vyžaduje autentifikáciu pre operácie ktoré v non-console RDP session-e fail-nú. Polkit rule explicit povolí tieto akcie pre všetky session-y (console aj remote).
sudo tee /etc/polkit-1/rules.d/02-allow-colord.rules >/dev/null <<'EOL'
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.color-manager.create-device" ||
action.id == "org.freedesktop.color-manager.create-profile" ||
action.id == "org.freedesktop.color-manager.delete-device" ||
action.id == "org.freedesktop.color-manager.delete-profile" ||
action.id == "org.freedesktop.color-manager.modify-device" ||
action.id == "org.freedesktop.color-manager.modify-profile") {
return polkit.Result.YES;
}
});
EOL
# Polkit reload (alebo reboot)
sudo systemctl restart polkit
Firewall — povoliť 3389/tcp
# Ak je ufw aktívne, otvor port. Ak nie je aktívne, allow je no-op (príkaz neumiera).
sudo ufw allow 3389/tcp comment 'xRDP'
sudo ufw status verbose | head -10
systemd Restart=always pre xrdp
Default xrdp.service nemá Restart= — keď proces spadne (segfault, OOM kill, rare race condition pri sesman komunikácii), service zostane mŕtva až do reboota. Drop-in override jej dá automatické restart-on-failure.
sudo mkdir -p /etc/systemd/system/xrdp.service.d
sudo tee /etc/systemd/system/xrdp.service.d/restart.conf >/dev/null <<'EOL'
[Service]
Restart=always
RestartSec=5s
StartLimitIntervalSec=0
EOL
sudo systemctl daemon-reload
Self-healing watchdog (check_xrdp.timer)
Druhá vrstva poistky — systemd timer ktorý každé 2 minúty zavolá script check_xrdp.sh. Script verifikuje že (a) xrdp service je active a (b) reálne počúva na porte 3389. Ak nie, reštartuje. Toto zachytí scenáre kde service vyzerá byť hore ale TCP listener je mŕtvy (typicky po long-running session leak), čo by samotný Restart=always nezdetekoval.
# Watchdog script
sudo tee /usr/local/sbin/check_xrdp.sh >/dev/null <<'EOL'
#!/bin/bash
set -u
SERVICE="xrdp"
PORT=3389
# 1. Service must be active
if ! systemctl is-active --quiet "$SERVICE"; then
logger -t check_xrdp "service $SERVICE not active — restarting"
systemctl restart "$SERVICE"
exit 0
fi
# 2. TCP listener must be present on the expected port
if ! ss -tln 2>/dev/null | awk '{print $4}' | grep -qE ":${PORT}\$"; then
logger -t check_xrdp "port ${PORT} not listening — restarting $SERVICE"
systemctl restart "$SERVICE"
fi
EOL
sudo chmod +x /usr/local/sbin/check_xrdp.sh
# systemd service (oneshot - spustí sa, urobí check, skončí)
sudo tee /etc/systemd/system/check_xrdp.service >/dev/null <<'EOL'
[Unit]
Description=xRDP health check (one-shot)
After=xrdp.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/check_xrdp.sh
EOL
# systemd timer (každé 2 min)
sudo tee /etc/systemd/system/check_xrdp.timer >/dev/null <<'EOL'
[Unit]
Description=Periodic xRDP health check
[Timer]
OnBootSec=2min
OnUnitActiveSec=2min
AccuracySec=10s
[Install]
WantedBy=timers.target
EOL
# Enable + štart
sudo systemctl daemon-reload
sudo systemctl enable --now xrdp.service check_xrdp.timer
Verifikácia
# Service je hore
sudo systemctl status xrdp --no-pager | head -10
# TCP listener na 3389 (xrdp + xrdp-sesman na 3350 internal)
sudo ss -tlnp | grep -E ":(3389|3350)"
# Self-healing timer aktívny
sudo systemctl list-timers | grep xrdp
sudo systemctl status check_xrdp.timer --no-pager | head -5
# Posledný beh watchdogu (mal by byť do ~2 min)
sudo journalctl -u check_xrdp.service --since "5 min ago"
# IP na pripojenie
ip -4 -brief addr show | grep -v lo
Z Windows klientu mstsc (Remote Desktop Connection) sa pripoj na zobrazenú IP, port 3389. Ako username použij linuxový login (cloud-init user z VRA blueprintu), heslo rovnaké ako na lokálne prihlásenie. Pri prvom pripojení ti klient ukáže warning ohľadom self-signed TLS certu (xRDP používa ssl-cert-snakeoil) — pre produkčné nasadenie nahraď certifikát z firemnej PKI v /etc/xrdp/cert.pem + /etc/xrdp/key.pem.
Časté problémy
- Black screen po prihlásení → chýba
XDG_SESSION_TYPE=x11vstartwm.sh, alebo je stále aktívna Wayland session na GDM (sekcia 12.3 to mala vypnúť — overgrep WaylandEnable /etc/gdm3/custom.conf). - "Authentication required" popup loop → polkit rule chýba alebo nebola reloadnutá.
sudo systemctl restart polkit. - "Already logged in" → user má otvorenú GDM session na lokálnej konzole. xRDP nevie ďalšiu inštanciu rovnakého usera spustiť. Odhláš sa z GDM (alebo používaj rozdielnych userov).
- Žiadny zvuk → základný setup audio nepúšťa zámerne (stabilita). Doinštaluj
pipewire-module-xrdpak ho distribúcia má, alebo audio nechaj na neskôr. - Clipboard nefunguje → over že beží
xrdp-chansrvproces per session:pgrep -af chansrv. Ak chýba, skontroluj/etc/xrdp/sesman.ini[Globals] sekciu. - RDP klient hlási TLS cert warning → očakávané pri default snakeoil certifikáte. Pre produkciu nahraď firemným certom.
14. Sealing skript seal-template.sh
Konsolidovaný skript ktorý spustíš tesne pred konverziou VM na šablónu. Nahrádza desiatky ručných príkazov z pôvodnej verzie návodu jediným sudo /usr/local/sbin/seal-template.sh.
sudo tee /usr/local/sbin/seal-template.sh >/dev/null <<'EOL'
#!/bin/bash
# Spusť pred konverziou VM na šablónu, potom poweroff.
set -e
echo "=== Sealing template ==="
# Cloud-init reset (ak je nainštalovaný)
if command -v cloud-init >/dev/null; then
cloud-init clean --logs --machine-id
fi
# SWAP off + zakomentovať v fstab
swapoff --all || true
sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab
# Force IPv4 pre apt (ipv6 občas zlyháva v exotickej sieti)
echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4
# Truncate logy
for f in /var/log/audit/audit.log /var/log/wtmp /var/log/lastlog /var/log/btmp \
/var/log/syslog /var/log/auth.log /var/log/kern.log; do
[ -f "$f" ] && truncate -s 0 "$f"
done
# Vyčistenie persistent rules a tmp
rm -f /etc/udev/rules.d/70-persistent-net.rules
rm -rf /tmp/* /var/tmp/*
# SSH host kľúče - regenerujú sa pri prvom boote (sekcia 8)
rm -f /etc/ssh/ssh_host_*
# Machine-ID wipe (regeneruje sa pri prvom boote)
echo "" > /etc/machine-id
[ -L /var/lib/dbus/machine-id ] || echo "" > /var/lib/dbus/machine-id
# APT cache cleanup
apt clean
# History
history -c
> ~/.bash_history
[ -f /root/.bash_history ] && > /root/.bash_history
# fstrim - vynuluje voľné bloky vo file systéme, dramaticky zmenší výslednú VMDK
# (pri thin-provisioned diskoch môže ušetriť desiatky GB pri 150 klonoch)
fstrim -av || true
echo "=== Done. Now: sudo poweroff ; convert to template in vCenter. ==="
EOL
sudo chmod +x /usr/local/sbin/seal-template.sh
15. Konverzia na šablónu a verifikácia
Záverečné kroky na zdrojovej VM:
sudo /usr/local/sbin/seal-template.sh
sudo poweroff
Vo vCenter:
- Right-click na VM → Template → Convert to Template
- Premenuj template (napr.
tpl-ubuntu-2604-desktop) a presuň do template foldera - V Aria Automation Cloud Assembly pridaj template ako Cloud Template Image Mapping
Po prvom deploye z VRA blueprintu na novej VM overiť:
# Cloud-init stav
cloud-init status
cloud-init analyze show
# Logy z prvého bootu
sudo tail -200 /var/log/cloud-init.log
sudo tail -200 /var/log/cloud-init-output.log
# Boot performance
systemd-analyze
systemd-analyze blame | head -10
# Tuned profil je aktívny
tuned-adm active # malo by ukázať "Current active profile: virtual-guest"
# Multipathd vypnutý
systemctl is-enabled multipathd 2>&1 | grep -E "disabled|not-found"
# Unattended-upgrades je aktívny + randomizácia funguje
systemctl status apt-daily.timer apt-daily-upgrade.timer
systemctl list-timers apt-daily*
sudo unattended-upgrade --dry-run -d
# Journald limit funguje
journalctl --disk-usage # <= ~200 MB
# Uniqueness — nesmie byť identické s template
cat /etc/machine-id
hostname
ip a
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Časté problémy a kde hľadať:
cloud-init statusukazujeerror→/var/log/cloud-init.log; najčastejšie nedostal žiadneguestinfoproperties z VRA blueprintu (chyba v cloud-config YAML šablóny)- Stále sa pripájaš ako root cez password ale nemáš → skontroluj
/etc/ssh/sshd_configajournalctl -u ssh - Machine-ID identický s template → sealing skript zlyhal alebo sa nespustil; ručne
echo "" > /etc/machine-id && reboot - Unattended-upgrades sa nespúšťa →
systemctl list-timers apt-daily*, prípadnesystemctl unmask apt-daily.service systemd-journald.servicezlyhá sError: code: 117 (Structure needs cleaning)— poškodené žurnálové súbory (typicky po VM snapshot/pause incident, alebo prerušenom IO na datastore). Žurnál nie je možné opraviť, treba ho zmazať a nechať journald vytvoriť nový:sudo rm -rf /var/log/journal/* /run/log/journal/* && sudo systemctl restart systemd-journald
Súvisiace návody
- VRA Ubuntu 26.04 Server Template — server variant tohto návodu (bez GUI)
- VRA Ubuntu 24.04 Template — predošlá verzia návodu pre Ubuntu 24.04 LTS
- Inštalácia Ubuntu šablóny pre vRealize Automation — pôvodný návod pre staršie Ubuntu
Odborník na kybernetickú bezpečnosť, správu Azure Cloud a VMware onprem. Využíva technológie, ako Checkmk a MRTG, na monitorovanie siete a zvyšovanie efektívnosti a bezpečnosti IT infraštruktúry. Kontakt: hasin(at)mhite.sk
