Files
ROMFASTSQL/docs/rclone-google-drive-headless.md
Claude Agent 3b7069e954 fix(maria): lacat intre reindexari, scriere atomica a indexului, XML invalid raportat
Descoperit la prima sincronizare reala din Drive: `maria-sync.timer` a pornit
peste rularea manuala si doua procese faceau embeddings in paralel pe acelasi
Ollama, ambele urmand sa scrie acelasi rag_index.json. Embedding-ul a incetinit
de la ~7s la ~20s din concurenta, iar ultimul care termina ar fi suprascris
munca celuilalt.

- config.exclusive(): lacat `flock` intre procese, luat la intrarea in sync.py si
  indexer.py. Nu asteapta — a doua rulare iese curat cu "o reindexare e deja in
  curs", fiindca ar reface exact acelasi lucru. Verificat pe procese reale.
- indexer scrie indexul atomic (tmp + os.replace): consumer-ul reciteste fisierul
  la 30s si putea prinde un JSON pe jumatate scris.
- build() intoarce `warnings` pentru XML-urile care nu se pot parsa, iar rularea
  din linia de comanda le scrie in stderr. Pana acum, un XML invalid se indexa
  tacut ca text simplu, cu o singura linie pierduta in log.

Context de performanta, masurat pe LXC 171 fara alta incarcare: un embedding
`nomic-embed-text` ia ~7,3s, deci o reindexare completa a celor 173 de chunk-uri
dureaza ~21 de minute — mai mult decat intervalul timer-ului. Nu e o problema
practica (amprenta reindexeaza doar la schimbare, iar lacatul opreste
suprapunerea), dar explica de ce prima rulare pare blocata.

docs/rclone-google-drive-headless.md: procedura de conectare a unui container
headless la Drive prin `rclone authorize`, cu transcriptul rularii reale de pe
Windows, capcanele (sync e distructiv pe destinatie, connection string in loc de
cale pe nume, unde stau secretele) si de ce nu contul de serviciu. Indexata in
CLAUDE.md.

6 teste noi (lacat, eliberare la exceptie, scriere atomica, avertismente).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4uzvgm7AyJch5WH8QHRhY
2026-08-31 18:42:01 +00:00

5.3 KiB

rclone + Google Drive pe un container headless (fără cont de serviciu)

Procedura de conectare a unui container Linux fără browser la Google Drive. Folosită prima dată pentru depozitul de documente al Mariei (LXC 171, maria-whatsapp-bridge), dar e generală — se aplică oricărui container din cluster.

Ideea: autorizarea OAuth are nevoie de un browser, containerul nu are. Deci autorizezi pe o mașină care are browser (stația Windows), iar rclone îți dă un token pe care îl muți pe container. Nu e nevoie de cont de serviciu și nu se atinge deloc consola Google Cloud.

De ce nu contul de serviciu

Prima variantă documentată era un service account în Google Cloud Console, cu dosarul din Drive partajat către adresa lui. Funcționează, dar cere: proiect în Google Cloud, activare Drive API, creare cont, descărcare JSON, partajare manuală a dosarului. Șapte pași în două interfețe. rclone authorize face același lucru în doi pași, dintr-o fereastră de browser deja autentificată.

Contul de serviciu rămâne varianta mai bună doar dacă ai nevoie de acces care nu depinde de niciun cont de om (ex. un serviciu care trebuie să meargă și după ce omul respectiv pleacă din firmă).

Pasul 1 — autorizezi pe Windows

Descarcă arhiva portabilă de la https://rclone.org/downloads/ (rclone-vX-windows-amd64.zip), dezarhiveaz-o oriunde — nu cere instalare. În acel dosar:

rclone.exe authorize "drive" --drive-scope=drive.readonly

drive.readonly fiindcă sincronizarea doar citește. Dacă ai nevoie și de scriere, folosește drive, dar atunci un rclone sync greșit poate șterge în Drive.

Se deschide browserul. Dacă nu se deschide, rclone scrie linkul în consolă. Cum arată o rulare reușită:

