SSD Nodes Learn
Guias Matt ConnorPor Matt Connor · Atualizado 2026-07-24

Como rodar Immich com 6GB RAM e upgrades seguros

Evite o erro de memória no container de machine-learning e falhas no pgvecto.rs na v3. Saiba como configurar o HTTPS na porta 2283 e fazer o restore do banco.

O que você está construindo

O Immich é um serviço de backup de fotos e vídeos self-hosted — um substituto real para o Google Photos. Ele possui um aplicativo móvel que faz o upload da sua galeria em segundo plano, uma linha do tempo, álbuns, reconhecimento facial e busca por machine learning que encontra termos como "beach" ou uma pessoa sem que você precise marcar nada. Você o executa em um VPS próprio, os arquivos originais permanecem no seu disco e ninguém os escaneia para vender produtos.

A instalação consiste em quatro containers a partir do arquivo Docker Compose do próprio projeto. Essa parte leva dez minutos. O restante deste guia aborda os problemas reais: o container de machine-learning consome muita memória em máquinas pequenas, os arquivos originais ocupam disco rapidamente, o aplicativo móvel não aceita servidores apenas com HTTP e o Immich lança breaking changes com frequência suficiente para que um docker compose pull descuidado deixe seu banco de dados incapaz de iniciar. Trate esses quatro pontos com seriedade e o Immich será extremamente estável. Ignore-os e você perderá um fim de semana inteiro.

Pré-requisitos e problemas conhecidos

  • RAM: a documentação oficial indica 6 GB de mínimo e 8 GB recomendados — considere 4 GB mais swap como o limite absoluto. Os containers immich-server e Postgres consomem pouco. O container immich-machine-learning é o mais pesado — ele carrega os modelos CLIP e de reconhecimento facial na RAM para criar os índices de busca; em máquinas com 2 GB, o kernel encerra o processo. Adicione swap mesmo se tiver 4 GB.
  • Disco: dimensione para toda a sua biblioteca, com uma margem extra. Seus arquivos originais são copiados integralmente, além disso o Immich gera thumbnails e imagens de preview (aproximadamente 10–20% adicionais). Uma coleção de 200 GB de fotos exige um volume de 300 GB. O Postgres é pequeno em comparação.
  • CPU: qualquer VPS KVM moderno é suficiente, mas ML em CPU é lento. A indexação de smart-search de um grande import pode levar horas em segundo plano. Isso é normal; não é necessário uma GPU.
  • Um nome de domínio apontado para o VPS. O aplicativo móvel exige um endpoint HTTPS, e recomenda-se o uso de um reverse proxy. Esta configuração é similar a uma instância self-hosted do Nextcloud com Docker, TLS e backups — o Immich é o equivalente para fotos desse servidor de arquivos.
  • Docker e o plugin Compose instalados — Docker Engine mais o plugin Compose v2 do repositório apt oficial da Docker, conforme explicado em nosso guia básico de Docker Compose.

Passo 1: Adicione swap antes de qualquer outra coisa

A falha mais comum do Immich em um VPS pequeno é o container de ML sofrer OOM-kill. Forneça espaço para o kernel antes de tudo.

sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -h

free -h deve mostrar agora uma linha Swap: de 4.0Gi. Isso não tornará o ML rápido, mas evita que o container morra durante o indexamento em uma máquina de 4 GB.

Passo 2: Obtenha o compose e o env oficiais — use os originais, não cópias

O Immich fixa as versões dos serviços e, crucialmente, a imagem do banco de dados nos arquivos fornecidos. Não utilize um arquivo compose copiado de blogs (incluindo este) como sua fonte de verdade. Baixe os assets da release:

sudo mkdir -p /opt/immich && cd /opt/immich
sudo wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
sudo wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env

