Tutoriais de VPS
Montar Nextcloud em VPS (2026): Docker, PostgreSQL, Redis, HTTPS com Caddy e sincronização móvel
Monte uma nuvem privada Nextcloud em VPS do zero: execute Nextcloud, PostgreSQL, Redis e Cron com Docker Compose, configure HTTPS com Caddy e trate por completo do upload de arquivos grandes, sincronização móvel, WebDAV, backup e restauração, atualizações e reforço de segurança.

Se você quer guardar fotos, documentos e arquivos da equipe em um servidor que controla, e também precisa de acesso web, links de compartilhamento, histórico de versões e upload automático pelo celular, o Nextcloud é uma solução de nuvem privada em VPS com alto volume de buscas e demanda real de uso. Ele é mais completo que uma simples listagem de arquivos WebDAV, mas também depende mais que o Syncthing ou o OpenList do banco de dados, do cache, das tarefas agendadas e de uma configuração correta de proxy reverso.
Este artigo usa Ubuntu 24.04 LTS, Nextcloud 33, PostgreSQL, Redis, Docker Compose e Caddy como exemplo para implantar do zero uma nuvem privada de servidor único que possa ser mantida a longo prazo. A aplicação escuta apenas na porta local do VPS, o banco de dados e o Redis não ficam expostos à internet, e o guia inclui upload de arquivos grandes, Cron, sincronização para desktop e celular, backup e restauração, atualizações e tratamento de alertas comuns.
As três ferramentas permitem acessar arquivos, mas resolvem problemas diferentes:
| Ferramenta | Necessidades em que se encaixa melhor | Principais contrapartidas |
|---|---|---|
| Nextcloud | Nuvem centralizada, usuários, compartilhamento, versões, calendário e colaboração | Completo, com maior custo de recursos e manutenção |
| Syncthing | Sincronização de pastas ponto a ponto entre vários dispositivos | Sincronização eficiente, mas não é um portal de nuvem completo |
| OpenList | Agregar nuvens, WebDAV e um ponto de entrada unificado para arquivos | Leve e prático, não deve ser a única cópia dos dados |
Se você só quer sincronizar arquivos entre o computador e um NAS, pode começar pelo tutorial de Syncthing em VPS. Se o foco é montar várias nuvens de terceiros, o tutorial de OpenList em VPS é mais adequado. O Nextcloud é mais indicado para pessoas ou pequenas equipes que precisam de contas, permissões, compartilhamento, histórico de versões e backup de fotos pelo celular.
A pressão de CPU do Nextcloud geralmente vem das miniaturas, da busca de texto completo, das atualizações de aplicativos e da concorrência de vários usuários, enquanto a pressão de disco vem de muitos arquivos pequenos, do histórico de versões e da lixeira.
| Escala de uso | Configuração recomendada | Observações |
|---|---|---|
| 1-3 pessoas, poucos documentos e fotos | 2 núcleos, 4 GB, 100 GB SSD | Executa sincronização e compartilhamento básicos |
| 3-10 pessoas, backup de fotos do celular | 4 núcleos, 8 GB, 250 GB SSD ou mais | Deixa margem para geração de prévias, banco de dados e Redis |
| Grandes volumes de fotos e vídeos ou colaboração em equipe | 4-8 núcleos, 8-16 GB, disco de dados separado | Exige monitorar capacidade, IOPS e janelas de backup |
O disco do sistema e o disco de dados podem ser separados, mas não coloque o diretório de dados do Nextcloud diretamente em uma montagem de rede instável. O armazenamento de objetos também não é mais rápido por padrão: ele serve para cenários que claramente precisam ampliar capacidade e desacoplar o ciclo de vida do host, enquanto um site pequeno de servidor único deve priorizar SSD/NVMe locais confiáveis e depois fazer backups externos. Consulte Quando um VPS precisa de armazenamento de objetos para avaliar se vale a pena adicionar complexidade.
Prepare um domínio, por exemplo cloud.example.com, e aponte os registros A / AAAA para o VPS. Abra para a internet apenas SSH, 80 e 443; não abra PostgreSQL 5432, Redis 6379 nem a porta local 8080 do Nextcloud.
Instale o Docker Engine e o Compose v2 a partir do repositório oficial do Docker e depois confirme as versões:
docker --version
docker compose version
Crie os diretórios de implantação, configuração e backup:
sudo mkdir -p /opt/nextcloud/backups
sudo chown -R "$USER":"$USER" /opt/nextcloud
cd /opt/nextcloud
Gere as senhas do PostgreSQL, do Redis e do administrador do Nextcloud:
openssl rand -hex 32
openssl rand -hex 32
openssl rand -base64 32
nano .env
chmod 600 .env
Escreva /opt/nextcloud/.env:
POSTGRES_DB=nextcloud
POSTGRES_USER=nextcloud
POSTGRES_PASSWORD=替换为第一组随机值
REDIS_HOST_PASSWORD=替换为第二组随机值
NEXTCLOUD_ADMIN_USER=ncadmin
NEXTCLOUD_ADMIN_PASSWORD=替换为第三组随机值
NEXTCLOUD_HOST=cloud.example.com
NEXTCLOUD_URL=https://cloud.example.com
PHP_MEMORY_LIMIT=1024M
PHP_UPLOAD_LIMIT=10G
Não use admin como conta de administrador e não reutilize a senha do VPS, do e-mail ou do banco de dados. Após a primeira inicialização, você ainda precisa manter .env, mas deve restringir as permissões de leitura e incluí-lo em backups criptografados.
Crie /opt/nextcloud/compose.yaml:
services:
db:
image: postgres:17-alpine
container_name: nextcloud-db
restart: unless-stopped
env_file:
- .env
environment:
POSTGRES_DB: "${POSTGRES_DB:?set POSTGRES_DB in .env}"
POSTGRES_USER: "${POSTGRES_USER:?set POSTGRES_USER in .env}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}"
volumes:
- nextcloud_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 20
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
redis:
image: redis:8-alpine
container_name: nextcloud-redis
restart: unless-stopped
env_file:
- .env
command:
- sh
- -c
- exec redis-server --appendonly yes --requirepass "$$REDIS_HOST_PASSWORD"
volumes:
- nextcloud_redis:/data
healthcheck:
test: ["CMD-SHELL", "redis-cli -a $$REDIS_HOST_PASSWORD ping | grep -q PONG"]
interval: 10s
timeout: 5s
retries: 20
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
app:
image: nextcloud:33-apache
container_name: nextcloud
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
ports:
- "127.0.0.1:8080:80"
env_file:
- .env
environment:
POSTGRES_HOST: db
POSTGRES_DB: "${POSTGRES_DB:?set POSTGRES_DB in .env}"
POSTGRES_USER: "${POSTGRES_USER:?set POSTGRES_USER in .env}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}"
REDIS_HOST: redis
REDIS_HOST_PASSWORD: "${REDIS_HOST_PASSWORD:?set REDIS_HOST_PASSWORD in .env}"
NEXTCLOUD_ADMIN_USER: "${NEXTCLOUD_ADMIN_USER:?set NEXTCLOUD_ADMIN_USER in .env}"
NEXTCLOUD_ADMIN_PASSWORD: "${NEXTCLOUD_ADMIN_PASSWORD:?set NEXTCLOUD_ADMIN_PASSWORD in .env}"
NEXTCLOUD_TRUSTED_DOMAINS: "${NEXTCLOUD_HOST:?set NEXTCLOUD_HOST in .env}"
TRUSTED_PROXIES: "172.16.0.0/12"
OVERWRITEHOST: "${NEXTCLOUD_HOST:?set NEXTCLOUD_HOST in .env}"
OVERWRITEPROTOCOL: https
OVERWRITECLIURL: "${NEXTCLOUD_URL:?set NEXTCLOUD_URL in .env}"
PHP_MEMORY_LIMIT: "${PHP_MEMORY_LIMIT:-1024M}"
PHP_UPLOAD_LIMIT: "${PHP_UPLOAD_LIMIT:-10G}"
APACHE_BODY_LIMIT: 0
volumes:
- nextcloud_data:/var/www/html
healthcheck:
test: ["CMD-SHELL", "php -r '$$c=@fsockopen(\"127.0.0.1\",80,$$e,$$s,5); exit($$c ? 0 : 1);'"]
interval: 30s
timeout: 10s
retries: 10
start_period: 120s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
cron:
image: nextcloud:33-apache
container_name: nextcloud-cron
restart: unless-stopped
entrypoint: /cron.sh
depends_on:
app:
condition: service_healthy
env_file:
- .env
volumes:
- nextcloud_data:/var/www/html
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
nextcloud_db:
name: nextcloud_db
nextcloud_redis:
name: nextcloud_redis
nextcloud_data:
name: nextcloud_data
O Nextcloud escuta apenas em 127.0.0.1:8080. PostgreSQL e Redis não têm mapeamento de portas e só podem ser acessados pela rede do Compose. TRUSTED_PROXIES deve confiar apenas no endereço de rede privada do Docker; não preencha 0.0.0.0/0. Se o pool de endereços do seu Docker for diferente, primeiro use docker network inspect para descobrir a sub-rede real e depois altere.
Verifique o resultado expandido do Compose antes de iniciar:
docker compose config >/dev/null
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=150 app db redis
A primeira inicialização pode levar alguns minutos. Quando o serviço estiver estável, verifique o ponto de entrada local:
curl -I http://127.0.0.1:8080/status.php
sudo ss -lntp | grep ':8080'
O endereço de escuta deve ser 127.0.0.1:8080, não 0.0.0.0:8080.
Edite /etc/caddy/Caddyfile:
cloud.example.com {
encode zstd gzip
request_body {
max_size 10GB
}
reverse_proxy 127.0.0.1:8080 {
transport http {
read_timeout 1h
write_timeout 1h
}
}
}
Valide e recarregue:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://cloud.example.com/status.php
O Caddy repassa X-Forwarded-For, X-Forwarded-Host e X-Forwarded-Proto. Os proxies confiáveis e os parâmetros de substituição no Compose permitem que o Nextcloud gere links HTTPS corretamente, evitando loops de login, endereços WebDAV errados e geração de URL HTTP pela linha de comando. Para problemas mais complexos de CDN, múltiplos domínios e certificados, consulte o guia completo de proxy reverso com Caddy em VPS.
O upload de arquivos grandes é afetado ao mesmo tempo pelo Caddy, pelo PHP, pelo Apache, pelos tempos limite do cliente e pelo disco disponível. Definir o limite em 10 GB não significa que 10 GB de memória serão usados de uma vez, mas o disco precisa ter espaço para os arquivos temporários de upload, o histórico de versões e a lixeira.
Abra https://cloud.example.com e faça login com a conta de administrador de .env. Como o Compose já passa as variáveis de banco de dados e de administrador, a instalação geralmente é concluída automaticamente na primeira inicialização.
Vá em “Configurações de administração → Visão geral” e verifique uma a uma as advertências de segurança e configuração. Depois execute uma verificação de status de dentro do contêiner:
docker compose exec -u www-data app php occ status
docker compose exec -u www-data app php occ config:system:get trusted_domains
docker compose exec -u www-data app php occ config:system:get trusted_proxies
docker compose exec -u www-data app php occ config:system:get overwriteprotocol
Não desative as verificações de segurança apenas para fazer as advertências desaparecerem. Advertências de domínio, proxy, cache, tarefas em segundo plano ou índices de banco de dados devem ser corrigidas conforme a causa real.
A varredura de arquivos, a limpeza de versões, as notificações e as tarefas de aplicativos do Nextcloud dependem de trabalhos em segundo plano. O modo AJAX padrão só é acionado quando um usuário visita uma página e não é adequado para produção.
O Compose já executa um contêiner cron separado, então defina o modo de tarefas em segundo plano como Cron:
docker compose exec -u www-data app php occ background:cron
docker compose logs --tail=100 cron
Mais tarde, confirme nas configurações de administração que o horário da “última execução de tarefa” continua sendo atualizado. O contêiner Cron e o App devem compartilhar o mesmo volume nextcloud_data; caso contrário, a configuração e os aplicativos instalados ficarão inconsistentes.
A imagem oficial configura o Redis com base em REDIS_HOST, mas após entrar em produção você ainda deve verificar:
docker compose exec -u www-data app php occ config:system:get redis
docker compose exec redis sh -c 'redis-cli -a "$REDIS_HOST_PASSWORD" ping'
O Redis é usado para cache distribuído e bloqueio transacional de arquivos, o que reduz a disputa por bloqueios de banco de dados durante a sincronização de vários usuários. O volume de dados do Redis não substitui os dados de arquivos do Nextcloud; mesmo que o Redis seja perdido, os arquivos principais e o banco de dados ainda devem ser recuperáveis, mas os bloqueios e caches em andamento serão reconstruídos.
Instale o cliente desktop oficial do Nextcloud ou o cliente iOS/Android e informe este endereço de servidor:
https://cloud.example.com
Para o upload automático pelo celular, recomenda-se primeiro criar um diretório dedicado, por exemplo Photos/Phone, e definir claramente se o envio ocorre apenas no Wi-Fi e durante o carregamento. Antes da primeira sincronização de muitas fotos, verifique o espaço livre do VPS, a cota de tráfego e a política de retenção de versões.
O endereço WebDAV geralmente é:
https://cloud.example.com/remote.php/dav/files/用户名/
Após ativar a autenticação de dois fatores, crie uma senha de aplicativo para clientes WebDAV que não suportam login web e não salve a senha principal em softwares antigos.
As versões de arquivos e a lixeira aumentam bastante o uso de disco. Não espere o disco encher para lidar com isso. Verifique o espaço atual e o status em segundo plano:
df -h
docker system df
docker compose exec -u www-data app php occ status
Em instâncias com muitas fotos, a geração de prévias consome CPU e disco. Ative apenas os tipos de prévia realmente necessários e gere-as antecipadamente em horários de baixa carga. Não instale scripts de miniaturas de origem desconhecida nem permita que vários programas modifiquem diretamente o diretório de dados do Nextcloud.
Se programas externos gravarem no diretório de dados, o banco de dados do Nextcloud não saberá automaticamente desses arquivos. Você deve usar um aplicativo de armazenamento externo compatível ou executar com cuidado:
docker compose exec -u www-data app php occ files:scan --all
Uma varredura completa pode demorar muito com muitos arquivos e não deve ser usada com frequência como método de sincronização.
Um backup completo inclui pelo menos o PostgreSQL e o volume nextcloud_data. O banco de dados guarda usuários, compartilhamentos, índice de arquivos e estado dos aplicativos; o volume de dados guarda config.php, aplicativos, temas e os arquivos reais.
Primeiro ative o modo de manutenção para evitar gravações contínuas durante o backup:
cd /opt/nextcloud
docker compose exec -u www-data app php occ maintenance:mode --on
Backup do PostgreSQL:
mkdir -p backups
docker compose exec -T db sh -c \
'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" --format=custom' \
> "backups/nextcloud-db-$(date +%F-%H%M).dump"
Backup do volume de dados:
docker run --rm \
-v nextcloud_data:/source:ro \
-v "$PWD/backups:/backup" \
alpine sh -c 'tar -C /source -czf /backup/nextcloud-data.tar.gz .'
Desative o modo de manutenção:
docker compose exec -u www-data app php occ maintenance:mode --off
Os backups não devem ficar apenas no mesmo VPS. Copie-os criptografados para armazenamento de objetos ou outro servidor e faça simulações de restauração regularmente. Você pode seguir diretamente o processo de verificação externa do tutorial de simulação de backup e restauração em VPS.
Ao restaurar, primeiro pare o App e o Cron, restaure o volume de dados e o banco de dados, depois inicie os serviços e execute:
docker compose exec -u www-data app php occ maintenance:repair
docker compose exec -u www-data app php occ db:add-missing-indices
docker compose exec -u www-data app php occ status
A aceitação da restauração deve verificar login, download de arquivos, links de compartilhamento, histórico de versões, upload pelo celular e WebDAV, não apenas a página inicial.
O Nextcloud só pode ser atualizado seguindo caminhos de versão principal suportados; não substitua a imagem diretamente pulando várias versões principais. Antes de atualizar, consulte as notas de versão oficiais, a compatibilidade dos aplicativos e o disco disponível, e conclua os backups do banco de dados e do volume de dados.
Atualização dentro da mesma versão principal:
cd /opt/nextcloud
docker compose config >/dev/null
docker compose pull
docker compose up -d
docker compose exec -u www-data app php occ upgrade
docker compose exec -u www-data app php occ status
docker compose logs --tail=200 app cron
Após a atualização, verifique a visão geral de administração, as tarefas em segundo plano, a sincronização dos clientes, os links de compartilhamento e as advertências de banco de dados. Se a nova versão falhar, pare as gravações e restaure a tag de imagem antiga, o banco de dados e o volume de dados. Apenas voltar a tag da imagem sem restaurar o banco de dados já atualizado geralmente não permite uma reversão confiável.
- Use uma senha longa para o administrador e ative a autenticação de dois fatores;
- Agrupe os usuários comuns com o mínimo de privilégios e não compartilhe a conta de administrador;
- Não exponha PostgreSQL, Redis nem 8080 à internet;
- Instale apenas aplicativos Nextcloud com manutenção ativa e que você realmente precise;
- Atualize regularmente o Nextcloud, o banco de dados, o Redis, o Caddy e o sistema hospedeiro;
- Defina limites de taxa razoáveis no login, mas sem bloquear por engano o WebDAV e os clientes de sincronização;
- Monitore disco, inodes, backups do banco de dados, Cron e HTTPS;
- Revogue sessões e senhas de aplicativo quando alguém sair da equipe ou um dispositivo for perdido.
Auto-hospedar significa que você é responsável pela segurança, pela capacidade e pela recuperação; não significa que os arquivos estejam naturalmente livres de perda. RAID, snapshots, histórico de versões e lixeira não substituem backups externos.
docker compose ps
curl -I http://127.0.0.1:8080/status.php
docker compose logs --tail=200 app
sudo journalctl -u caddy --no-pager -n 100
Se o App ainda estiver inicializando ou executando uma atualização, o Caddy retornará temporariamente 502. Se continuar falhando, verifique o banco de dados, o Redis, a memória e as permissões do volume de dados.
Confirme que o domínio em .env corresponde ao ponto de entrada real e verifique:
docker compose exec -u www-data app php occ config:system:get trusted_domains
docker compose exec -u www-data app php occ config:system:get trusted_proxies
docker compose exec -u www-data app php occ config:system:get overwritehost
docker compose exec -u www-data app php occ config:system:get overwriteprotocol
Não configure redirecionamentos HTTP/HTTPS conflitantes entre o CDN, o Caddy e o Nextcloud. Os proxies confiáveis também não devem ser ampliados para endereços públicos arbitrários.
Primeiro confirme o max_size do Caddy e depois verifique o ambiente do contêiner e o PHP:
docker compose exec app php -i | grep -E 'upload_max_filesize|post_max_size|memory_limit'
docker compose logs --tail=200 app
df -h
Se o upload falhar em um tamanho fixo, geralmente é um limite do proxy ou do PHP; se expirar no meio, continue verificando o cliente, os tempos limite do proxy reverso, o disco e a estabilidade da rede.
docker compose ps cron
docker compose logs --tail=200 cron
docker compose exec -u www-data app php occ background:cron
Confirme que o Cron e o App usam a mesma versão de imagem e o mesmo volume de dados. Após atualizar o App, atualize também o contêiner Cron.
Primeiro verifique se o Redis e o banco de dados estão saudáveis; não exclua diretamente os registros de bloqueio do banco de dados:
docker compose ps redis db
docker compose logs --tail=200 redis db app
docker compose exec redis sh -c 'redis-cli -a "$REDIS_HOST_PASSWORD" ping'
Só trate mais a fundo os bloqueios residuais quando tiver confirmado que nenhum cliente está gravando, tiver feito backup do banco de dados e entender o impacto.
- O Nextcloud escuta apenas em
127.0.0.1:8080, e o banco de dados e o Redis não estão expostos à internet - Domínio, HTTPS, proxies confiáveis e URL de substituição estão configurados de forma consistente
- O contêiner Cron separado funciona normalmente e o horário das tarefas em segundo plano continua sendo atualizado
- O cache do Redis e o bloqueio transacional de arquivos funcionam normalmente
- O cliente desktop, o upload automático pelo celular e o WebDAV foram testados
- O caminho de upload de 10 GB ou do tamanho necessário foi realmente testado
- Tanto o PostgreSQL quanto o volume de dados do Nextcloud têm backups externos
- Foi feita uma simulação de restauração e verificados compartilhamento, versões e sincronização dos clientes
- A versão foi fixada e o backup feito antes da atualização, e a compatibilidade dos aplicativos foi verificada depois
Depois de concluir estas etapas, este Nextcloud não será apenas “uma página web que abre”, mas uma nuvem privada em VPS com HTTPS, cache, tarefas agendadas, sincronização móvel, gerenciamento de versões e capacidade de recuperação.