Configurando Debian, Nginx e Gunicorn para um projeto Django



Bom Dia a todos.

Havia uma tarefa de aumentar o servidor Debian no Nginx para os projetos Django 3.x. Quebrando um monte de informações na Internet, consegui fazer isso combinando recomendações de vários sites diferentes. Se você estiver interessado em ler como configurar seu primeiro servidor para um projeto Django, então seja bem-vindo.

Vou falar um pouco sobre você para entender quem eu sou. Não sou desenvolvedor, nem programador, nem administrador de sistemas, nem tenho formação em TI. Eu sou professor de ciências da computação. Mas no trabalho, tenho que explicar aos alunos alguns pontos que estão muito distantes do curso escolar de ciência da computação, e um deles é o desenvolvimento de projetos no Django.

Configurações básicas


Para começar, já temos um servidor com o Debian 10 instalado, não deve haver problemas ao instalar o Debian. Como eu tinha uma instalação limpa, sem configurações adicionais, fui ao meu servidor via root e comecei a instalar alguns dos principais componentes para mim.

apt-get update
apt-get install -y sudo htop git curl wget unzip zip gcc build-essential make
apt-get install -y tree redis-server nginx  libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-dev python-pil ython3-pil 
apt-get install -y python3-lxml libxslt-dev python-libxml2 python-libxslt1 python-dev gnumeric libpq-dev libxml2-dev libxslt1-dev libjpeg-dev libfreetype6-dev libcurl4-openssl-dev supervisor libgdbm-dev libnss3-dev ufw

Você pode colocar tudo isso em uma instalação, mas eu recebi um erro e, nessa ordem, tudo correu bem.

Em seguida, crie um novo usuário e adicione-o ao grupo sudo para que ele possa iniciar processos em nome do superusuário.

adduser username 
usermod -aG sudo username

onde username é o nome de usuário que você usará no futuro.
Instale a versão mais recente do Python da fonte. No momento da redação deste texto, isso era 3.8.2 .

cd /home/username
curl -O https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
tar -xf Python-3.8.2.tar.xz
cd Python-3.8.2

Explicação das ações
cd — , change directory;
curl — URL. ;
tar — .

Depois de baixar a versão mais recente do Python e passar para o diretório de origem, executamos:

./configure --enable-optimizations
make -j 2

Isso nos permitirá preparar tudo o necessário para instalar o Python. Aqui, o número 2, este é o número de núcleos do processador. Você pode descobrir com o comando nproc .
Iniciamos a instalação.
make altinstall

Você pode verificar se o Python foi instalado usando o comando:

python3.8 -V

Ele produzirá uma versão do Python .
Depois disso, atualizamos o pip e instalamos os pacotes mais usados ​​para o Python .
python3.8 -m pip install -U pip
python3.8 -m pip install -U setuptools
python3.8 -m pip install pillow
python3.8 -m pip install virtualenv

Configuração do Django


Reiniciamos o sistema e passamos ao usuário que você criou. Vamos para o diretório / var / www e faça o download do nosso projeto, que é carregado no GitHub .

cd /var/www
sudo git clone LINK_TO_PROJECT

Configure os direitos para operação normal com o diretório / var / www
sudo chown -R www-data:www-data /var/www
sudo usermod -aG www-data username
sudo chmod go-rwx /var/www
sudo chmod go+x /var/www
sudo chgrp -R www-data /var/www
sudo chmod -R go-rwx /var/www
sudo chmod -R g+rwx /var/www

Pode parecer que realizamos determinadas ações e as cancelamos, mas o ponto é que primeiro removemos todas as permissões para todos e depois as atribuímos a um usuário ou grupo específico.

Vamos ao nosso projeto, criamos um ambiente virtual e o executamos:

cd djangoprojectname/
virtualenv env
source ./env/bin/activate

Se tudo estiver ativado, haverá uma linha no formato: (env) username @ server.

Entregaremos / atualizaremos os principais pacotes necessários para o nosso projeto.

pip install -U pip
pip install -U setuptools
pip install -U pillow

Colocamos Django, Gunicorn e um adaptador para o PostgreSQL.

pip install django gunicorn psycopg2-binary

Você também pode colocar os pacotes necessários para o seu projeto, uso o summernote para o texto:

pip install django-summernote

Como configuramos um firewall, precisamos criar uma exceção para ele na porta 8000 (nós o usamos por padrão, se planejamos usar outro, especifique-o):

sudo ufw allow 8000

A etapa necessária é verificar a integridade do servidor:

