Herramientas 3D fáciles con Docker Compose
Qué herramientas 3D se instalan con un comando de Compose, por servicios y valores a editar, y qué queda a mano. Incluye la instalación mínima de PrintStash.
Cuenta el trabajo, no los contenedores. Con esa medida, las instalaciones más cortas de esta categoría son Spoolman si solo quieres inventario de filamento, la imagen «solo» de Manyfold o PrintStash si quieres una biblioteca de modelos, y OctoPrint si la impresora está conectada a la misma máquina que Docker. Cada una es un fichero de Compose y un up -d, y las diferencias aparecen en lo que tienes que decidir antes de ese comando y en lo que sigue faltando después.
PrintStash arranca dos contenedores y no necesita ningún fichero de entorno: cada valor del fichero de Compose trae un valor por defecto que funciona, y la aplicación genera su propio secreto de firma en el primer arranque. El único paso que añade es un token de configuración que se imprime en el log de la API y que pegas en el asistente de primer arranque. La imagen «solo» de Manyfold es un único contenedor, pero quiere un SECRET_KEY_BASE que generas tú. Ninguna de las dos necesita Postgres.
Comprobado contra la documentación y el repositorio actuales de cada proyecto el 17 de agosto de 2026. Los detalles de PrintStash se leyeron de la etiqueta v0.11.4 en lugar de la página de documentación, así que unos cuantos van por delante de la guía de instalación.
Qué hace fácil una instalación con Compose
Contar contenedores es una mala medida. Una sola imagen que se niega a arrancar sin un secreto generado y un bind mount con el propietario correcto da más trabajo que dos imágenes que arrancan con los valores por defecto. Lo que cuesta tiempo es cuántos servicios levanta un fichero por defecto, si una base de datos externa es obligatoria, cuántos valores tienes que editar antes del primer arranque, si algo se compila en local y qué queda por hacer a mano cuando los contenedores ya están sanos.
| Herramienta | Servicios con el fichero por defecto | Base de datos externa | Valores que fijar antes | Lo que queda tras up |
|---|---|---|---|---|
| PrintStash 0.11.4 | 2 (frontend, api) | Ninguna. SQLite en un volumen con nombre | Ninguno | Leer el token de configuración en el log de la API y crear la cuenta de administrador en el navegador |
| Manyfold solo v0.147.2 | 1 (base de datos y Redis incluidos) | Ninguna | SECRET_KEY_BASE, más PUID/PGID para que coincidan con el propietario de tus volúmenes |
Crear la cuenta de administrador en el navegador |
| Manyfold estándar | 3 (app, postgres:15, redis:7) |
Postgres y Redis | SECRET_KEY_BASE, DATABASE_*, REDIS_URL |
Crear la cuenta de administrador en el navegador |
| Spoolman | 1 | Ninguna. SQLite por defecto | Ninguno (TZ es opcional) |
Crear la carpeta data y hacerle chown 1000:1000 antes de arrancar |
| OctoPrint | 1 | Ninguna | Ninguno | Pasar al contenedor el dispositivo serie de la impresora y ejecutar el asistente de OctoPrint |
| Mainsail | 1, y es solo la interfaz web | Ninguna | Las direcciones de las impresoras en config.json |
Instalar Klipper y Moonraker en el host de la impresora, algo que este método no hace |
Mainsail es el caso límite honesto. Su página de Docker es corta y exacta, y dice sin rodeos que Klipper y Moonraker no se instalan así y tienen que estar ya funcionando en la impresora. Con Compose consigues un panel de control, no una pila de impresión. Si alguien te dice que la pila de Klipper se despliega con un solo comando de Compose, está contando el último contenedor.
La instalación mínima de PrintStash
La instalación entera son dos comandos y un grep, sin nada que abrir en un editor:
mkdir printstash && cd printstashcurl -O https://raw.githubusercontent.com/xiao-villamor/PrintStash/main/docker-compose.ymldocker compose up -dEl fichero descarga imágenes ya compiladas de GHCR para linux/amd64 y linux/arm64, así que en tu equipo no se compila nada. Clonar el repositorio también funciona y es lo que muestra la guía de instalación, pero solo necesitas ese fichero. Tanto el fichero como las imágenes que nombra siguen la última versión publicada, que es el valor por defecto correcto para una primera instalación y el equivocado para un servidor que actualizas de forma deliberada: para eso, pon en PRINTSTASH_VERSION la versión que quieras y coge el fichero de Compose de la etiqueta correspondiente en lugar de main.
Después busca el token de primer arranque y abre la interfaz:
docker compose logs api | grep "setup token"Abre http://localhost:3000, pega el token y crea la primera cuenta de administrador. No hay usuario ni contraseña por defecto, y el asistente rechaza un token incorrecto con un 403.
El propio README del proyecto es más cauteloso que su código, y cada diferencia hace la instalación más corta de lo anunciado, no más larga.
.env es opcional. Todas las variables del fichero de Compose traen un valor por defecto, así que la pila levanta sin él. Copiar .env.example sirve para cuando quieres cambiar algo.
No tienes que inventarte un secreto JWT. El valor de relleno que viene en el fichero de Compose es público, así que desde 0.8.4 la API se niega a firmar nada con él: en el primer arranque genera un secreto real y lo guarda en su propia base de datos, donde sobrevive a los reinicios. Fija VAULT_JWT_SECRET tú mismo si prefieres tener ese valor bajo tu control, pero dejarlo como está no es el agujero de seguridad que el valor de relleno parece.
El token de configuración se genera por proceso cuando no has fijado VAULT_SETUP_TOKEN, así que si el contenedor de la API se reinicia antes de que termines el asistente, el token anterior deja de valer y vuelves a hacer grep en el log. Poner la variable con un valor propio lo vuelve estable, y merece la pena en un host donde los contenedores se reinician de forma programada.
Lo que sale de esa instalación por defecto es SQLite y disco local, ambos en volúmenes de Docker con nombre, con las migraciones de base de datos que ejecuta el entrypoint de la imagen en cada arranque. Con 1 GB de RAM funciona, con 2 GB va cómodo porque generar miniaturas de mallas grandes es el paso pesado, y uno o dos núcleos bastan. Desde v0.12.0 la imagen completa genera previsualizaciones STEP y STP en ARM además de en amd64.
Por qué dos contenedores en lugar de uno
El contenedor frontend es nginx. Sirve la aplicación de página única ya compilada y hace de proxy de /api/v1, WebSockets incluidos, hacia el contenedor api en el mismo origen, y por eso no hay ninguna URL de API que configurar en el navegador. Eso elimina un fallo conocido de los despliegues con orígenes separados, donde la página carga bien y todas las peticiones posteriores van al host equivocado.
También significa que el puerto de la API no se publica en el host. El servicio api solo expone el 8000 en la red interna de Compose, así que el endpoint de vida que puedes alcanzar desde el host es http://localhost:3000/api/v1/health, a través de nginx. Con los perfiles opcionales apagados, el puerto 3000 es lo único publicado, así que tienes un puerto en el que pensar en lugar de tres.
Configuración avanzada que sigue siendo opcional
Los servicios opcionales viven detrás de perfiles de Compose, así que se quedan parados hasta que los nombras. Esa es la parte que se les suele escapar a las comparativas de despliegue: PrintStash incluye un servicio de Postgres y otro compatible con S3 en el mismo fichero que entrega a quien instala por primera vez, y ninguno de los dos arranca.
# Postgres instead of SQLitedocker compose --profile postgres up -d
# A local SeaweedFS target for S3-compatible storagedocker compose --profile s3 up -d seaweedfsSeaweedFS 4.41 está fijado por digest y su endpoint S3 queda en el puerto 9000. MinIO salió de la pila normal en v0.12.0 y los volúmenes existentes se migran con docker-compose.migrate-minio.yml, que copia los objetos sin borrar el origen, ya que el proyecto original de MinIO está archivado y abandonar datos de objetos en silencio sería peor que mantener un camino de migración. Que necesites uno u otro es una decisión real y no un valor por defecto: SQLite o Postgres, local o S3 razona cuándo el servicio añadido se paga solo, y para una biblioteca doméstica de un solo usuario la respuesta suele ser que no.
También hay un fichero más pequeño y, desde v0.12.0, cambia más cosas que su número de líneas. docker-compose.light.yml declara solo frontend y api, que es lo que una instalación por defecto ejecuta de todas formas, pero el api que nombra ahora es otra imagen: printstash-api-lite en lugar de printstash-api. La imagen lite se compila sin Chromium, así que desaparecen las importaciones asistidas por navegador de páginas que bloquean una petición simple, y sin la teselación de OpenCASCADE que genera previsualizaciones STEP, en todas las plataformas y no solo en ARM. Mantiene las miniaturas de mallas con NumPy, Pillow y Trimesh, así que las previsualizaciones de STL, 3MF y OBJ quedan intactas. La CI rechaza la compilación a menos que lite salga al menos 700 MiB más pequeña que la completa y no arranque más lento.
El fichero también quita 101 líneas y 24 claves de entorno, todas para cosas que luego no puede hacer: VAULT_STORAGE_BACKEND y las nueve variables VAULT_S3_* del almacenamiento de la bóveda en S3 o R2, las cinco variables VAULT_BACKUP_S3_* para enviar copias de seguridad a un bucket, el ajuste de retención y las credenciales de los servicios opcionales.
curl -o docker-compose.yml https://raw.githubusercontent.com/xiao-villamor/PrintStash/main/docker-compose.light.ymldocker compose up -dGuardarlo con el nombre estándar mantiene el comando corto y trae una trampa: cualquier instrucción posterior que vuelva a descargar docker-compose.yml lo sobrescribe con el fichero completo. Coge el fichero ligero si te vas a quedar en SQLite y disco local y no necesitas previsualizaciones STEP ni importaciones asistidas por navegador. Sáltalo si el almacenamiento puede cambiar más adelante, y ten en cuenta que es el camino menos rodado: las notas de la versión 0.8.2 recogen que hubo que repararlo para quienes lo usaban.
Para cualquier cosa accesible desde fuera de la LAN, docker-compose.prod.yml publica solo el frontend y lo enlaza a 127.0.0.1, así que nada queda expuesto salvo a través del proxy que pongas delante:
curl -O https://raw.githubusercontent.com/xiao-villamor/PrintStash/main/docker-compose.prod.ymlecho "VAULT_JWT_SECRET=$(openssl rand -hex 32)" >> .envdocker compose -f docker-compose.prod.yml up -dEste es el único sitio donde el secreto no es opcional, y es a propósito. El fichero de producción lo declara como ${VAULT_JWT_SECRET:?set a strong VAULT_JWT_SECRET in .env}, así que Compose se niega a arrancar sin él en lugar de recurrir en silencio a un valor generado en un host que estás a punto de exponer. Si te dejas esa línea fuera, obtienes un error, no una pila funcionando.
Como nginx ya hace de proxy de la API y de los WebSockets, tu proxy inverso tiene exactamente un upstream. Un Caddyfile que funciona son dos líneas, y proxy inverso y TLS cubre los equivalentes en nginx y Traefik, más el límite de tamaño de cuerpo que tienes que subir a la vez que VAULT_MAX_UPLOAD_MB.
El resto de la superficie avanzada se activa igual, solo si lo pides. PRINTSTASH_VERSION en .env fija la etiqueta de la imagen para actualizaciones deliberadas. VAULT_OIDC_ENABLED y las variables de issuer, cliente y claim de grupo añaden inicio de sesión con Authentik, Authelia o Keycloak mientras las cuentas locales siguen funcionando como respaldo. FORWARDED_ALLOW_IPS le dice a uvicorn qué dirección de proxy puede fijar la IP del cliente, y dejarla sin valor confía solo en loopback, que es el valor por defecto correcto cuando el puerto se publica directamente.
Dos detalles de operación cuestan más de lo que su tamaño sugiere. Las credenciales guardadas en la base de datos se cifran con un fichero de clave que PrintStash crea en /data/db/.printstash-secrets-key a menos que le pases VAULT_SECRETS_KEY, y una copia de seguridad de la base de datos no puede descifrarlas sin él, así que ese fichero necesita su propia copia. El otro es que 0.11.4 deja explícita la topología soportada en un proceso de API por bóveda: al arrancar reclama un lock y falla rápido cuando ya hay otro proceso de API vivo, así que escalar ese contenedor no es una palanca de la que dispongas.
Donde PrintStash no es la opción más fácil
La imagen «solo» de Manyfold es un contenedor frente a dos y, si lo que optimizas es la pila más corta posible, gana en ese recuento. Spoolman es aún más pequeño, porque llevar la cuenta de las bobinas es un trabajo más pequeño. Ninguna de las dos cosas es una crítica a un proyecto. Es lo que compra un alcance más estrecho.
PrintStash tampoco es un panel de control de impresoras ni un slicer, así que un fichero de Compose que te da una biblioteca no sustituye a Mainsail, Fluidd ni OctoPrint, y no lamina nada. Habla con Moonraker para el estado, la subida y el envío a imprimir, y funciona al lado de esas interfaces. Si tu pregunta real era cómo poner una impresora en la red con el menor esfuerzo, la biblioteca es la capa equivocada por la que empezar.
El token de configuración es un paso más que «abre la página y crea una cuenta», y existe porque el endpoint de primer arranque tiene que ser alcanzable antes de que exista cualquier cuenta. Prefiero hacer grep en una línea de log que dejar ese endpoint abierto, pero es un paso, y cualquier comparativa que llame a PrintStash una instalación sin fricción se lo está saltando.
Preguntas frecuentes
¿Qué herramienta de impresión 3D autoalojada es de verdad la más fácil de desplegar con Docker Compose?
Depende del trabajo, y la clasificación útil es por decisiones y no por contenedores. Spoolman es lo más pequeño que hay aquí: una imagen, SQLite, un bind mount que tienes que crear y cambiar de propietario antes, y solo lleva la cuenta del filamento. Para una biblioteca de modelos, la imagen «solo» de Manyfold y PrintStash están cerca, con Manyfold en un contenedor que necesita un SECRET_KEY_BASE generado y PrintStash en dos contenedores que no necesitan fichero de entorno pero sí un token de configuración sacado del log de la API. OctoPrint es un contenedor y su limitación es física antes que de software, porque la impresora tiene que estar conectada al host de Docker. Mainsail se instala como un único contenedor que es solo la interfaz, así que es el despliegue más fácil y el menos completo.
¿PrintStash necesita Postgres o un bucket S3?
No. La instalación por defecto es SQLite más disco local, ambos en volúmenes de Docker con nombre, y también es el camino mejor probado. Postgres y SeaweedFS vienen en el mismo fichero de Compose, pero están detrás de perfiles llamados postgres y s3, lo que significa que Docker nunca los arranca a menos que pases el perfil en la línea de comandos. La confusión se entiende, porque el servicio de Postgres está ahí mismo en el fichero que has descargado, pero leerlo como parte de la instalación se equivoca en dos contenedores al calcular la huella.
¿Tengo que fijar un secreto antes de arrancarlo?
No desde 0.8.4. El fichero de Compose deja VAULT_JWT_SECRET con un valor de relleno que está publicado en el repositorio y, como es público, la API lo trata como inservible: en el primer arranque genera un secreto real, lo guarda en su propia tabla de configuración y sigue usando ese entre reinicios, así que a nadie se le cierra la sesión. Poner el tuyo con openssl rand -hex 32 sigue siendo razonable si quieres controlar ese valor o llevarlo de una instalación a otra, pero es una preferencia y no un requisito previo. El README del proyecto y el fichero de Compose ligero siguen diciéndote que lo cambies primero, lo que exagera lo que el código exige.
¿Por qué el primer arranque pide un token de configuración y dónde está?
Porque el endpoint que crea al primer administrador no puede exigir una sesión existente, así que algo tiene que protegerlo. Cuando VAULT_SETUP_TOKEN está vacío, la API genera uno aleatorio por proceso y lo escribe en su log mientras la bóveda sigue sin configurar, y docker compose logs api | grep "setup token" basta para encontrarlo. Enviar el asistente sin él devuelve un 403. Que el token sea por proceso importa en un caso: si reinicias el contenedor de la API a mitad de la configuración, necesitas el nuevo valor del log, algo que puedes evitar por completo fijando la variable a un valor que elijas tú.
¿Puedo ejecutar también la pila web de Klipper con Compose?
En parte, y vale la pena ser preciso sobre qué parte. La configuración de Docker documentada por Mainsail ejecuta la interfaz web en un contenedor y configura las direcciones de red de las impresoras con las que debe hablar, y su propia documentación dice que Klipper y Moonraker no se instalan con ese método y tienen que estar ya funcionando en la impresora. Klipper necesita hablar con la placa controladora de la impresora, así que vive en la máquina que está físicamente conectada a ella. Compose encaja bien con el panel de control y mal con la capa de firmware que hay debajo.
¿Cuál es la forma con menos trabajo de llegar desde fuera de la LAN?
Cambia a docker-compose.prod.yml, que publica solo el frontend y lo enlaza a 127.0.0.1, y luego apunta un proxy que termine TLS a ese único puerto. Ese fichero es también el único sitio donde VAULT_JWT_SECRET pasa a ser obligatorio: está declarado para que Compose falle en lugar de arrancar con un secreto generado en un host que estás a punto de exponer, así que pon antes en .env un valor de openssl rand -hex 32. Como el nginx del frontend ya hace de proxy de la API y de sus WebSockets en el mismo origen, tu proxy tiene un upstream y ninguna regla de rutas, y un Caddyfile para eso son dos líneas. Sube el límite de tamaño de cuerpo de las peticiones del proxy hasta VAULT_MAX_UPLOAD_MB o las subidas grandes fallarán antes de llegar a la API. No redirijas puertos a los contenedores directamente, y trata el acceso remoto como tu responsabilidad y no como algo que resuelva la aplicación.
¿La instalación simple me cierra la puerta a Postgres o S3 más adelante?
No, pero mudarse es trabajo real y no un interruptor, así que elige de forma deliberada si ya sabes que quieres Postgres. Los backends de almacenamiento y las URL de base de datos son configuración, y los servicios opcionales están en el fichero que ya tienes, así que no hay que reinstalar nada. Lo que sí necesitas es migrar los datos existentes, y la ruta práctica es una copia de seguridad completa primero. Empezar en SQLite y disco local es la recomendación normal porque es el camino que usa la mayoría de las instalaciones, que también es donde los problemas salen y se arreglan antes.
Fuentes
docker-compose.yml,docker-compose.prod.yml,.env.example,backend/app/core/config.py,backend/app/services/setup_token.py,backend/app/api/v1/setup.py,backend/app/main.pyyfrontend/nginx.confde PrintStash en la etiquetav0.11.4, más las entradas de changelog de 0.8.4 y 0.11.4. Leído el 17 de agosto de 2026.- Manyfold Docker installation y administrator setup, versión v0.147.2 según manyfold.app. Consultado el 17 de agosto de 2026.
- Spoolman installation wiki, octoprint-docker y Mainsail Docker setup. Consultado el 17 de agosto de 2026.
Si ya te has decidido por PrintStash, primeros pasos continúa desde el asistente de configuración hasta el primer modelo y una impresora conectada. Para el lado de las funciones de la decisión sobre Manyfold en lugar del lado del despliegue, lee PrintStash frente a Manyfold.