Estes arquivos vêm da release tagueada, garantindo que as referências de imagem coincidam. O arquivo compose define quatro serviços; é importante saber a função de cada um antes de iniciar a configuração:

  • immich-server (ghcr.io/immich-app/immich-server, container immich_server) — a API e a interface web, operando na porta 2283. Realiza o mount dos seus uploads em /data.
  • immich-machine-learning (ghcr.io/immich-app/immich-machine-learning, container immich_machine_learning) — busca CLIP e reconhecimento facial. Armazena modelos baixados em um volume model-cache. Este serviço consome muita memória.
  • database (container immich_postgres) — Postgres com a extensão vetorial VectorChord, responsável pela busca por similaridade. A tag da imagem é fixada por digest diretamente no compose, como em ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:.... Configurações antigas utilizavam pgvecto.rs; o suporte foi removido no Immich v3.0, portanto, qualquer instalação atual utiliza VectorChord. Nunca edite esta tag manualmente.
  • redis (container immich_redis) — uma instância Valkey/Redis para filas de tarefas (job queues).

Passo 3: Configurar .env — onde suas fotos e o banco de dados residem

Abra o .env e configure quatro itens. Tudo abaixo da linha marcada deve permanecer como está.

# Where original uploads are stored on the host
UPLOAD_LOCATION=/opt/immich/library

# Where the Postgres data lives. NEVER put this on an NFS/network share.
DB_DATA_LOCATION=/opt/immich/postgres

# "v3" is a floating tag that tracks the latest v3.x. Pin a full tag like
# v3.0.2 instead — then you upgrade on purpose, not by surprise.
IMMICH_VERSION=v3.0.2

# Change this to a long random string. Letters and digits only.
DB_PASSWORD=REPLACE_WITH_A_LONG_RANDOM_STRING

# Set your timezone so timestamps and "on this day" line up
TZ=Europe/London

###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich

Duas regras para evitar problemas. O UPLOAD_LOCATION deve apontar para seu disco grande — se você anexar um volume de dados posteriormente, defina este caminho de montagem desde o início, pois mudar o caminho depois exigirá a movimentação de thumbnails e a atualização de caminhos de assets. O DB_DATA_LOCATION deve estar em um disco local: o Postgres corrompe em compartilhamentos NFS ou SMB, conforme indicado na documentação. Se você usar apenas letras e dígitos no DB_PASSWORD, evitará erros de escape em connection-strings.

Passo 4: Primeira execução e criação do usuário admin

cd /opt/immich
sudo docker compose up -d
sudo docker compose ps

O resultado correto são quatro containers, todos running e eventualmente healthy:

NAME                      STATUS
immich_machine_learning   Up (healthy)
immich_postgres           Up (healthy)
immich_redis              Up (healthy)
immich_server             Up (healthy)

O primeiro up baixa vários gigabytes de imagens; aguarde a conclusão. Acompanhe o progresso com sudo docker compose logs -f immich-server; o servidor registra que está escutando na porta 2283 quando estiver pronto. Agora abra http://YOUR_SERVER_IP:2283 no navegador. A primeira visita exibe um assistente de Getting Started — a primeira conta criada será a admin. Defina uma senha forte; esta conta possui as configurações do servidor, gerenciamento de usuários e a configuração de ML necessária posteriormente.

Passo 5: O aplicativo móvel e o backup em segundo plano

Instale o "Immich" pela App Store ou Play Store. Na tela de login, será solicitado o Server Endpoint URL. Insira a URL completa incluindo o scheme, por exemplo https://photos.example.com (o aplicativo adiciona /api automaticamente). Faça login com a conta que você acabou de criar, abra a tela de Backup do aplicativo, selecione os álbuns para proteger (geralmente Camera e Screenshots) e ative o Background backup. O backup em segundo plano no iOS é limitado pelo sistema operacional — uploads em primeiro plano sempre funcionam, enquanto os de segundo plano ocorrem quando o OS permite.

É exatamente aqui que as pessoas encontram problemas, portanto leia o Passo 6 antes de tentar configurar o aplicativo.

Passo 6: HTTPS via reverse proxy — e a regra de URL completa

