R e shiny na nuvem

Autor

José de Jesus Filho

Data de Publicação

sábado, 13 de julho de 2024

Introdução

Neste tutorial, irei mostrar o caminho para instalar o R, o RStudio-server e o shiny-server de modo que você possa, não somente trabalhar com o RStudio do navegador, mas também publicar seus aplicativos shiny e nunca mais ter de contar com as 25 horas mensais do shinyapps.io.

Este tutorial é fruto de mais de três anos de experiência instalando dezenas de vezes o R, o Rstudio e o Shiny em máquinas virtuais. Obviamente, ele não está isento de erros, mas foi testado múltiplas vezes. Por outro lado, sugestões para aprimoramento são sempre bem-vindas.

Máquina virtual

Primeiramente, você deve criar uma máquina virtual. Para quem está começando, eu recomendo o Contabo. Por menos de 10 dólares mensais, você tem uma máquina rodando e com um ip público à sua disposição. Nesse tutorial, eu irei pressupor que você já criou uma máquina virtual (instância no AWS ou no GCP) ou VM no Contabo. Também estou assumindo que esta máquina foi criada com o Ubuntu 22.04 ou superior. Para criar uma máquina virtual (VM na sigla em inglês), você só precisa criar uma conta num desses serviços e selecionar a configuração que caiba no seu bolso.

Instalação do R

Os passos seguintes orientam a instalação atualizável do R no Ubuntu-server, ou seja, se você seguir esses passos, cada vez que der apt update e apt -y upgrade, a versão mais recente do R disponível para Ubuntu será instalada.

Assegure-se de que o lsb-release está instalado:

O lsb-release serve apenas para mostrar a versão da distribuição linux instalada. Se você já sabe a versão, esse passo é desnecessário. Eu uso para ajustar a url do R a fim de informar o sistema onde buscar a versão mais recente do R.

 sudo apt update && sudo apt -y install lsb-release && sudo apt-get clean all

Adicione a chave GPG

A instalação da chave GPG preserva uma comunicação segura entre o cliente e o servidor. Ela é importante para assegurar a integridade dos dados e a autenticidade da fonte. Ou seja, os dados são criptografados antes de serem baixados por seu computador e decriptografados pela chave previamente instalada. Isso reduz significativamente as chances de que um terceiro intervenha no processo de transmissão e instale algo nocivo na sua máquina.

 wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | sudo gpg --dearmor -o /usr/share/keyrings/r-project.gpg

Adicione o endereço do repositório do cran ao sources.list.d:

Aqui eu interpolo o resultado do lsb-release com a url a fim de adicioná-la adicioná-la ao sources.list.d, que nada mais é do que uma lista consultada pelo gerenciador do pacotes, o apt, a fim de saber o repositório de onde obter a versão mais recente do R ou de qualquer outro programa.

echo "deb [signed-by=/usr/share/keyrings/r-project.gpg] https://cloud.r-project.org/bin/linux/ubuntu `lsb_release -cs`-cran40/" | sudo tee -a /etc/apt/sources.list.d/r-project.list

Instalar o R

Enfim, podemos instalar R, utilizando o gerenciador de pacotes APT.

 sudo apt -y update
 sudo apt -y install r-base r-base-dev 

Instalação de pacotes com dependência em c/c++ no R.

Se você é também usuário de Windows ou MAC, seguramente uma das coisas que lhe incomoda no Linux é a necessidade de instalar as bibliotecas em C das quais os pacotes do R dependem. Por exemplo, para usar o pacote httr, você precisa antes instalar as bibliotecas libssl-dev e libcurl4-openssl-dev. Isso nem sempre é agradável, principalmente quando você não sabe que existe essa dependência, aguarda um bom tempo para instalar o pacote R, para descobrir que não foi instalado porque falta instalar essa ou aquela lib em C.

Instalação do Java - opcional

Esse passo é opcional, mas há muitos pacotes do R que dependem de Java.

 sudo apt-get install -y default-jre
 sudo apt-get install -y default-jdk

Informar onde o R deve encontrar o Java.

Para que o rJava, o qual instalaremos em seguida, possa encontrar o Java, você deve rodar o seguinte comando.

 sudo R CMD javareconf 

Instalação do rJava

Agora podemos instalar o rJava diretamente do shell, sem necessidade de entrar na interação do R, por ora.

 Rscript -e 'install.packages("rJava")'

Instalação do libpoppler - opcional

