Tag: nextcloud

  • Problema: timeout em sites atrás do proxy reverso via OpenVPN

    Um dia o nginx que configurei como proxy reverso aqui passou a dar timeout ao tentar carregar o Nextcloud. Ao investigar, verifiquei que mesmo ao fazer a solicitação ao servidor Nextcloud a partir do próprio servidor que hospeda o nginx/OpenVPN, através do comando abaixo, a solicitação não completava.

    $ curl -v http://10.8.0.3

    As solicitações feitas dentro da LAN funcionavam, indicando que o problema acontecia apenas dentro da VPN. No entanto, dentro da VPN o ping funcionava, solicitações para outras páginas do Nextcloud também funcionavam, como:

    $ curl -v http://10.8.0.3/status.php

    Tentei aprofundar a investigação mas eu não sou nenhum especialista em redes, só um entusiasta que se mete profissionalmente. Uma explicação que consegui foi que o problema podia ser relacionado ao MTU (maximum transmission unit) da interface virtual de rede do OpenVPN.

    Tanto a interface virtual do OpenVPN (tun0) quanto a interface de rede da máquina (eth0) possuíam o mesmo MTU: 1500 bytes. Isso pode ser verificado com:

    $ ip a

    Diminui o MTU do tun0 para 1380, tanto no servidor quanto no cliente, que foi uma sugestão que encontrei e funcionou. Esqueci o problema até acontecer com outra instalação do Nextcloud que mantenho. Mesmo problema, mesma solução. Eventualmente retornei o MTU pra 1500 e continuou funcionando.

    O blog não existia na época da primeira ocorrência com o Nextcloud. Agora, tive o mesmo problema com o WordPress e o novo Nextcloud. E o problema parece inconsistente. Tudo funciona, até que de repende para. E em momentos diferentes, sem nenhum gatilho claro, mas claramente alguma tentativa de enviar um pacote maior que não poderia ser fragmentado falhou.

    Dessa vez parei pra investigar um pouco melhor. Já que o MTU da tun0 é 1500, um ping com tamanho de 1472 bytes (-20 do cabeçalho IP -8 do cabeçalho ICMP) deve passar sem ser fragmentado. Não passou. 100% dos pacotes perdidos. Fui baixando até encontrar o ponto onde os pings tem resposta: 1396 bytes. MTU de 1424 bytes.

    Testei então: ping sem opções definidas e com tamanhos 1396 e 1397 bytes, monitorando também com o tcpdump tanto no servidor quanto no cliente:

    $ ping 10.8.0.3
    $ ping -M do -s 1396 10.8.0.3
    $ ping -M do -s 1397 10.8.0.3

    Para o tcpdump:

    # tcpdump -i tun0 icmp

    Resultados:

    • “ping 10.8.0.3” e “ping -M do -s 1396 10.8.0.3”:
      • pra cada 10 pings, 0% de perda de pacotes.
      • tcpdump reporta 20 pacotes capturados tanto no servidor quanto no cliente: solicitação e resposta

    Ótimo. Agora:

    • “ping -M do -s 1397 10.8.0.3” e valores acima:
      • pra cada 10 pings, 100% de perda de pacotes
      • tcpdump reporta 10 pacotes capturados no servidor, 20 no cliente: o pacote sai do servidor e chega ao cliente, que responde, mas as respostas do cliente não chegam ao servidor.

    O mesmo foi feito pingando do cliente para o servidor. Mesmo sucesso para pacotes de 1396 bytes e menores. Já com

    • ping -M do -s 1397 10.8.0.1:
      • pra cada 10 pings, 100% de perda de pacotes
      • tcpdump reporta 10 pacotes capturados no cliente, 0 no servidor.

    Ou seja, o problema está no envio de pacotes dos clientes para o servidor através do túnel.

    O ping não alerta que o pacote é grande demais nem dá qualquer erro específico, apenas para pings com tamanho acima de 1472 (que resultariam num pacote acima do MTU). Em vez disso, apenas falha silenciosamente.

    Adicionalmente ao ping, fiz testes com requisições às páginas que resultavam em timeout usando curl e monitorando com tcpdump.

    Solução: baixar o valor do MTU da interface tun0 do servidor e clientes da VPN para 1424 bytes: tamanho total do maior pacote do ping que funcionou (1396 de payload, 20 do cabeçalho IP e 8 do cabeçalho ICMP).

    Isso pode ser feito de forma não persistente com:

    # ip link set dev tun0 mtu 1424

    O MTU vai voltar para 1500 quando o serviço do OpenVPN for reiniciado. Para configurar de forma persistente, inclua essa linha nos arquivos de configuração do OpenVPN do servidor e dos clientes:

    tun-mtu 1424

    Eu ainda não entendi 100% o que causa esse problema e ele não parece afetar todos os clientes igualmente ou ao mesmo tempo. O servidor recebia resposta do ping com payload de 1472 de alguns clientes sem problemas, que exibiam a página e operavam com a MTU padrão de 1500 bytes no tun0.

    Até então, após a mudança para o MTU de 1424, o problema não reincidiu. Sendo mais conservador, eu colocaria um valor mais baixo, pra deixar uma margem pra possíveis alterações que possam vir a acontecer no OpenVPN ou nos outros servidores, masss eu tô aqui pra ver o que acontece.

  • Configuração do nginx como proxy reverso para WordPress, Nextcloud e Proxmox

    Nenhuma das publicações sobre instalação de WordPress ou Nextcloud aborda acesso via HTTPS ou certificados SSL, apenas HTTP.

    Acontece que isso é centralizado em uma instalação do nginx, atuando como proxy reverso. O servidor que hospeda o nginx e o servidor de OpenVPN são a mesma máquina: um VPS com 512mb de RAM e 1vCPU.

    O nginx recebe as requisições em HTTPS e as encaminha em HTTP* de forma segura para os outros servidores – clientes da VPN: WordPress, Nextcloud e Proxmox – 3 máquinas diferentes.

    * Proxmox usa HTTPS por padrão mas com um certificado verificado por uma CA interna

    Vantagens:

    • só é necessário gerenciar os certificados em um servidor, independente de quantos sites são.
    • as 3 máquinas diferentes poderiam estar em qualquer rede, qualquer lugar – isso é, se não fossem virtualizadas dentro do Proxmox, podendo até ser uma rede residencial que bloqueia tráfego de entrada (muito obrigado, Claro), basta se conectar na VPN.

    Desvantagem:

    • existe um pouco de latência devido à distância entre as máquinas (Rio de Janeiro) e o VPS (São Paulo).

    Ainda que fosse possível abrir as portas na rede e o OpenVPN não fosse necessário, usar o nginx como um proxy reverso na mesma LAN ainda poderia ser vantajoso pelo o gerenciamento centralizado dos certificados SSL, logs de acesso e uso de múltiplos nomes de domínio em diferentes servidores pro mesmo IP na mesma porta.

    Os arquivos de configuração do nginx para cada site devem ficar localizados em /etc/nginx/sites-available e para habilitá-los basta criar um symlink em /etc/nginx/sites-enabled com:

    # ln -s /etc/nginx/sites-available/sua_config /etc/nginx/sites-enabled/

    A primeira configuração recomendada é para receber a solicitação HTTP na porta 80 e redirecionar o cliente para fazer uma solicitação HTTPS na porta padrão 443.

    server {
        listen 80 default_server;
        server_name _;
        return 301 https://$host$request_uri;
    }

    Em todos os exemplos de configuração abaixo, substitua o nome do servidor (FQDN), o caminho para o certificado e chave SSL e o IP privado para onde deve ser encaminhada a solicitação.

    Como mencionado, é possível usar a mesma porta para todos os servidores, como a porta padrão HTTPS, desde que cada um tenha o parâmetro server_name diferente, cada um com um nome de domínio (FQDN).

    Configuração para o Proxmox:

    upstream proxmox {
        server "seuproxmox.dominio.com";
    }
    
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name seuproxmox.dominio.com;
        ssl_certificate /etc/letsencrypt/live/seu.dominio.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/seu.dominio.com/privkey.pem;
        proxy_redirect off;
        location / {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_pass https://10.8.0.2:8006;
            proxy_buffering off;
            client_max_body_size 0;
            proxy_connect_timeout  3600s;
            proxy_read_timeout  3600s;
            proxy_send_timeout  3600s;
            send_timeout  3600s;
        }
    }

    Para o Nextcloud:

    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        ssl_certificate /etc/letsencrypt/live/seu.dominio.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/seu.dominio.com/privkey.pem;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Content-Type-Options "nosniff";
        server_name seunextcloud.dominio.com;
        location / {
            proxy_pass http://10.8.0.3;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_redirect off;
        }
        send_timeout 1800;
    }

    Configurações adicionais são recomendadas no lado do servidor Nextcloud, no arquivo /var/www/nextcloud/config/config.php

      'trusted_proxies' =>
      array (
        0 => '10.8.0.1',
      ),
      'overwritehost' => 'seunextcloud.dominio.com',
      'overwriteprotocol' => 'https',
      'overwritecondaddr' => '^10\\.8\\.0\\.1$',
      'overwritewebroot' => '/',
      'overwrite.cli.url' => 'https://seunextcloud.dominio.com',

    Para o WordPress:

    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        ssl_certificate /etc/letsencrypt/live/seu.dominio.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/seu.dominio.com/privkey.pem;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Content-Type-Options "nosniff";
        server_name seuwordpress.dominio.com;
        location / {
            proxy_pass http://10.8.0.4;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_redirect off;
        }
        send_timeout 1800;
    }

    Configurações adicionais são requeridas no lado do servidor do WordPress, no arquivo /var/www/html/wp-config.php

    define('WP_HOME', 'https://seuwordpress.dominio.com');
    define('WP_SITEURL', 'https://seuwordpress.dominio.com');
    
    if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
        $_SERVER['HTTPS'] = 'on';
    }
    
    if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
        $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
    }

    Sugestão de configuração adicional para o WordPress – o WordPress não tem um mecanismo de proteção contra tentativas de acesso por força bruta. Para mitigar isso, além de usar boas senhas, você pode limitar o acesso por IP às localizações /wp-admin e /wp-login.php na configuração do proxy reverso adicionando essa configuração:

    server {
        location ~* ^/(wp-admin|wp-login.php) {
            allow 186.205.1.165;    # seu IP de casa
            allow 191.252.110.50;    # seu IP do trabalho
            deny all;
            proxy_pass http://10.8.0.4;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

    Por conveniência, você também pode fazer o nginx escutar pra solicitações a HTTP na porta 80 e redirecionar todos os clientes para uma solicitação HTTPS:

    server {
        listen 80 default_server;
        server_name _;
        return 301 https://$host$request_uri;
    }

    Após configurado, inicie o serviço.

    # systemctl enable --now nginx

    Caso ainda não tenha certificados SSL válidos, eles podem ser obtidos gratuitamente com a Let’s Encrypt, uma organização sem fins lucrativos, com o comando certbot. Primeiro, pare o serviço nginx, já que o certbot vai criar um processo que também vai escutar na porta 80. Então, use o comando nesse formato:

    # certbot certonly --standalone -d seu.dominio.com -d seunextcloud.dominio.com -d seuproxmox.dominio.com -d seuwordpress.dominio.com

    Siga os prompts do programa e, ao terminar, inicie o nginx.service novamente.

    Caso esteja usando o proxy reverso para servidores dentro de uma VPN, você pode querer ver isso aqui.

  • Instalação e configuração de servidor Nextcloud

    Nextcloud é uma solução de armazenamento de arquivos acessível via web, como Google Drive, que conta também com aplicativos de calendário, contatos, conversas e chamadas de vídeo, cliente de e-mail e suporte a compartilhamento de arquivos. Também tem suporte a integração de suíte office, através do ONLYOFFICE ou Nextcloud Office (baseado no LibreOffice).

    Além disso, Nextcloud trás também o conceito de federação: instâncias distintas do Nextcloud podem se comunicar se assim os administradores quiserem, permitindo uma rede descentralizada de servidores, onde um usuário de uma instância pode se comunicar e compartilhar arquivos com um usuário de outra.

    É software livre e aberto, licenciado sob a AGPLv3, e conta também com planos empresariais.

    No momento os sistemas recomendados para o Nextcloud são Ubuntu 24.04 e RHEL 9, mas tem suporte também a outros como OpenSUSE, Debian e Alpine. Aqui vamos usar o Ubuntu 24.04.

    O Nextcloud precisa de: um servidor web, um banco de dados e PHP. Eu segui a instalação com Apache pro servidor web e PostgreSQL pro banco de dados.

    Outras alternativas suportadas são Nginx para o servidor web e MySQL e MariaDB para o banco de dados.

    Instalação e configuração do Apache com PHP:

    # apt install apache2 php

    Caso tenha habilitado o firewall (Ubuntu traz o UFW desabilitado por padrão), permita o acesso por http:

    # ufw allow http

    Visite o seu servidor web via http e verifique que o Apache funciona. Coloque um arquivo como index.php na pasta do servidor web /var/www/html com o conteúdo

    <?php phpinfo() ?>

    e visite sua página no local /index.php para verificar que o Apache está processando PHP.

    Instalando e configurando o banco de dados:

    # apt install postgresql
    # sudo -u postgres psql

    Isso vai te levar à linha de comando do PostgreSQL, onde você pode criar o usuário e o banco de dados a ser usado no Nextcloud:

    > CREATE USER nextcloud_operator WITH PASSWORD 'senhaNoPost-it';
    > CREATE DATABASE nextcloud_db WITH OWNER nextcloud_operator TEMPLATE template0 ENCODING 'UTF8';
    > \q

    Baixe o arquivo do servidor em https://nextcloud.com/install/

    Instale o utilitário unzip com

    # apt install unzip

    Extraia o arquivo .zip na pasta /var/www. Você vai ver uma pasta nextcloud. Mude o proprietário dela e dos arquivos e subpastas para o usuário www-data, que executa o Apache:

    # chown -hR www-data:www-data /var/www/nextcloud

    Edite o arquivo de configuração do Apache,
    /etc/apache2/sites-enabled/000-default.conf
    para alterar/adicionar as seguintes configurações:

    	DocumentRoot /var/www/nextcloud
    
    	<Directory /var/www/nextcloud/>
    	Require all granted
    	AllowOverride All
    	Options Indexes FollowSymLinks MultiViews
    		<IfModule mod_dav.c>
    			Dav off
    		</IfModule>
    	</Directory>

    Instale outros módulos PHP necessário para o Nextcloud:

    # apt install php-curl php-xml php-gd php-mbstring php-zip php-pgsql 

    Reinicie seu servidor web

    # systemctl restart apache2.service

    e dê sequência à instalação pela página web. O básico já está funcionando.

    Agora existem alguns ajustes que podem ser feitos e você pode vê-los na seção de Configurações de administração > Visão geral

    Um dos principais é o limite de memória usada na execução de scripts PHP. O recomendado é pelo menos 512mb mas a configuração padrão usa 128mb.

    Outro é o limite do buffer do módulo OPcache, para o qual é sugerido um valor acima de 8mb.

    Ajuste os seguintes valores no arquivo
    /etc/php/8.3/apache2/php.ini

    memory_limit = 512M
    opcache.interned_strings_buffer=32

    E no arquivo /etc/php/8.3/cli/php.ini

    opcache.interned_strings_buffer=32

    e reinicie o Apache.

    Algumas mensagens de erro vão sugerir que você execute um script occ com algum argumento. Você pode fazer isso com

    # sudo -u www-data php /var/www/nextcloud/occ argumento_sugerido

    Sugestão de configuração adicional: os arquivos de usuários ficam na pasta /var/www/nextcloud/data, dentro da pasta raiz do Nextcloud. No caso de um bug num dos scripts PHP ou no servidor web, arquivos privados poderiam ser expostos. Então você pode querer configurar a pasta data em outro local, fora da raiz /var/www do servidor web, como por exemplo /var/nextcloud_data.

    Essas e outras questões menos críticas de configuração são abordadas também na documentação oficial do Nextcloud.

    O acesso via HTTPS será feito utilizando o servidor web Nginx atuando como proxy reverso, abordado em outra postagem.