Celery Flower Security in Production Celery Flower Security in Production nginx nginx

Celery Flower Security in Production


You can run flower with --auth flag, which will authenticate using a particular google email:

celery flower --auth=your.email@gmail.com

Edit 1:

New version of Flower requires couple more flags and a registered OAuth2 Client with Google Developer Console:

celery flower \    --auth=your.email@gmail.com \    --oauth2_key="client_id" \    --oauth2_secret="client_secret" \    --oauth2_redirect_uri="http://example.com:5555/login"

oauth2_redirect_uri has to be the actual flower login url, and it also has to be added to authorized redirect url's in Google Development Console.

Unfortunately this feature doesn't work properly in current stable version 0.7.2, but it is now fixed in development version 0.8.0-dev with this commit.

Edit 2:

You can configure Flower using basic authentication:

celery flower --basic_auth=user1:password1,user2:password2

Then block 5555 port for all but localhost and configure reverse proxy for nginx or for apache:

ProxyRequests offProxyPreserveHost OnProxyPass / http://localhost:5555

Then make sure proxy mod is on:

sudo a2enmod proxysudo a2enmod proxy_http

In case you can't set it up on a separate subdomain, ex: flower.example.com (config above), you can set it up for example.com/flower:

run flower with url_prefix:

celery flower --url_prefix=flower --basic_auth=user1:password1,user2:password2

in apache config:

ProxyPass /flower http://localhost:5555

Of course, make sure SSL is configured, otherwise there is no point :)


I have figured out it using proxy on Django side https://pypi.org/project/django-revproxy/. So Flower is hidden behind Django auth which is more flexible than basic auth. And you don't need rewrite rule in NGINX.

Flower 0.9.5 and higher

URL prefix must be moved into proxy path: https://github.com/mher/flower/pull/766

urls.py

urlpatterns = [    FlowerProxyView.as_url(),    ...]

views.py

class FlowerProxyView(UserPassesTestMixin, ProxyView):    # `flower` is Docker container, you can use `localhost` instead    upstream = 'http://{}:{}'.format('flower', 5555)    url_prefix = 'flower'    rewrite = (        (r'^/{}$'.format(url_prefix), r'/{}/'.format(url_prefix)),     )    def test_func(self):        return self.request.user.is_superuser    @classmethod    def as_url(cls):        return re_path(r'^(?P<path>{}.*)$'.format(cls.url_prefix), cls.as_view())

Flower 0.9.4 and lower

urls.py

urlpatterns = [    re_path(r'^flower/?(?P<path>.*)$', FlowerProxyView.as_view()),    ...]

views.py

from django.contrib.auth.mixins import UserPassesTestMixinfrom revproxy.views import ProxyViewclass FlowerProxyView(UserPassesTestMixin, ProxyView):    # `flower` is Docker container, you can use `localhost` instead    upstream = 'http://flower:5555'    def test_func(self):        return self.request.user.is_superuser


I wanted flower on a subdirectory of my webserver, so my nginx reverse proxy configuration looked like this:

location /flower/ {    proxy_pass http://localhost:5555/;    proxy_redirect off;    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-Protocol $scheme;    proxy_set_header Upgrade $http_upgrade;    proxy_set_header Connection "upgrade";    proxy_http_version 1.1;    auth_basic  "Restricted";    auth_basic_user_file  /etc/nginx/.htpasswd;}

Now I can get to flower (password-protected) via www.example.com/flower

Most of this is derived from the Flower documentation page about configuring an nginx reverse proxy:

http://flower.readthedocs.org/en/latest/reverse-proxy.html