title: How to setup production ubuntu server with django, gunicorn, nginx and celery?
body: <p>I need to setup production server on ubuntu precise, I read lot of howtos and put bits and pieces together.Below I will post (hopefully) all related configs. But to point you where to look first I list all the problems:</p>
  
  <ol>
  <li>when I don't manually type https:// I got incorrect redirect in firefox</li>
  <li>when I type https:// I got to admin login but can't login with correct username/pass and I don't know how to debug it because I can't find any log containing what runserver outputs to console(i tried file logger in settings.py but log stays empty)</li>
  <li>my app runs under subdomain.domain.com -should I put subdomain.domain.com or just domain.com in settings.py DOMAIN= ?</li>
  <li>what to chenge to make gunicorn work with self signed certificate as in commented line in<code>gunicorn.conf</code>?</li>
  <li>Why <code>/var/log/upstart/celercam.log</code> is full of <code>Error in timer: TransactionManagementError("This code isn't under transaction management",)</code></li>
  </ol>
  
  <hr>
  
  <p><code>pip freeze</code>:</p>
  
  <pre><code>Django==1.5.4
  MySQL-python==1.2.4
  PIL==1.1.7
  Pillow==2.2.1
  PyYAML==3.10
  South==0.8.4
  amqp==1.3.3
  anyjson==0.3.3
  argparse==1.2.1
  billiard==3.3.0.8
  celery==3.1.5
  django-celery==3.1.1
  django-crispy-forms==1.4.0
  django-money==0.3.3
  django-sortable-listview==0.23
  easy-thumbnails==1.4
  gevent==1.0
  google-api-python-client==1.2
  greenlet==0.4.1
  gunicorn==18.0
  httplib2==0.8
  kombu==3.0.6
  oauth2client==1.2
  psycopg2==2.5.1
  py==1.4.17
  py-moneyed==0.4.1
  pyadb==0.1.1
  pyaml==13.07.1
  pylibmc==1.2.3
  pytest==2.4.2
  python-dateutil==2.1
  python-gflags==2.0
  pytz==2013.8
  reportlab==2.7
  six==1.4.1
  vobject==0.8.1c
  wsgiref==:
  </code></pre>
  
  <p>0.1.2</p>
  
  <p><code>settings.py</code></p>
  
  <pre><code># Django settings for crm project.
  DEBUG = False
  TEMPLATE_DEBUG = DEBUG
  
  ADMINS = (
  # ('Your Name', 'your_email@example.com'),
  )
  DOMAIN = '&lt;MY_DOMAIN&gt;'
  MANAGERS = ADMINS
  
  DATABASES = {
      'default': {
          'ENGINE': 'django.db.backends.postgresql_psycopg2',
          'NAME': '&lt;DB_NAME&gt;', # Or path to database file if using sqlite3.
          'USER': '&lt;DB_USER&gt;',
          'PASSWORD': '&lt;DB_PASS&gt;',
          'HOST': '127.0.0.1', 
          'PORT': '', 
      }
  }
  
  ALLOWED_HOSTS = ['*',] 
  
  TIME_ZONE = 'Europe/Warsaw'
  LANGUAGE_CODE = 'pl'
  
  SITE_ID = 1
  USE_I18N = True
  USE_L10N = True
  USE_TZ = True
  MEDIA_ROOT = '/var/www/media/'
  MEDIA_URL = '/media/'
  STATIC_ROOT ='/var/www/static/'
  STATIC_URL = '/static/'
  
  # Additional locations of static files
  STATICFILES_DIRS = (
  
  )
  
  # List of finder classes that know how to find static files in
  # various locations.
  STATICFILES_FINDERS = (
      'django.contrib.staticfiles.finders.FileSystemFinder',
      'django.contrib.staticfiles.finders.AppDirectoriesFinder',
      #  'django.contrib.staticfiles.finders.DefaultStorageFinder',
  )
  
  # Make this unique, and don't share it with anybody.
  SECRET_KEY = '&lt;NOT_THAT_STUPID&gt;'
  
  # List of callables that know how to import templates from various sources.
  TEMPLATE_LOADERS = (
      'django.template.loaders.filesystem.Loader',
      'django.template.loaders.app_directories.Loader',
      #     'django.template.loaders.eggs.Loader',
  )
  
  MIDDLEWARE_CLASSES = (
      'django.middleware.common.CommonMiddleware',
      'django.contrib.sessions.middleware.SessionMiddleware',
      'django.middleware.csrf.CsrfViewMiddleware',
      'django.contrib.auth.middleware.AuthenticationMiddleware',
      'django.contrib.messages.middleware.MessageMiddleware',
      # Uncomment the next line for simple clickjacking protection:
      # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  )
  
  ROOT_URLCONF = 'crm.urls'
  
  # Python dotted path to the WSGI application used by Django's runserver.
  WSGI_APPLICATION = 'crm.wsgi.application'
  
  import os
  SESSION_COOKIE_SECURE = True
  
  TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), '..', 'templates').replace('\\', '/'),)
  
  INSTALLED_APPS = (
      'django.contrib.auth',
      'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.sites',
      'django.contrib.messages',
      'django.contrib.staticfiles',
      'django.contrib.humanize',
      'django.contrib.admin',
      'main',
      'crm',
      'crispy_forms',
      'django_localflavor_us',
      'django_localflavor_pl',
      'investApp',
      'addressbook',
      'sortable_listview',
      'djcelery',
      'gunicorn',
  #    'south'
  )
  
  LOGGING = {
      'version': 1,
      'disable_existing_loggers': False,
      'formatters': {
          'verbose': {
              'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
              'datefmt': "%d/%b/%Y %H:%M:%S"
          },
          'simple': {
              'format': '%(levelname)s %(message)s'
          },
      },
      'filters': {
          'require_debug_false': {
              '()': 'django.utils.log.RequireDebugFalse'
          }
      },
      'handlers': {
          'mail_admins': {
              'level': 'ERROR',
              'filters': ['require_debug_false'],
              'class': 'django.utils.log.AdminEmailHandler'
          },
          'console': {
              'level': 'DEBUG',
              'class': 'logging.StreamHandler',
              'formatter': 'simple',
          },
      'file': {
          'level': 'INFO',
              'class': 'logging.FileHandler',
              'filename': '/home/&lt;USER&gt;/spcrm/debug.log',
      },
      },
      'loggers': {
          'django.request': {
              'handlers': ['mail_admins'],
              'level': 'ERROR',
              'propagate': True,
          },
          'investApp': {
              'handlers': ['console'],
              'level': 'DEBUG',
          }
      }
  }
  #memcache
  CACHES = {
      'default': {
          'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
          'LOCATION': '127.0.0.1:11211',
      }
  }
  #djcelery
  BROKER_URL = "amqp://&lt;USER&gt;:&lt;PASS&gt;@localhost:5672/crm"
  CELERY_RESULT_BACKEND = "database"
  CELERY_RESULT_DBURI = "postgresql://&lt;USER&gt;:&lt;PASS&gt;@localhost/spcrm"
  
  #crispy_forms theme
  CRISPY_TEMPLATE_PACK = 'bootstrap'
  
  DEFAULT_CHARSET = 'utf-8'
  DEFAULT_CURRENCY = 'PLN'
  
  LOGIN_URL = 'LogMeIn'
  LOGIN_REDIRECT_URL = 'after_login'
  # Converting warnings to errs to get line no NOT IN PRODUCTION!
  # warnings.filterwarnings(
  #         'error', r"DateTimeField received a naive datetime",
  #         RuntimeWarning, r'django\.db\.models\.fields')
  
  
  # put these two lines at the very bottom of the settings file
  import djcelery
  djcelery.setup_loader()
  </code></pre>
  
  <p><code>/etc/init/celeryd.conf</code>:</p>
  
  <pre><code>description "celeryd"
  
  start on (filesystem)
  stop on runlevel [016]
  
  respawn
  console log
  setuid &lt;USER&gt;
  setgid nogroup
  chdir /home/&lt;USER&gt;/spcrm
  
  exec /home/&lt;USER&gt;/.virtualenvs/crm/bin/python /home/&lt;USER&gt;/spcrm/manage.py celeryd -B -E -loglevel=DEBUG
  </code></pre>
  
  <p><code>/etc/init/gunicorn.conf</code>:</p>
  
  <pre><code>description "gunicorn"
  
  start on (filesystem)
  stop on runlevel [016]
  
  respawn
  console log 
  setuid &lt;USER&gt;
  setgid nogroup
  chdir /home/&lt;USER&gt;/spcrm
  
  #exec /home/&lt;USER&gt;/.virtualenvs/crm/bin/python /home/&lt;USER&gt;/spcrm/manage.py run_gunicorn -w 3 -k gevent --certfile=/home/&lt;USER&gt;/guni-cert.pem --keyfile=/home/&lt;USER&gt;uni-key.pem
  exec /home/&lt;USER&gt;/.virtualenvs/crm/bin/python /home/&lt;USER&gt;/spcrm/manage.py run_gunicorn 
  </code></pre>
  
  <p><code>/etc/nginx/sites-enabled/spcrm</code>:</p>
  
  <pre><code>server {
      listen 80;
      # If you want certain Non-SSL areas on your site, add a location block here
      # read up on the nginx docs.
      # Be sure to replace localhost in the following rule to the server name/IP address.
      return 301 https://subdomain.domain.com/;
  }
  server {
      listen  443 ssl;
      # server_name  _;
      # start mine
      ssl on;
      ssl_certificate /home/&lt;USER&gt;/guni-cert.pem;
      ssl_certificate_key /home/&lt;USER&gt;/guni-key.pem;
      ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers          HIGH:!aNULL:!MD5;
      server_name localhost;
      root /home/&lt;USER&gt;/spcrm/crm;
      access_log /var/log/nginx/spcrm.access.log;
      error_log /var/log/nginx/spcrm.error.log;
  
      location /static/{
          autoindex on;
  
          root /var/www/;
      }
  
      location / {
          proxy_pass_header Server;
          proxy_set_header Host $http_host;
          proxy_redirect off;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Scheme $scheme;
          proxy_connect_timeout 10;
          proxy_read_timeout 10;
          proxy_pass http://localhost:8000/;
      }
  
      error_page  404              /404.html;
      location = /404.html {
          root   /usr/share/nginx/html;
      }
  
      # redirect server error pages to the static page /50x.html
      #
      error_page   500 502 503 504  /50x.html;
      location = /50x.html {
          root   /usr/share/nginx/html;
      }
  }
  </code></pre>