Ir al contenido
  1. Posts/

Immich: monté mi propio Google Photos y ahora tengo 47.000 fotos bajo control

Durante años tuve mis fotos en Google Photos sin pensar demasiado en ello. Funciona bien, las búsquedas son buenas, la app móvil hace backup solo. Cómodo. Hasta que Google decidió que el almacenamiento gratuito ilimitado había terminado y que ahora tocaba pagar, o comprimir fotos, o ambas cosas.

Tengo 47.000 fotos acumuladas desde 2012. Fotos de viajes, de familia, de proyectos, de todo. Meter eso en Google One tiene un coste mensual que no me apetece pagar para siempre, más cuando ya tengo infraestructura propia corriendo en casa. Y encima, todas esas fotos están en servidores de Google. Google las analiza. Google las usa para entrenar modelos. Puede que no te importe, pero a mí me importa cada vez más.

La alternativa obvia era buscar algo self-hosted. Estuve mirando Photoprism primero, que lleva más tiempo en el mercado y tiene buena reputación. El problema es que Photoprism ha ido cerrando funciones detrás de un modelo de licencia de pago, el rendimiento con colecciones grandes no es su punto fuerte, y la app móvil es bastante básica. No terminó de convencerme.

Luego llegué a Immich. Y aquí me quedé.

Qué es Immich
#

Immich es una alternativa self-hosted a Google Photos, de código abierto, con app móvil nativa para iOS y Android, reconocimiento facial, búsqueda semántica con IA, álbumes compartidos y una interfaz que se parece bastante a la de Google Photos. No es un clon exacto, pero si vienes de Google Photos no te vas a perder.

Lo que lo diferencia de otras alternativas es que está construido para ser una solución completa: no solo almacenamiento de fotos, sino también el stack de IA que hace que las búsquedas funcionen de verdad. Puedes buscar “playa 2019” y te saca las fotos de la playa de 2019. Puedes buscar “perro en el jardín” y funciona. Eso no es magia, es CLIP, un modelo de embeddings semánticos que corre localmente en tu servidor.

Pantalla de bienvenida de Immich
La pantalla de bienvenida de Immich. Primer arranque en el cluster K3s.

La infraestructura donde lo monté
#

Mi cluster K3s corre sobre tres ZimaBoard 2 actuando como workers. Cada uno tiene un procesador Intel N150 y 16GB de RAM. No es potencia bruta, pero para un homelab personal aguanta todo lo que le echo.

El storage lo gestiona Longhorn, que distribuye los datos entre los nodos. Para Immich esto es relevante porque necesitas persistencia real: las fotos, la base de datos y los modelos de IA tienen que sobrevivir a reinicios y actualizaciones.

El despliegue quedó en el namespace immich-demo con cuatro pods corriendo:

  • immich-server: la API y la interfaz web
  • machine-learning: el pod que corre los modelos de reconocimiento facial y búsqueda semántica CLIP
  • postgres: PostgreSQL con la extensión pgvecto-rs para búsqueda vectorial
  • valkey: la caché (fork de Redis)

Este punto de PostgreSQL con pgvecto-rs es importante y no siempre está bien documentado. Immich no funciona con un PostgreSQL estándar. Necesita la extensión pgvecto-rs (o VectorChord en versiones más recientes) para almacenar y consultar los embeddings vectoriales que hacen posible la búsqueda semántica. Si intentas apuntar Immich a una instancia de Postgres normal, te vas a encontrar con errores en el arranque.

La URL del cluster es fotos.mi-homelab.local con certificado autofirmado, solo accesible desde la red local. Para acceso externo usaría Cloudflare Tunnel o Tailscale, pero por ahora me basta con tenerlo en la red de casa.

Cómo instalarlo en K3s con Helm
#

La forma más limpia de desplegar Immich en Kubernetes es con el chart oficial de Helm. El repositorio está en https://immich-app.github.io/immich-charts.

1
2
helm repo add immich https://immich-app.github.io/immich-charts
helm repo update