Se você optou por instalar o tesseract, seguramente irá querer instalar o libpoppler também. Por meio dele, você extrai textos mesmos de pdfs. Recordo que pdf é um mero contêiner. O conteúdo pode perfeitamente ser texto, imagem ou mesmo gráficos.

 sudo apt-get install -y libpoppler-cpp-dev libcurl4-openssl-dev

O pacote do R que chama o poppler é o pdftools:

 Rscript -e 'install.packages("pdftools")'

Instalação do tesseract - opcional

Esse passo também é opcional. Se você acredita que irá fazer leituras de textos em imagens, inclusive aquelas contidas em pdf, o tesseract é necessário. Por meio dele, é possível realizar a leitura ótica dos textos contidos em imagens.

 sudo apt -y install libtesseract-dev libleptonica-dev tesseract-ocr-eng tesseract-ocr-por

Depois disso, você pode instalar o pacote tesseract do R.

 Rscript -e 'install.packages("tesseract")'

Instalação do devtools, tidyverse e companhia

Se você trabalha com ciência de dados, o conjunto de pacotes incluídos no tidyverse é de suma importância. Além disso, para instalar pacotes em desenvolvimento, o pacote remotes é muito importante. Ademais, esses dois pacotes se encarregam de instalar outros igualmente importantes, como o xml2 e o httr.

Para instalá-los, antes devemos instalar algumas dependências.

 sudo apt install libssl-dev libxml2-dev \
libfontconfig1-dev libharfbuzz-dev libfribidi-dev \
libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev
 Rscript -e 'install.packages(c("remotes","tidyverse"))'

Instalação do rstudio-server

Estamos em condições de instalar o rstudio-server. Vá para a página de download o rstudio-server para Ubuntu, copie e rode a sequência de comandos de maneira similar à que está abaixo:

 sudo apt-get install gdebi-core
 wget https://download2.rstudio.org/server/trusty/amd64/rstudio-server-1.2.5033-amd64.deb
 sudo gdebi rstudio-server-1.2.5033-amd64.deb

Se tudo correr bem, você terá o Rstudio-server instalado. Para verificar se ele está rodando, chame o comando a seguir.

 sudo systemctl status rstudio-server

Por padrão, o Rstudio-server é acessado via porta 8787. Nós faremos uso dela mais adiante quando formos configurar o proxy reverso no nginx.

Instalando o Shiny-server

Seguiremos procedimento similar para instalar o shiny-server. O passo adicional é a instalação do shiny previamente à instalação do shiny-server.

 Rscript -e 'install.packages("shiny")'

Vá para a página de download do shiny-server para Ubuntu, copie e rode os comandos conforme a seguir. Note que eu apenas deixo de instalar o gdebi, porque isso já foi feito quando baixamos o rstudio-server.

 wget https://download3.rstudio.org/ubuntu-12.04/x86_64/shiny-server-1.5.5.872-amd64.deb
 sudo gdebi shiny-server-1.5.5.872-amd64.deb

Para verificar se está tudo bem, rode o seguinte comando:

 sudo systemctl status shiny-server

O shiny-server é acessado, por padrão, via porta 3838. Logo faremos uso dessa informação.

Mantendo uma biblioteca comum

