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 :
| Service | Ce que c'est |
|---|---|
postgres | PostgreSQL avec l'extension pgvector (obligatoire) |
web | L'application Rails (Puma derrière Thruster) |
worker | Tâ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)
opensslsur 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)
| Variable | Notes |
|---|---|
SECRET_KEY_BASE | Clé de session/signature Rails. openssl rand -hex 64 |
ACTIVE_RECORD_PRIMARY_KEY | Chiffre les tokens OAuth et les clés IA au repos. openssl rand -hex 16 |
ACTIVE_RECORD_DETERMINISTIC_KEY | Idem |
ACTIVE_RECORD_KEY_DERIVATION_SALT | Idem |
CAMPBOOKS_DATABASE_PASSWORD | Mot 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)
| Variable | Défaut | Notes |
|---|---|---|
APP_HOST | localhost | Le 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_SSL | false | Laissez false pour une utilisation locale en HTTP simple. Mettez true uniquement derrière un proxy TLS (voir Production). |
SELF_HOSTED | 1 | Inscription 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).
| Variable | Déverrouille |
|---|---|
OPENAI_API_KEY | IA textuelle + analyse de documents/vision + embeddings (recherche sémantique). La clé unique la plus complète. |
ANTHROPIC_API_KEY | IA textuelle (Claude) |
MISTRAL_API_KEY | IA textuelle (hébergée en EU) |
DEEPSEEK_API_KEY | IA textuelle |
GEMINI_API_KEY | IA 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).
- Google Cloud Console → créez un projet → APIs & Services → Credentials → OAuth client ID (type : Web application).
- Activez l'API Gmail et l'API Google Calendar pour le projet.
- Ajoutez l'URI de redirection :
<your-app-url>/oauth/gmail/callback. - Définissez
GOOGLE_CLIENT_IDetGOOGLE_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.
- Créez un deuxième client OAuth (ou un projet séparé).
- Ajoutez le scope
https://www.googleapis.com/auth/driveet l'URI de redirection<your-app-url>/oauth/google/callback. - Définissez
GOOGLE_DRIVE_CLIENT_IDetGOOGLE_DRIVE_CLIENT_SECRET.
Zoho Mail
- Console API Zoho → Server-based Application.
- URI de redirection :
<your-app-url>/oauth/zoho/callback. - Définissez
ZOHO_CLIENT_ID,ZOHO_CLIENT_SECRETetZOHO_REGION(eu,com,in,au,jp— selon votre centre de données Zoho).
Microsoft 365 / Outlook
- Centre d'administration Entra → Inscriptions 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/). - Ajoutez un URI de redirection Web :
<your-app-url>/oauth/microsoft/callback. - Créez un secret client.
- Définissez
MICROSOFT_CLIENT_ID,MICROSOFT_CLIENT_SECRETetENABLE_MICROSOFT_MAILBOX=1(ce dernier affiche le bouton "Connecter Microsoft 365").
Notion — "Envoyer vers Notion"
- notion.so/my-integrations → nouvelle intégration, type Public, avec les capacités Read/Insert content.
- URI de redirection :
<your-app-url>/oauth/notion/callback. - Définissez
NOTION_CLIENT_IDetNOTION_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.
- Pointez un domaine vers votre serveur et définissez, dans
.env:APP_HOST=app.example.comFORCE_SSL=trueWEB_PORT=3000 - Placez un proxy terminant TLS devant. Avec Caddy (HTTPS automatique), c'est simplement :
Le proxy parle HTTPS avec l'extérieur et transfère vers le conteneur surapp.example.com {reverse_proxy localhost:3000}
:3000;FORCE_SSL=truefait émettre à Rails des liens https, définir des cookies sécurisés et envoyer HSTS. (Le point de terminaison de santé/upreste accessible en HTTP simple pour les sondes.) 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.