Démarrage avec Docker Compose
Peristyle tient dans une image Docker, à côté de PostgreSQL. Il vous faut Docker avec Docker Compose sur une machine amd64, et les fichiers docker-compose.yml et .env.example du dépôt sur le serveur : l’image est téléchargée depuis ghcr.io/zeguym/peristyle.
-
Préparer la configuration
Copiez le fichier d’exemple, puis remplacez
POSTGRES_PASSWORDpar un vrai mot de passe.cp .env.example .env -
Démarrer
Docker Compose télécharge l’image et lance Peristyle et PostgreSQL.
docker compose up -d -
Créer le compte administrateur
Ouvrez
http://<serveur>:8085et créez un compte : le premier compte administre l’instance. Créez ensuite les autres comptes, ou envoyez des invitations. -
Fermer les inscriptions
Une fois tout le monde inscrit, désactivez Inscriptions ouvertes dans Administration → Réglages, ou mettez
ALLOW_REGISTRATION=falsedans.envet relancezdocker compose up -d.
Le port se change avec PERISTYLE_PORT dans .env.
Mettre à jour
Sauvegardez d’abord l’instance, puis téléchargez la nouvelle image. La base de données se met à jour au démarrage.
docker compose pull
docker compose up -d
PERISTYLE_VERSION dans .env choisit l’image : latest par défaut, une version (1.2.3) ou une série (1.2).
Construire depuis les sources
Avec une copie complète du dépôt :
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
Utiliser un serveur PostgreSQL existant
Retirez le service db de docker-compose.yml et faites pointer ConnectionStrings__peristyle vers votre serveur, avec une base et un utilisateur dédiés.
NAS Synology
L’installation passe par Container Manager et le même fichier docker-compose.yml.
-
Copier les fichiers
Copiez
docker-compose.ymlet.env.exampledans un dossier du NAS, puis.env.examplevers.env, et changezPOSTGRES_PASSWORD. -
Créer le projet
Dans Container Manager → Projet → Créer, indiquez ce dossier. Vous pouvez aussi lancer
docker compose up -den SSH. -
Créer les comptes
Ouvrez
http://<ip-du-nas>:8085, créez le compte administrateur, puis ceux de la famille. -
Fermer les inscriptions
Mettez
ALLOW_REGISTRATION=falsedans.envet relancez le projet, ou utilisez Administration → Réglages.
Proxy inverse
Pour publier l’instance en HTTPS, placez-la derrière un proxy inverse. Sur un NAS Synology, ouvrez Panneau de configuration → Portail de connexion → Avancé → Proxy inversé :
- source :
https://peristyle.exemple.fr; - destination :
http://localhost:8085; - en-têtes personnalisés : activez
WebSocket.
Peristyle ne fait confiance aux en-têtes X-Forwarded-* que depuis les adresses listées dans TRUSTED_PROXIES (adresses ou réseaux CIDR, séparés par des virgules). Vide, cette variable accepte tout le réseau local.
Sauvegardes
Une sauvegarde complète réunit deux éléments : la base de données et le volume /data. Gardez aussi votre fichier .env.
Avec le service db de docker-compose.yml, la base s’exporte ainsi :
docker compose exec -T db pg_dump -U peristyle peristyle > peristyle.sql
Le volume /data contient :
| Dossier | Contenu |
|---|---|
archives/ | les copies de pages archivées |
image-cache/ | le cache d’images, qui peut se reconstruire |
locales/, themes/, plugins/ | les langues, thèmes et extensions déposés |
keys/ | les clés qui chiffrent les cookies de session et le mot de passe SMTP enregistré dans l’administration |
Sauvegarde planifiée
Copiez backup.sh à côté de docker-compose.yml. Le script écrit trois fichiers datés : la base (.dump), le volume /data sans le cache d’images (.tar.gz) et une copie de .env. Il supprime ensuite les sauvegardes plus anciennes que la durée indiquée, uniquement si tout a réussi.
sh backup.sh /chemin/des/sauvegardes 14
Sans argument, il écrit dans ./backups et garde 14 jours. Il ne couvre que le service db de docker-compose.yml, pas un serveur PostgreSQL existant.
Sur un NAS Synology, ouvrez Panneau de configuration → Planificateur de tâches → Créer → Tâche planifiée → Script défini par l’utilisateur :
- utilisateur :
root; - calendrier : tous les jours, à une heure creuse ;
- paramètres de la tâche :
sh /volume1/docker/peristyle/backup.sh /volume1/sauvegardes/peristyle 14; - notification : envoyez les détails par e-mail en cas d’arrêt anormal.
Lancez la tâche une première fois avec Exécuter et vérifiez les fichiers. Si le script ne trouve pas le conteneur, le projet Container Manager ne porte pas le nom du dossier : ajoutez COMPOSE_PROJECT_NAME=<nom du projet> à .env.
Sur un autre serveur Linux, une ligne de crontab suffit :
0 3 * * * sh /opt/peristyle/backup.sh /srv/sauvegardes/peristyle 14
.env, donc le mot de passe de la base : gardez cette copie privée.Restaurer
Depuis le dossier de docker-compose.yml, avec le .env de la sauvegarde et la même version majeure de PostgreSQL :
docker compose up -d db
docker compose stop web
docker compose exec -T db pg_restore -U peristyle -d peristyle --clean --if-exists --no-owner < peristyle-AAAA-MM-JJ_HHMM.dump
docker run --rm -i --volumes-from "$(docker compose ps -aq web)" alpine:3.22 tar xzf - -C / < peristyle-AAAA-MM-JJ_HHMM.tar.gz
docker compose up -d
Sur une installation neuve, lancez d’abord docker compose up -d pour créer les conteneurs et les volumes.
Configuration
Les réglages viennent de variables d’environnement (Peristyle__Nom, imbriquées avec __). La plupart se changent aussi dans Administration → Réglages ou Administration → E-mail. L’ordre de priorité est le suivant : valeur enregistrée dans l’administration, puis variable d’environnement, puis valeur par défaut.
La colonne .env donne le nom à utiliser dans ce fichier. Une variable sans nom dans cette colonne n’est pas transmise par docker-compose.yml : ajoutez-la sous environment: du service web, ou passez par l’administration.
Réglages du serveur
La mention au redémarrage signale ceux qui ne prennent effet qu’au prochain démarrage.
| Variable | .env | Défaut | Rôle |
|---|---|---|---|
Peristyle__AllowRegistration | ALLOW_REGISTRATION | true (false dans docker-compose.yml sans cette ligne) | Autorise les inscriptions. Le tout premier compte, administrateur, est toujours possible. |
Peristyle__AllowPrivateNetworkFeeds | — | false | Autorise les flux du réseau local (192.168.x.x…). Au redémarrage. |
Peristyle__RefreshIntervalMinutes | REFRESH_INTERVAL_MINUTES | 30 | Intervalle de rafraîchissement des flux. |
Peristyle__MaxConcurrentFetches | — | 4 | Téléchargements simultanés. |
Peristyle__InitialArticlesPerSubscription | — | 50 | Articles récents marqués non lus lors d’un abonnement à un flux déjà connu de l’instance. |
Peristyle__ArticleRetentionDays | ARTICLE_RETENTION_DAYS | 90 | Conservation des articles en jours (0 = illimitée). Les favoris sont toujours gardés. |
Peristyle__DisableFailingFeedAfterDays | DISABLE_FAILING_FEED_AFTER_DAYS | 30 | Désactive un flux en échec depuis ce nombre de jours (0 = jamais). Réessayer le rétablit. |
Peristyle__SourceTimeoutSeconds | — | 60 | Temps maximal pour récupérer et lire un flux. |
Peristyle__ProcessorTimeoutSeconds | — | 10 | Temps maximal d’une étape de traitement d’un article. Au-delà, l’étape est sautée. |
Peristyle__ArchiveQuotaMegabytes | — | 1024 | Espace d’archives par utilisateur, en Mo (0 = illimité). |
Peristyle__MaxConcurrentArchives | — | 1 | Pages archivées en même temps. Au redémarrage. |
Peristyle__LinkCheckIntervalDays | LINK_CHECK_INTERVAL_DAYS | 7 | Vérifie l’adresse de chaque signet tous les N jours (0 = jamais). Un lien mort est revérifié le lendemain. Au redémarrage. |
Peristyle__LinkCheckBatchSize | — | 200 | Adresses vérifiées au plus par passage (un passage par heure). |
Peristyle__ImageProxy | IMAGE_PROXY | true | Proxy d’images : les navigateurs ne chargent plus les images depuis les sites d’origine. Au redémarrage. |
Peristyle__ImageCacheMegabytes | IMAGE_CACHE_MEGABYTES | 500 | Taille maximale du cache d’images, en Mo. |
Peristyle__ImageCacheDays | — | 30 | Durée de conservation d’une image en cache, en jours. |
Peristyle__MaxImageBytes | — | 5242880 | Taille maximale d’une image passant par le proxy, en octets (en Mo dans l’administration). |
Peristyle__Plugins__RequireApproval | — | true | Une extension déposée doit être approuvée avant d’être chargée. Au redémarrage. |
Peristyle__DefaultLanguage | DEFAULT_LANGUAGE | fr | Langue quand le navigateur n’en demande aucune de disponible, et pour les textes non traduits. Au redémarrage. |
Infrastructure
Ces variables restent dans l’environnement : une erreur dans l’une d’elles peut ainsi toujours se corriger.
| Variable | .env | Défaut | Rôle |
|---|---|---|---|
ConnectionStrings__peristyle | — | — | Chaîne de connexion PostgreSQL. docker-compose.yml la construit à partir de POSTGRES_PASSWORD. |
Peristyle__TrustedProxies | TRUSTED_PROXIES | — | Voir Proxy inverse. |
Peristyle__DataPath | — | /data dans l’image | Clés, archives, cache d’images, langues, thèmes et extensions déposés. |
Peristyle__Plugins__SafeMode | PLUGINS_SAFE_MODE | false | Démarre sans aucune extension déposée. Les extensions fournies restent actives. |
TZ | TZ | Europe/Paris | Fuseau horaire de l’instance, sous la forme d’un nom comme America/Montreal. Les dates s’affichent dans ce fuseau pour tous les comptes : il n’y a pas de réglage par compte. |
DOTNET_GCHeapHardLimit | — | — | Plafond du tas .NET, en hexadécimal (0x10000000 = 256 Mo). |
OTEL_EXPORTER_OTLP_ENDPOINT | — | — | Export OpenTelemetry, facultatif. Rien n’est envoyé sans cette variable. |
E-mail (SMTP)
Sans serveur SMTP ni adresse publique, Peristyle n’envoie rien : l’administrateur transmet lui-même les liens de mot de passe et d’invitation. Avec les deux, Peristyle envoie :
- les liens de Mot de passe oublié ?, uniquement vers une adresse confirmée ;
- la confirmation d’une adresse donnée à l’inscription ou changée dans Préférences → Adresse e-mail ;
- les invitations ;
- les liens de mot de passe envoyés par un administrateur, et un e-mail de test.
Chaque e-mail est rédigé dans la langue du destinataire : celle de son compte, sinon celle de la page qu’il a utilisée, sinon Peristyle__DefaultLanguage. Une invitation utilise la langue choisie par l’administrateur, et la page d’inscription s’ouvre dans cette langue.
Le serveur se règle dans Administration → E-mail ou avec les variables ci-dessous. Les valeurs enregistrées dans l’administration sont prioritaires ; le mot de passe y est chiffré avec les clés de /data/keys.
| Variable | .env | Défaut | Rôle |
|---|---|---|---|
Peristyle__PublicUrl | PUBLIC_URL | — | Adresse utilisée pour ouvrir l’instance, par exemple https://lecteur.exemple.org. Tous les liens des e-mails commencent par elle. Vide : aucun e-mail. |
Peristyle__Smtp__Host | SMTP_HOST | — | Serveur SMTP. Vide : aucun e-mail. |
Peristyle__Smtp__Port | SMTP_PORT | 587 | Port (465 SSL direct, 25 ou 1025 relais local). |
Peristyle__Smtp__Security | SMTP_SECURITY | Auto | Auto (SSL sur le port 465, STARTTLS ailleurs s’il est proposé), StartTls, SslOnConnect ou None. |
Peristyle__Smtp__UserName | SMTP_USERNAME | — | Identifiant. Vide : pas d’authentification. |
Peristyle__Smtp__Password | SMTP_PASSWORD | — | Mot de passe. |
Peristyle__Smtp__From | SMTP_FROM | — | Adresse de l’expéditeur, obligatoire. |
Peristyle__Smtp__FromName | SMTP_FROM_NAME | Peristyle | Nom de l’expéditeur. |
Exemples : Gmail smtp.gmail.com:587 et Outlook.com smtp-mail.outlook.com:587 avec un mot de passe d’application ; Synology MailPlus Server ou un autre relais du NAS avec None sur le réseau local.
Jetons d’application
Chaque utilisateur crée ses jetons dans Préférences → Applications, un par application, avec une expiration facultative (voir le guide d’utilisation). Peristyle ne garde que l’empreinte SHA-256 du jeton : il n’est affiché qu’à sa création et se révoque à tout moment.
Une application envoie son jeton dans l’en-tête Authorization. GET /api/me permet de le vérifier : la réponse donne le nom d’utilisateur, ou l’erreur 401 si le jeton est invalide, révoqué ou expiré.
curl -H "Authorization: Bearer ps_…" https://peristyle.exemple.fr/api/me
Un compte désactivé ne peut plus utiliser ses jetons.
Extensions
Le traitement des articles passe par des extensions. Il en existe trois sortes :
- Fournie avec Peristyle : podcasts, article complet automatique, image principale de l’article complet, vidéos YouTube et diaporama. Actives par défaut, elles peuvent être désactivées.
- Par flux : une telle extension ne s’applique qu’aux flux où un abonné l’a activée, dans Paramètres du flux… → Contenu. L’activation est partagée par les abonnés du flux et retraite ses 20 articles les plus récents.
- Déposée : un dossier
/data/plugins/<id>/contenantmanifest.json, les assemblys et, si besoin,wwwroot/pour les scripts et les styles. Elle reste En attente jusqu’à son approbation dans Administration → Extensions.
Une extension modifiée repasse en attente, car Peristyle compare l’empreinte SHA-256 de son dossier. Les décisions s’appliquent au redémarrage.
Si une extension empêche le démarrage, lancez Peristyle avec PLUGINS_SAFE_MODE=true : aucune extension déposée n’est chargée, et vous pouvez la désactiver.
Langues
L’interface existe en français et en anglais. Chacun choisit sa langue dans ses Préférences ou sur la page de connexion ; à défaut, Peristyle suit le navigateur.
Pour ajouter une langue ou changer quelques textes sans reconstruire l’image, déposez dans /data/locales/ un fichier nommé d’après le code de la langue (de.json, pt-BR.json, ou fr.json pour modifier le français), puis redémarrez le conteneur.
{
"Language": { "Name": "Deutsch" },
"Nav": { "AllArticles": "Alle Artikel", "Starred": "Favoriten" }
}
- Seules les clés présentes sont remplacées ; un texte absent s’affiche dans la langue par défaut.
- Les clés s’écrivent imbriquées, comme ci-dessus, ou à plat (
"Nav.Starred": "…"). {0},{1}… sont des paramètres ; les clés en.Oneet.Othersont le singulier et le pluriel.- Les e-mails se traduisent de la même façon (clés
Email.*).
data de docker-compose.yml est un volume nommé. Pour déposer des fichiers facilement, remplacez-le par un dossier du serveur, par exemple ./data:/data.Thèmes
Chacun choisit son thème dans ses Préférences : Comme le système, Clair, Sombre ou un thème installé.
Un thème installé est un dossier de /data/themes/, dont le nom (minuscules, chiffres, tirets) sert d’identifiant. Il contient deux fichiers obligatoires et, si besoin, des polices .woff2 et des images.
/data/themes/sepia/
├── manifest.json { "name": "Sépia", "author": "…", "version": "1.0.0", "scheme": "light" }
├── theme.css redéfinit les variables CSS voulues
└── fonts/… référencé en relatif : url(fonts/literata.woff2)
scheme(lightoudark) donne la palette de base ; le thème ne redéfinit que ce qu’il veut changer.- Les variables disponibles sont listées en tête de
src/Peristyle.Web/wwwroot/app.css, etsamples/themes/sepiadonne un exemple complet. - Pas de JavaScript ni de ressource externe : un
theme.csscontenant@import, uneurl()absolue ou uneurl()qui remonte (../) est ignoré, avec un avertissement dans les journaux. - Les thèmes sont lus au démarrage : redémarrez le conteneur après en avoir ajouté un ou modifié un manifeste.
Administration
L’entrée Administration de la barre latérale apparaît pour les administrateurs. Le premier compte en est un ; il peut en nommer d’autres. Chaque sujet a son onglet.
Tableau de bord
Une vue d’ensemble de l’instance, avec sa version : Comptes, Flux (dont ceux en erreur, désactivés ou en retard), Contenus et Serveur (taille et état de la base, files d’attente en cours). Rafraîchir recalcule les chiffres.
Comptes
La liste des comptes, avec leur adresse, leur dernière connexion et leur volume de données. Sur le compte d’un autre :
- Rendre administrateur ou Retirer les droits d’admin ;
- Désactiver ou Réactiver : un compte désactivé ne peut plus se connecter ni utiliser ses jetons ;
- Lien de nouveau mot de passe : un lien à transmettre à la personne, valable une seule fois pendant 24 heures ;
- Envoyer le lien par e-mail, si l’adresse du compte est confirmée et l’envoi d’e-mails configuré ;
- Supprimer : tapez le nom du compte, puis Supprimer définitivement.
Invitations
Un lien d’invitation permet de créer un compte même quand les inscriptions sont fermées. Il ne sert qu’une fois. La carte Inscriptions rappelle si elles sont Ouvertes ou Fermées.
Dans Nouvelle invitation, indiquez pour qui (facultatif) et une durée de validité de 1, 7 ou 30 jours, puis Créer le lien. Copiez le lien tout de suite : il ne sera plus affiché. Si l’envoi d’e-mails est configuré, vous pouvez aussi saisir une adresse et choisir la Langue de l’e-mail.
La liste donne l’état de chaque invitation : En attente, Utilisée ou Expirée. Révoquer annule une invitation en attente.
Réglages
Les réglages du serveur, par thème : Inscriptions, Flux, Conservation, Archives, Signets, Images, Langue et Extensions. Chaque ligne indique d’où vient sa valeur.
Enregistrer garde la valeur en base, où elle l’emporte sur la variable d’environnement. Rétablir revient à celle-ci. Si un réglage marqué au redémarrage a changé, un bandeau propose Redémarrer Peristyle : l’application s’arrête proprement et Docker la relance.
État indique si l’envoi est Activé ou Désactivé : il faut au moins l’adresse publique, le serveur et l’adresse de l’expéditeur. Serveur d’envoi (SMTP) reprend les réglages de la section E-mail (SMTP), sans redémarrage. Envoyer un e-mail de test vérifie la configuration ; l’éventuelle erreur du serveur s’affiche sur la page.
Extensions
Chaque extension affiche sa version, son empreinte, les capacités qu’elle demande (network, readable, script, frame), ses points d’accroche et, une fois chargée, ses appels, ses erreurs et son temps moyen.
- Extension fournie : Désactiver ou Réactiver.
- Extension déposée : Approuver, Désactiver ou Refuser. Une extension invalide ou incompatible ne peut pas être approuvée ; ses problèmes sont listés.
Les statuts sont En attente, Approuvée, Refusée, Désactivée et En échec. Une décision s’applique au redémarrage : Redémarrer Peristyle apparaît quand il le faut.
Stockage
La place occupée, calculée à l’ouverture de la page, ce qui peut prendre quelques secondes :
- Base de données, par catégorie ;
- Fichiers : Pages archivées et Cache d’images ;
- Par utilisateur : un flux suivi par plusieurs personnes est réparti entre elles au prorata.