Seu próprio servidor de sincronização
O Polypodium funciona 100% offline — o servidor só é necessário se você quiser sincronizar sua coleção entre vários aparelhos. Este guia mostra como subir o servidor com Docker em poucos minutos, sem precisar compilar nada.
O que você vai precisar
- Uma máquina que fique ligada quando você quiser sincronizar: um VPS, um mini-PC, um NAS ou até um computador na sua rede local.
- Docker com o plugin Docker Compose (já incluído nas instalações atuais).
- Opcional, mas recomendado para acesso pela internet: um domínio (ou subdomínio) apontando para a máquina, para ativar HTTPS com Let's Encrypt.
Não é preciso clonar repositório nem instalar Dart: o servidor é distribuído como
imagem Docker pronta em ghcr.io/bruno1pb13/polypodium_server.
1 Criar os arquivos de configuração
Crie uma pasta (por exemplo polypodium-server) e, dentro dela, um arquivo
docker-compose.yml com o conteúdo abaixo. Ele sobe dois contêineres: o
banco PostgreSQL e o servidor do Polypodium.
services:
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: polypodium
POSTGRES_USER: polypodium
POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U polypodium -d polypodium"]
interval: 5s
timeout: 5s
retries: 10
server:
image: ghcr.io/bruno1pb13/polypodium_server:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
DATABASE_URL: postgresql://polypodium:${DB_PASSWORD}@db/polypodium
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
APP_ENV: production
DB_SSL: "false"
# O HTTPS fica a cargo do proxy reverso (passo 3).
BEHIND_PROXY: "true"
REGISTRATION_TOKEN: ${REGISTRATION_TOKEN:-}
PHOTOS_DIR: /photos
volumes:
- photos_data:/photos
depends_on:
db:
condition: service_healthy
volumes:
db_data:
photos_data:
Na mesma pasta, crie um arquivo .env com os segredos do seu servidor:
# Senha do banco de dados (usada só internamente, entre os contêineres)
DB_PASSWORD=troque-por-uma-senha-forte
# Chave que assina os tokens de login. Mínimo de 32 caracteres.
# Gere uma com: openssl rand -base64 48
JWT_SECRET=troque-por-uma-chave-aleatoria-bem-longa
# Opcional, recomendado se o servidor ficar exposto na internet:
# protege a criação da primeira conta (veja o passo 4).
REGISTRATION_TOKEN=
JWT_SECRET estiver ausente ou tiver menos de 32 caracteres. Guarde o
.env em local seguro — quem tem esses valores tem acesso ao servidor.
2 Subir o servidor
Ainda na pasta criada, execute:
docker compose up -d
Na primeira execução o Docker baixa as imagens e o servidor cria as tabelas do banco automaticamente. Para conferir que está tudo no ar:
curl http://localhost:8080/api/v1/health
Se a resposta chegar com status 200, o servidor está funcionando. Para acompanhar os
logs a qualquer momento: docker compose logs -f server.
http://192.168.0.10:8080), você já pode pular para o passo 4.
O HTTPS do passo 3 é essencial quando o servidor fica acessível pela internet.
3 HTTPS com proxy reverso (Let's Encrypt)
A configuração acima (BEHIND_PROXY: "true") espera que um proxy reverso
na frente do servidor cuide do HTTPS. A forma mais simples é usar o
Caddy, que obtém e renova
certificados Let's Encrypt sozinho. Com o domínio já apontando para a máquina,
instale o Caddy e use um Caddyfile de duas linhas:
plantas.seudominio.com {
reverse_proxy 127.0.0.1:8080
}
Pronto: o app passa a acessar https://plantas.seudominio.com. Alternativas
que funcionam igualmente bem, com o mesmo BEHIND_PROXY=true:
- Nginx Proxy Manager — interface gráfica para gerenciar proxies e certificados Let's Encrypt;
- Nginx ou Traefik, se você já usa um deles no seu servidor;
- Um túnel como o Cloudflare Tunnel, que também termina o TLS por você.
Nesse arranjo, deixe a porta 8080 fechada para a internet no firewall — só o proxy (portas 80/443) precisa ficar exposto.
Alternativa: o próprio servidor termina o HTTPS
Se preferir não usar proxy, o servidor pode servir HTTPS diretamente. No
docker-compose.yml, troque BEHIND_PROXY: "true" por:
BEHIND_PROXY: "false"
SSL_CERT_PATH: /certs/fullchain.pem
SSL_KEY_PATH: /certs/privkey.pem
e monte a pasta dos certificados no contêiner (em volumes: do serviço
server):
- /caminho/para/seus/certs:/certs:ro
Nesse caso a renovação dos certificados (ex.: via certbot) fica por sua
conta. Em produção o servidor exige uma das duas opções — proxy reverso ou
certificados — e se recusa a iniciar servindo HTTP puro na internet.
4 Criar a primeira conta (administrador)
A primeira conta criada em um servidor novo vira automaticamente a conta de administrador. Depois dela, o cadastro público se fecha: novas contas só podem ser criadas pelo administrador, dentro do app.
Sem REGISTRATION_TOKEN (rede local)
- No app, abra Configurações → Servidor (workspaces) e adicione um workspace remoto com a URL do seu servidor.
- O app detecta que o servidor ainda não tem contas e oferece a criação da primeira — informe e-mail e senha (mínimo de 8 caracteres) e pronto: você é o admin.
Com REGISTRATION_TOKEN (recomendado na internet)
Se você definiu REGISTRATION_TOKEN no .env, a primeira conta
precisa apresentar esse token — assim ninguém "rouba" o posto de admin chegando
primeiro no seu servidor recém-instalado. Crie a conta com uma chamada direta à API:
curl -X POST https://plantas.seudominio.com/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "voce@exemplo.com",
"password": "sua-senha-com-8+-caracteres",
"registrationToken": "o-valor-do-seu-REGISTRATION_TOKEN"
}'
Depois disso, basta fazer login normalmente pelo app com o e-mail e a senha criados. As próximas contas (família, amigos) você cria pela tela de administração do servidor, dentro do próprio app.
5 Backups
Seus dados vivem em dois lugares: o banco PostgreSQL (plantas, espécies, diário…) e o volume de fotos. Faça backup dos dois periodicamente.
Banco de dados (pg_dump)
docker compose exec db pg_dump -U polypodium -d polypodium \
> backup-polypodium-$(date +%F).sql
Para restaurar em um servidor recém-criado (com o banco ainda vazio):
docker compose exec -T db psql -U polypodium -d polypodium \
< backup-polypodium-2026-07-10.sql
Fotos
docker compose cp server:/photos ./backup-fotos-$(date +%F)
Automatize com um cron semanal e guarde as cópias em outra máquina ou em
um serviço de armazenamento — um backup que mora no mesmo disco do servidor não
protege contra a falha desse disco.
Atualizando o servidor
Para atualizar para a versão mais recente da imagem:
docker compose pull
docker compose up -d
As migrações do banco rodam automaticamente na inicialização — não há passo manual.
Referência: variáveis de ambiente
| Variável | Para que serve |
|---|---|
DB_PASSWORD | Senha do PostgreSQL (obrigatória). |
JWT_SECRET | Assina os tokens de login. Obrigatória, mínimo de 32 caracteres, única por servidor. |
REGISTRATION_TOKEN | Opcional. Quando definida, a criação da primeira conta exige esse token (passo 4). |
BEHIND_PROXY | true quando o HTTPS termina em um proxy reverso; senão, informe SSL_CERT_PATH/SSL_KEY_PATH. |
SSL_CERT_PATH / SSL_KEY_PATH | Certificado e chave para o servidor servir HTTPS diretamente. |
ALLOWED_ORIGINS | CORS: * ou lista de origens separadas por vírgula. Padrão: *. |
AUTH_RATE_LIMIT_MAX / AUTH_RATE_LIMIT_WINDOW | Limite contra força bruta no login. Padrão: 20 requisições / 300 s por IP. |
MAX_JSON_BODY_BYTES / MAX_PHOTO_BYTES | Tamanho máximo de requisições e fotos. Padrão: 1 MB / 15 MB. |
Dúvidas ou problemas? Abra uma issue no repositório do servidor ou escreva para bruno1pb13@gmail.com.