Luego creas un archivo values.yaml con tu configuración. Lo mínimo que necesitas configurar es el storage (PersistentVolumeClaims para las fotos y la base de datos) y las credenciales de PostgreSQL. Un ejemplo básico:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
immich:
  persistence:
    library:
      existingClaim: immich-library-pvc

postgresql:
  enabled: true
  global:
    postgresql:
      auth:
        password: "tu-password-aqui"
        database: immich
        username: immich

redis:
  enabled: false

valkey:
  enabled: true

Y el despliegue:

1
2
3
4
kubectl create namespace immich-demo
helm install immich immich/immich \
  --namespace immich-demo \
  --values values.yaml

Si vienes de Proxmox y prefieres Docker Compose, el proceso es incluso más directo. El repositorio oficial incluye un docker-compose.yml listo para usar. Para immich docker, básicamente copias el compose, ajustas las rutas de volúmenes y las variables de entorno en el .env, y levantas con docker compose up -d. En diez minutos tienes Immich corriendo.

Para immich proxmox, lo más habitual es correrlo en un LXC con Docker o en una VM. Funciona perfectamente en ambos casos. La única consideración es asegurarte de que el LXC tenga acceso a suficiente almacenamiento y, si quieres aceleración hardware para los modelos de IA, que puedas pasar la GPU o la iGPU al contenedor.

Dashboard principal de Immich en modo oscuro
El dashboard de Immich recién instalado. 9.7 GiB disponibles en Longhorn, v2.0.0 corriendo en K3s.

La migración desde Google Photos
#

Migrar 47.000 fotos no es un proceso rápido, pero tampoco es complicado. Google Takeout te permite exportar todo tu contenido en archivos ZIP. Pides la exportación, recibes un email con los links de descarga, y te bajas todo.

El problema de los exports de Google Takeout es que vienen con los metadatos en archivos JSON separados. foto_001.jpg tiene su foto_001.jpg.json con la fecha original, la ubicación y demás. Immich tiene una herramienta de línea de comandos que maneja esto correctamente y preserva las fechas originales al importar. Si simplemente copias las fotos sin pasar por el importador, todas van a aparecer con la fecha de importación, no con la fecha en que las hiciste.

El proceso es: exportar desde Google Takeout, descomprimir en el servidor, usar immich upload con el CLI para importar manteniendo metadatos. Tardé varias horas en la primera importación, pero Immich lo hace en background y puedes seguir usándolo mientras procesa.

Después de importar toca esperar a que el pod de machine-learning procese todas las fotos. El reconocimiento facial y los embeddings CLIP se calculan en background. Con 47.000 fotos y un N150, este proceso tardó un par de días. No bloquea nada, simplemente va procesando en segundo plano.

La app móvil y el backup automático
#

Este punto es donde Immich marca la diferencia frente a otras alternativas self-hosted. La app móvil es buena de verdad. No es un port de la web con funciones recortadas, es una app nativa con backup automático en background.

Configuras la URL de tu servidor en la app, le dices que haga backup de la cámara, y a partir de ahí cada foto que haces en el móvil sube automáticamente a tu servidor. Igual que Google Photos, pero yendo a tu servidor.

Tiene opciones para backup solo con WiFi, para no usar datos móviles, para excluir carpetas concretas. Lo básico que necesitas está ahí.

El backup desde el móvil funciona con HTTPS, así que si tu servidor está solo en la red local necesitas o VPN o algún tipo de túnel para que el móvil pueda llegar cuando estás fuera de casa. Con Tailscale es trivial: instalas Tailscale en el móvil y en el servidor, y tienes acceso desde cualquier sitio.

Reconocimiento facial y búsqueda semántica
#

Aquí es donde Immich adelanta a casi todo lo que hay en el espacio self-hosted, incluido Photoprism.

El reconocimiento facial agrupa automáticamente tus fotos por personas. Una vez que el pod de machine-learning ha procesado el catálogo, vas a la sección “Explorar” y ves caras agrupadas. Le pones nombre a cada persona y a partir de ahí puedes buscar “fotos de [nombre]” y te saca todas las fotos donde aparece esa persona.

