vinibaggio.net

Careful With That Hax, Eugene

(Esta é uma brincadeira com o nome da música “Careful with that axe, Eugene”, do Pink Floyd)

Dificilmente temos um site hoje em dia em que não precisamos usar jobs em background. Para Rails, o Resque é uma das soluções mais populares.

O resque vem com uma ferramenta bem elegante para monitoração das filas:

Resque-web

Essa ferramenta é excelente para monitorar e depurar os jobs executando no site atualmente. Por isso é bastante comum colocarmos o resque-web em algum ponto tal que possamos acessar de qualquer lugar para gerenciar as filas.

Jeito 1: servidor embutido do resque-web

O jeito mais simples de colocar esse monitor no ar é executando o resque-web manualmente e protegê-lo via HTTP Basic auth.

Dessa forma, basicamente basta rodar o resque-web:

resque-web config/resque-web.rb

E, em seguida, protegê-lo, no nginx podemos fazer:

upstream resque {
  server 127.0.0.1:5678;
}

server {
  server_name resque.example.com;

  location / {
    auth_basic "Restricted";
    auth_basic_user_file /opt/nginx/conf/htpasswd;
    proxy_pass http://resque;
  }
}

Assim, ao acessar resque.example.com, você será apresentado por uma tela de autenticação comum HTTP (lógico que você precisa gerar o htpasswd).

Rá! Pegadinha do Mallandro! Ié ié!

Tem um problema nessa história. Por padrão, o resque-web faz bind no host 0.0.0.0. Isso significa que requisições por qualquer interface de rede irá responder. Assim, se você digitar o IP e a porta diretamente, o nginx não irá interceptar a requisição e irá cair no resque-web, que é um grande risco, já que você pode deletar as filas e ver informações talvez sensíveis.

A solução é bem simples. Basta você iniciar o resque-web com o comando para fazer o bind no host 127.0.0.1. Isso fará com que o vegas (servidor HTTP que o resque-web) receba apenas conexões via loopback, ou seja, apenas de servidores locais (tudo isso quem faz é o esperto do kernel do Linux).

resque-web -o 127.0.0.1 config/resque-web.rb

Ou seja, se você for ao endereço de IP, por exemplo 200.100.123.456:5678, a requisição jamais irá chegar no resque-web pois o servidor vegas não estará ouvindo requisições da interface de rede exposta à internet, mas o nginx será capaz de comunicar-se pois estão em contato via loopback. Legal né?

Jeito 2: resque-web dentro do Rails

Outra maneira é embutir o resque-web dentro da sua aplicação Rails. O problema dessa forma é que você irá ocupar preciosos recursos de sua web app com painel de administração. Ou talvez você nem queira ter sua app rails rodando no mesmo servidor em que o resque estiver executando.

A grande vantagem dessa forma é que você pode usar de regras de aplicação dentro do Rails. O resque-web não deixa de ser uma Rack app, podendo ser montada facilmente dentro do Rails:

{{< highlight ruby >}} Coolapp::Application.routes.draw do mount Resque::Server.new, :at => “/resque” end {{< / highlight >}}

O mais legal de tudo é que se você usar o Devise, você pode usar o sistema de login da sua própria aplicação para permitir apenas admins a entrarem no resque-web:

{{< highlight ruby >}} Coolapp::Application.routes.draw do authenticate :admin_user do mount Resque::Server.new, :at => “/resque” end end {{< / highlight >}}

Um único porém dessa solução é que, ao tentar entrar deslogado, rola uma redireção infinita, mas deve ser alguma coisa que eu fiz de errado, que no meu caso deve relacionar-se com o ActiveAdmin.

Essa versão também tem outro problema. Em produção, quem serve os arquivos estáticos é o nginx ou Apache. Dessa forma, ao fazer deploy, você tem que fazer um symlink dos estáticos dentro da gem para o seu public, que pode ser um pouco chato.


Vinicius Baggio Fuentes

Written by Vinicius Baggio Fuentes, who works in tech in NY but would rather be in the kitchen all the time. Twitter Instagram