Dos Mac mini: uno sirve, el otro piensa
Two Mac minis: one serves, the other thinks
Hasta hace nada, un Mac mini lo hacía todo en casa. Llegó el M6 y tocaba repartir: el M4 sirve la web, el blog y los scripts; el M6 trabaja y hace de cerebro con Ollama. Cambié mistral por gemma 4, medí antes de opinar, y lo que más me costó fue un permiso de Red local de macOS que no se ve en los ajustes. Post completo: https://sergiocomeron.com/blog/posts/dos-mac-mini-servidor-y-trabajo/
Until recently one Mac mini did everything at home. Then the M6 arrived and it was time to split the work: the M4 serves the website, the blog and the scripts; the M6 is where I work, and it is the brain, running Ollama. I swapped mistral for gemma 4, measured before judging, and the hardest part was a macOS Local Network permission you cannot see in Settings. Full post: https://sergiocomeron.com/blog/en/posts/dos-mac-mini-servidor-y-trabajo/
Lo escribe Sergio. Lo lee una voz generada · Written by Sergio. Read by a generated voice · Colophon
TranscripciónTranscript · del guión del episodio· from the episode script
Hasta hace nada, en casa había un Mac mini que lo hacía todo. El M4.
Servía la web y el blog. Servía también onemore, el fan site de Apple. Ejecutaba los scripts programados, y me mandaba los avisos por Telegram. Y cargaba con todo lo de LiftCoach, mi app de gimnasio.
Su API, la que sincroniza entrenos, rutinas, nutrición y salud. Y su servidor MCP, con su inicio de sesión.
Todo eso, en una máquina pequeña debajo de la mesa. Y encima, era donde yo programaba. El editor abierto, las pruebas, los cacharreos, todo en el mismo sitio que la web que estaba sirviendo.
Y entonces llegó a casa el M6. Con dos máquinas, ya no tenía sentido que una cargara con todo. Tocaba repartir.
El reparto es sencillo. Uno sirve y el otro piensa.
El M4 pasa a ser servidor, sin pantalla. La web, el blog, onemore, los scripts y Telegram. Lo de siempre, pero sin que yo esté encima con el editor abierto. Una máquina que sirve y que no se toca.
El M6 es la máquina de trabajo. Ahí programo yo. Y ahí vive Ollama, que es lo que mueve los modelos de inteligencia artificial en local.
Lo curioso es que los scripts del M4 no llevan modelo propio. Cuando necesitan redactar algo, llaman al M6 por la red de casa. Le preguntan, el M6 piensa, y devuelve la respuesta. El servidor sirve, y el otro hace de cerebro.
¿Y por qué así, y no al revés? Por la memoria.
El M4 tiene dieciséis gigas. El M6 tiene treinta y dos, el doble. Y con ese doble puedo tener el modelo cargado todo el rato sin quitarle memoria a lo que esté haciendo.
Con el reparto hecho, aproveché para cambiar los modelos. Tres scripts del servidor escriben texto. El resumen diario que leo cada mañana. El contexto que acompaña a las alertas. Y el detector de fallos.
Hasta ahora usaban mistral, un modelo de siete mil millones de parámetros. Ahora usan gemma cuatro, que es bastante más grande.
Y yo iba con una idea clara. Pensaba que el pequeño se quedaba corto. Que el grande iba a escribir mejor, sin más. Pero antes de contarlo, quise medirlo. Cogí los datos reales del resumen de hoy, y pasé cada modelo tres veces.
Y el resultado no fue el que esperaba. Ninguno de los dos se inventó cifras. Y tardaban parecido, unos segundos cada uno. El pequeño no se quedaba tan corto como yo creía.
La diferencia estaba en otra parte. En la constancia.
Con mistral, cada pasada salía distinta. Unas veces corta, otras casi el doble de larga. En una se inventó un apartado que se llamaba «Disco», que no estaba en el formato por ningún lado. Y en esa misma pasada se olvidó de los ataques críticos, que es justo lo que más me interesa ver.
Con gemma, las tres veces salió el mismo formato, y casi la misma longitud. Tampoco es perfecto, ojo. En una pasada mezcló dos cifras, las amenazas de Cloudflare con las direcciones de los ataques. Pero para un parte que leo cada mañana, prefiero el que sale igual todos los días.
Hay un detalle con gemma que conviene saber. Si no le dices que no piense, piensa en voz alta. Y todo ese razonamiento acaba metido en el mensaje que te llega. Así que hay que pedirle, de forma explícita, que no razone por escrito.
Luego estaban los artículos relacionados, los que salen al final de cada post del blog y de onemore. Eso funciona con embeddings, que es una forma de convertir un texto en números para comparar de qué habla. Ahí también cambié de modelo.
Y aquí el motivo era más simple. El modelo anterior tenía un contexto muy corto. Le pasabas un post un poco largo y devolvía un error. Así que había que recortar cada post antes de compararlo, y quedarse solo con el principio.
El nuevo acepta textos mucho más largos. Ya no hay que trocear nada.
Y antes de tocar cada script, hice una copia. Es lo mínimo cuando cambias cinco cosas a la vez.
Mientras andaba por ahí, me encontré algo que no debía estar. El token del bot de Telegram estaba escrito dentro del código del script de alertas. Lo saqué a un archivo aparte, con permisos cerrados, fuera del código.
Y al hacerlo, vi otra cosa. El resumen y el detector ni siquiera tenían token. No podían enviar nada. Llevaban un tiempo trabajando para nadie.
Pero lo que de verdad me llevó tiempo vino después. Esta mañana, a las ocho, me llegó el resumen por Telegram. En crudo. Sin redactar. El modelo no había respondido.
Miré el log, y decía que no había ruta hasta el otro equipo. Como si el M6 no existiera. Pero desde Terminal, en el mismo M4, el M6 respondía sin problema. Misma máquina, mismo destino, y una vez sí y otra no.
La diferencia era quién lanzaba el proceso. Los scripts programados los lanza launchd, el que arranca las tareas en el Mac. Y macOS tiene un permiso de privacidad que se llama Red local. Decide qué apps pueden hablar con otros equipos de tu casa.
Un python lanzado directamente por launchd no podía llegar al M6. Ni el python del sistema, ni el de Homebrew. Desde Terminal sí, porque ahí manda el permiso de Terminal.
Probé a cambiar de python, y no lo arregló. Y lo más curioso es que ese python ni siquiera aparece en los ajustes de Red local. No hay ningún interruptor que activar.
Lo que funcionó fue un pequeño rodeo. Que launchd no lance python, sino un bash con un script envoltorio. Ese bash sí tiene el permiso de Red local. Y python corre debajo, como proceso hijo suyo.
El detalle importante es no usar exec. Con exec, python sustituye al bash, y vuelves a estar como al principio.
Antes de tocar los trabajos de verdad, lo probé con una tarea temporal que solo llamaba al modelo y no enviaba nada. Funcionó. Luego pasé los tres scripts al envoltorio.
No es la primera vez que macOS me cambia las reglas del servidor por debajo. Ya me pasó cuando una actualización me tumbó el servidor.
Así que así queda la casa. Un Mac mini que sirve y no se toca. Otro que trabaja, y hace de cerebro para el primero.
Lo que más tiempo me llevó no fue el modelo. Fue un permiso de privacidad que no se ve en los ajustes. Si un script programado te dice que no hay ruta, y desde Terminal todo va, mira quién lanza el proceso.
Los detalles, con el código, están en el blog. Esto ha sido el podcast de Sergio por hoy. Nos escuchamos en el próximo.