Aller au contenu principal

Guide d'auto-hébergement

Faites tourner votre propre instance Campbooks avec Docker en quelques minutes. Ce guide couvre la configuration complète : la pile, les secrets nécessaires, et comment connecter chaque intégration externe.

Vous l'essayez juste en local ? Passez au Démarrage rapide. Vous le faites tourner sur un vrai serveur ? Lisez aussi Exécution en production.

Ce que vous obtenez

docker compose up exécute trois conteneurs :

ServiceCe que c'est
postgresPostgreSQL avec l'extension pgvector (obligatoire)
webL'application Rails (Puma derrière Thruster)
workerTâches en arrière-plan — analyse des e-mails, IA, indexation (Solid Queue)

Postgres contient tout : données applicatives, cache, jobs et Action Cable (via les adaptateurs Solid), plus les embeddings vectoriels pour la recherche sémantique (pgvector). Un quatrième service, opensearch, est optionnel et ne sert qu'à l'autocomplétion en texte intégral des contacts — voir Recherche.

Les fichiers téléversés (pièces jointes d'e-mails enregistrées en tant que documents) sont stockés sur un volume Docker local par défaut, ou dans un stockage d'objets compatible S3 si vous le configurez.

Prérequis

  • Docker et le plugin Docker Compose (Docker Desktop, ou Docker Engine ≥ 24 avec docker compose)
  • Environ 2 Go de RAM libres pour la pile par défaut (ajoutez ~1 Go si vous activez OpenSearch)
  • openssl sur votre machine (déjà présent sur macOS/Linux) pour générer les secrets
  • Facultatif, pour un vrai déploiement : un nom de domaine et un reverse proxy qui termine TLS (Caddy, Traefik, nginx)

Démarrage rapide

git clone https://github.com/notacamp/campbooks.git
cd campbooks

cp .env.example .env
bin/generate-secrets # fills SECRET_KEY_BASE, the AR encryption keys, and the DB password

# (optional) edit .env to add an AI key and any integrations you want
docker compose up -d --build

# watch it come up; first boot creates the databases and runs migrations
docker compose logs -f web

Ensuite, ouvrez http://localhost:3000 et créez le premier compte — sur une instance auto-hébergée, l'inscription est ouverte et le premier utilisateur crée l'espace de travail.

Le premier démarrage initialise également un espace de travail de démonstration avec l'identifiant admin@example.com / changeme123 (et partner@example.com). Changez ce mot de passe après la première connexion, ou définissez SEED_PASSWORD dans .env avant le premier démarrage. Vous ne voulez pas des données de démonstration ? Créez simplement votre propre compte et supprimez l'espace de travail de démonstration.

L'application fonctionne entièrement sans aucune clé API externe ; les fonctionnalités IA et les connexions aux boîtes aux lettres s'activent au fur et à mesure que vous ajoutez des informations d'identification (ci-dessous).

Pour arrêter : docker compose down (ajoutez -v pour supprimer également la base de données et les fichiers téléversés).

Configuration

Toute la configuration se fait via des variables d'environnement dans .env. bin/generate-secrets gère les secrets obligatoires ; tout le reste est optionnel. La liste annotée se trouve dans .env.example.

Obligatoires (générés pour vous)

VariableNotes
SECRET_KEY_BASEClé de session/signature Rails. openssl rand -hex 64
ACTIVE_RECORD_PRIMARY_KEYChiffre les tokens OAuth et les clés IA au repos. openssl rand -hex 16
ACTIVE_RECORD_DETERMINISTIC_KEYIdem
ACTIVE_RECORD_KEY_DERIVATION_SALTIdem
CAMPBOOKS_DATABASE_PASSWORDMot de passe pour le Postgres intégré

Vous n'avez pas besoin de config/master.key — l'auto-hébergement lit SECRET_KEY_BASE depuis l'environnement.

Obligatoires (à définir vous-même)

VariableDéfautNotes
APP_HOSTlocalhostLe nom d'hôte sur lequel vous accédez à l'application. Doit correspondre à l'en-tête Host (localhost, une IP ou votre domaine) — les autres hôtes sont rejetés pour des raisons de sécurité.
FORCE_SSLfalseLaissez false pour une utilisation locale en HTTP simple. Mettez true uniquement derrière un proxy TLS (voir Production).
SELF_HOSTED1Inscription ouverte + lecture des clés IA depuis l'environnement.

Intégrations externes

Chaque intégration est optionnelle. Ajoutez celles que vous voulez ; ignorez les autres.

Pour chaque fournisseur OAuth, vous devez enregistrer une application dans la console de ce fournisseur et autoriser l'URL de rappel, qui est <your-app-url>/oauth/<provider>/callback — p. ex. http://localhost:3000/oauth/gmail/callback en local, ou https://app.example.com/oauth/gmail/callback en production.

Fournisseurs IA

L'IA est ce qui fait de Campbooks ce qu'il est (tri, l'assistant Scout, brouillons de réponse, analyse de documents, recherche sémantique) — mais tout est optionnel et désactivé jusqu'à ce que vous ajoutiez une clé. Vous pouvez définir des clés ici pour toute l'instance, ou laisser chaque utilisateur saisir les siennes dans Paramètres → IA (stockées chiffrées par espace de travail).

VariableDéverrouille
OPENAI_API_KEYIA textuelle + analyse de documents/vision + embeddings (recherche sémantique). La clé unique la plus complète.
ANTHROPIC_API_KEYIA textuelle (Claude)
MISTRAL_API_KEYIA textuelle (hébergée en EU)
DEEPSEEK_API_KEYIA textuelle
GEMINI_API_KEYIA textuelle + embeddings
  • Pour l'assistant/tri : définissez n'importe quel fournisseur textuel.
  • Pour l'analyse des pièces jointes/documents et la meilleure recherche : définissez OPENAI_API_KEY.
  • Sans fournisseur d'embeddings (OpenAI ou Gemini), la recherche se rabat sur la correspondance par mots-clés.

Google — Gmail et Calendrier

Permet aux utilisateurs de se connecter avec Google et de connecter une boîte aux lettres Gmail (ce qui synchronise également leur Google Agenda avec la même autorisation).

  1. Google Cloud Console → créez un projet → APIs & Services → Credentials → OAuth client ID (type : Web application).
  2. Activez l'API Gmail et l'API Google Calendar pour le projet.
  3. Ajoutez l'URI de redirection : <your-app-url>/oauth/gmail/callback.
  4. Définissez GOOGLE_CLIENT_ID et GOOGLE_CLIENT_SECRET.

Google Drive — "Envoyer vers Drive"

L'export Drive interactif utilise le scope complet drive, un scope restreint de Google, donc il nécessite sa propre application OAuth vérifiée séparément.

  1. Créez un deuxième client OAuth (ou un projet séparé).
  2. Ajoutez le scope https://www.googleapis.com/auth/drive et l'URI de redirection <your-app-url>/oauth/google/callback.
  3. Définissez GOOGLE_DRIVE_CLIENT_ID et GOOGLE_DRIVE_CLIENT_SECRET.

Zoho Mail

  1. Console API ZohoServer-based Application.
  2. URI de redirection : <your-app-url>/oauth/zoho/callback.
  3. Définissez ZOHO_CLIENT_ID, ZOHO_CLIENT_SECRET et ZOHO_REGION (eu, com, in, au, jp — selon votre centre de données Zoho).

Microsoft 365 / Outlook

  1. Centre d'administration EntraInscriptions d'applications → Nouvelle inscription. Types de comptes pris en charge : Comptes dans n'importe quel annuaire organisationnel (comptes professionnels/scolaires ; l'application utilise le point de terminaison /organizations/).
  2. Ajoutez un URI de redirection Web : <your-app-url>/oauth/microsoft/callback.
  3. Créez un secret client.
  4. Définissez MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET et ENABLE_MICROSOFT_MAILBOX=1 (ce dernier affiche le bouton "Connecter Microsoft 365").

Notion — "Envoyer vers Notion"

  1. notion.so/my-integrations → nouvelle intégration, type Public, avec les capacités Read/Insert content.
  2. URI de redirection : <your-app-url>/oauth/notion/callback.
  3. Définissez NOTION_CLIENT_ID et NOTION_CLIENT_SECRET.

Si vous laissez ces valeurs non définies, les utilisateurs peuvent tout de même connecter Notion en collant un token d'intégration interne dans Paramètres.

E-mail sortant (SMTP)

Sans SMTP, l'application n'envoie aucun e-mail (les codes OTP d'inscription, les notifications et les rapports sont ignorés — acceptable pour un essai mono-utilisateur, mais vous en aurez besoin pour un usage réel).

SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=you@example.com
SMTP_PASSWORD=your_smtp_password
MAILER_FROM=Campbooks <no-reply@example.com>

Stockage de fichiers (S3)

Par défaut, les téléversements vivent sur le volume Docker storage. Pour utiliser un stockage d'objets (recommandé si vous faites tourner plusieurs réplicas web ou souhaitez des sauvegardes plus simples), définissez :

S3_ACCESS_KEY_ID=...
S3_SECRET_ACCESS_KEY=...
S3_BUCKET=campbooks-storage
S3_REGION=eu-central-1
# For non-AWS providers (MinIO, Hetzner, Backblaze B2, ...):
S3_ENDPOINT=https://...
S3_FORCE_PATH_STYLE=true

Recherche (OpenSearch)

OpenSearch est optionnel et ne sert qu'à l'autocomplétion en texte intégral des contacts. La recherche dans les e-mails, la recherche dans les documents et la palette Cmd+K utilisent toutes Postgres + pgvector et fonctionnent sans ; la recherche de contacts se rabat sur la correspondance SQL. Pour l'activer :

# in .env
OPENSEARCH_URL=http://opensearch:9200
docker compose --profile search up -d

Surveillance des erreurs et push

  • SENTRY_DSN — un DSN compatible Sentry (p. ex. GlitchTip auto-hébergé). Désactivé si non défini.
  • APNS_* / FCM_* — nécessaires uniquement si vous construisez les applications natives iOS/Android. Désactivés si non définis.

Exécution en production

Pour tout usage au-delà du local, terminez TLS avec un reverse proxy et activez SSL.

  1. Pointez un domaine vers votre serveur et définissez, dans .env :
    APP_HOST=app.example.com
    FORCE_SSL=true
    WEB_PORT=3000
  2. Placez un proxy terminant TLS devant. Avec Caddy (HTTPS automatique), c'est simplement :
    app.example.com {
    reverse_proxy localhost:3000
    }
    Le proxy parle HTTPS avec l'extérieur et transfère vers le conteneur sur :3000 ; FORCE_SSL=true fait émettre à Rails des liens https, définir des cookies sécurisés et envoyer HSTS. (Le point de terminaison de santé /up reste accessible en HTTP simple pour les sondes.)
  3. docker compose up -d --build.

N'exposez pas l'application en HTTP simple sur Internet. Avec FORCE_SSL=false, les sessions et les cookies voyagent non chiffrés. Utilisez toujours un proxy TLS en production.

Sauvegardes

Deux choses conservent l'état : le volume Postgres et les fichiers téléversés.

# Database (the app DB; cache/queue/cable are regenerable)
docker compose exec -T postgres pg_dump -U campbooks_app cb_primary | gzip > campbooks-$(date +%F).sql.gz

# Uploads (only if you use local disk storage, not S3)
docker run --rm -v campbooks_storage:/data -v "$PWD":/backup alpine \
tar czf /backup/campbooks-storage-$(date +%F).tar.gz -C /data .

Stockez les sauvegardes hors du serveur. Si vous utilisez S3 pour le stockage, seule la base de données a besoin d'être sauvegardée ici.

Mises à jour

git pull
docker compose up -d --build # the entrypoint runs migrations on boot

Sauvegardez la base de données au préalable. Les migrations s'exécutent automatiquement au démarrage du conteneur web.

Console et tâches

docker compose exec web bin/rails console
docker compose exec web bin/rails db:seed # optional demo data / login

Dépannage

Chaque requête redirige vers https:// et échoue. FORCE_SSL est activé mais il n'y a pas de proxy TLS. Définissez FORCE_SSL=false pour une utilisation locale, ou placez un proxy TLS devant pour la production.

"Blocked hosts" / 403 sur chaque page. APP_HOST ne correspond pas à la façon dont vous accédez à l'application. Définissez-le avec l'exact nom d'hôte/IP dans la barre d'adresse et recréez les conteneurs.

web redémarre continuellement avec une erreur de base de données/extension. Vérifiez que le service postgres utilise l'image pgvector/pgvector intégrée (une image postgres standard ne peut pas exécuter CREATE EXTENSION vector). Si vous l'avez changée, revenez en arrière.

worker journalise des erreurs juste après le démarrage. Il attend que web termine les migrations ; les erreurs transitoires au premier démarrage se stabilisent une fois web opérationnel.

Secret obligatoire manquant au docker compose up. Vous avez sauté bin/generate-secrets, ou .env manque d'une clé. Relancez le script.