feat(stacks): migrate rss
This commit is contained in:
52
stacks/rss.opytex.org/README.md
Normal file
52
stacks/rss.opytex.org/README.md
Normal 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/
|
||||
53
stacks/rss.opytex.org/docker-compose.yml
Normal file
53
stacks/rss.opytex.org/docker-compose.yml
Normal 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
|
||||
26
stacks/rss.opytex.org/env_file
Normal file
26
stacks/rss.opytex.org/env_file
Normal 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"
|
||||
26
stacks/rss.opytex.org/secrets.env.yaml
Normal file
26
stacks/rss.opytex.org/secrets.env.yaml
Normal 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
|
||||
Reference in New Issue
Block a user