python3.8 manage.py runserver 0.0.0.0:8000

E acesse seu site, DOMAIN_NAME: 8000 , para garantir que tudo funcione! Mas, no momento, ainda não configuramos muito, essas são apenas configurações básicas, precisamos configurar a operação normal do servidor, conectar a estática etc.
Se o seu site não iniciar, você precisará se aprofundar nas configurações (possivelmente direitos de acesso) e ver qual pacote não foi instalado, tudo é muito individual.

Para completar, pressionando as teclas: CTRL + C a .

Em seguida, seguiremos em frente apenas se o seu projeto tiver começado, eu recomendo não seguir em frente se algo não der certo. É melhor corrigir o problema no estágio inicial do que derrubar o servidor até a raiz (demoli 3 vezes e comecei a escrever esta instrução, corrigindo todas as ações).

Verificando o trabalho de Gunicorn:

gunicorn --bind 0.0.0.0:8000 MAINAPPNAME.wsgi

MAINAPPNAME é o nome do aplicativo principal que contém settings.py .

Se o servidor estiver funcionando, siga em frente.

Para completar, premindo as teclas de: a C TRL + a C .

Definindo settings.py


Ao implantar em um servidor de produção, você precisa desativar a depuração do projeto e alterar várias configurações, fiz isso da seguinte maneira em settings.py do meu projeto.

DEBUG = False
if DEBUG:
    ALLOWED_HOSTS = ['*']
else:
    ALLOWED_HOSTS = ['HOST IP', 'DOMAIN NAIM', 'localhost']
...
STATIC_URL = '/static/'
if DEBUG:
    STATIC_DIR = os.path.join(BASE_DIR, 'static')
    STATICFILES_DIRS = [
        STATIC_DIR,
        '/var/www/static/',
    ]
else:
    STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    )
MEDIA_URL = '/media/'

No urls.py, alterei as configurações de estática e mídia.

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Não sei quanto é a decisão certa e talvez haja mais alterações corretas nesses arquivos. Mas, neste caso, basta alterar o valor de DEBUG para alternar entre desenvolvimento e publicação.

Execute o comando:

python3.8 manage.py collectstatic

Para coletar estatísticas e desativar o ambiente virtual:

deactivate

Configurar Gunicorn


Vamos abrir para personalização

sudo nano /etc/systemd/system/gunicorn.socket

Vamos escrever algumas configurações no arquivo:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Criamos a seção [Unit] para descrever o soquete, na seção [Socket] determinamos a localização do soquete e na seção [Install] precisamos instalar o soquete no momento certo.

Abra o arquivo do utilitário systemd para configurar o serviço:

sudo nano /etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=username
Group=www-data
WorkingDirectory=/var/www/djangoprojectname
ExecStart=/var/www/djangoprojectname/env/bin/gunicorn \
          --access-logfile - \
          --workers 5 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

[Install]
WantedBy=multi-user.target

Não se esqueça de indicar seu usuário, seu nome de projeto e seu ambiente virtual.

Conforme explicado, os trabalhadores são calculados como o número de núcleos do processador * 2 + 1 .
Agora lançamos e ativamos o soquete Gunicorn.

sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

E não deixe de testar se tudo funciona!

sudo systemctl status gunicorn.socket

Deve exibir informações sobre o serviço em execução.

Pressione a tecla Q para sair (necessário no layout em inglês).

file /run/gunicorn.sock

O último comando deve exibir uma mensagem sobre o arquivo.

Se o primeiro comando sudo systemctl status gunicorn.socket falhar ou se o segundo comando /run/gunicorn.sock do arquivo relatar que o arquivo gunicorn.sock não está no diretório, o soquete Gunicorn não poderá ser criado. Você precisa verificar os logs do soquete Gunicorn com o seguinte comando:

sudo journalctl -u gunicorn.socket

Veja qual é o erro e corrija-o.

Vamos seguir para testar a ativação do soquete.

sudo systemctl status gunicorn

Provavelmente você terá um registro:

Active: inactive (dead)

Até agora, tudo está indo bem.

Estabeleça uma conexão com o soquete através do enrolamento.

curl --unix-socket /run/gunicorn.sock localhost


Pode gerar erro de solicitação incorreta (400).

Tente, em vez de localhost, especificar o IP do seu servidor , se estiver tudo bem, provavelmente isso se deve às configurações do nginx que ainda não fizemos. Apenas siga em frente.

E, novamente, solicite a saída do status:

sudo systemctl status gunicorn

Active: active (running)