Quando instalamos o Rstudio-server, bem como, o shiny-server, possivelmente queremos dar acesso a vários usuários. O próprio shiny-server roda com o usuário shiny. Se você quiser permitir que todos os usuários partilhem da mesma biblioteca de pacotes, você deve editar o arquivo /etc/R/Renviron e comentar (adicionar # ao início) a linha similar a esta:

#R_LIBS_USER=${R_LIBS_USER-'~/R/x86_64-pc-linux-gnu-library/4.0'}

Protegendo o acesso via proxy reverso

Se você pretende acessar o rstudio, bem como, publicar seus shinyapps via navegador, é necessário tomar uma série de medidas de proteção. Quando você instalou o rstudio-server e o shiny-server, eles passaram a ser disponibilizados via portas 8787 e 3838, respectivamente. Assim, se quiser trabalhar no rstudio, basta você digitar http://ip:8787. Igualmente, para acessar o shinyapp, você digita http://ip:3838/meushinyapp.

Acontece que, deixar essas portas abertas torna sua máquina vulnerável a ataques. Além disso, as informações são transferidas sem qualquer criptografia. A seguir, mostraremos como instalar o certificado SSL/TSL, para que os dados em trânsito estejam criptografados e, melhor, como proteger essas portas via proxy reverso. O proxy reverso serve para, dentre outras tantas funções, distribuir as requisições para o local adequado.

Para facilitar a compreensão, pense na sua máquina virtual como uma dessas vilinhas com várias casas e que, uma dessas casas é o rstudio-server e outra o shiny-server. Os visitantes regularmente se dirigem às casas. Após alguns assaltos, os moradores decidem colocar um portão para acesso à vila, uma portaria e contratar um porteiro para controlar as saídas e entradas.

Pense no proxy reverso como a função do porteiro do condomínio, que recebe as encomendas direcionadas a cada casa e as distribui. O porteiro seria como o web-server. O web-server, como o próprio nome sugere, disponibiliza o conteúdo da sua máquina para a web. O rstudio-server e o shiny-server já são capazes de servir requisições sem carecer de um proxy, ou seja, um intermediário. No entanto, sem um proxy,i.e., o porteiro, eles ficam mais vulneráveis. O implementador de proxy reverso mais popular atualmente é o nginx (pronuncia-se engine-x), que é um o web-server, assim como o apache.

Outra vantagem de usar o nginx é que ele pode ser configurado para servir por meio de uma única porta, a porta 443, que geralmente é usada para transmissão de dados criptografados. A porta 443 funcionaria como o portão do condomínio. Ela possui algumas seguranças adicionais pois é única que ficaria exposta ao público. No entanto, como você já deve ter imaginado, ela não oferece absoluta proteção, apenas adiciona uma camada importante de segurança. Ela é acessada por meio do protocolo https.

Quando alguém escreve o seu endereço no navegador, os dados são transmitidos seguindo as regras desse protocolo, ou do http, cuja principal diferença é que este último não inclui a criptografia. Além disso, a transmissão por http se dá via porta 80. Por essa razão, esta porta deve também ficar aberta. No entanto, ao configurarmos a criptografia, esta orientará o nginx a redirecionar as tentativas de acesso por http para https.

A criptografia pode ser configurada por meio do programa openssl e certificada por várias entidades. Nós usaremos o Let’s encrypt, porque oferece esse serviço gratuitamente.

Uma outra porta que deve estar aberta é a porta para acesso remoto à VM. Geralmente isso fica sob responsabilidade da porta 22. Para acessá-la, usa-se o protocolo ssh, o qual dá acesso ao servidor por meio de senha ou via par de chaves criptografadas.

Dito isso, vamos instalar o nginx e proceder à configuração do SSL.

 sudo apt-get update
 sudo apt-get upgrade
 sudo apt-get install nginx

Ao ser instalado, o nginx cria alguns arquivos de configuração. O principal deles é o /etc/nginx/nginx.conf. Este arquivo chama outros localizados em subpastas do mesmo diretório /etc/nginx. Nós iremos editar este e um outro, o /etc/nginx/sites-available, a fim de configurar o proxy reverso para o rstudio-server e o shiny-server.

Firewall

Hora de habilitar o firewall para permitir acesso apenas ao nginx, portas 443 e 80 e ao acesso remoto via ssh. Para tanto, certifique-se de que você tem instalado o ufw:

 apt install ufw

Em seguida, autorize a porta ssh. Esse passo é fundamental, do contrário, ao habilitar o firewall, você perderá acesso remoto à VM.

 ufw allow ssh

Agora podemos habilitar o firewall.

 ufw enable

Por fim, autorize o nginx-full, ou seja, as portas 443 e 80.

 ufw allow 'Nginx Full'

Se você tentar acessar o rstudio ou o shiny, não será possível porque as portas 3838 e 8787 têm seu acesso negado pelo firewall. Vamos emitir o certificado SSL. O certbot cuida de todo o processo. No entanto, o certificado SSL só pode ser emitido para um domínio. Por essa razão, antes de proceder aos passos seguintes, você deve obter um domínio e apontá-lo para o ip público da sua VM.

Configurando o SSL

Para adquirir o certificado ssl, iremos instalar o certbot, o qual automatiza o processo.

 apt -y install python3-certbot-nginx

O Let’s Encrypt não emite certificado para IP, somente para domínio. Se você não possui um domínio, você pode adquirir um por meio das tantas empresas denominadas registrars. Particularmente, eu recomendo o registro.br. Depois disso, direcione o domínio criado para serviço na nuvem que você contratou sua VM, ou seja o DNS, que ficará responsável por mapear o domínio para o ip da sua máquina. Se foi o Digital Ocean, você obtêm as orientações aqui.

Além disso, você tem de apontar o domínio para o droplet ou instância. Geralmente, no painel de controle do serviço onde você adquiriu a máquina, existe uma opção para apontar para o ip. Ainda, se for o Digital Ocean, você pode fazer isso por meio da opção networking. Selecione as opções A e AAAA para apontar o domínio para o ipv4 e o ipv6 respectivamente.

Feito isso, abra o seguinte arquivo com seu editor preferido. No caso, usarei o vim.

 sudo vim /etc/nginx/sites-available/default

Procure a seguinte linha e substitua o sublinhado do server name:

server_name _;

pelo domínio:

server_name dominio.com.br;

Naturalmente, substitua o “domínio.com.br” pelo seu domínio.

Solicitar a certificação

Somente agora, estamos em condições de solicitar a certificação.

 certbot --nginx -d dominio.com.br

Responda às perguntas solicitadas durante o processo de certificação e, pronto, o certificado será emitido e os arquivos de configuração do nginx serão propriamente alterados para contemplar a criptografia na transmissão de dados.

Proxy reverso

Estamos em condições de adicionar o rstudio-server e o shiny-server ao nginx para que este redirecione as requisições às respectivas portas. Abra o arquivo abaixo.

 sudo vim /etc/nginx/sites-available/default

Isso deve ser adicionado em qualquer parte abaixo do html.index…


location /rstudio/ {
  proxy_pass http://127.0.0.1:8787/;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

location /shiny/ {
      rewrite ^/shiny/(.*)$ /$1 break;
      proxy_pass http://127.0.0.1:3838/;
      proxy_redirect / $scheme://$http_host/shiny/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;
      proxy_read_timeout 20d;
      proxy_buffering off;
}

location ~ /.well-known {
  allow all;
}

Além disso, para que o shiny-server funcione, você tem de adicionar a seguinte diretiva no arquivo /etc/nginx/nginx.conf, dentro da diretiva http {…}

http {
    ...

map $http_upgrade $connection_upgrade {
      default upgrade;
      ''      close;
    }

}

O Rstudio permite que você faça upload de arquivos ou pastas zipadas por meio da aba upload. No entanto, o nginx limita o tamanho dos uploads a 1MB. Para aumentar, acrescente a seguinte diretiva no arquivo /etc/nginx/nginx.conf, também dentro da diretiva http {…}

http {
    ...
    client_max_body_size 100M;
}  

Verifique se não há erro na configuração:

 nginx -t

Se tudo correr bem, você receberá uma mensagem assim:

configuration file /etc/nginx/nginx.conf test is successful

Recarregue o nginx para habilitar a edição:

 sudo systemctl reload nginx

Segurança extra

Se quiser adicionar uma camada se segurança, configure o parâmetro de criptografia para 2048 bits em vez do padrão 1024.

 sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Gerenciamento de usuários

Irei criar um usuário que acessará o rstudio-server (você pode criar quantos quiser). Além disso, eu recomendo você criar um grupo e adicionar todos os usuários que usarão o rstudio-server, inclusive o usuário shiny, o qual foi criado quando você instalou o shiny-server, a este grupo. Depois disso, torne esse grupo o proprietário do diretório onde serão instalados o pacotes do R. Assim, você terá um diretório único com os pacotes do R para todos os usuários, de modo a evitar múltiplas bibliotecas.

Além disso, sugiro tornar esse grupo o proprietário da pasta onde se encontram os aplicativos shiny.

 adduser jose

Após criar uma senha para o usuário. Crie o grupo:

 addgroup usuarios

Adiciona usuário ao grupo

O código abaixo adiciono o usuário recém criado ao grupo usuarios e torna o grupo proprietário, com poderes de escrita e leitura à biblioteca de pacotes R.

 sudo usermod -a -G usuarios jose

 sudo chown -R :usuarios /usr/local/lib/R/site-library

 sudo chmod -R g+w /usr/local/lib/R/site-library

 sudo chmod -R o-x /usr/local/lib/R/site-library

Faça o mesmo com shiny

 sudo usermod -a -G usuarios shiny

 sudo chown -R :usuarios /srv/shiny-server

 sudo chmod -R g+w /srv/shiny-server

 sudo chmod -R o-x /srv/shiny-server

Pronto, agora você pode trabalhar livremente com o R e o shiny na nuvem. Se quiser testar se tudo está bem. Entre no demo shiny que já vem com a instalação:

https://dominio.com.br/shiny

E no Rstudio:

https://dominio.com.br/rstudio