runv-server

server tooling for runv.club
Log | Files | Refs | README

commit f8727360c032cb898c381f0d3e56e7b5229eb518
parent 291ff8fe1a57461580be413f656e1c9a98a81941
Author: Pablo Murad <pblmrd@gmail.com>
Date:   Mon, 23 Mar 2026 14:12:48 -0300

fix rss

Diffstat:
Mdocs/06-site-and-apache.md | 2+-
Mdocs/13-troubleshooting.md | 5+++--
Msite/genlanding.py | 12++++++++----
3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/docs/06-site-and-apache.md b/docs/06-site-and-apache.md @@ -15,7 +15,7 @@ - Opcional: `--certbot` (incompatível com `--dev`). - Após cópia, por omissão chama `build_directory.py` para gravar `data/members.json` no DocumentRoot (`--no-refresh-members` para omitir). - **`--sync-public-only`:** só copia `site/public/` → DocumentRoot, `chown www-data` e regenera `members.json`; **não** altera Apache (uso típico após `create_runv_user.py` e disponível para correr à mão). -- **RSS (`/news/feed.rss`):** o `genlanding` completo (sem `--sync-public-only`) grava `/etc/apache2/conf-available/runv-landing-rss-mime.conf` com **`ForceType text/xml`** e activa com **`a2enconf runv-landing-rss-mime`**. Esse snippet é **global** ao Apache, por isso aplica-se a **:80 e :443** sem editar o VirtualHost SSL que o Certbot gerou. Após mudar o DocumentRoot (ex. `--dev` vs produção), volte a correr o `genlanding` completo para actualizar o snippet. +- **RSS (`/news/feed.rss`):** o `genlanding` completo (sem `--sync-public-only`) grava `/etc/apache2/conf-available/runv-landing-rss-mime.conf` com **`RemoveType`**, **`ForceType text/xml`** e **`Header set Content-Type`** (sobrepor `mod_mime` / `application/rss+xml`), activa **`a2enmod headers`** e **`a2enconf runv-landing-rss-mime`**. O snippet é **global** ao Apache (**:80 e :443**) sem editar o VirtualHost SSL do Certbot. Após mudar o DocumentRoot, volte a correr o `genlanding` completo para actualizar o snippet. - Versão actual do script: constante `VERSION` no ficheiro (ex.: `0.07`). ## TLS e DNS diff --git a/docs/13-troubleshooting.md b/docs/13-troubleshooting.md @@ -24,8 +24,9 @@ ## Feed RSS descarrega em vez de abrir no browser -- Com `genlanding` ≥ 0.07: confirme que existe **`/etc/apache2/conf-available/runv-landing-rss-mime.conf`**, que o symlink em `conf-enabled` está activo (`a2enconf runv-landing-rss-mime`) e que o `<Directory>` aponta ao **DocumentRoot correcto**; depois `sudo systemctl reload apache2`. O snippet cobre **HTTPS** sem tocar no ficheiro do Certbot (ver [06-site-and-apache.md](06-site-and-apache.md)). -- Instalações antigas só com `ForceType` no `:80`: acrescente o mesmo bloco `<Directory …/news><Files "feed.rss">ForceType text/xml</Files></Directory>` no VirtualHost **:443** ou migre correr o `genlanding` completo de novo. +- O `mod_mime` trata `.rss` como `application/rss+xml`; o Chromium costuma **descarregar**. Com `genlanding` ≥ 0.08 o snippet usa **`RemoveType`**, **`Header set Content-Type`** (requer **`mod_headers`**) e **`a2enconf runv-landing-rss-mime`**. Verifique: `curl -sI https://runv.club/news/feed.rss | grep -i content-type` → deve ser **`text/xml`**. +- Com `genlanding` ≥ 0.07 e &lt; 0.08: confirme **`/etc/apache2/conf-available/runv-landing-rss-mime.conf`**, symlink em `conf-enabled`, DocumentRoot correcto; volte a correr o **`genlanding` completo** (0.08+) para aplicar `Header` + `headers`. +- Instalações antigas só com `ForceType` no `:80`: corra o `genlanding` completo de novo ou veja [06-site-and-apache.md](06-site-and-apache.md). ## Quotas diff --git a/site/genlanding.py b/site/genlanding.py @@ -11,7 +11,7 @@ a :80 e :443 sem editar o vhost SSL do Certbot. Executar como root (excepto --dry-run). Apenas biblioteca padrão Python 3. -Versão 0.07 — runv.club +Versão 0.08 — runv.club """ from __future__ import annotations @@ -28,7 +28,7 @@ import sys from pathlib import Path from typing import Final -VERSION: Final[str] = "0.07" +VERSION: Final[str] = "0.08" EXIT_OK: Final[int] = 0 EXIT_USAGE: Final[int] = 1 EXIT_ERROR: Final[int] = 2 @@ -47,7 +47,7 @@ DEV_SITE_CONF: Final[str] = "runv-dev.conf" APACHE_SITES_AVAILABLE: Final[Path] = Path("/etc/apache2/sites-available") APACHE_CONF_AVAILABLE: Final[Path] = Path("/etc/apache2/conf-available") -# Snippet global: aplica ForceType ao feed em todos os vhosts (:80 e :443), sem tocar no SSL do Certbot. +# Snippet global: MIME do feed em todos os vhosts (:80 e :443), sem tocar no SSL do Certbot. RSS_MIME_CONF_FILE: Final[str] = "runv-landing-rss-mime.conf" RSS_MIME_CONF_STEM: Final[str] = "runv-landing-rss-mime" APACHE_CTL: Final[str] = "/usr/sbin/apache2ctl" @@ -79,12 +79,15 @@ def render_rss_mime_conf_contents(document_root: Path) -> str: """Snippet em conf-available: vale para :80 e :443 (evita editar o vhost SSL do Certbot à mão).""" root = document_root.as_posix() return f"""# Gerado por genlanding.py v{VERSION} — runv.club -# Chromium descarrega feed.rss com application/rss+xml; text/xml mostra o XML na aba. +# Chromium descarrega com application/rss+xml (mod_mime por extensão .rss). +# RemoveType + Header forçam text/xml na resposta; requer mod_headers (a2enmod headers). # Global ao servidor para o caminho actual do DocumentRoot (volte a correr genlanding se mudar). <Directory {root}/news> + RemoveType rss <Files "feed.rss"> ForceType text/xml + Header set Content-Type "text/xml; charset=utf-8" </Files> </Directory> """ @@ -411,6 +414,7 @@ def main(argv: list[str] | None = None) -> int: run_cmd(["a2enmod", "userdir"], dry_run=args.dry_run) run_cmd(["a2enmod", "rewrite"], dry_run=args.dry_run) + run_cmd(["a2enmod", "headers"], dry_run=args.dry_run) rss_conf_path = APACHE_CONF_AVAILABLE / RSS_MIME_CONF_FILE rss_body = render_rss_mime_conf_contents(document_root)