Manuale VPS Gemini9

Infrastruttura CRM, Servizi e Procedure Operative
v12 — 15 Aprile 2026

Indice

1. Panoramica Sistema

Informazioni Generali

HostnameVPS Gemini9
IP Pubblico185.198.244.81
IP VPN10.0.0.1
Dominio CRMcrm.gemini9.it
SSHPorta 22, user claudeuser
aaPanelhttps://10.0.0.1:15685/a8f0d4e9 (solo VPN)
TimezoneUTC (Roma calcolato nel codice)
TitolareDanilo Bertone — Agente commerciale termoidraulica (Latina/Frosinone)

Architettura Generale

Browser → Nginx (443/80)
  └─ /api/*        → Backend CRM Python      (127.0.0.1:9099)  → PostgreSQL (Docker)
  └─ /salute/*     → Salute API Python        (127.0.0.1:9098)
  └─ /mcp/*        → MCP Salute Python        (127.0.0.1:9096)
  └─ /mcp-ops/*    → MCP Operations Python    (127.0.0.1:9091)
  └─ /gps/*        → Traccar-CRM Python       (127.0.0.1:9093)
  └─ /             → Frontend HTML statico    (index.html, salute.html, gps.html)

Tutti i backend sono bindati a 127.0.0.1 e accessibili solo tramite reverse proxy Nginx. Il database PostgreSQL gira in Docker (container dk_nocodb-nocodb-db-1) sulla rete interna 172.23.0.2:5432.

Accesso al CRM

DispositivoURLNote
Machttps://crm.gemini9.itAggiunto in /etc/hosts → 10.0.0.1
iPhonehttp://10.0.0.1Safari forza HTTPS, usare IP diretto
Generico (VPN)https://crm.gemini9.itRichiede connessione VPN attiva

Mandanti

Vaillant, Euroacque, Resideo, Sunerg, Uponor, GF, Ici Caldaie

2. Servizi e Porte

Servizi systemd

ServizioPortaBindStatoDescrizione
crm-link-proxy9099127.0.0.1AttivoBackend CRM principale
salute-api9098127.0.0.1AttivoAPI Salute (uscite, body, workout)
whatsapp-bridge9097127.0.0.1AttivoBridge WhatsApp (Baileys/Node.js)
mcp-salute9096127.0.0.1AttivoMCP Server Salute (16 tool)
mcp-memory9095127.0.0.1AttivoMCP Memory Server
mcp-crm9094127.0.0.1AttivoMCP CRM Direttore
traccar-crm9093127.0.0.1AttivoBridge Traccar-CRM (GPS)
mcp-operations9091127.0.0.1AttivoMCP Operations (Paperclip)
paperclip3100/31010.0.0.0AttivoPaperclip AI (API 3100, UI 3101)
lamu-botAttivoBot Telegram Lamù
paperclip-webhook9089127.0.0.1VecchioWebhook bridge (sostituito da claude_local)

Porte Nginx Reverse Proxy

PathDestinazione
/api/*127.0.0.1:9099
/salute/*127.0.0.1:9098
/mcp/*127.0.0.1:9096
/mcp-ops/*127.0.0.1:9091
/gps/*127.0.0.1:9093
/.well-known/oauth*127.0.0.1:9096

Docker Containers

ContainerPorteReteDescrizione
dk_nocodb-nocodb-db-15432172.23.0.2 (dk_nocodb_default)PostgreSQL (database CRM + Salute)
dk_openclaw-openclaw-gateway-118789172.19.x.x (dk_openclaw_default)OpenClaw bot
Traccar8082, 5055Traccar GPS server
Wallabag + MariaDB + Redis8888wallabag_netWallabag News reader

File di Configurazione

  • Nginx vhost: /www/server/panel/vhost/nginx/crm.gemini9.it.conf
  • Paperclip Nginx: /www/server/panel/vhost/nginx/paperclip.conf
  • Nginx reload: sudo /www/server/nginx/sbin/nginx -s reload

3. CRM

Frontend

CRM principale/www/wwwroot/crm.gemini9.it/index.html (~531 KB)
Salute/www/wwwroot/crm.gemini9.it/salute.html (~44 KB)
GPS/www/wwwroot/crm.gemini9.it/gps.html

Stile UI: Apple/macOS Ventura con font Inter, sidebar gradiente blu notte, icone Lucide SVG, glassmorphism leggero, animazioni fadeSlideIn. Colore accent #007AFF.

Backend

File/www/wwwroot/crm.gemini9.it/link_contatto.py
Porta9099 (bind 127.0.0.1)
Serviziocrm-link-proxy
HandlerClasse con do_GET() e do_POST()
MAI killare il processo. Per riavviare: sudo systemctl restart crm-link-proxy. Se la porta è occupata: fuser -k 9099/tcp poi restart.

Database PostgreSQL

Host172.23.0.2:5432 (Docker)
Databasenocodb
Schemappc8j1wrkypcy4m
Tabelle24 totali (15 CRM + 9 Salute)
Connection Poolpsycopg2 ThreadedConnectionPool (min=2, max=10)

Credenziali e .env

  • File: /www/wwwroot/crm.gemini9.it/.env (chmod 600, owner www)
  • Caricamento: env_helper.pyload_env(), env(), db_conn_string(), get_db(), put_db()
  • Nessuna credenziale hardcoded nei file Python

Dati CRM Attuali

575 clienti, 767 contatti (dopo import Google contacts del 03-04/04/2026).

CRM Vecchio (Sync)

URLhttps://rcm.mysalescrm1.it/admin/index.php
Script sync/opt/sync-crm-vecchio.py (filtra solo autore Danilo id=2)

4. MCP Servers

L'infrastruttura MCP (Model Context Protocol) espone i dati del CRM e dei servizi come tool utilizzabili da Claude e dagli agenti Paperclip.

MCP CRM Direttore (porta 9094)

File/www/wwwroot/crm.gemini9.it/mcp_crm.py
Serviziomcp-crm
Porta9094

Tool disponibili: analisi fatturato, analisi ordine, briefing cliente, cerca ordini, clienti dormienti, confronto condizioni, previsione ordini, promo efficaci, riepilogo visite, strategia commerciale, tattiche chiusura, top prodotti, artiglieria.

MCP Salute (porta 9096)

File/www/wwwroot/crm.gemini9.it/mcp_salute.py
Serviziomcp-salute
Porta9096
URL pubblicahttps://crm.gemini9.it/mcp/
ProtocolloJSON-RPC 2.0 over Streamable HTTP
AuthOAuth 2.0 (dynamic registration, authorization code + PKCE)

16 tool: get/post uscite, body, workout, alimentazione, integratori, acqua, info, riepilogo, sync.

MCP Memory (porta 9095)

Serviziomcp-memory
Porta9095

Tool: memory_read, memory_write, memory_append, memory_list, memory_search. Gestisce file memory persistenti (PROFILE, ARCHITECTURE, PROJECTS, ecc.).

MCP Operations (porta 9091)

File/www/wwwroot/crm.gemini9.it/mcp_operations.py
Serviziomcp-operations
Porta9091
Proxy Nginx/mcp-ops/*

22 tool suddivisi per area: Finance (5), Marketing (5), IT (7), Email (5). Usato dagli agenti Paperclip.

5. Paperclip

Accesso

UI Webhttp://10.0.0.1:3101 (solo VPN, porta aperta per 10.0.0.0/24)
APIhttp://localhost:3100/api (dalla VPS)
Installazione/opt/paperclip/
Serviziosystemd paperclip
DBPGlite embedded ~/.paperclip/instances/default/db
Modello AIclaude-haiku-4-5-20251001 per tutti gli agenti

Company

Gemini9 - Danilo Bertone
ID: aee1074a-ab88-4588-81b4-bc847d696aa8

6 Agenti

AgenteDipartimentoRuolo
Executive AssistantChief of OperationsCEO role — coordina, legge email, classifica, smista
Sales AgentSales & ClientsGestione clienti, vendite, CRM
Finance AgentFinance & BillingFatture, scadenze, contabilità
Marketing AgentOutreach & CampaignsCampagne, outreach, comunicazione
IT AgentInfrastructure & MonitoringMonitoraggio servizi, infrastruttura
Project ManagerProposals & Follow-upRDO, proposte, tracking follow-up

Configurazione Agenti

  • API Key Anthropic configurata nel systemd service come Environment
  • Heartbeat: tutti disabilitati (da attivare quando pronto)
  • Skill files: ogni agente ha AGENTS.md in ~/.paperclip/instances/default/companies/{company_id}/agents/{agent_id}/instructions/
  • Gli agenti usano claude_local per le operazioni (il vecchio webhook bridge su porta 9089 è stato sostituito)

Backup Paperclip

  • Pre-installazione: /opt/backups/pre-paperclip/ (DB, file CRM, nginx, systemd, Docker)
  • Giornaliero: file paperclip-data (~116 MB) su Google Drive

6. Lamù Bot Telegram

Informazioni Bot

NomeLamù
Username@lamu_gemini9_bot
Chat ID Danilo292335472
File/opt/lamu-fuel-bot/bot.py (v2, riscritto da zero)
Serviziolamu-bot
Comando avviopython3 -u /opt/lamu-fuel-bot/bot.py
Backup vecchio/opt/lamu-fuel-bot/bot.py.bak

Comandi Disponibili

ComandoDescrizione
/helpLista comandi
/pienoRifornimento carburante (2 foto, analisi Gemini Flash)
/ultimoUltimo rifornimento
/statsStatistiche carburante
/rdoLista RDO aperte
rdo Cliente rif Riferimento descCrea nuova RDO
/briefingBriefing giornaliero (via MCP Operations)
/statusStato servizi
/annullaAnnulla operazione in corso

Gestione Foto

  • Foto senza testo: chiede [Rifornimento] o [Allegato RDO]
  • Foto con didascalia “rdo ...”: avvia RDO con allegato

Integrazione Gmail

  • Account: d.bertone@agenziarcm.com
  • Token: /www/wwwroot/crm.gemini9.it/.gmail_token.json
  • Refresh automatico con GOOGLE_CLIENT_ID/SECRET hardcodati nel bot

7. Gmail

Configurazione

Accountd.bertone@agenziarcm.com (Google Workspace)
Client ID275001080436-rss2f69kdvpk5it9gm1c8p4k1pvs5kmj.apps.googleusercontent.com
Client SecretIn .env (variabile GOOGLE_CLIENT_SECRET)
Token file/www/wwwroot/crm.gemini9.it/.gmail_token.json (chmod 600)
Redirect URIhttp://localhost
Scopegmail.readonly, gmail.send, gmail.modify

Token Refresh

Il refresh_token è permanente. L'access_token scade ogni ora e si rinnova automaticamente.

Utilizzo per Agente

Agente PaperclipUso Gmail
Executive AssistantLegge email, classifica, smista
Project ManagerCerca risposte RDO, invia RDO a Stefano
Finance AgentCerca fatture, scadenze

8. RDO (Richieste d'Offerta)

Panoramica

Le RDO sono richieste d'offerta inviate all'ufficio tecnico di Stefano per ottenere preventivi dai mandanti. Possono essere create da Telegram (Lamù) o intercettate dalle email dei clienti.

Email RDO

Destinatario PRODufficiotecnico@agenziarcm.com (Stefano)
Destinatario TESTdanilo@dbertone.com
Mittented.bertone@agenziarcm.com (OAuth gmail.send)
OggettoRDO - {mandante1/mandante2} - {cliente} - rif {riferimento}
CorpoInizia SEMPRE con “Ciao Stefano,” — firma “Grazie\nDanilo”

Mandanti Disponibili (bottoni Telegram)

Vaillant, Euroacque, Resideo, Sunerg, Uponor, GF, Ici Caldaie

Flusso da Telegram (richiesta manuale)

1
Danilo scrive rdo NomeCliente rif Riferimento descrizione + eventuale allegato
2
Lamù cerca il cliente nel CRM (query ILIKE)
3
Se trovato 1 cliente → selezione automatica. Se più risultati → bottoni inline per scegliere. Se 0 → possibilità di cercare di nuovo o usare comunque.
4
Bottoni multi-selezione mandanti con spunta (tick con conferma)
5
Preme [Invia RDO] → email inviata a Stefano + salvataggio in DB + tracking stato

Flusso da Email (richiesta cliente)

1
Executive Assistant legge email cliente con richiesta offerta
2
Notifica Danilo su Telegram con richiesta precompilata
3
Danilo conferma mandanti + inserisce riferimento
4
Email parte a Stefano con allegato originale del cliente
5
Project Manager traccia stato

Tracking Stato RDO

richiesta → inviata_a_stefano → in_lavorazione → completata → inviata_al_cliente
  • Sollecito WhatsApp/Telegram dopo 2 giorni lavorativi se non completata
  • Verifica che l'offerta sia spedita al cliente
  • Registra esito nel CRM

Database

TabellaRDO_Offerte
Campi chiaveemail_body, gmail_message_id
API/api/rdo con filtri stato/mandante

Sezione CRM

Il frontend CRM ha una sezione dedicata RDO con: nav item nella sidebar, funzioni loadRdo() e showRdoDetail(), modale dettaglio con link “Apri in Gmail” (usa gmail_message_id salvato nel DB).

Allegati

  • Da email cliente: Executive Assistant cattura e allega alla RDO
  • Da Telegram: Lamù supporta foto, PDF, documenti
  • Tipici: capitolati, disegni, specifiche tecniche

9. WhatsApp Bridge

Configurazione

File/opt/whatsapp-bridge/server.js
Porta9097 (bind 127.0.0.1)
Serviziowhatsapp-bridge
TecnologiaNode.js + Baileys

Limiti Operativi

Limiti severi per evitare ban: massimo 50 messaggi/giorno, delay obbligatorio 2-4 minuti tra un messaggio e l'altro.

Uso

Usato per campagne WhatsApp (es. auguri Pasqua, comunicazioni commerciali) e per solleciti RDO. La lista contatti disponibile conta 1867 cellulari unici.

10. GPS Traccar

Traccar Server

Web UIhttp://10.0.0.1:8082 (solo VPN)
Porta GPS5055 (TCP/UDP, solo VPN)
Docker compose/opt/traccar/docker-compose.yml
Data/opt/traccar/data/
Deviceiphone-danilo (uniqueId: 123456, deviceId: 1)

Bridge Traccar-CRM (porta 9093)

File/www/wwwroot/crm.gemini9.it/traccar_crm.py
Serviziotraccar-crm

Endpoints: /position, /route, /km, /nearby, /visits-today, /map-data, /health

Auto-Visite

  • Script: /opt/gps_auto_visits.py
  • Cron: ogni giorno alle 23:00
  • Logica: soste >10 minuti entro 2500 m da un cliente = visita registrata automaticamente

Frontend GPS

File: /www/wwwroot/crm.gemini9.it/gps.html — Mappa con posizioni, percorsi e visite.

11. OpenClaw

Configurazione

URLhttp://10.0.0.1:18789 (solo VPN)
Containerdk_openclaw-openclaw-gateway-1
Rete Dockerdk_openclaw_default (172.19.x.x)
Docker Compose/www/dk_project/dk_app/dk_openclaw/docker-compose.yml
Workspace/Memory/www/dk_project/dk_app/dk_openclaw/data/work/
Python3.11.2, psycopg2 2.9.5

Bot Telegram Vecchio

OpenClaw usa un token Telegram separato (bot Lamù vecchio). Non toccare questo token.

Note Importanti

Dopo un riavvio del server:
  • Ricollegare il container alla rete NocoDB: il container deve essere connesso sia a dk_openclaw_default che a dk_nocodb_default per raggiungere il DB.
  • Reinstallare psycopg2 dentro il container.
TOOLS.md: usare SEMPRE PostgreSQL diretto per accedere al DB. MAI usare l'API HTTP sulla porta 9099.

Il path /opt/lamu-fuel-bot è montato rw con permessi 777 dentro il container.

12. VPN WireGuard

Configurazione

Config/etc/wireguard/wg0.conf
HubVPS Gemini9 porta 51820/udp
MTU1280 (previene disconnessioni su download grossi)
PersistentKeepalive25 su iPhone, Mac, Mac Roma, iPad

Peer

IP VPNDispositivoNote
10.0.0.1VPS Gemini9Hub centrale
10.0.0.2VPS Nextcloud185.198.244.34 — cloud.gemini9.it
10.0.0.3Server RomaProxmox + Home Assistant (http://10.0.0.3:8123)
10.0.0.4HA Cercepiccola #1IP locale 192.168.1.113, wg-quick a livello sistema
10.0.0.5HA Cercepiccola #2IP locale 192.168.178.24, wg-quick a livello sistema
10.0.0.6iPhoneKeepalive 25
10.0.0.7MacKeepalive 25
10.0.0.8Mac RomaKeepalive 25
10.0.0.9iPadKeepalive 25

Home Assistant Cercepiccola

WireGuard sui dispositivi HA Cercepiccola DEVE girare a livello sistema (wg-quick), NON come addon Docker. La configurazione è in /homeassistant/wg0.conf con script di avvio /homeassistant/wireguard-start.sh e automazione HA “Start WireGuard” al boot con delay 30s.

Porte Aperte sulla VPN

22, 80, 443, 8888, 15685

13. Backup

Google Drive

Accountd.bertone@agenziarcm.com
PercorsoDrive → VPS-Gemini → CRM_Backups
Folder ID1vzABb6l2yE1nS44s9zZKv-EJ2xa6QTM-
Token Drive/www/wwwroot/crm.gemini9.it/.drive_token.json (scope drive)
Upload script/www/wwwroot/crm.gemini9.it/drive_upload.py

Backup ore 01:00 — /opt/backup-crm.sh (7 file)

Nome FileContenuto
crm-codeCodice CRM Python, HTML, .env, .gmail_token.json
nocodb-sqldumpDump SQL database PostgreSQL completo
opt-scriptsLamù bot, WhatsApp bridge, backup scripts, GPS scripts
nginxConfig nginx tutti i vhost
configsSystemd services, WireGuard
docsManuale
paperclip-dataDB Paperclip, agenti, skill, company (~116 MB)

Backup ore 03:00 — /opt/backup-openclaw.sh (1 file)

Nome FileContenuto
openclawDati OpenClaw workspace, memory, config (~22 MB)

Riepilogo

File totali/giorno8
Volume totale~140 MB/giorno
Retention Drive15 file per tipo
Retention locale14 giorni

14. Disaster Recovery

Prerequisiti

Scaricare tutti i file di backup dalla cartella Google Drive VPS-Gemini → CRM_Backups (account d.bertone@agenziarcm.com).

Procedura di Ripristino Completa

1
Reinstalla OS + software base
# Installa Docker, Docker Compose, Node.js 20, pnpm, Python 3, pip
apt update && apt upgrade -y
apt install docker.io docker-compose nodejs npm python3 python3-pip -y
npm install -g pnpm
2
Ripristina WireGuard
tar xzf configs-*.tar.gz
cp etc/wireguard/wg0.conf /etc/wireguard/
systemctl enable wg-quick@wg0 && systemctl start wg-quick@wg0
3
Ripristina Docker containers
# NocoDB (PostgreSQL)
docker-compose up -d nocodb
# Traccar GPS
cd /opt/traccar && docker-compose up -d
# Wallabag
docker-compose up -d wallabag wallabag-db wallabag-redis
4
Ripristina Database PostgreSQL
gunzip nocodb-sqldump-*.sql.gz
# Restore nel container Docker PostgreSQL
docker exec -i dk_nocodb-nocodb-db-1 psql -U nocodb < nocodb-sqldump-*.sql
5
Ripristina codice CRM
tar xzf crm-code-*.tar.gz -C /www/wwwroot/crm.gemini9.it/
chmod 600 /www/wwwroot/crm.gemini9.it/.env
chmod 600 /www/wwwroot/crm.gemini9.it/.gmail_token.json
6
Ripristina script /opt
tar xzf opt-scripts-*.tar.gz -C /opt/
7
Ripristina Nginx
tar xzf nginx-*.tar.gz -C /www/server/panel/vhost/nginx/
sudo /www/server/nginx/sbin/nginx -s reload
8
Ripristina servizi systemd
tar xzf configs-*.tar.gz
# Copia i .service files in /etc/systemd/system/
systemctl daemon-reload
9
Ripristina Paperclip
cd /opt && git clone [repo-paperclip] paperclip
cd paperclip && pnpm install
tar xzf paperclip-data-*.tar.gz -C ~/.paperclip/
10
Ripristina OpenClaw
tar xzf openclaw-*.tar.gz -C /www/dk_project/dk_app/dk_openclaw/
docker restart dk_openclaw-openclaw-gateway-1
# Ricollegare a rete NocoDB + reinstallare psycopg2
11
Avvia tutti i servizi
systemctl start crm-link-proxy salute-api mcp-salute mcp-crm mcp-memory \
  mcp-operations traccar-crm whatsapp-bridge paperclip lamu-bot
systemctl enable crm-link-proxy salute-api mcp-salute mcp-crm mcp-memory \
  mcp-operations traccar-crm whatsapp-bridge paperclip lamu-bot
Tempo stimato di ripristino: 30-60 minuti dalla disponibilità del server.

15. Troubleshooting

ProblemaSoluzione
CRM non risponde sudo systemctl restart crm-link-proxy
Porta 9099 occupata fuser -k 9099/tcp poi systemctl restart crm-link-proxy
Salute API non risponde sudo systemctl restart salute-api
MCP non risponde sudo systemctl restart mcp-salute
WhatsApp ban Aspettare 24-48h, poi rispettare limiti: max 50 msg/giorno con delay 2-4 min
iPhone 403 su CRM Usare http://10.0.0.1 (Safari forza HTTPS su crm.gemini9.it)
Sync uscite senza GPS Verificare che usi fileId (non spec_id) per download FIT
Uscite senza assist mode ebike_assist_mode è nei RECORD del FIT, non negli eventi
OpenClaw non raggiunge DB dopo riavvio Ricollegare container a rete dk_nocodb_default + reinstallare psycopg2
aaPanel non accessibile Verificare VPN attiva + usare User-Agent browser + RSA login + CSRF token
HA Cercepiccola VPN down dopo reboot Verificare automazione HA “Start WireGuard” (delay 30s) + wg-quick a livello sistema
SSH da iPhone via VPN non funziona Problema noto: SSH porta 22 non raggiungibile da iPhone via VPN
Lamù bot non risponde sudo systemctl restart lamu-bot
Paperclip non risponde sudo systemctl restart paperclip
Wallabag non carica notizie Verificare cron /opt/wallabag-rss-fetch.sh (ogni 30 min, cron id 72 aaPanel)

Comandi Diagnostici Utili

# Stato di tutti i servizi
systemctl status crm-link-proxy salute-api mcp-salute mcp-crm mcp-memory \
  mcp-operations traccar-crm whatsapp-bridge paperclip lamu-bot

# Log di un servizio
journalctl -u crm-link-proxy -f --no-pager -n 50

# Verifica porte in ascolto
ss -tlnp | grep -E '909[0-9]|3100|3101'

# Stato Docker
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# Test connessione DB
docker exec dk_nocodb-nocodb-db-1 psql -U nocodb -c "SELECT count(*) FROM ppc8j1wrkypcy4m.nc_acjx___Clienti;"

# Stato WireGuard
wg show

Note Operative Generali

  • Il server è in UTC — il timezone Roma viene calcolato nel codice
  • Backend CRM: servizio systemd — NON killare, usare sempre systemctl restart
  • Nessuna credenziale hardcoded nei file Python (tutto in .env)
  • Per eseguire comandi su Gemini9 da remoto: cron job via aaPanel, aspettare 75s, leggere output, eliminare cron

Manuale VPS Gemini9 v12 — Generato il 15 Aprile 2026

Danilo Bertone — Gemini9