BlogDevelopment

Development · 6 min čitanja

Kako smo složili backup baza tako da ga može održavati AI agent

Backup za self-hosted Supabase i Postgres podešavamo u Git repozitoriju, a ne u dashboardu, pa AI agent ima sve što mu treba da ga mijenja. Četiri mjeseca nakon što smo zadnji put dirali kod, novu bazu dodali smo u backup za otprilike pet minuta.

Ranije ovog mjeseca dodali smo novu Postgres bazu u backup. Trebalo je otprilike pet minuta, a većinu tog vremena AI agent je čitao repozitorij. Kod nismo otvorili od svibnja.

Činilo nam se da to vrijedi opisati, dijelom da pokažemo kako smo to složili, a dijelom zbog jedne odluke koju smo donijeli usput: gotovo sve postavke su u običnim tekstualnim datotekama u Gitu, a ne u dashboardu koji smo također napravili, jer agent najbolje radi upravo s tekstualnim datotekama.

Problem

Na jednom Hetznerovom VPS-u vrtimo nekoliko Postgres baza, sve deployane preko Coolifyja. Jedna je self-hosted Supabase za aplikaciju jednog klijenta, a ostale su obični Postgres za naše projekte.

Ako Supabase koristite kao hostanu uslugu, backup i restore rješava Supabase. Ako ga hostate sami, ne rješava: dobijete Docker Compose stack, a sve ostalo je na vama.

Noćni pg_dump je par linija shella, ali nedostajalo nam je sve oko njega: da znamo da sinoćnji backup stvarno postoji i izvan servera, i da ga možemo vratiti u Supabase koji radi, a da ne improviziramo u najgorem mogućem trenutku. Zato smo to napravili sami, a na kraju otišli i malo dalje nego što smo planirali.

Prvo skripta

Prva verzija bila je shell skripta koja napravi dump baze i kopira ga na Hetzner Storage Box, i druga koja se pokrene nekoliko sati kasnije i provjeri je li najnoviji backup dobro odrađen. Ako nešto ne štima, javi nam Uptime Kuma. Raspored je u repozitoriju, a na server ga instalira GitHub Actions, pa nitko ne mora ručno uređivati crontab.

Repozitorij smo od početka pisali za dva čitatelja: za nas za šest mjeseci i za AI agenta. Jedna datoteka sadrži pravila kojih se agent mora držati (nikad ne commitaj tajne, ne diraj cron izravno, ažuriraj dokumentaciju kad se ponašanje promijeni). Druga je ono što prvo pročitaš kad se vratiš nakon pauze, s naredbama za provjeru svakog dijela i popisom stvari na kojima smo već zapeli.

To je bilo dovoljno da imamo backup kojem vjerujemo. Onda smo ga htjeli i vidjeti.

Zašto imamo Go agenta

Htjeli smo dashboard koji pokazuje koji backupi postoje, gdje su, koliko su veliki i kad ide sljedeći, s gumbom da ga pokrenemo odmah.

Problem je u tome što skripte za backup trebaju puni pristup serveru: ulaze u druge kontejnere, čitaju pristupne podatke i drže ključ za Storage Box. Web aplikacija koja ih može pokrenuti u principu može pokrenuti bilo što. Naša bi bila iza auth proxyja, ali nismo htjeli da jedno krivo postavljeno pravilo na proxyju bude jedino što stoji između interneta i shella na serveru.

Zato smo to podijelili na dva dijela. Mali servis u Go-u radi izravno na serveru, a dashboard, koji kao i sve ostalo radi u kontejneru, može razgovarati samo s tim servisom.

Taj servis je zapravo popis onoga što je dopušteno. Ne prima naredbe, nego samo imena akcija definiranih u repozitoriju, a svaka od njih vodi na jednu točno određenu skriptu. Izvana mu se ne može pristupiti i odgovara samo na zahtjeve s tokenom koji ima backend dashboarda. Netko tko bi prošao auth proxy i dalje bi mogao samo ono što dashboard već nudi.

Prvu verziju i servisa i dashboarda napisao je AI agent. Kad je proradila, i cron smo prebacili na Go servis, pa backup po rasporedu i onaj pokrenut iz dashboarda prolaze kroz isti kod i završe u istoj povijesti. Tada servis više nije bio dodatak dashboardu, nego ono što pokreće sve.

Postavke u datotekama, namjerno

Svaka baza ima kratku YAML datoteku u repozitoriju. Ovo je jedna od njih, skraćena:

id: app-db
label: App Production Database
type: postgres-selfhosted
enabled: true

# Backups run twice a week; the longest gap is Thursday -> Monday (4 days).
verification:
  max_age_hours: 102
  min_size_bytes: 100000

schedules:
  postgres_backup:
    action: postgres_backup
    cron: "30 2 * * 1,4"
  postgres_check:
    action: postgres_check
    cron: "50 7 * * 1,4"