La búsqueda semántica usa CLIP, un modelo desarrollado por OpenAI y disponible en versiones open source. Lo que hace es convertir cada foto en un vector numérico que representa su contenido visual, y lo mismo con tu texto de búsqueda. Buscar “atardecer en la montaña” encuentra fotos de atardeceres en montañas aunque no tengan esa etiqueta en ningún sitio. Buscar “mesa de madera con café” funciona. Es sorprendentemente bueno para correr en local en un N150.

Todo esto corre en tu servidor. Ninguna foto sale a servicios externos para ser analizadas.

Immich vs Photoprism: la comparación real
#

He probado los dos y me quedo con Immich por varias razones.

App móvil: Immich tiene una app nativa con backup automático funcional. Photoprism tiene una app web progresiva que no es lo mismo.

Velocidad de desarrollo: Immich lleva un ritmo de releases muy activo. Photoprism ha ralentizado su desarrollo y ha movido funciones a una versión de pago.

Búsqueda semántica: Los dos tienen CLIP, pero la implementación de Immich está más pulida y el rendimiento es mejor.

Comunidad: Immich tiene una comunidad más activa en este momento, más documentación, más casos de uso documentados.

Contra de Immich: requiere más recursos que Photoprism. El pod de machine-learning necesita RAM. En un servidor con poca memoria puede ser un problema.

Para un homelab con recursos decentes, Immich gana. Para instalaciones muy limitadas en hardware, Photoprism puede ser la opción más práctica.

La versión que estoy corriendo y la que deberías usar
#

Tengo montada la v2.0.0 en el cluster de demo, pero en el momento de escribir esto la versión estable es la v2.5.6. Hay mejoras importantes entre medias, incluyendo mejor soporte para VectorChord como extensión PostgreSQL, mejoras en el rendimiento del pod de machine-learning y varias correcciones en la app móvil.

Si estás montando Immich desde cero, usa v2.5.6. Si ya tienes una instalación corriendo en una versión anterior, actualiza: Immich gestiona las migraciones de base de datos automáticamente con cada release.

Lo que funciona bien y lo que no
#

Funciona bien:

  • La app móvil y el backup automático
  • La búsqueda semántica con descripciones en lenguaje natural
  • El reconocimiento facial, una vez que el proceso inicial termina
  • La interfaz web, que es rápida y limpia
  • La organización por álbumes y por fecha
  • El mapa con geolocalización de fotos

Lo que tiene margen de mejora:

  • El proceso inicial de indexado es lento en hardware modesto. Con 47.000 fotos y un N150 tardé días en tener todo procesado.
  • La documentación para K3s/Helm no es tan completa como la de Docker Compose. Tuve que complementar con issues de GitHub para algunos detalles de configuración.
  • El pod de machine-learning consume bastante memoria. En un servidor compartido con otros servicios hay que reservarle recursos explícitamente.
  • No hay deduplicación automática de fotos. Si importas el mismo archivo dos veces, aparece duplicado.

Por qué no volvería a Google Photos
#

No es solo una cuestión de precio, aunque el precio ayuda. Es que una vez que tienes esto corriendo te das cuenta de que Google Photos tiene tus fotos, no tú. Si Google decide cambiar sus políticas, subir precios otra vez, o simplemente discontinuar el producto, tus recuerdos están en sus manos.

Con Immich, las fotos están en mis discos, gestionadas por software que puedo controlar, con un historial de versiones que puedo auditar. Si mañana el proyecto Immich desapareciera, seguiría teniendo las fotos en disco en formato normal, sin formatos propietarios.

El backup automático desde el móvil funciona igual de bien. La búsqueda es tan buena o mejor que la de Google Photos para la mayoría de consultas. El reconocimiento facial funciona. La única cosa que sigue siendo mejor en Google Photos es la integración con el ecosistema Google, pero si estás leyendo esto probablemente no sea tu prioridad número uno.

Si tienes un homelab corriendo, sea en K3s, en Proxmox, o con Docker Compose en cualquier servidor, Immich merece el tiempo que lleva montarlo. No es mucho, y el resultado es una solución que funciona de verdad.