feat(stacks): migrate rss

This commit is contained in:
2026-08-17 14:58:35 +02:00
parent 322f2f89b5
commit b220593def
4 changed files with 157 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
# FreshRSS — rss.opytex.org
Agrégateur RSS, PostgreSQL dédié, authentification SSO via Authentik.
## Déploiement
Depuis ce dossier, sur chioggia :
```bash
sops exec-env secrets.env.yaml 'docker compose up -d'
```
Le nom du dossier (`rss.opytex.org`) donne le nom de projet Compose
`rssopytexorg`, dont dérivent les noms de volumes
(`rssopytexorg_freshrss_data`, …) et le nom du dump de base
(`rssopytexorg.sql.gz`). **Renommer ce dossier ferait repartir la stack sur
des volumes vides.**
Après une rotation de secret, `docker compose up -d` répond « up to date » et
garde l'ancienne valeur :
```bash
sops exec-env secrets.env.yaml 'docker compose up -d --force-recreate'
```
## Volumes
| Volume | Contenu | Sauvegarde |
| ---------------------------------- | -------------------------------- | -------------------------------------------------- |
| `rssopytexorg_pgsql_data` | base PostgreSQL | dump SQL (`backup.type=postgres` sur le conteneur) |
| `rssopytexorg_freshrss_data` | config, comptes, articles locaux | label `backup.enable=true` sur le volume |
| `rssopytexorg_freshrss_extensions` | extensions installées | label `backup.enable=true` sur le volume |
Les deux volumes FreshRSS portent `backup.enable=true` **depuis leur
création** : le label est donc conservé dans le compose. Le retirer, comme
l'ajouter à un volume qui ne l'a pas, ferait diverger la déclaration du volume
réel — Compose proposerait alors de le recréer, donc de vider FreshRSS.
Ils figurent en plus dans `MANUAL_VOLUMES` (`backup.conf`), ce qui les fait
sauvegarder deux fois : le script empile les chemins de `MANUAL_VOLUMES` puis
ceux des volumes labellisés, sans dédoublonner. Redondance héritée de l'ancien
dépôt, sans conséquence (restic déduplique) — à nettoyer quand `backup.conf`
sera migré dans `ops/backup/`.
`pgsql_data` n'a délibérément aucun label : sauvegarder les fichiers d'un
PostgreSQL en cours d'écriture ne donne pas une base restaurable, c'est le dump
SQL qui le couvre.
Références :
- https://freshrss.github.io/FreshRSS/en/admins/16_OpenID-Connect-Authentik.html
- https://docs.goauthentik.io/integrations/services/freshrss/

View File

@@ -0,0 +1,53 @@
services:
postgresql:
image: postgres:16.2
container_name: freshrss-db
restart: unless-stopped
env_file:
- env_file
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?}
volumes:
- pgsql_data:/var/lib/postgresql/data
networks:
- default
labels:
- backup.enable=true
- backup.type=postgres
freshrss:
image: freshrss/freshrss:1.28.1
restart: unless-stopped
depends_on:
- postgresql
env_file:
- env_file
environment:
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET:?}
volumes:
- freshrss_data:/var/www/FreshRSS/data
- freshrss_extensions:/var/www/FreshRSS/extensions
networks:
- default
- traefik-proxy
labels:
- traefik.enable=true
- traefik.docker.network=traefik-proxy
- traefik.http.routers.freshrss.entrypoints=web-secure
- traefik.http.routers.freshrss.rule=Host(`rss.opytex.org`)
- traefik.http.routers.freshrss.tls.certresolver=letsencrypt
- traefik.http.routers.freshrss.middlewares=crowdsec@file
- traefik.http.services.freshrss.loadbalancer.server.port=80
volumes:
pgsql_data:
freshrss_data:
labels:
backup.enable: true
freshrss_extensions:
labels:
backup.enable: true
networks:
traefik-proxy:
external: true

View File

