Tutoriais de VPS
Hospedar o FreshRSS em uma VPS (2026): Docker Compose, HTTPS com Caddy, atualização automática e sincronização móvel
Este tutorial explica como hospedar o FreshRSS em uma VPS para criar um leitor RSS leve e sem interferência de algoritmos. O conteúdo cobre implantação com Docker Compose, a opção padrão com SQLite, HTTPS automático com Caddy, atualização automática via CRON_MIN, a API Google Reader para dispositivos móveis, integração com o RSSHub, backup, atualização, reforço de segurança e solução de problemas comuns.

Hospedar o FreshRSS em uma VPS (2026): Docker Compose, HTTPS com Caddy, atualização automática e sincronização móvel
Muitas pessoas voltaram a usar RSS, não por nostalgia, mas porque o fluxo de informações está cada vez mais cansativo. As plataformas sociais empurram conteúdo por algoritmo, os resultados de busca estão cada vez mais cheios de anúncios e lixo de IA, e as newsletters facilmente transformam seu e-mail em um segundo depósito de spam.
A vantagem do RSS é simples: você lê o que assina. Sem feed de recomendações, sem sequestro por listas de tendências, e sem precisar entregar seus hábitos de leitura a uma plataforma de terceiros.
O FreshRSS é um leitor RSS auto-hospedado muito adequado para rodar em uma VPS. É leve, de código aberto, suporta múltiplos usuários, suporta sincronização web e móvel, e pode ser combinado com ferramentas como RSSHub e RSS-Bridge para incluir nas suas assinaturas sites que não oferecem RSS.
Este artigo trata da implantação do FreshRSS em uma VPS com Docker Compose e do uso do Caddy para obter HTTPS automaticamente. Vamos usar a opção padrão com SQLite, a mais simples e estável, adequada para indivíduos e equipes pequenas; se você tiver um volume muito grande de assinaturas, mais adiante também explicaremos quando você deve considerar o PostgreSQL.
É adequado para estes cenários:
- Você quer criar seu próprio substituto do Google Reader / Inoreader / Feedly.
- Você quer que seus feeds, estados de leitura e artigos salvos fiquem no seu próprio servidor.
- Você quer sincronizar o progresso de leitura entre o navegador do computador, o app do celular e o tablet.
- Você precisa assinar blogs, sites técnicos, GitHub Releases, feeds de notícias e atualizações de podcasts.
- Você quer combinar com o RSSHub para assinar alguns sites em chinês que originalmente não têm RSS.
É menos adequado para estes cenários:
- Você só lê alguns artigos ocasionalmente e os favoritos do navegador bastam.
- Você não quer de jeito nenhum manter uma VPS, backups e HTTPS.
- Você precisa de permissões de equipe muito complexas, colaboração com comentários ou funções de base de conhecimento.
- Você quer principalmente arquivar capturas de páginas web; o Linkwarden ou o Wallabag estariam mais próximos da sua necessidade.
O FreshRSS se posiciona como um "leitor", não como um sistema de arquivamento web. O que ele faz melhor é buscar feeds, sincronizar estados de leitura e manter listas de artigos a longo prazo.
Os serviços RSS de terceiros poupam preocupações, mas têm alguns problemas:
- Os planos gratuitos costumam limitar o número de assinaturas, a frequência de atualização e os recursos de busca.
- Seus dados e histórico de leitura ficam na plataforma de outra pessoa.
- Alguns serviços não suportam bem sites em chinês, o acesso pela rede da China continental nem feeds do RSSHub.
- Quando um serviço encerra ou aumenta o preço, migrar é chato.
As vantagens de auto-hospedar o FreshRSS são: o OPML das assinaturas pode ser exportado a qualquer momento, os dados ficam na sua própria VPS, você define a frequência de atualização e os clientes móveis podem sincronizar por uma API padrão.
O FreshRSS é muito leve. A imagem Docker oficial suporta amd64, arm64 e arm/v7, e o uso pessoal tem requisitos de máquina muito baixos.
| Cenário | Configuração recomendada |
|---|---|
| Uso pessoal, de dezenas a centenas de feeds | 1 vCPU / 512MB-1GB RAM / 10GB SSD |
| Vários usuários ou combinado com RSSHub | 1-2 vCPU / 1-2GB RAM / 20GB SSD |
| Muitos feeds, retenção de texto completo a longo prazo | 2 vCPU / 2GB RAM / 40GB+ SSD |
Se sua VPS já roda serviços leves como Caddy, Uptime Kuma, Vaultwarden ou Umami, o FreshRSS pode rodar junto com eles. O que realmente ocupa espaço é o cache de artigos, o cache de imagens, o banco de dados SQLite e o diretório de extensões, não o programa FreshRSS em si.
O FreshRSS suporta SQLite, PostgreSQL e MySQL/MariaDB.
Para um tutorial de VPS pessoal, recomendo SQLite por padrão, por motivos simples:
- Um contêiner de banco de dados a menos.
- Fazer backup é fazer backup do diretório
data. - A migração é simples.
- É totalmente suficiente para 1-5 usuários.
Quando considerar o PostgreSQL?
- Você tem muitos usuários.
- Você tem uma quantidade muito grande de feeds.
- Você já tem um serviço PostgreSQL unificado.
- Você quer um gerenciamento mais padronizado de backup, monitoramento e permissões do banco de dados.
Este artigo usa a opção padrão com SQLite. Não é uma "solução de brinquedo", mas sim a solução mais tranquila para um leitor RSS pessoal.
Este artigo assume:
- Ubuntu 22.04 / 24.04 ou Debian 12.
- Docker e Docker Compose V2 instalados.
- Você tem um domínio, por exemplo
rss.example.com. - O registro A do domínio aponta para o IP público da VPS.
- As portas 80 e 443 podem ser abertas para o Caddy obter HTTPS automaticamente.
Criar os diretórios:
sudo mkdir -p /opt/freshrss
sudo chown -R "$USER":"$USER" /opt/freshrss
cd /opt/freshrss
mkdir -p data extensions backups caddy-data caddy-config
Finalidade dos diretórios:
| Diretório | Finalidade |
|---|---|
data | Configuração do FreshRSS, dados de usuário, banco de dados SQLite, cache |
extensions | Extensões de terceiros |
backups | Backups locais |
caddy-data | Certificados e estado do Caddy |
caddy-config | Dados de configuração do Caddy |
Como este artigo usa bind mounts para montar diretórios do host no contêiner, também é preciso tratar as permissões de escrita. O usuário web dentro do contêiner FreshRSS geralmente é www-data, com UID/GID numéricos normalmente 33:33. Em uma VPS Linux, recomenda-se executar:
sudo chown -R 33:33 data extensions
sudo chmod -R u+rwX,g+rwX data extensions
Se o UID de www-data for diferente no seu ambiente, você pode entrar primeiro no contêiner para confirmar, ou mudar para volumes nomeados do Docker. Os volumes nomeados ficam mais próximos do exemplo oficial do Compose e têm menos problemas de permissão; a vantagem do bind mount é que os caminhos são mais intuitivos ao fazer backup e migrar.
A documentação oficial exige explicitamente o backup de data, e se você usar extensões de terceiros, também é recomendado fazer backup de extensions.
Criar .env:
nano .env
Escrever:
FRESHRSS_DOMAIN=rss.example.com
TZ=Asia/Shanghai
CRON_MIN=7,37
Explicação:
FRESHRSS_DOMAIN: o domínio usado pelo Caddy.TZ=Asia/Shanghai: usar o fuso horário da China para evitar que os horários dos artigos e das atualizações pareçam errados.CRON_MIN=7,37: atualizar os feeds no minuto 7 e no minuto 37 de cada hora, ou seja, aproximadamente uma vez a cada 30 minutos.
A documentação oficial do FreshRSS informa que o script de atualização não fará com que um feed seja atualizado com frequência excessiva, então não é preciso configurar a tarefa agendada com intervalos muito curtos. Para uso pessoal, uma vez a cada 20-30 minutos é suficiente.
Criar docker-compose.yml:
nano docker-compose.yml
Escrever:
services:
freshrss:
image: freshrss/freshrss:latest
container_name: freshrss
restart: unless-stopped
env_file:
- .env
environment:
TZ: ${TZ}
CRON_MIN: ${CRON_MIN}
FRESHRSS_ENV: production
volumes:
- ./data:/var/www/FreshRSS/data
- ./extensions:/var/www/FreshRSS/extensions
ports:
- "127.0.0.1:8080:80"
logging:
options:
max-size: 10m
healthcheck:
test: ["CMD", "cli/health.php"]
timeout: 10s
start_period: 60s
interval: 75s
retries: 3
caddy:
image: caddy:2-alpine
container_name: freshrss-caddy
restart: unless-stopped
env_file:
- .env
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-data:/data
- ./caddy-config:/config
depends_on:
- freshrss
Aqui o FreshRSS é deliberadamente vinculado a 127.0.0.1:8080, de modo que a porta 8080 não pode ser acessada diretamente pela internet. O que realmente fica exposto externamente é a 80/443 do Caddy.
Se você busca reprodutibilidade a longo prazo, em produção pode fixar freshrss/freshrss:latest em uma tag de versão específica, por exemplo freshrss/freshrss:1.29.1. A documentação oficial indica que latest é a versão estável mais recente e edge é o branch contínuo; não é recomendado que iniciantes usem edge diretamente em produção.
Criar Caddyfile:
nano Caddyfile
Escrever:
{$FRESHRSS_DOMAIN} {
encode zstd gzip
reverse_proxy freshrss:80
}
Abrir o firewall:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
Se o seu provedor de nuvem tiver grupos de segurança, também é preciso liberar 80 e 443 lá. Quando o Caddy falha ao obter o certificado, a primeira coisa a verificar é o DNS, o firewall do sistema e os grupos de segurança da nuvem.
A documentação oficial do Caddy do FreshRSS também suporta implantação em subdiretório, mas não recomendo que iniciantes o montem sob um caminho como /rss/. Um subdomínio como rss.example.com é mais simples e evita problemas com cookies, API e sincronização móvel.
Executar:
cd /opt/freshrss
docker compose up -d
Ver o status:
docker compose ps
Ver os logs:
docker compose logs -f --tail=100 freshrss
Abrir o navegador e acessar:
https://rss.example.com
Na primeira vez você verá o assistente de instalação. Opções recomendadas:
- Idioma: chinês simplificado ou English.
- Banco de dados: SQLite.
- Conta de administrador: não use uma senha fraca.
- Endereço do site: informe o domínio HTTPS real.
Se aparecerem problemas de permissão no assistente de instalação, verifique primeiro se data e extensions foram concedidos ao usuário www-data dentro do contêiner. Com a abordagem de bind mount deste artigo, a correção mais comum é executar novamente:
cd /opt/freshrss
sudo chown -R 33:33 data extensions
Esta configuração do Compose já habilitou o cron dentro do contêiner por meio de CRON_MIN=7,37.
Você pode observar as atualizações nos logs:
docker compose logs --tail=200 freshrss
O FreshRSS oferece oficialmente três métodos de atualização:
- Cron dentro do contêiner: o mais simples, usado neste artigo.
- Cron do host chamando
actualize_script.php. - Um contêiner separado apenas para cron.
Não ative os três ao mesmo tempo. Atualizações duplicadas não farão com que um único feed fique infinitamente mais rápido; só aumentam o ruído nos logs e a complexidade de diagnóstico.
O FreshRSS suporta adicionar feeds RSS/Atom manualmente e também importar OPML.
Se você está migrando de outro serviço RSS, o processo habitual é:
- Exportar o OPML do serviço antigo.
- Importar o OPML no painel administrativo do FreshRSS.
- Esperar uma rodada de atualização automática.
- Verificar os feeds que falharam.
- Organizar por categoria.
Recomenda-se importar primeiro um lote pequeno para teste, não milhares de feeds de uma vez. Muitos OPML antigos contêm sites já inativos, e a primeira atualização pode ser muito lenta.
O FreshRSS suporta a API Google Reader e a API Fever. A documentação oficial também indica que, para dispositivos móveis, recomenda-se a API Google Reader, por ser mais completa.
Passos no painel administrativo:
- Entrar nas configurações.
- Habilitar o acesso à API nas configurações relacionadas à autenticação.
- Definir a senha da API no perfil do usuário.
- Abrir a página de verificação da API e confirmar que a configuração passa.
Para dispositivos móveis, você pode escolher clientes compatíveis com a API Google Reader, como Reeder, NetNewsWire, FeedMe, Read You etc. Manter a senha da API separada da senha de login é bom: os apps móveis usam a senha da API, e você não deve preencher sua senha principal em todo lugar.
Um endereço de API comum costuma ser parecido com:
https://rss.example.com/api/greader.php
Cada cliente preenche de forma um pouco diferente; alguns só precisam do domínio raiz, outros precisam do caminho da API. Se o login falhar, abra primeiro a página de verificação da API no painel do FreshRSS; ela dirá diretamente o que está errado na configuração do servidor.
Muitos sites da internet em chinês não têm RSS, ou têm um RSS muito ruim. Nesse caso, o FreshRSS pode ser combinado com o RSSHub.
Mas há um ponto de segurança que você precisa observar: o FreshRSS bloqueia por padrão o acesso a alguns endereços internos para evitar riscos do tipo SSRF. Se você rodar o RSSHub na mesma rede Docker, precisa configurar INTERNAL_HOST_ALLOWLIST conforme a documentação oficial do Docker, permitindo apenas serviços internos explícitos, por exemplo:
environment:
INTERNAL_HOST_ALLOWLIST: rsshub:1200
Não escreva * ou 0.0.0.0/0 por conveniência. Isso abre o acesso a todos os endereços internos e é muito arriscado.
Se você não implantar o RSSHub e assinar diretamente feeds RSS públicos, não precisa dessa configuração.
Com a opção SQLite, o backup principal é data e extensions. Mas bancos de dados SQLite não são adequados para serem empacotados online como único backup enquanto o serviço grava continuamente. Uma abordagem mais confiável é: parar temporariamente o contêiner do FreshRSS antes do backup, concluir o arquivamento dos arquivos e depois iniciá-lo novamente.
Criar um script de backup:
nano backup-freshrss.sh
Escrever:
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/opt/freshrss"
BACKUP_DIR="$APP_DIR/backups"
DATE="$(date +%F-%H%M)"
mkdir -p "$BACKUP_DIR/$DATE"
cd "$APP_DIR"
# 先尝试生成 FreshRSS 自带数据库快照,便于迁移和细粒度恢复。
# 如果这一步失败,脚本会停止,避免产生“看似成功但实际不完整”的备份。
docker exec --user www-data freshrss cli/db-backup.php
# 停止 FreshRSS,避免在线打包 SQLite 数据库时出现不一致。
docker compose stop freshrss
# 备份配置、SQLite 数据、扩展、Compose 和 Caddy 配置。
tar czf "$BACKUP_DIR/$DATE/freshrss-data.tar.gz" data extensions docker-compose.yml Caddyfile .env
# 重新启动服务。
docker compose start freshrss
# 保留最近 14 天备份。
find "$BACKUP_DIR" -mindepth 1 -maxdepth 1 -type d -mtime +14 -exec rm -rf {} \;
echo "Backup saved to $BACKUP_DIR/$DATE"
Adicionar permissão de execução e testar:
chmod +x backup-freshrss.sh
./backup-freshrss.sh
ls -lh backups
Adicionar uma tarefa agendada:
crontab -e
Backup às 3 da manhã todos os dias:
0 3 * * * /opt/freshrss/backup-freshrss.sh >> /opt/freshrss/backups/backup.log 2>&1
Este script para brevemente o FreshRSS, o que costuma ser aceitável para um leitor pessoal. Se você não pode aceitar tempo de inatividade, deve usar a exportação db-backup.php integrada do FreshRSS como caminho principal de backup do banco de dados, fazer backup da configuração e das extensões separadamente, e não tratar um tar online do arquivo SQLite em execução como única base de recuperação.
O backup local é apenas a primeira camada. Uma abordagem mais confiável é usar o rclone para sincronizar com armazenamento de objetos, outra VPS ou um NAS.
Parar o serviço antes de restaurar:
cd /opt/freshrss
docker compose down
Encontrar o backup a restaurar, por exemplo:
ls -lh /opt/freshrss/backups
Supondo que o diretório de backup seja /opt/freshrss/backups/2026-07-09-0300/, extrair:
tar xzf /opt/freshrss/backups/2026-07-09-0300/freshrss-data.tar.gz -C /opt/freshrss
Se o que você vai restaurar é um snapshot de banco de dados gerado por cli/db-backup.php, também pode usar cli/db-restore.php conforme o processo oficial de restauração do FreshRSS. Não misture sem cuidado a restauração em nível de arquivo e a restauração em nível de banco de dados; primeiro confirme se você está restaurando o diretório completo do site ou uma exportação do banco de dados.
Corrigir as permissões do bind mount:
cd /opt/freshrss
sudo chown -R 33:33 data extensions
Reiniciar:
docker compose up -d
Após restaurar, verificar:
- Se você consegue fazer login.
- Se os feeds ainda estão lá.
- Se os estados de leitura estão corretos.
- Se a API móvel ainda conecta.
- Se a atualização automática é executada.
Não faça apenas backups sem ensaiar. Os dados RSS não são necessariamente um negócio crítico, mas perder anos de assinaturas e artigos salvos também é doloroso.
Fazer backup antes de atualizar:
cd /opt/freshrss
./backup-freshrss.sh
Se usar Docker Compose:
docker compose pull
docker compose up -d
Verificar após atualizar:
docker compose ps
docker compose logs --tail=100 freshrss
A documentação oficial de atualização alerta: para atualizações entre versões, é melhor ir versão por versão, não pular diretamente de uma versão muito antiga para uma muito nova. Para instâncias sem manutenção por muito tempo, recomenda-se ver primeiro as Release Notes e depois decidir o caminho de atualização.
No mínimo, faça isto:
- Abrir apenas 80/443, não abrir 8080.
- Usar uma senha de administrador forte.
- Definir a senha da API separada da senha de login.
- Não colocar
data,extensionsoubackupsem diretórios acessíveis pela web. - Não configurar
INTERNAL_HOST_ALLOWLIST=*de qualquer jeito. - Se você não precisa de registro público, não habilite o registro multiusuário.
- Atualizar regularmente a imagem e os patches do sistema da VPS.
- Sincronizar os backups fora do site.
- Se só você usa, você pode adicionar ainda Cloudflare Access, Tailscale ou WireGuard.
O FreshRSS em si não é pesado, mas ele busca URLs externas. Todo serviço que consegue buscar páginas web externas deve prestar atenção a SSRF e aos limites de acesso à rede interna.
Primeiro verifique o contêiner:
docker compose ps
Depois verifique o Caddy:
docker compose logs --tail=100 caddy
Foque em DNS, 80/443, firewall e grupos de segurança. No modo proxy do Cloudflare, uma configuração incorreta de certificado ou de origem também pode causar problemas de acesso.
Verificar se CRON_MIN existe em .env:
grep CRON_MIN .env
Depois verificar os logs:
docker compose logs --tail=200 freshrss
Se você escolher o cron do host, não configure CRON_MIN novamente, para evitar que dois mecanismos de atualização rodem ao mesmo tempo.
Verificar na ordem:
- Se o acesso à API está habilitado no painel administrativo.
- Se a senha da API está definida no perfil do usuário.
- Se o cliente selecionou a API Google Reader.
- Se o endereço da API está preenchido corretamente.
- Se o proxy reverso encaminha o caminho corretamente.
A página de verificação da API do painel do FreshRSS é muito útil; veja primeiro o PASS/FAIL dela e não altere o cliente às cegas.
Isso é algo que o FreshRSS não consegue resolver. O FreshRSS é um leitor, não um scraper universal.
Soluções:
- Procurar se o site tem um RSS oculto.
- Usar o RSSHub.
- Usar o RSS-Bridge.
- Usar o recurso de scraping web do FreshRSS para páginas simples.
Mas quanto mais parecer scraping, mais é preciso prestar atenção à frequência, aos direitos autorais e às regras do site de destino.
As causas comuns são cache, imagens, extensões ou uma grande quantidade de artigos históricos.
Primeiro verificar o tamanho dos diretórios:
du -h --max-depth=2 /opt/freshrss | sort -h
A documentação oficial de backup menciona que cache pode ser ignorado, porque o FreshRSS pode reconstruir o cache. Você também pode ajustar a política de retenção de artigos históricos para evitar crescimento ilimitado.
Essas ferramentas costumam ser confundidas, mas têm finalidades diferentes.
| Ferramenta | Finalidade principal |
|---|---|
| FreshRSS | Leitura RSS, assinaturas, sincronização de estados de leitura |
| RSSHub | Converter sites sem RSS em feeds RSS |
| Linkwarden | Gerenciamento de favoritos e arquivamento web |
| Wallabag | Leitura posterior e salvamento de artigos |
Se o seu objetivo é ler feeds todos os dias, escolha o FreshRSS. Se o seu objetivo é salvar páginas web e guardar capturas, escolha o Linkwarden. Se você quer assinar fontes complexas como Zhihu, Weibo ou Bilibili, o FreshRSS pode ser combinado com o RSSHub.
Verificar antes do uso formal:
- O domínio já resolve para a VPS.
- 80/443 estão liberados no firewall e nos grupos de segurança.
- O FreshRSS está vinculado apenas a
127.0.0.1:8080. - O Caddy obteve o certificado HTTPS com sucesso.
-
TZ=Asia/Shanghaiestá definido. -
CRON_MINestá definido e apenas um método de atualização está habilitado. -
dataeextensionsforam concedidos ao usuáriowww-datadentro do contêiner, ou foram trocados por volumes nomeados. - A senha de administrador está definida como uma senha forte.
- A API móvel está habilitada e testada com sucesso.
- O script de backup foi executado com sucesso.
- Pelo menos um ensaio de restauração foi feito.
- Se usar o RSSHub,
INTERNAL_HOST_ALLOWLISTpermite apenas serviços explícitos.
O valor do FreshRSS não está em exibir técnica, mas em transformar o fluxo de informações novamente em algo que você controla.
Você pode colocar no FreshRSS blogs técnicos, Releases de projetos de código aberto, sites de notícias, atualizações de podcasts e posts de fóruns. Abra o leitor todos os dias e leia apenas o que você assinou, sem ser levado por um feed de recomendações.
Se você já tem uma VPS, o FreshRSS é um aplicativo leve que vale muito a pena auto-hospedar. Ele não consome recursos, o backup é simples, a sincronização móvel é madura e, combinado com o RSSHub, também se encaixa muito bem em cenários de assinatura de informações da internet em chinês.