Se o registro for este +, ainda há muitas informações, mas não erros, tudo está bem.

Caso contrário, verificamos erros no log

sudo journalctl -u gunicorn

E reinicie os processos gunicorn

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

Configuração NGINX


Vamos criar um novo bloco de servidor para o nosso site e configurá-lo para que, ao acessar o site na barra de endereços, o servidor entenda do que e de onde obtê-lo.

sudo nano /etc/nginx/sites-available/djangoprojectname

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /var/www/djangoprojectname/static/;
    }

    location /media/ {
        alias /var/www/djangoprojectname/media/;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

Na seção sever_name, você pode especificar vários endereços separados por espaços.

Teste para erros de sintaxe:

sudo nginx -t

Se não houver erros, reinicie o servidor e dê ao nosso firewall os direitos necessários:

sudo systemctl restart nginx
sudo ufw allow 'Nginx Full'

Você também pode remover o acesso à porta 8000

sudo ufw delete allow 8000

Neste ponto, tudo deve funcionar, mas não funcionou bem até eu configurar o https. Infelizmente, não consigo explicar com o que isso está conectado, mas as estatísticas não foram carregadas, embora os arquivos de mídia tenham sido carregados normalmente.

Configuração HTTPS


Usaremos o Cerbot para configurar

sudo apt-get install certbot python-certbot-nginx
sudo certbot –nginx

E siga as instruções na tela. Se houver erros, elimine e tente novamente. Por exemplo, um erro pode ocorrer se você especificar um nome de domínio que não esteja relacionado a este servidor.
Para renovar automaticamente o certificado, digite o comando

sudo certbot renew --dry-run 

Agora estamos testando o site e tudo deve funcionar!

Se a estática ainda não aparecer, tente abrir algum arquivo css indicando o endereço completo antes dela. Se você receber um erro 403, tudo está bem, mas o problema dos direitos de acesso deve ser experimentado, tente redefinir todas as configurações de direitos para www-data para diretório / var / www . Se o erro for 404, você precisará procurar as configurações de localização nas configurações do NGINX .

Configuração do PostgreSQL


Configure o PostgreSQL e importe dados do SQLite. Se você não precisar, pule esta etapa ou siga apenas as configurações do PostgreSQL.

Crie um banco de dados e um usuário.

sudo -u postgres psql

CREATE DATABASE dbforproject;
CREATE USER projectdbuser WITH PASSWORD 'password';

Seguiremos as recomendações para o projeto Django.

Definimos a codificação padrão como UTF-8, definimos o esquema de isolamento de transação padrão como "leitura confirmada", para bloquear a leitura de transações não confirmadas. Defina o fuso horário como GMT (UTC).

ALTER ROLE projectdbuser SET client_encoding TO 'utf8';
ALTER ROLE projectdbuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE projectdbuser SET timezone TO 'UTC';

Depois disso, você precisa fornecer ao usuário que criamos o acesso para administrar o novo banco de dados:

GRANT ALL PRIVILEGES ON DATABASE dbforproject TO projectdbuser;

Após a conclusão de todos os comandos, você pode fechar a caixa de diálogo PostgreSQL usando o comando:

\q

Agora a configuração do PostgreSQL está concluída, agora vamos configurar o Django para funcionar corretamente com o PostreSQL.

Primeiro, copie os dados antigos do SQLite (se necessário). Para fazer isso, acesse seu projeto e inicie o ambiente virtual:

cd /var/www/djangoprojectname
source ./env/bin/activate
cd mainappname/
python3.8 manage.py dumpdata > datadump.json

Altere as configurações para conectar-se ao banco de dados:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'dbforproject',
        'USER': 'projectdbuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

Execute a migração para o banco de dados:

python3.8 manage.py migrate --run-syncdb

Após este shell:

python3 manage.py shell

E escreva nele:

>>> from django.contrib.contenttypes.models import ContentType
>>> ContentType.objects.all().delete()
>>> quit()

E carregue os dados enviados anteriormente do SQLite:

python3.8 manage.py loaddata datadump.json

Isso é tudo, tudo começou e funciona para mim, mas, no caso de erros, é muito individual, por isso recomendo não pular as etapas com o teste de desempenho para que você possa entender em que estágio o erro ocorreu.

Ao escrever, eu usei:

  1. www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04-ru
  2. vexxhost.com/resources/tutorials/how-to-deploy-django-on-nginx-gunicorn-with-postgres
  3. pythonworld.ru/web/django-ubuntu1604.html

All Articles