Tri grupe, tri sloja repozitorija i jedan zajednički stroj — flora-nexus — za nadzor, sigurnosne kopije i povrat sva tri imanja.
Ovo je spremno, ali nije na redu. Vlasnikov redoslijed od 19. rujna 2026. stavlja nexus iza pet koraka koji moraju doći prvi: CI/CD dovršen → API na dev-platform.plant-garden.com → Pages na dev-v2.plant-garden.si → test → brzina pipelinea. Tek onda nexus, nadzor nad svime, pravi produkcijski katalog, frontend i CMS.
Promptovi 20a i 21a su napisani i spremni — i to je upravo razlog zašto se dvaput uzelo prvo ono što nije na redu. Spreman prompt izgleda kao sljedeći korak. Nije.
Jedna stvar ipak čeka baš ovdje. Brana pred migracijom izvađena je iz flora-deploya 19. 9., jer deploy koji odbija poći bez dokazanog backupa — dok iza tog uvjeta ne stoji stvarna pohrana — zaustavlja sve i ne štiti ništa. To je dug, ne otkaz: vraća se s fazom nexusa koja donese pohranu, a blok i tekst odbijanja čuvaju se u komentaru koji ju je zamijenio.
Stroj nije preopterećen — nadzor jednostavno ne radi. To je bitna razlika, jer se ne rješava većim serverom.
| Kvar | Dokaz | Uzrok |
|---|---|---|
| 62 % ciljeva ne odgovara | /api/v1/targets s nexusa: 21 od 34 down — 16 timeouta, 1 odbijen, 1 HTTP 404 | portovi 9113 (nginx) i 9558 (systemd) nisu otvoreni ni u jednom environments/*.tf; dev-child i dev-master uopće nemaju svoj terraform |
| Retencija logova ne briše | compactor: 12 465 uspješnih prolaza; najstariji chunk 19. 4. 2026.; 194 942 datoteka | u živoj konfiguraciji retention_period: 0s. Stari host_vars traže 720h, ali stroj njih više ne vrti |
| Stroj je pobjegao ispred koda | radi Loki 3.7.1 i Prometheus 3.11.2, alloy aktivan, promtail ugašen | playbookovi traže Loki 3.5.1, Prometheus 2.52.0 i promtail. Pokrenuti ih danas znači vratiti promtail. |
| Prometheus ne skreipa ni sam sebe | job prometheus → HTTP 404 | web.route-prefix iz konfiguracije za 2.52 ne pogađa put u 3.11 |
| Alarmi nisu u kodu | files/grafana/alerting/ sadrži samo README; grafana_alerts nije definiran nigdje | pravila su klikana u Grafani. Preživljavaju samo kroz blob backup, ne kroz git |
Prva analiza je tvrdila da nexus pati jer dijeli stroj s osam servisa (Vaultwarden, Umami, n8n, Homer, Uptime Kuma, OliveTin). To je bilo izvedeno iz komentara u konfiguraciji, bez ijednog mjerenja, i netočno je: load 0,16, nula OOM zapisa u 129 dana, 1 581 MB slobodnog RAM-a. Susjedi nisu problem. Zapisano je da se ista greška ne ponovi — komentar u konfiguraciji nije dokaz.
brunoafk.grafana_observability u rasadnik-infrastructure/ansible/collections/ je već napisana — i nexus je već dijelom vrti.
| Mjera | Vrijednost |
|---|---|
| Praćenih datoteka | 258 |
| YAML | 212 datoteka · 6 243 retka |
| Rola | 27 — Grafana, Prometheus, Loki, Tempo, Alertmanager, Alloy, autodiscover i 19 exportera |
| Testovi | 3 molecule scenarija: default, client-autodiscover, server-stack |
| Već podržava | --web.enable-remote-write-receiver, S3 backend za Loki, Grafana Git Sync |
Rješava tri od četiri strukturna problema starog sustava: Alloy umjesto promtaila, autodiscover umjesto 295 redaka ručno upisanih ciljeva, i remote-write umjesto povlačenja preko interneta.
| Sloj | Treba | Danas | Rola u kolekciji |
|---|---|---|---|
| MySQL rasadnik | mysqld_exporter | nema | exporter_mysql ✓ |
| PHP-FPM rasadnik | php-fpm_exporter | nema | exporter_phpfpm ✓ |
| PostgreSQL plant-garden | postgres_exporter | nema | exporter_postgres ✓ |
| Node.js runtime Vendure | heap, event loop, GC | nema | exporter_nodejs ✓ |
| Zdravlje diska | smartmon | nema | exporter_smartmon ✓ |
| HTTP izvana i istek TLS-a | blackbox_exporter | nema | ne postoji |
| Uspjeh i starost backupa | vlastita metrika | nema | ne postoji |
| GitLab pipelineovi | gitlab-ci-pipelines-exporter | nema | ne postoji |
| Vendure poslovne metrike | red poslova, narudžbe | nema | — |
Prvih pet je konfiguracija — role postoje i samo ih treba uključiti. Zadnje četiri su stvarni razvoj.
Stari sustav povlači metrike preko javnog interneta, pa svaki nadzirani stroj mora otvoriti portove. Novi gura — pa nijedan ne mora.
Kolekcija danas ima dva puta za istu stvar: 19 zasebnih exporter rola i sedam istih exportera ugrađenih u Alloy. Na stroju s Alloyem su te role suvišne.
| Što treba | Kako | Zasebni proces |
|---|---|---|
| host, procesi, kontejneri, Redis, Memcached, NGINX, Kubernetes | Alloy ih ugrađuje — prometheus.exporter.unix, .process, .cadvisor, .redis, .memcached, .nginx, .kubernetes | ne |
| HTTP i TLS izvana | prometheus.exporter.blackbox — Alloy ga ima, kolekcija nema rolu | ne |
| MySQL, PostgreSQL, PHP-FPM, systemd, SMART, LVM, ZFS, IPMI, DNS, Vault, RabbitMQ | zasebna rola iz kolekcije | da |
Jedan proces umjesto osam, jedan systemd unit umjesto osam, i nijedan port — jer Alloy skreipa u sebi i gura van. Zasebne role ostaju samo za ono što Alloy ne zna.
Alloyev unix exporter ima textfile collector uključen po zadanom — ali predložak kolekcije nabraja collectore izrijekom:
set_collectors = ["cpu", "diskstats", "filesystem", "loadavg",
"meminfo", "netdev", "stat", "time", "uname"]
Kad se popis navede, vrijedi samo on — pa je textfile danas isključen i svaka .prom datoteka nevidljiva. To je bitno jer je textfile način na koji se skripte javljaju nadzoru bez ijednog novog porta; tako radi čišćenje diska na runneru, i tako rade smartmon i lvm role. Treba dodati "textfile" u popis i blok textfile { directory = … }.
Čišćenje diska na CI runneru. Stroj je mjesecima stajao na 42 % s 8 GB smeća — deset slika i 32 cache volumena koje je držalo deset mrtvih runner tokena, dok je registriran bio jedan. Nitko to nije prijavio jer nitko nije gledao.
Sada systemd timer svakih 15 minuta provjeri disk, očisti iznad praga (80 %, varijabla u Ansibleu), preskoči ako posao radi, i svaki put ostavi metrike: postotak diska, oslobođeni bajtovi, vrijeme zadnjeg čišćenja i brojač preskočenih prolaza. Zadnji je najkorisniji — ako raste, čišćenje nikad ne dolazi na red.
Čišćenje je sigurno i dok posao radi: prune ne dira ništa u upotrebi. Provjera „nema jobova" nije zaštita od kvara nego od buke — da čišćenje ne produžuje tuđi prolaz. Slike su besplatne za brisanje jer je pull policy always, pa lokalne kopije ionako ništa ne ubrzavaju.
| Port | Danas | S flora-nexusom |
|---|---|---|
| 9100 node_exporter | 0.0.0.0/0 bez prijave, bez TLS-a | zatvoren — veže se na 127.0.0.1 |
| 9256 process_exporter | 0.0.0.0/0 — izvozi pune komandne linije svih procesa | zatvoren |
| 9113 nginx_exporter | nije otvoren nigdje → 6 od 7 ciljeva mrtvo | zatvoren, i više ne treba biti |
| 9558 systemd_exporter | nije otvoren nigdje → 6 od 7 mrtvo | zatvoren |
| 9150 memcached_exporter | 0.0.0.0/0 | zatvoren |
Ulazno na nadziranom stroju: ništa novo. Nula. Svi exporteri slušaju na 127.0.0.1, Alloy ih skreipa lokalno i gura van. Izlazno mu treba samo 443 prema nexusu.
| Port | Otvoren kome | Za što |
|---|---|---|
| 22 | samo admin IP | ssh |
| 443 | svijet iza Cloudflarea | Grafana i OliveTin, oboje uz prijavu |
| 443 | IP-evi nadziranih strojeva | isti port prima i push: /loki/api/v1/push, /api/v1/write, /otlp — nginx razdvaja po putanji |
| 80 | svijet | samo preusmjeravanje na 443 i ACME |
Ništa drugo nije otvoreno. Prometheus (9090), Grafana (3000), Loki (3100), Tempo (3200), Alertmanager (9093) slušaju na 127.0.0.1 i vide se samo kroz nginx.
| Podatak | Danas | Plan | Brojka iza odluke |
|---|---|---|---|
| Logovi | zauvijek retention_period: 0s | 30 dana | 1,8 GB/mjesec — 30 dana stane u 1,8 GB na 10 GB disku |
| Metrike | 30 dana | 90 dana | 2,2 GB za 30 dana; sezonski trend vrijedi više od starog loga |
| Tragovi | ne postoje | 7 dana | najskuplji po bajtu, star trag nitko ne gleda |
| Kopija baze | 3 dana | 7 dnevnih · 4 tjedna · 6 mjeseci | kvar u petak, primijećen u utorak — uz 3 dana je svaka kopija koju imaš već pokvarena |
Starost najstarijeg i najnovijeg zapisa mora biti metrika s alarmom — za logove, metrike i kopije. Compactor je 12 465 puta uspješno obrisao ništa i nitko to nije vidio pet mjeseci. Retencija koja tiho ne radi izgleda identično kao retencija koja radi.
| Površina | Za koga | Što može | Zašto baš to |
|---|---|---|---|
| Grafana | svi koji smiju gledati | metrike, logovi, tragovi, GitLab pipelineovi, poslovne brojke | namjerno samo čitanje — Grafana nije konzola |
| OliveTin | klijent | skini kopiju, skini snapshot, vrati snapshot, restartaj servis | ima ACL po akciji, prijavu, argumente kao formu umjesto slobodnog shella, potvrdu i zapis tko je što pokrenuo |
| CLI / TUI u repozitoriju | devops | sve gore plus dijagnostika, izbor verzije, suhi prolaz, razlog pada | ista konvencija kao ./flora i ./run |
Sve troje zove istu skriptu. Ako klijentov gumb i devops TUI imaju dvije izvedbe povrata, jedna od njih nije testirana — i to će biti ona koju klijent pritisne.
Vlastiti GUI se ne gradi. Značio bi ponovno pisati prijavu, ACL, validaciju argumenata i reviziju — točno ono što se u takvim alatima prvo pogriješi. OliveTin to ima i već se vrti na starom nexusu.
| Grupa | id | Imanje |
|---|---|---|
| rasadnik-milic | 14405474 | WordPress trgovina, master i child, nexus |
| self-legal1 | 82015692 | self-legal |
| plant-garden | 142577323 | Vendure, dvije trgovine, deset repozitorija |
Odluka vlasnika, 19. 9.: sve ide u vlastiti repozitorij, po grupi. Ova kartica zapisuje kako se to reže da ne završi s tri kopije istog.
Pitanje nije hoćemo li dijeliti — flora-infra je već vani i raste. Pitanje je po čemu se reže, da se osam dupliciranih datoteka ne pretvori u dvadeset i četiri.
| Sloj | Repozitorij | Zna za | Stanje |
|---|---|---|---|
| Knjižnica | brunoafk.grafana_observability kasnije i brunoafk.base za setup, secure, users |
ništa o imanjima | izdvojena 19. 9. u afk-ops/grafana-observability, s vlastitom poviješću i licencom |
| Zajedničko | flora-nexus | sva tri — jer ih nadzire | postoji od 20. 9. u plant-garden/flora-nexus, korijen grupe |
| Po imanju | rasadnik-milic/…-infra · plant-garden/flora-infra · self-legal1/…-infra | samo sebe | flora-infra postoji, druga dva su današnji rasadnik-infrastructure |
Tri repozitorija bez knjižnice znače tri kopije setup.yml-a i secure.yml-a. Već ih imaš dvije, i već su se razišle — flora-infra ima vlastito učvršćivanje pisano od nule jer se devsec pokazao preširokim.
Izvuci kolekciju u vlastiti repozitorij prije nego podijeliš imanja. Obrnuto znači da duplikaciju prepišeš u tri smjera i tek je onda pokušaš skupiti — a skupljanje je uvijek skuplje od nekopiranja.
Kolekcija je 258 datoteka i 27 rola i već je napisana tako da ne zna ništa o rasadniku. Jedino što joj treba je vlastiti repozitorij i broj verzije, pa da je sva tri imanja troše kao ovisnost umjesto da je kopiraju.
Zapisane su jer su ulaz u izvedbu, ne prijedlog. Ostatak ove stranice pisan je 19. 9. i mjestimice ih još ne prati — gdje se razilaze, vrijedi ovo.
| Pitanje | Odluka | Što to znači |
|---|---|---|
| Ime zajedničkog repozitorija | flora-nexus | Ostaje kako je ova stranica i pisala. Repozitorij postoji lokalno od 20. 9. Kroz jedan prolaz toga dana zvao se plant-nexus; vlasnik je to ispravio isti dan, prije ijednog pusha, pa je zamjena ostala ono što je stranica i tvrdila da jest — jeftina dok repozitorij ne postoji. Promptovi 20b, 21a i 21b time nisu zaostatak nego su cijelo vrijeme bili u pravu. |
| U kojoj grupi živi | plant-garden korijen, ne podgrupa |
Grupa nije bila otvorena nego zapisana. Deset repozitorija već stoji pod gitlab.com:plant-garden/ — devet u flora-platform, sync-nexus u ecommerce-tools. Ni jedna podgrupa nije dom: flora-platform je platforma jednog imanja, ecommerce-tools su njegovi alati, a ovaj stroj nadzire sva tri — pa stoji iznad obje, isto kao runner, koji je registriran na grupi a ne na projektu upravo zato što služi više od jedne stvari. Živo od 20. 9.: git@gitlab.com:plant-garden/flora-nexus.git, pet commita. |
| Što biva sa starim strojem | smanjuje se, ne gasi | rasadnik-nexus prestaje biti nadzor, ne prestaje postojati. Ostaje domaćin aplikacijama koje su korisne ondje gdje jesu, a u fazi 3 ulazi na popis kao nadzirani klijent. Ranija formulacija „zamjenjuje ga, ne stoji pokraj njega trajno" više ne vrijedi. |
| Namespace kolekcije | brunoafk | brunoafk.grafana_observability, verzija 0.1.0 — provjereno u galaxy.yml. Ranije je ova stranica na tri mjesta pisala afk_ops; to je bilo krivo i ispravljeno je. |
Sync zaliha ide na taj popis uz Vaultwarden, Umami, n8n, Homer i Uptime Kumu. sync-nexus i sync-probe.rasadnik-milic.hr nisu dio ovog posla. To je važno reći naglas jer je sync-probe.rasadnik-milic.hr isti stroj kao rasadnik-nexus — 23.88.40.182 — pa „selimo nadzor s tog stroja" i „ne diramo aplikaciju na njemu" moraju stajati jedno pokraj drugog. Prebacivanje na flora-nexus je moguće kasnije i nije prioritet.
Repozitorij je pushan 20. 9. na plant-garden/flora-nexus. Ono što i dalje nije sesijina ruka je apply — po dogovoru od 18. 9. stroj diže vlasnik. Do tada validate i fmt rade, a plan traži GITLAB_PROJECT_ID u .env: broj s pregledne stranice tog projekta.
Checkout stoji pokraj flora-basea, ne u njemu — i to se s korijenom grupe slaže samo od sebe. flora-base okuplja flora-platform, a ovaj repozitorij ondje nije, pa bi red u repos.json bio tvrdnja da jest. Treba li ga ./flora status ipak znati prikazati je vlasnikova odluka, ne sesijin git mv.
Metrike se ne sele. Vlasnikova odluka od 19. 9. — novi nexus kreće s praznom bazom, pa se stari i novi mogu vrtjeti usporedno dok se ne dokaže da novi radi.
| Faza | Što radi | Gotova kad | Ovisi o |
|---|---|---|---|
| 1 · Stroj i kostur nije počelo | Novi repozitorij flora-nexus, OpenTofu za stroj i firewall, kolekcija brunoafk.grafana_observability kao ovisnost. Prometheus, Loki, Grafana, Alertmanager iza nginxa — sve na 127.0.0.1 osim 443. | nmap izvana vidi samo 22, 80 i 443. Grafana traži prijavu. | — |
| 2 · Guranje i retencija nije počelo | Alloy na jednom stroju gura metrike i logove kroz 443. Retencija upisana i dokazana brisanjem. Metrika starosti najstarijeg zapisa, s alarmom. | Zapis stariji od retencije nestane, i to se vidi na grafu. Nijedan exporter ne sluša na javnom sučelju. | 1 |
| 3 · Sva tri imanja i sve metrike nije počelo | Alloy na rasadniku, plant-gardenu i self-legalu. Uključuju se exporter_mysql, exporter_phpfpm, exporter_postgres, exporter_nodejs, exporter_smartmon. Piše se blackbox rola i gitlab-ci-pipelines-exporter. | Nula mrtvih ciljeva. Istek TLS certifikata je metrika s alarmom. Pipelineovi se vide u Grafani. | 2 |
| 4 · Kopije i povrat nije počelo | restic za datoteke, wal-g za Postgres, mysqldump za WordPress. Jedna skripta, tri pozivatelja. Provjera povrata po rasporedu: vrati u prazan cilj, prebroji, sruši. | Povrat je izveden, ne tvrđen: broj tablica i redaka nakon vraćanja, i vrijeme koje je trebalo. | 1 |
| 5 · Gumbi i TUI nije počelo | OliveTin akcije za klijenta uz ACL i potvrdu; CLI/TUI u repozitoriju za devops. Obje površine zovu iste skripte iz faze 4. | Klijent skine kopiju i vrati snapshot bez ssh-a. Svaka akcija ostavlja zapis tko ju je pokrenuo. | 4 |
| Repozitorij | Uloga | Sadrži |
|---|---|---|
| brunoafk.grafana_observability | knjižnica | 27 rola, molecule testovi. Ne zna ništa o rasadniku ni o plant-gardenu. Zaslužuje vlastiti repozitorij — danas je zakopana u rasadnik-infrastructure/ansible/collections/. |
| flora-nexus nov | izvedba | OpenTofu za stroj i firewall, inventar triju imanja, vrijednosti po imanju, skripte za kopiju i povrat, OliveTin akcije, CLI/TUI. |
| rasadnik-infrastructure | zatečeno | Ostaje kakvo jest dok faza 3 ne prebaci njegove strojeve na novi nexus. |
Zašto knjižnica odvojeno: ako ostane unutar rasadnik-infrastructure, opet se zalijepi za jedno imanje — a cijela poanta je da ista kolekcija poslužuje tri.
Ime: flora-nexus, potvrđeno 20. 9. 2026. Repozitorij je git@gitlab.com:plant-garden/flora-nexus.git — korijen grupe, iznad flora-platforma i ecommerce-toolsa, jer nadzire sva tri imanja a ne pripada nijednom.
Prve dvije faze imaju napisan par. Faze 3 do 5 namjerno čekaju: svaka stoji na tome što prethodna izmjeri na stvarnom stroju — isto pravilo po kojem je pisan CI.
| Datoteka | Što nosi |
|---|---|
| prompts/20a-nexus-kostur-developer.md | Faza 1. Nosi izmjereno zatečeno stanje, tablicu portova i tvrdi STANI na tome da ništa osim 22/80/443 ne smije biti otvoreno. |
| prompts/20b-nexus-kostur-verifikator.md | Sam skenira stroj izvana, sam provjerava da Grafana traži prijavu, sam gleda sluša li ijedan exporter na javnom sučelju. |
| prompts/21a-nexus-guranje-developer.md | Faza 2. Alloy, retencija i dokaz brisanjem — zapis stariji od retencije mora nestati. |
| prompts/21b-nexus-guranje-verifikator.md | Sam ubacuje zapis s lažnim datumom i gleda hoće li ga compactor pojesti. |