Compare commits

...
10 Commits
6 changed files with 358 additions and 49 deletions
+65
View File
@@ -0,0 +1,65 @@
# Mastodon
> Your self-hosted, globally interconnected microblogging community
<!-- metadata -->
* **Maintainers**: `@3wordchant` (Matrix: `@3wc:autonomic.zone`), `Nick` (Matrix: `@nicksellen:matrix.org`)
* **Status**: `stable`
* **Category**: Apps
* **Features**: 1
* **Image**: [`tootsuite/mastodon`](https://hub.docker.com/r/tootsuite/mastodon)
* **Healthcheck**: No
* **Backups**: No
* **Email**: Yes
* **Tests**: No
* **SSO**: Yes
<!-- endmetadata -->
## Quick start
Mastodon expects secrets to be formatted in a very specific way, so please
choose "No" when prompted to generate secrets for `abra app new mastodon`. The
secrets must be generated outside of `abra` and that is achieved in step 2. See
the [`abra.sh`](./abra.sh) for more.
1. `abra app new mastodon`
1. `abra app cmd --local <domain> secrets`
1. `abra app cmd --local <domain> secrets_activerecord`
1. `abra app secret insert <domain> smtp_password v1 <password>`
1. `abra app config <domain>` (uncomment SMTP details)
1. `abra app deploy <domain>`
Then, on your host (outside of the containers), you'll need to fix permissions
for the volume (see [#10](https://git.coopcloud.tech/coop-cloud/mastodon/issues/10)):
```
chown -R 991:991 /var/lib/docker/volumes/<domain>_app/_data
```
And finally, within the `app` container, create an admin account:
```
abra app cmd <domain> app admin -- <username> <email>
```
## Tips & tricks
### Auto-complete is not working?
Check the sidekiq logs (`/sidekiq/retries`), is a bunch of stuff failing? What
is the error?
If it looks anything like `blocked by: [FORBIDDEN/12/index read-only / allow
delete (api)];` then it might mean that your elastic search service has put
itself into "read-only" state. This could be due to running close to no free
disk space one time. ES doesn't undo this state, even when you have more free
disk space once more, so you need to handle this manually:
```
abra app run <domain> es bash
curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}'
```
Then head back to the sidekiq retries panel and retry one job. You should see
the ticket of retries go down by one if if passed. Then you can "retry all" and
they should get scheduled & run.
+247 -48
View File
@@ -1,65 +1,264 @@
# Mastodon
# Mastodon — adaptaciones de Escuela Común
> Your self-hosted, globally interconnected microblogging community
Este repositorio es un fork de la receta oficial de Mastodon para Co-op Cloud:
<!-- metadata -->
* **Maintainers**: `@3wordchant` (Matrix: `@3wc:autonomic.zone`), `Nick` (Matrix: `@nicksellen:matrix.org`)
* **Status**: `stable`
* **Category**: Apps
* **Features**: 1
* **Image**: [`tootsuite/mastodon`](https://hub.docker.com/r/tootsuite/mastodon)
* **Healthcheck**: No
* **Backups**: No
* **Email**: Yes
* **Tests**: No
* **SSO**: Yes
<!-- endmetadata -->
https://git.coopcloud.tech/coop-cloud/mastodon
## Quick start
El objetivo de este fork es mantener y documentar los cambios que utilizamos en la infraestructura de Escuela Común mientras estos todavía no estén incorporados en la receta oficial.
Mastodon expects secrets to be formatted in a very specific way, so please
choose "No" when prompted to generate secrets for `abra app new mastodon`. The
secrets must be generated outside of `abra` and that is achieved in step 2. See
the [`abra.sh`](./abra.sh) for more.
No buscamos mantener una versión independiente de la receta. La intención es seguir de cerca el desarrollo de Co-op Cloud y retirar nuestros parches cuando upstream incorpore una solución equivalente.
1. `abra app new mastodon`
1. `abra app cmd --local <domain> secrets`
1. `abra app cmd --local <domain> secrets_activerecord`
1. `abra app secret insert <domain> smtp_password v1 <password>`
1. `abra app config <domain>` (uncomment SMTP details)
1. `abra app deploy <domain>`
## Organización de las ramas
Then, on your host (outside of the containers), you'll need to fix permissions
for the volume (see [#10](https://git.coopcloud.tech/coop-cloud/mastodon/issues/10)):
### `main`
```
chown -R 991:991 /var/lib/docker/volumes/<domain>_app/_data
Es un espejo del desarrollo oficial de:
`coop-cloud/mastodon:main`
No realizamos modificaciones propias directamente sobre esta rama.
### `escuela-comun`
Contiene únicamente las modificaciones que Escuela Común todavía necesita mantener encima de la receta oficial.
---
# Cambios mantenidos actualmente
## Ejecutar Rails/Puma como usuario `mastodon`
La configuración `compose.character-limit.yml` necesita ejecutar inicialmente algunas tareas como `root` para modificar archivos de Mastodon mediante `sed`.
La receta oficial termina iniciando Rails/Puma mediante:
```sh
su -c "RAILS_ENV=production bundle exec rails s -p 3000"
```
And finally, within the `app` container, create an admin account:
En este contexto Rails/Puma continúa ejecutándose como `root`.
```
abra app cmd <domain> app admin -- <username> <email>
En nuestra instalación observamos que esto provocaba que algunos archivos multimedia fueran creados como:
```text
root:root
```
## Tips & tricks
mientras Sidekiq procesa los adjuntos utilizando el usuario `mastodon`.
### Auto-complete is not working?
El problema se manifestó especialmente durante el procesamiento de videos: Sidekiq podía encontrar archivos creados con permisos incompatibles y fallar durante el postprocesamiento.
Check the sidekiq logs (`/sidekiq/retries`), is a bunch of stuff failing? What
is the error?
Nuestra modificación mantiene como `root` solamente la preparación inicial y posteriormente inicia Rails/Puma explícitamente como el usuario `mastodon`:
If it looks anything like `blocked by: [FORBIDDEN/12/index read-only / allow
delete (api)];` then it might mean that your elastic search service has put
itself into "read-only" state. This could be due to running close to no free
disk space one time. ES doesn't undo this state, even when you have more free
disk space once more, so you need to handle this manually:
```
abra app run <domain> es bash
curl -XPUT -H "Content-Type: application/json" http://localhost:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}'
```sh
exec su -s /bin/sh -c \
"RAILS_ENV=production bundle exec rails s -p 3000" \
mastodon
```
Then head back to the sidekiq retries panel and retry one job. You should see
the ticket of retries go down by one if if passed. Then you can "retry all" and
they should get scheduled & run.
Después de aplicar este cambio comprobamos que:
- Rails/Puma se ejecuta como `mastodon`;
- los archivos multimedia nuevos son creados con permisos compatibles;
- Sidekiq puede realizar el postprocesamiento;
- la carga y procesamiento de videos funciona correctamente.
Existe un seguimiento relacionado en upstream:
https://git.coopcloud.tech/coop-cloud/mastodon/issues/63
Este parche debe retirarse cuando la receta oficial incorpore una solución equivalente.
---
## Mitigación temporal contra solicitudes automatizadas `“Boom Protocol” / “BoomProtocolProbe”`
### Contexto
Durante septiembre de 2026 observamos una campaña automatizada de solicitudes de registro contra Mastodon.
Las solicitudes presentan nombres con un patrón similar a:
```text
bp60...
bp129...
bp...
```
y utilizan como motivo de registro:
```text
Automated protocol deliverability probe
```
Las solicitudes llegan desde múltiples direcciones IP y utilizan diferentes proveedores de correo.
En nuestro caso, la rotación de IP y dominios hizo que el bloqueo individual por IP o por proveedor de correo no fuera una solución suficiente.
### Impacto observado
Estas solicitudes pueden:
- llenar la cola de solicitudes de registro;
- generar actividad innecesaria en Mastodon;
- provocar envíos repetidos de correos de confirmación;
- dificultar distinguir solicitudes legítimas;
- generar carga innecesaria en Rails, PostgreSQL, Sidekiq y el servicio de correo.
### Mitigación utilizada
Se añadió una restricción `CHECK` sobre la tabla:
```text
public.user_invite_requests
```
La restricción rechaza nuevas filas cuyo campo `text` sea:
```text
Automated protocol deliverability probe
```
La restricción utilizada es:
```sql
CHECK (
text IS NULL
OR text NOT ILIKE 'Automated protocol deliverability probe'
)
```
Inicialmente se crea como:
```sql
NOT VALID
```
Esto permite que existan solicitudes antiguas que ya contienen el texto bloqueado, pero hace que los nuevos `INSERT` y `UPDATE` tengan que cumplir la restricción desde el momento en que se instala.
### Aplicar la mitigación
El script se encuentra en:
```text
scripts/mitigacion-bp-spam.sql
```
Puede aplicarse desde el directorio de la receta `~/.abra/recipes/mastodon` con:
```sh
abra aplicacion lanzar medialibre.social db -- \
psql \
-U mastodon \
-d mastodon_production \
< scripts/mitigacion-bp-spam.sql
```
Antes de modificar el esquema se recomienda crear un respaldo de la tabla:
```sh
abra aplicacion lanzar medialibre.social db -- \
pg_dump \
-U mastodon \
-d mastodon_production \
-t user_invite_requests \
-Fc \
> /home/yanadmin/user_invite_requests_pre_bp_filter.dump
```
### Comprobar la restricción
```sh
abra aplicacion lanzar medialibre.social db -- \
psql \
-U mastodon \
-d mastodon_production \
-c "
SELECT
conname,
convalidated,
pg_get_constraintdef(oid)
FROM pg_constraint
WHERE conname = 'invite_block_boom_protocol';
"
```
Mientras existan solicitudes antiguas que violan la regla, `convalidated` aparecerá como:
```text
f
```
Esto es esperado cuando la restricción fue creada con `NOT VALID`.
Aunque todavía no esté validada contra todas las filas históricas, las filas nuevas y las actualizaciones sí quedan sujetas a la restricción.
### Validar definitivamente la restricción
Primero se **rechazan todas las solicitudes a través de la interfaz de adminsitración web**.
Una vez que ya no existan filas antiguas incompatibles, puede desde la carpeta de la receta `~/.abra/recipes/mastodon` validarse utilizando:
```text
scripts/validar-mitigacion-bp-spam.sql
```
Puede aplicarse con:
```text
abra aplicacion lanzar medialibre.social db -- \
psql \
-U mastodon \
-d mastodon_production \
< scripts/validar-mitigacion-bp-spam.sql
```
Si todavía existen filas antiguas que violan la restricción, PostgreSQL rechazará la validación.
El estado esperado es:
```text
invite_block_boom_protocol | t
```
### Retirar la mitigación
La mitigación debe considerarse temporal.
Si la campaña termina, cambia de comportamiento o Mastodon incorpora una solución adecuada, puede retirarse desde la carpeta de la receta `~/.abra/recipes/mastodon` utilizando:
```text
scripts/quitar-mitigacion-bp-spam.sql
```
Ejemplo:
```sh
abra aplicacion lanzar medialibre.social db -- \
psql \
-U mastodon \
-d mastodon_production \
< scripts/quitar-mitigacion-bp-spam.sql
```
La restricción también puede retirarse manualmente mediante:
```sql
ALTER TABLE public.user_invite_requests
DROP CONSTRAINT IF EXISTS invite_block_boom_protocol;
```
### Limitaciones de esta mitigación
Esta regla reconoce específicamente el texto:
```text
Automated protocol deliverability probe
```
Si la campaña cambia el contenido de las solicitudes, esta regla dejará de reconocerlas.
Por esta razón no debe considerarse una solución general contra bots.
Tampoco se ejecuta automáticamente durante un despliegue de la receta, porque modifica el esquema interno de la base de datos de Mastodon fuera de sus migraciones oficiales.
La decisión de aplicarla o retirarla debe ser explícita y documentada.
---
+1 -1
View File
@@ -9,4 +9,4 @@ services:
# [0]: See https://github.com/mastodon/mastodon/pull/30091
user: root
command: >
/bin/sh -c 'set -x && ls && sed -i -e "s/500/$MAX_CHARS/g" app/javascript/mastodon/features/compose/components/compose_form.jsx && sed -i -e "s/500/$MAX_CHARS/g" app/validators/status_length_validator.rb && rm -f /mastodon/tmp/pids/server.pid && su -c "RAILS_ENV=production bundle exec rails s -p 3000"'
/bin/sh -c 'set -x && ls && sed -i -e "s/500/$MAX_CHARS/g" app/javascript/mastodon/features/compose/components/compose_form.jsx && sed -i -e "s/500/$MAX_CHARS/g" app/validators/status_length_validator.rb && rm -f /mastodon/tmp/pids/server.pid && exec su -s /bin/sh -c "RAILS_ENV=production bundle exec rails s -p 3000" mastodon'
+30
View File
@@ -0,0 +1,30 @@
-- Mitigación temporal contra la campaña automatizada conocida como
-- "Automated protocol deliverability probe".
--
-- Bloquea nuevas solicitudes de registro cuyo motivo sea exactamente:
--
-- Automated protocol deliverability probe
--
-- Se utiliza NOT VALID porque pueden existir solicitudes antiguas
-- que ya contienen ese texto.
--
-- Las filas nuevas y las actualizaciones sí quedan protegidas desde
-- el momento en que se crea la restricción.
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM pg_constraint
WHERE conname = 'invite_block_boom_protocol'
AND conrelid = 'public.user_invite_requests'::regclass
) THEN
ALTER TABLE public.user_invite_requests
ADD CONSTRAINT invite_block_boom_protocol
CHECK (
text IS NULL
OR text NOT ILIKE 'Automated protocol deliverability probe'
) NOT VALID;
END IF;
END
$$;
+4
View File
@@ -0,0 +1,4 @@
-- Elimina la mitigación temporal contra Boom Protocol / bp spam.
ALTER TABLE public.user_invite_requests
DROP CONSTRAINT IF EXISTS invite_block_boom_protocol;
+11
View File
@@ -0,0 +1,11 @@
-- Valida la restricción contra solicitudes automatizadas bp.
--
-- Debe ejecutarse una vez eliminadas o rechazadas las solicitudes antiguas
-- que todavía contengan:
--
-- Automated protocol deliverability probe
--
-- Si aún existen filas incompatibles, PostgreSQL rechazará la validación.
ALTER TABLE public.user_invite_requests
VALIDATE CONSTRAINT invite_block_boom_protocol;