Hospede o Immich para sua biblioteca de fotos
Siga isso no seu próprio servidor. Comece grátis, sem cartão
O Google Fotos faz backup da sua biblioteca de graça até deixar de ser de graça, e no momento em que para de ser gratuito, também já indexou cada rosto e cada local onde suas fotos foram tiradas numa infraestrutura que você não controla. O Immich é uma alternativa open-source que faz o mesmo trabalho (backup automático do seu celular, uma linha do tempo, reconhecimento facial, busca por objeto ou lugar) como um app self-hosted: uma imagem principal, um worker de machine learning para os recursos de IA, Redis para jobs em segundo plano e Postgres com uma extensão vetorial para busca. Este guia monta tudo isso a partir de um servidor vazio, e depois mostra o caminho de um clique se você preferir não rodar os containers você mesmo.
No final, você vai ter o Immich acessível no seu próprio domínio via HTTPS, seu celular fazendo backup para ele automaticamente, e um plano de backup para as duas coisas que de fato importam: suas fotos e o banco de dados que as indexa.
O que você vai precisar
- Um servidor com memória de sobra de verdade. O worker de machine learning do Immich (detecção de rosto, busca por objeto) precisa de CPU e RAM de verdade além do app web e do banco de dados, então um Hetzner CX33 (4 vCPUs, 8 GB de RAM, 80 GB NVMe) por €8,99/mês sem VAT é um ponto de partida mais seguro do que o menor nível; um servidor de tamanho parecido de qualquer outro provedor funciona da mesma forma.
- Um domínio ou subdomínio com um registro A de DNS que você possa apontar para o servidor (este guia usa
photos.example.com). - O app mobile do Immich (iOS ou Android) depois que o servidor estiver no ar.
- Acesso SSH e cerca de 20 minutos.
Etapa 1: Provisione o servidor e aponte o DNS para ele
Crie o servidor no Ubuntu 24.04 (ou qualquer distribuição recente baseada em Debian), anote o IPv4 público dele e crie um registro A de DNS:
photos.example.com. A 203.0.113.20
Conecte via SSH e atualize o sistema:
ssh root@203.0.113.20
apt update && apt upgrade -y
Etapa 2: Instale o Docker
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
docker --version
docker compose version
Você deve ver uma versão do Docker engine e uma versão v2.x do Compose, sem erros.
Etapa 3: Escreva o arquivo de ambiente
A própria documentação de instalação do Immich aponta para um par docker-compose.yml e .env mantido no repositório dele no GitHub; este guia usa a versão atual, Immich v3.3.5. Crie um diretório de trabalho e o arquivo .env:
mkdir -p /opt/immich && cd /opt/immich
UPLOAD_LOCATION=./library
DB_DATA_LOCATION=./postgres
DB_PASSWORD=change-this-to-a-random-alnum-string
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.3.5
TZ=America/Montreal
DB_PASSWORD tem uma restrição real que vale saber antes de gerar uma: a própria documentação do Immich pede só letras e números, sem pontuação, já que a senha é interpolada direto numa string de conexão. UPLOAD_LOCATION é onde cada foto e vídeo de fato vive no disco, então trate esse caminho como o único diretório neste servidor que você nunca pode se dar ao luxo de perder.
Etapa 4: Escreva o arquivo Docker Compose
Isso espelha o arquivo compose oficial do Immich, com o Caddy adicionado na frente para o HTTPS:
services:
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy-data:/data
- caddy-config:/config
immich-server:
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-v3.3.5}
restart: always
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
depends_on:
- redis
- database
immich-machine-learning:
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-v3.3.5}
restart: always
volumes:
- model-cache:/cache
env_file:
- .env
environment:
MACHINE_LEARNING_MODEL_REVISION: v2
redis:
image: docker.io/valkey/valkey:9
restart: always
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep -q PONG || exit 1"]
database:
image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
restart: always
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_DB: ${DB_DATABASE_NAME}
POSTGRES_INITDB_ARGS: "--data-checksums"
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
shm_size: 128mb
volumes:
model-cache:
caddy-data:
caddy-config:
A imagem do banco de dados não é o Postgres comum: é a própria build do Immich com as extensões vectorchord e pgvecto.rs já embutidas, que é o que torna a busca por rosto e objeto rápida em escala. Não troque por uma imagem postgres genérica mesmo que as variáveis de ambiente pareçam idênticas.
Valide antes de subir:
docker compose config
Etapa 5: Escreva o Caddyfile
photos.example.com {
reverse_proxy immich-server:2283
request_body {
max_size 10GB
}
}
O bloco request_body importa especificamente aqui: o limite padrão de tamanho de requisição do Caddy é confortável para uma página web, mas não para um vídeo 4K de um celular, então sem aumentar isso, uploads de vídeos grandes falham no meio do caminho com um reset de conexão confuso em vez de um erro claro.
Etapa 6: Suba a stack
docker compose up -d
docker compose ps
Você deve ver caddy, immich-server, immich-machine-learning, redis e database todos listados como running. Acompanhe os logs do servidor na primeira vez para confirmar que ele terminou suas próprias migrações de inicialização:
docker compose logs -f immich-server
Acesse https://photos.example.com; você deve cair na tela de criação de conta do Immich com um certificado HTTPS válido. Crie a primeira conta, que se torna a administradora do servidor.
Etapa 7: Conecte o app mobile
Instale o Immich na App Store ou Play Store, abra, e digite a URL do seu servidor (https://photos.example.com) na tela de login, depois entre com a conta da Etapa 6. Ative o backup em segundo plano nas configurações do app. Você deve ver o rolo da sua câmera começar a enviar fotos, visível como um indicador de progresso no app e como fotos novas aparecendo no painel web dentro de um ou dois minutos.
Etapa 8: Faça backup do que de fato importa
Duas coisas não podem ser regeneradas: o banco Postgres (o índice: álbuns, rostos, metadados) e a pasta library (os arquivos de foto e vídeo em si). Faça backup dos dois, numa agenda, para algum lugar fora deste servidor:
docker compose exec -T database pg_dumpall -U postgres | gzip > /opt/immich/backups/immich-db-$(date +%F).sql.gz
tar -czf /opt/immich/backups/immich-library-$(date +%F).tar.gz -C /opt/immich library
Copie os dois arquivos para fora do servidor (object storage, outra máquina) num cron job. Restaurar o banco de dados a partir só de um dump já é suficiente para o app voltar a rodar; restaurar a pasta library junto com ele é o que faz o app restaurado de fato mostrar suas fotos de novo.
Etapa 9: Upgrades
Mude IMMICH_VERSION no .env para a nova tag, depois:
docker compose pull
docker compose up -d
O Immich lança releases com frequência, e o app mobile e o servidor são versionados juntos: se o app mostrar um aviso de incompatibilidade de versão depois de um upgrade, atualize o app na loja antes de qualquer outra coisa, em vez de investigar o servidor.
O caminho curto: faça com o Railyard
Tudo isso acima, os quatro containers, o arquivo de ambiente, o proxy reverso, a agenda de backup, é o que o template de stack do Immich no Railyard configura para você. Conecte um servidor e escolha Immich no catálogo de templates: https://app.railyard.run/deploy?stack=immich. O Railyard provisiona os quatro serviços juntos, liga automaticamente as strings de conexão do banco de dados e do Redis, e emite o certificado HTTPS para o seu domínio.
Um limite honesto que vale saber: o worker de machine learning consome bastante CPU e memória da mesma forma que na configuração manual, então dimensione o servidor pensando nisso em vez de escolher a menor opção disponível, exatamente como na Etapa 1. E uma peculiaridade que você vai ver nos logs de qualquer jeito: o próprio log de inicialização do Immich sempre imprime 127.0.0.1 para um servidor vinculado a 0.0.0.0, que é uma substituição de exibição do próprio framework, não um sinal de que algo está mal configurado.
Depois de estar no ar, database backups cobre o lado do Postgres numa agenda; o volume library ainda merece sua própria cópia fora do servidor, da mesma forma que na configuração manual acima.
Solução de problemas
O HTTPS nunca é emitido. O DNS ainda não está apontando para o servidor. dig +short photos.example.com deve retornar o IP do servidor; o Caddy tenta de novo por conta própria depois disso.
Uploads falham no meio do caminho, especialmente vídeos. Isso quase sempre é o limite de tamanho de requisição do Caddy, abordado na Etapa 5. Confirme que o bloco request_body está mesmo no Caddyfile ativo com docker compose exec caddy caddy fmt --overwrite /etc/caddy/Caddyfile seguido de um restart.
O container de machine learning fica lento ou é encerrado. Confira docker stats enquanto um backup estiver rodando. Se immich-machine-learning ficar travado em 100% de CPU ou o container sair, o servidor está subdimensionado para tarefas em segundo plano como reconhecimento facial numa biblioteca grande; um CX33 aguenta o uso normal, mas a primeira varredura completa de uma biblioteca já grande se beneficia de mais recursos.
O app mobile mostra incompatibilidade de versão. O Immich fixa a compatibilidade entre o app e o servidor de forma bem rígida. Atualize o que estiver atrasado, geralmente o app, na loja dele.
A página de login carrega, mas a conta de admin não se cria. Confira docker compose logs database em busca de uma migração que falhou, geralmente causada por DB_PASSWORD com um caractere fora de A-Za-z0-9 que quebrou a string de conexão que a Etapa 3 avisa sobre.
Perguntas frequentes
Quanto espaço eu realmente preciso? O tamanho que sua biblioteca de fotos e vídeos tem hoje, mais margem para crescer; o Immich não comprime nem reencoda os originais por padrão, então o volume library cresce em ritmo parecido com o do rolo da sua câmera.
Mais de uma pessoa pode usar a mesma instância? Sim. Crie contas adicionais no painel de admin; cada uma tem sua própria biblioteca e configurações de compartilhamento, com cotas de armazenamento por usuário controladas pelo admin, se você quiser usá-las.
O worker de machine learning precisa de GPU? Não, ele roda em CPU por padrão e é isso que este guia configura; a própria documentação do Immich cobre aceleração de hardware opcional (NVIDIA, Intel, AMD) para bibliotecas maiores, que troca mais complexidade de configuração por indexação mais rápida.
O que acontece se eu perder o servidor sem backup? Tudo se perde: as fotos e o índice, os dois. A Etapa 8 não é opcional para nada que você de fato sentiria falta.
Isso é mesmo de graça para rodar? O software é; o servidor não é; um CX33 por cerca de nove euros por mês é o custo real contínuo, sem taxa por foto ou por gigabyte em cima, do jeito que alguns planos de armazenamento em nuvem funcionam.
O Immich te dá a maior parte do que um serviço de fotos hospedado oferece, numa infraestrutura que você controla, pelo custo de um servidor pequeno em vez de uma assinatura que escala com quantas fotos você tira. A configuração aqui é um arquivo de ambiente, um arquivo compose e um proxy reverso; a partir daí, é o mesmo app no seu celular, fazendo backup do mesmo jeito, para um servidor com o seu nome na conta em vez do nome de outra pessoa.
Por que escolhem o Railyard para isso
- Sua própria conta de cloud. Faça deploy no DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou em qualquer servidor Linux via SSH, cobrado direto pelo seu provedor, sem markup.
- Um preço fixo por equipe. O Free é grátis para sempre: um servidor mais um servidor de banco de dados, três apps, sem cartão. O Pro custa US$19 por mês para até cinco servidores e apps ilimitados. O Team custa US$49 por mês com servidores ilimitados. Sem cobrança por app, por deploy, por assento ou por gigabyte.
- Templates de um clique. Faça deploy de apps open source, como bancos de dados, analytics e ferramentas de dev, no seu próprio servidor em um clique.
- Bancos de dados gerenciados. Postgres, MySQL e Redis com backups programados, verificados por restauração, e recuperação point-in-time.
- Push-to-deploy. Faça deploy a partir do GitHub, GitLab ou da CLI, com HTTPS automático e releases sem downtime.