forked from coop-cloud/mastodon
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10de16a56d | ||
|
|
10092c0d64 | ||
|
|
0186debe1f | ||
|
|
77b9fd6ee3 | ||
|
|
8fe7df4080 | ||
|
|
422ced0456 | ||
|
|
500a154d37 | ||
|
|
e4372d33ca | ||
|
|
09e5c0ee10 | ||
|
|
f9745acb0d |
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
$$;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user