Kad pushamo na main, GitHub Actions osvježi repozitorij na serveru, ponovno builda Go servis i iz tih datoteka iznova generira raspored za cron.

Dashboard sve to može prikazati, preuzeti backup ili pokrenuti restore, ali postavke ne može mijenjati. Mogli smo napraviti forme za dodavanje baze ili uređivanje rasporeda, ali odlučili smo da nećemo. AI agent dobro čita mapu punu YAML-a i Markdowna, napravi malu promjenu, objasni je u commit poruci i testira je. Klikanje po stranici s postavkama ide mu puno lošije, a promjena napravljena tako ne ostavlja diff koji bi itko mogao pregledati.

Dashboard za backup: četiri baze s najnovijim backupima, lokalnim i udaljenim kopijama i njihovim veličinama, zauzeće prostora na serveru i na Storage Boxu, nedavna pokretanja i sljedeći rasporedi.
Svaka baza s najnovijim backupom, gdje su kopije i koliko su velike.

Vraćanje iz backupa

Kad je sve to bilo gotovo, na red je došao restore. Za razliku od backupa, restore prepisuje bazu koja radi, pa krivi potez može obrisati upravo ono što pokušavamo spasiti. Zato dashboard prije svakog restorea pokaže što će se točno dogoditi i provjeri sve što se može provjeriti, od toga je li restore za tu bazu uopće dopušten do toga ima li dovoljno mjesta na disku. Prije nego što išta dira, napravi backup trenutnog stanja, za slučaj da smo odabrali krivi. Restore radi kroz isti Go servis i isti dashboard kao i sve ostalo.

Provjere prije restorea: trinaest provjera, od toga je li restore za ovu bazu dopušten do toga ima li dovoljno prostora na disku za sigurnosni backup. Sve su prošle osim jedne preskočene i jednog upozorenja.
Provjere prije restorea. Tek nakon njih traži frazu za potvrdu.

Povratak u listopadu

Repozitorij nismo dirali od svibnja, a onda nam je trebao backup za novu bazu, jedan naš projekt na istom serveru.

Otvorili smo repozitorij u Claude Codeu i zamolili ga da doda backup za novu bazu. Agent je slijedio upute iz repozitorija, sam zaključio koji kontejner treba backupirati i dao nam jednu naredbu za pokrenuti na serveru, da se spreme pristupni podaci. To je bio jedini korak koji smo napravili ručno.

Sve je trajalo otprilike pet minuta. U istoj sesiji promjenom jedne linije pauzirao je i backup za klijentovu bazu, čija se aplikacija trenutno ne koristi. Ništa nismo morali ispravljati.

Agent nije napravio ništa osobito pametno. Sve što mu je trebalo već je bilo zapisano u datotekama koje je mogao pročitati.

Koliko je to trajalo

Četiri dana u svibnju, s tim da su većinu koda napisali AI agenti dok smo mi radili na klijentskim projektima. To je oko 5500 linija Go-a, 3800 JavaScripta, 1100 shella i 4300 Markdowna.

Dokumentacije je gotovo koliko i koda. Toliko je za interni alat nikad ne bismo napisali ručno, a upravo je zbog toga promjena u listopadu bila tako brza.

Prije nekoliko godina ovo uopće ne bismo radili. Tjedne rada na internom dashboardu za backup teško je opravdati u tvrtki naše veličine, pa bismo ostali na skripti i crontabu. Odluke su i dalje naše: što ide u backup, što restore smije napraviti i što nikad ne ide u Git. Promijenilo se to koliko je jeftino te odluke provesti do kraja, sve do testova, dokumentacije i sučelja.

Ako self-hosted Supabase vrtite na jednom serveru, vjerojatno vam ne trebaju ni Go servis ni dashboard. Ono što bismo preporučili je dio zbog kojeg je listopad prošao tako lako: držite skripte, rasporede i upute u jednom repozitoriju i pišite upute za onoga tko ga sljedeći otvori. Danas je to često agent.

Ivan

Piše

Ivan Cvitanović

Ivan je jedan od programera u Threennovateu. Ako je vaša aplikacija prerasla prvu verziju, vjerojatno ćete razgovarati s njim.

Pročitajte i ovo · Development · 5 min čitanja

Kako smo booking chatbot preradili oko modela za odlučivanje

U staroj verziji našeg chatbota za rezervacije otprilike je pola poruka prolazilo kroz LLM. Sada je to otprilike svaka deseta. Većinu ostalih obrađuje Jev, model koji ništa ne piše, nego samo bira između odgovora koje mu ponudimo.

Imate vlastite servere?

Pomoći ćemo vam postaviti backup i održavanje na koje se možete osloniti.

Vašu poruku čitaju isti ljudi koji ovdje pišu.