C:\Users\mmari\Downloads\rclone-v1.75.0-windows-amd64>rclone.exe authorize "drive" --drive-scope=drive.readonly
NOTICE: Config file "C:\\Users\\mmari\\AppData\\Roaming\\rclone\\rclone.conf" not found - using defaults
NOTICE: Make sure your Redirect URL is set to "http://127.0.0.1:53682/" in your custom config.
NOTICE: If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth?state=...
NOTICE: Log in and authorize rclone for access
NOTICE: Waiting for code...
NOTICE: Got code
Paste the following into your remote machine --->
{"access_token":"ya29...","token_type":"Bearer","refresh_token":"1//03...","expiry":"...","expires_in":3599}
<---End paste

Cele două mesaje despre „Config file not found" și „Redirect URL" nu sunt erori — authorize nu scrie niciun config pe Windows, doar obține tokenul. Dosarul rclone de pe Windows poate fi șters după.

Copiază tot JSON-ul dintre ---> și <---, inclusiv acoladele.

Pasul 2 — creezi remote-ul pe container

rclone config create gdrive drive \
  scope=drive.readonly \
  token='<TOKEN_JSON>' \
  --non-interactive

Ghilimelele simple sunt obligatorii — JSON-ul conține ghilimele duble.

Pentru Maria există un script care face pasul ăsta plus verificarea, scrierea în env și prima sincronizare: maria-whatsapp-bridge/ops/setup-drive.sh '<TOKEN_JSON>'.

Pasul 3 — fixezi dosarul după ID, nu după nume

rclone lsf 'gdrive,root_folder_id=<FOLDER_ID>:'

<FOLDER_ID> e din URL-ul dosarului în Drive (https://drive.google.com/drive/folders/<FOLDER_ID>).

Sintaxa remote,parametru=valoare: e „connection string"-ul rclone. Folosește-o în loc de căi pe nume (gdrive:romfast/document_store): calea pe nume se rupe dacă dosarul e mutat sau redenumit în Drive, iar rclone sync nu dă eroare — pur și simplu nu găsește nimic și, dacă e sincronizare bidirecțională, poate goli destinația.

Unde stau secretele

Tokenul ajunge în ~/.config/rclone/rclone.conf pe container. Fișierul conține refresh_token, adică acces continuu la Drive-ul contului — nu ajunge niciodată în git și nu se copiază între containere.

access_token expiră într-o oră; refresh_token îl reînnoiește singur, la nesfârșit, cât timp aplicația rămâne autorizată în contul Google. Se poate revoca oricând din https://myaccount.google.com/permissions.

Dacă tokenul e revocat sau expiră, sincronizarea începe să eșueze — se reiau pașii 1-2.

Capcane

  • rclone sync e distructiv pe destinație. Șterge local ce nu mai există în sursă. Depozitul devine o oglindă a dosarului din Drive, nu o colecție care crește: un fișier pus manual acolo dispare la prima sincronizare. Dacă vrei doar adăugare, e rclone copy.
  • Filtrează ce aduci. --include '*.md' --include '*.xml' etc. Un dosar de Drive strânge în timp tot felul de lucruri (.json, .ps1, .docx) care n-au ce căuta în depozit.
  • rclone authorize nu merge pe container, nici prin Tailscale: pornește un server local pe 127.0.0.1:53682 la care redirectează Google, deci browserul trebuie să fie pe aceeași mașină.
  • Versiunea de pe container poate fi mai veche decât cea de pe Windows (aici: 1.60.1 vs 1.75.0). Nu contează pentru token — formatul e stabil de mult.

Vezi și

  • proxmox/lxc171-claude-agent/maria-whatsapp-bridge/README.md, secțiunea „Sincronizare cu Google Drive" — configurarea concretă pentru Maria.
  • proxmox/lxc171-claude-agent/maria-whatsapp-bridge/ops/setup-drive.sh — scriptul care face pașii 2-3 plus prima sincronizare.