O aplicativo móvel exige HTTPS. Coloque um reverse proxy à frente da porta 2283 e realize o término do TLS nele. Se você já utiliza vários containers, o Traefik com TLS automático para múltiplos apps Docker é a opção mais organizada — um bloco de labels roteia photos.example.com para o container immich-server e obtém o certificado para você. Se preferir o nginx, o guia Let's Encrypt com Certbot e nginx fornece um certificado e um bloco proxy_pass http://127.0.0.1:2283;. Uma configuração de proxy é essencial para o Immich: aumente o limite de tamanho de upload, pois vídeos de celular são grandes. No nginx, isso é o client_max_body_size 50000M; dentro do server block — o padrão de 1 MB rejeita uploads de vídeo com 413 Request Entity Too Large.

A regra aplicada pelo app: o endpoint deve estar acessível e, na prática, deve ser HTTPS. Endpoints http://, ou um IP direto sem a porta, causam o erro "o aplicativo não consegue alcançar o servidor" — detalhado abaixo como uma falha específica.

Passo 7: Bibliotecas externas vs uploads — importando uma árvore de fotos existente

Existem duas formas de adicionar fotos ao Immich, e elas não são a mesma coisa.

  • Uploads são arquivos que o Immich gerencia. O uploader (app ou web) copia o arquivo para UPLOAD_LOCATION. O Immich pode renomear, mover e deletar esses arquivos.
  • Bibliotecas externas são importações de apenas leitura de arquivos que já estão em uma pasta no seu servidor — uma árvore Pictures antiga ou um export de um NAS. O Immich indexa os arquivos no local original e os exibe na timeline, mas nunca modifica ou deleta os originais.

Para importar uma árvore existente, monte-a como read-only no container do servidor. Edite o docker-compose.yml em immich-server: e adicione um volume:

  immich-server:
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
      - /srv/photos:/mnt/media/photos:ro

O :ro garante que o Immich nunca altere os originais. Recrie o container com sudo docker compose up -d e, na interface web, vá em seu avatar → Administration → External Libraries → Create Library, selecione o usuário proprietário, clique em Add em Folders e insira o caminho do container/mnt/media/photos, e não o caminho do host /srv/photos. Clique em Scan. Usar o caminho do host em vez do caminho do container é o erro mais comum em bibliotecas externas; o scan não encontrará nada e reportará zero assets.

Passo 8: A disciplina de upgrade que o Immich exige

Esta etapa diferencia uma instância estável do Immich de uma corrompida. O Immich lança atualizações rapidamente e não faz backport de correções nem suporta downgrades. Seguir cegamente a tag floating v3 acabará quebrando seu banco de dados. A disciplina consiste em:

  1. Fixar uma versão. Mantenha o IMMICH_VERSION configurado para uma tag específica como v3.0.2, e não para a floating v3 que sempre puxa a versão v3.x mais recente.
  2. Ler as notas de lançamento sempre antes de atualizar. Mudanças que quebram o sistema — especialmente em bancos de dados ou extensões de vetor — são listadas lá. O lançamento da v3.0 é um exemplo claro: ele removeu o pgvecto.rs completamente, então quem ainda usava a extensão antiga precisava concluir a migração para o VectorChord (introduzida na v1.133) antes de atualizar.
  3. Fazer backup do banco de dados primeiro (Passo 9). Sempre, mas com atenção redobrada quando as notas mencionarem o banco de dados.
  4. Baixar o novo arquivo compose também. O IMMICH_VERSION fixa apenas as imagens do server e do ML. A imagem do Postgres é fixada por digest dentro do docker-compose.yml, portanto, uma versão que exija uma extensão de banco de dados mais nova virá com um novo arquivo compose. Baixe ambos os arquivos de release, reaplique seus valores de .env e então atualize.
  5. Atualizar os clientes mobile no mesmo período. O servidor só aceita sua própria versão major correspondente, e o app suporta a versão major atual e a anterior. Um servidor com versão superior ao app exibirá Your app major version is not compatible with the server! no celular até que o app seja atualizado; por isso, o mais seguro é atualizar o app primeiro.

