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:
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:
Coolapp::Application.routes.draw do
mount Resque::Server.new, :at => "/resque"
end
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
:
Coolapp::Application.routes.draw do
authenticate :admin_user do
mount Resque::Server.new, :at => "/resque"
end
end
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.