@@ -0,0 +1,26 @@
# =============================================================================
# FRESHRSS — configuration NON sensible
# =============================================================================
# POSTGRES_PASSWORD et OIDC_CLIENT_SECRET sont dans secrets.env.yaml et
# injectés par `sops exec-env`.
#
# Ce fichier ne contient QUE ce que les conteneurs consomment. Le domaine et
# la version d'image sont en dur dans docker-compose.yml : `env_file:`
# n'alimente pas l'interpolation ${...}, et une version en dur est détectée
# par Renovate.
# =============================================================================
# --- Base de données ---
POSTGRES_USER=freshrss
POSTGRES_DB=freshrss
# --- Conteneur FreshRSS ---
CRON_MIN=*/20
TZ=Europe/Paris
# --- SSO OpenID Connect (Authentik) ---
OIDC_ENABLED=1
OIDC_PROVIDER_METADATA_URL=https://sso.opytex.org/application/o/freshrss/.well-known/openid-configuration
OIDC_CLIENT_ID=3YF3MIapyVz45EQ8BcFGwk2q47BTstmPMhRwwPlZ
OIDC_X_FORWARDED_HEADERS="X-Forwarded-Port X-Forwarded-Proto X-Forwarded-Host"
OIDC_SCOPES="openid email profile"

View File

@@ -0,0 +1,26 @@
POSTGRES_PASSWORD: ENC[AES256_GCM,data:2QAKvkuKOxME53FF3YGugKZSxVjfgF4NEXRMFNmSP6Z9ICkUHIQvFlxcFCKIJ1L8,iv:shO6GH4mlqPpEXO9Q/0LgUb7l/zDOghDbTxMzlkJBjg=,tag:vlBr1hE4GimoobZ8+ejgrg==,type:str]
OIDC_CLIENT_SECRET: ENC[AES256_GCM,data:GqKQQHL7X8CMd+vflksqGLjg0vIsceQMP5p5sCAJaYjKMiiaFoSRefbOVseTmo3zGdAfLz6tFNpWi6Q7BQCg6+i0fH7B5shZf/s/GxnerbJ1qC9UVNQ49dea88f/sC85ByGxgZ/9HGTQ/li2DDMkTnt1iNF46o5WolRdhmXgV0k=,iv:Taxpju1C2eGc4FGyLDONo1E+n2EkBWrHfdxi1ca0neg=,tag:C3TNHS0eIlcTwwNMKcDU9w==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNUS9xaUMxV2EreEVwdmFV
c1kzbkNOOCt2WisvQjhvU0wxb0hSUkRkMUVRCnFxUmNXNUhoemRKWjlpN2E0Z0kz
cWorU3ZINm5ISEhMWWRsVVFJRUFqZ1EKLS0tIGVMZUloa2RxK0daWHVFNW1CSzZZ
NVhNZUxjcmZTYTk5UjNZUmFrRnlXeW8KQVe3zJMofheTzg6vDtKSEYefRFz9ND9v
CPTWmjv0tGAsWX6sdnKeBniw29A9QRKlAKubvES7hl4cf2vEtruYzQ==
-----END AGE ENCRYPTED FILE-----
recipient: age18m2zl3pwgw97djshzcf4wmhrqxksl4erqse6edkpxpkg5rcz0ujs8u4c7s
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsZEVuejgwMXhCV1BCaHlp
RG5TZklLa0xQYWVTTU40VVhOSEVsb2xHZXlVClJiYXhtZ2ZCRklRTGRGSVBtaUFP
VXFjME9WZHhyRXJDazR4VnV2R0VXaWMKLS0tIE9LcmZjMFFhRWJqbU52S1BHSldx
Wk8wcis2bzgwSWpFVTUwOC9mT3UzVjQK4X6/iYoec/k1r/yLIQoT0XhfYryJ75KN
X7aDRlHniIPPPUg9tdIjGIUKpRBidOBw7s1PYImxOMTqjs0CUoIRzw==
-----END AGE ENCRYPTED FILE-----
recipient: age1fh70nny5hzz8a8g9077kgfca0lhlh3wsjf4fjrv4klx5ucdtpdmsazuqdj
lastmodified: "2026-08-17T04:27:36Z"
mac: ENC[AES256_GCM,data:mvGIwaflMEAT+QuVCIiU3PHRJf7gC8rIA0093WXSYV92HdK8eRX6Y624DTMxThL6BKhaEWojsARhd2ldDsz/iQdbSJEmfcOTIw8SCatByRucK9wen6L7AZqsAB5lZVXTQQp4PfwxbrVj/pYG5K8twYSrt7JJiHWZnZ//gJZPTAM=,iv:eK765KsM7eNgWy3Y3OGqol+99rbop/rYYs+w3Rn4Brc=,tag:2P7QQdxjj/5kCL1THSnUDg==,type:str]
unencrypted_suffix: _unencrypted
version: 3.13.3