Os comandos reais, após posicionar os novos arquivos:

cd /opt/immich
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune

Passo 9: Backups — um dump do banco de dados MAIS os originais, e teste-o

O backup do Immich consiste em duas partes, e uma sem a outra é inútil. O database contém a estrutura dos álbuns, rostos, índices de busca e o mapeamento do asset para o arquivo. O originals directory contém as fotos reais. Restaurar um sem o outro resulta em fotos sem organização ou em uma estrutura vazia apontando para arquivos inexistentes.

Faça o dump do banco de dados com pg_dump de dentro do container Postgres — especificamente o banco de dados immich, não o cluster inteiro:

sudo docker exec -t immich_postgres pg_dump --clean --if-exists \
  --dbname=immich --username=postgres | gzip > /opt/immich/immich-db-$(date +%F).sql.gz

Em seguida, faça o backup de UPLOAD_LOCATION — a árvore /opt/immich/library completa, especialmente as subpastas library/, upload/ e profile/ — usando restic, rsync ou borg para outra máquina ou object storage. Faça o banco de dados primeiro e os arquivos depois, para que o dump nunca referencie uma foto que o backup de arquivos ainda não copiou. Bibliotecas externas devem ser backupeadas separadamente em suas fontes originais; o Immich não é o dono delas.

Agora a parte que todos pulam: teste a restauração. Uma restauração deve ser executada em um stack novo cujo servidor nunca foi iniciado, em uma imagem Postgres cuja extensão vector seja compatível com o dump — é exatamente por isso que você nunca deve improvisar a tag da imagem do DB. Em uma máquina limpa com o mesmo compose e .env, apague qualquer estado antigo, suba apenas o banco de dados e, então, carregue o dump:

cd /opt/immich
sudo docker compose down -v
sudo docker compose pull
sudo docker compose create
sudo docker start immich_postgres
sleep 10
gunzip --stdout immich-db-2026-07-15.sql.gz |
  sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" |
  sudo docker exec -i immich_postgres psql --dbname=immich --username=postgres --single-transaction --set ON_ERROR_STOP=on
sudo docker compose up -d

A reescrita sed de search_path não é opcional em um banco de dados VectorChord — se omitir, a restauração será abortada no meio do processo. Quando o stack subir com seus arquivos originais no lugar, abra a interface web: se suas fotos e álbuns estiverem lá, seu backup funciona. Se você nunca executou isso, você não tem um backup — você tem uma esperança.

Modos de falha e as strings que você verá

O container de ML sofre OOM-kill. O sudo docker compose logs immich-machine-learning termina abruptamente, o docker compose ps mostra que ocorreu Restarting, e o exit code é 137. O sudo dmesg | grep -i oom confirma: Out of memory: Killed process ... (python3). Os jobs de busca e reconhecimento facial travam. A causa é falta de RAM para os modelos. Soluções, em ordem: adicione swap (Passo 1); aumente a RAM do VPS; ou, se não for possível, desative o ML em Administration → Settings → Machine Learning Settings desativando Smart Search e Facial Recognition — você mantém backups e álbuns, mas perde a busca por conteúdo. Remover o serviço immich-machine-learning do arquivo compose tem o mesmo efeito.

O Postgres recusa a inicialização após um upgrade. O log do servidor apresenta um loop com uma linha como The database currently has VectorChord 0.5.3 activated, but the Postgres instance only has 0.4.2 available. This most likely means the extension was downgraded. — ou, em stacks antigas, The pgvecto.rs extension is not available in this Postgres instance.. A causa é uma imagem de banco de dados com versão de extensão inferior à versão dos dados atualizados, geralmente devido à edição manual da tag da imagem ou restauração de um dump recente em uma imagem antiga. A solução é usar a imagem do Postgres compatível — utilize o arquivo compose da release correspondente ao seu banco de dados, não faça downgrade, e restaure apenas em uma imagem compatível.

O app mobile não consegue conectar ao servidor. A tela de login exibe um erro de conexão / Server is not reachable após inserir a URL. Três causas: você digitou http:// onde o proxy só atende https://; você conectou diretamente ao backend mas omitiu a porta, fazendo com que ele tentasse example.com (porta 443) em vez de example.com:2283; ou o reverse proxy não está encaminhando /api. Corrija inserindo a URL completa com https://photos.example.com e confirme se ela carrega primeiro em um navegador de celular. Se o navegador funcionar e o app não, o proxy está removendo o path ou o certificado é self-signed — o app rejeita certificados não confiáveis.

Falta de espaço em disco durante o import. Os uploads começam a falhar, as thumbnails ficam em branco e os logs mostram ENOSPC: no space left on device ou, no Postgres, could not extend file ... No space left on device. O df -h mostra o volume UPLOAD_LOCATION com 100% de uso. Por isso é necessário dimensionar o disco antes de importar uma biblioteca grande. Recupere anexando um volume maior, parando a stack, movendo UPLOAD_LOCATION para ele, atualizando .env e iniciando novamente — ou expanda o disco existente se o seu provedor permitir. O Postgres pode travar se o disco encher, portanto, libere espaço e reinicie o container do banco de dados antes de assumir corrupção de dados.

FAQ

Quanto de RAM e disco o Immich precisa?

Os requisitos oficiais do Immich são 6 GB de RAM no mínimo e 8 GB recomendados — 4 GB com swap é o limite prático para uma biblioteca pequena. Configure o swap de qualquer forma, pois o container de machine-learning causa picos de uso. Para o disco, reserve o tamanho total da sua biblioteca mais cerca de 10–20% para thumbnails e previews gerados em armazenamento local — nunca coloque o diretório de dados do Postgres em um compartilhamento de rede. Se você ainda estiver decidindo o que mais hospedar, o guia do que hospedar você mesmo em 2026 compara o consumo do Immich com outros serviços.

Posso rodar o Immich sem uma GPU?

Sim. O container de machine-learning funciona normalmente em CPU — uma GPU apenas acelera a indexação de smart-search e, com a imagem correta, a transcodificação de vídeo. Em CPU, a indexação inicial de uma biblioteca grande pode levar horas em segundo plano, mas isso não bloqueia backups ou navegação. Se o seu hardware for insuficiente para ML, você pode desativar o Smart Search e o Facial Recognition nas configurações de admin e manter o restante.

Como atualizar o Immich com segurança?

Fixe o IMMICH_VERSION em uma tag específica como v3.0.2, leia as release notes antes de cada atualização e faça backup do banco de dados primeiro. Como a imagem do Postgres é fixada dentro do docker-compose.yml em vez de usar IMMICH_VERSION, baixe novamente o arquivo compose e o example.env da versão desejada, reaplique seus valores e execute o docker compose pull && docker compose up -d. Nunca deixe a versão em modo float — o Immich possui breaking changes e não suporta downgrades.

O que exatamente eu devo fazer backup?

Duas coisas, juntas: um pg_dump do banco de dados immich e o diretório de originais UPLOAD_LOCATION completo. O banco de dados contém álbuns, rostos e o mapeamento de asset-para-arquivo; o diretório contém as fotos reais. Um restore exige ambos, além de uma imagem de banco de dados com uma extensão de vetor compatível. Faça o dump do banco de dados primeiro e a cópia dos arquivos depois. Teste o restore em uma máquina de teste pelo menos uma vez — um backup não testado não é um backup.

Como importar minha pasta de fotos existente?

Monte a pasta como read-only no container immich-server como um volume extra (por exemplo - /srv/photos:/mnt/media/photos:ro), recrie o container e, em Administration → External Libraries, crie uma biblioteca e adicione o caminho do container /mnt/media/photos. O Immich indexa os arquivos no local e nunca os modifica ou deleta. O erro mais comum é inserir o caminho do host em vez do caminho do container, o que faz com que o scan não encontre nada.