From d7927470451587ab754a67506478eb35934ef469 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Silva Date: Fri, 1 Mar 2019 16:55:13 -0300 Subject: [PATCH] =?UTF-8?q?Created=20Instala=C3=A7=C3=A3o=20em=20servidor?= =?UTF-8?q?=20de=20Produ=C3=A7=C3=A3o=20(markdown)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Instalação-em-servidor-de-Produção.md | 956 ++++++++++++++++++++++ 1 file changed, 956 insertions(+) create mode 100644 Instalação-em-servidor-de-Produção.md diff --git a/Instalação-em-servidor-de-Produção.md b/Instalação-em-servidor-de-Produção.md new file mode 100644 index 0000000..df6a1d8 --- /dev/null +++ b/Instalação-em-servidor-de-Produção.md @@ -0,0 +1,956 @@ +Instalação em servidor de Produção +================================== + +**Atualizado em:** 01/03/2019 + +-------------------------------------------------------------------------------- + +Trata-se de um exemplo para configuração de um servidor de produção para o **SAPL**. + +Requisitos de Hardware +---------------------- + +Este exemplo roda em uma maquina virtual instalada em um cluster **Proxmox** com os seguintes recursos: + +* 4GB memória RAM +* 4x CPU +* 64GB de Armazenamento + +Sistema operacional +------------------- + +O sistema operacional utilizado para esse exemplo foi Ubuntu 18.04.1 LTS. + +``` +lsb_release -a +``` + +``` +No LSB modules are available. +Distributor ID: Ubuntu +Description: Ubuntu 18.04.1 LTS +Release: 18.04 +Codename: bionic +``` + +Configuração do sistema +----------------------- + +### Atualização + +Após a instalação do SO e a configuração da rede, atualize o sistema. + +``` +sudo apt update +sudo apt upgrade +``` + +### Editor de texto + +Para melhorar as condições de trabalho quando houver necessidade de editar arquivos de texto no servidor, instale o editor de textos `vim`. + +``` +sudo apt install vim +``` + +Para tornar o `vim` o editor padrão do sistema execute o comando abaixo e em seguida escolha a opção referente ao `vim`. + +``` +sudo update-alternatives --config editor +``` + +Por último, configure o `vim` para exibir o número das linhas por padrão. + +``` +sudo vim /etc/vim/vimrc +``` + +Adicione as linhas abaixo no final do arquivo. + +``` +" Line number +set number +``` + +### Unzip + +O utilitário `unzip` deve ser instalado para realizar a extração de pacotes `.zip` se necessário. + +``` +sudo apt install unzip +``` + +### HTOP + +Instale o `htop` para monitorar sistema operacioal, seus processos, etc. + +``` +sudo apt install htop +htop +``` + +### Timezone + +A _Timezone_ padrão do servidor deve ser modificada para a região em que estamos. + +``` +sudo dpkg-reconfigure tzdata +``` + +No menu escolha, por exemplo, `America` e posteriormente `Sao_Paulo`. + +O arquivo `/etc/timezone` exibe o fuzo horário escolhido com o comando anterior. + +``` +cat /etc/timezone +``` + +``` +America/Sao_Paulo +``` + +### Locale + +Adicionado o idioma Português do Brasil e instale os pacotes de idiomas em português. + +``` +sudo dpkg-reconfigure locales +``` + +No menu, selecione as opções: + +``` +en_US.ISO-8859-1 +en_US.UTF-8 +pt_BR.ISO-8859-1 +pt_BR.UTF-8 +``` + +Escolha `pt_BR.UTF-8` como opção padrão. O comando abaixo exibe a configuração: + +``` +locale -a +``` + +``` +C +C.UTF-8 +en_US +en_US.iso88591 +en_US.utf8 +POSIX +pt_BR +pt_BR.iso88591 +pt_BR.utf8 +``` + +### Ntpdate + +Para que o servidor sincronize o seu horário, instale o utilitário `ntpdate` e crie um script no diretório `/etc/cron.hourly/` chamado `ntp-time-sync`. + +``` +sudo apt install ntpdate +sudo vim /etc/cron.hourly/ntp-time-sync +``` + +O conteúdo do arquivo é exibido na saída do comando `cat`. + +``` +cat /etc/cron.hourly/ntp-time-sync +``` + +``` +#! /bin/sh +# +ntp=$(which ntpdate) +# +$ntp -s a.ntp.br +``` + +Conceda a permissão de execução para o script. + +``` +sudo chmod +x /etc/cron.hourly/ntp-time-sync +``` + +Para efeitos de teste você pode executar o script. A saída do script pode ser vista no log padrão do sistema em `/var/log/syslog`. + +``` +sudo /etc/cron.hourly/ntp-time-sync +sudo tail -f /var/log/syslog +``` + +Segurança +--------- + +### Fail2ban + +Para implementar um nível de segurança contra ataques de força bruta instale o software `fail2ban`. + +``` +sudo apt install fail2ban +``` + +O arquivo de configuração `/etc/fail2ban/jail.conf` deve copiado para outro arquivo, para que as configurações locais possam ser aplicadas, e, para não se perderem após a atualizações do sistema. Atualizações do sistema geralmente sobrescrevem aquivos de configuração do `fail2ban`. + +``` +cd /etc/fail2ban +sudo cp jail.conf jail.d/local.conf +``` + +Por padrão o `fail2ban` bloqueia tentativas de ataque de força bruta no servidor SSH. + +Mais informações: [https://www.fail2ban.org/wiki/index.php/Main_Page](https://www.fail2ban.org/wiki/index.php/Main_Page) + +### Firewall + +Configure um firewall utilizando o `ufw`, para implementar um pouco de segurança ao servidor. + +``` +sudo apt install ufw +``` + +Configure o firewall para impedir qualquer tentativa de conexão de entrada e permitir todas as conexões de saída como padrão. + +``` +sudo ufw default deny incoming +sudo ufw default allow outgoing +sudo ufw status verbose +``` + +Em seguida, libere as portas para permitir conexões SSH, HTTP e HTTPS. + +``` +sudo ufw allow 22/tcp +sudo ufw allow 80/tcp +sudo ufw allow 443/tcp +``` + +Por último habilite o firewall. **Tenha certeza ter liberado as portas antes de habilitar o firewall.** + +``` +sudo ufw status verbose +``` + +Tudo certo? Então habilite o firewall. + +``` +sudo ufw enable +``` + +SAPL +---- + +### Usuário + +Crie o usuário sob o qual irá rodar o servidor de aplicação: + +``` +sudo groupadd --system webapps +sudo useradd --system --gid webapps --shell /bin/bash --home /var/interlegis gunicorn +``` + +### Git + +Instale o `git`: + +``` +sudo apt install git +``` + +Configure as opções globais do `git`: + +``` +git config --global user.name "Seu Nome" +git config --global user.email "seu@e-mail.sp.leg.br" +``` + +Para ver as configurações: + +``` +git config --list +``` + +### Outras Dependências + +Instalação: + +``` +sudo apt install pkg-config software-properties-common build-essential libxml2-dev libjpeg-dev libssl-dev libffi-dev libxslt1-dev curl poppler-utils antiword default-jre libpq-dev graphviz-dev graphviz python3-dev python-psycopg2 python3-setuptools python3-pip python3-venv +``` + +### PostgreSQL + +Instalação: + +``` +sudo apt install postgresql postgresql-contrib +``` + +Depois de instalado, altere a senha do administrador do `postgresql` com o utilitário `psql`. + +``` +sudo su postgres +psql +``` + +No shell do cliente do `postgresql` (`postgres=#`), rode o seguinte comando para alterar a senha do usuário `postgres`: + +``` +postgres=# alter user postgres with password 'senha-do-postgresql'; +``` + +Sair do `psql`: + +``` +postges=# \q +``` + +Na sequência, altere o arquivo `/etc/postgresql/10/main/pg_hba.conf` para permitir o uso do `psql` por outros usuário além do usuário `postgres` do sistema. + +``` +sudo vim /etc/postgresql/10/main/pg_hba.conf +``` + +A linha 85 do arquivo foi alterada. + +``` +local all postgres password +``` + +O serviço foi reiniciado. + +``` +sudo systemctl restart postgresql.service +``` + +#### Base de Dados + +Rode os seguintes comandos para criar a Base de Dados do SAPL: + +``` +sudo -u postgres psql -c "CREATE ROLE sapl LOGIN ENCRYPTED PASSWORD 'uma-senha' NOSUPERUSER INHERIT CREATEDB NOCREATEROLE NOREPLICATION;" +sudo -u postgres psql -c "ALTER ROLE sapl VALID UNTIL 'infinity';" +sudo -u postgres psql -c "CREATE DATABASE sapl WITH OWNER = sapl ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'pt_BR.UTF-8' LC_CTYPE = 'pt_BR.UTF-8' CONNECTION LIMIT = -1 TEMPLATE template0;" +``` + +Utilize a `senha-do-postgresql` criada anteriormente. + +### Virtualenvwrapper + +Instalação: + +``` +sudo pip3 install virtualenvwrapper +``` + +Diretório: + +``` +sudo mkdir -p /var/interlegis/.virtualenvs +sudo chown -R gunicorn:webapps /var/interlegis +``` + +Configuração: + +``` +sudo vim /etc/bash.bashrc +``` + +``` +# Virtualenvwrapper +export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 +export WORKON_HOME=/var/interlegis/.virtualenvs +export PROJECT_HOME=/var/interlegis/ +export VIRTUALENVWRAPPER_SCRIPT=/usr/local/bin/virtualenvwrapper.sh +source /usr/local/bin/virtualenvwrapper.sh +``` + +### Projeto + +Logar com o usuário `gunicorn`: + +``` +sudo su - gunicorn +``` + +Checar o diretório atual + +``` +pwd +``` + +``` +/var/interlegis +``` + +Clonar o repositório do SAPL: + +``` +git clone -b 3.1.x --single-branch git@github.com:interlegis/sapl.git sapl +``` + +### Ambiente Virtual + +Criar o ambiente virtual e instalar as dependecias da aplicação: + +``` +mkvirtualenv -a /var/intelegis/sapl -p python3 -r requirements/requirements.txt sapl +``` + +### Configuração do SAPL + +Criar o arquivo `sapl/.env`: + +``` +vim sapl/.env +``` + +Inserir o seguinte conteúdo (Atenção na segunda linha SECRTE_KEY): + +```env +DATABASE_URL = postgresql://sapl:uma-senha@localhost:5432/sapl +SECRET_KEY = '&*&*&-chave-gerada-com-o-comando-abaixo-*&*&*&*&*&' +DEBUG = False +EMAIL_USE_TLS = True +EMAIL_PORT = 587 +EMAIL_HOST = 'smtp.interlegis.leg.br' +EMAIL_HOST_USER = 'sapl@cidade.uf.leg.br' +EMAIL_SEND_USER = 'sapl@cidade.uf.leg.br' +EMAIL_HOST_PASSWORD = 'uma-senha' +``` + +Gerar a chave secreta e substituir no arquivo `sapl/.env`: + +``` +python manage.py generate_secret_key +``` + +Gerar a base de dados: + +``` +./manage.py migrate +``` + +Gerar arquivos estáticos: + +``` +./manage.py collectstatic --no-input --clear +``` + +Copiar o arquivo que servirá para inicialização do sistema: + +``` +cp gunicorn-start.sh ../gunicorn-start.sh +``` + +_A cópia desse arquivo é opcional. Dependendo que como você prefere iniciar o SAPL, será preciso promover ajustes nesse aquivo. Abaixo segue o arquivo com as mundanças necessárias para inicialização do SAPL nesse exemplo:_ + +``` +#!/bin/bash + +# As seen in http://tutos.readthedocs.org/en/latest/source/ndg.html + +SAPL_DIR="/var/interlegis/sapl" + +# Seta um novo diretório foi passado como raiz para o SAPL +# caso esse tenha sido passado como parâmetro +if [ "$1" ] +then + SAPL_DIR="$1" +fi + +NAME="SAPL" # Name of the application (*) +DJANGODIR=/var/interlegis/sapl/ # Django project directory (*) +SOCKFILE=/var/interlegis/sapl/run/gunicorn.sock # we will communicate using this unix socket (*) +USER=gunicorn # the user to run as (*) +GROUP=webapps # the group to run as (*) +NUM_WORKERS=9 # how many worker processes should Gunicorn spawn (*) + # NUM_WORKERS = 2 * CPUS + 1 +TIMEOUT=60 +MAX_REQUESTS=100 # number of requests before restarting worker +DJANGO_SETTINGS_MODULE=sapl.settings # which settings file should Django use (*) +DJANGO_WSGI_MODULE=sapl.wsgi # WSGI module name (*) + +echo "Starting $NAME as gunicorn on base dir $SAPL_DIR" + +# parameter can be passed to run without virtualenv +if [[ "$@" != "no-venv" ]]; then + # Activate the virtual environment + cd $DJANGODIR + source /var/interlegis/.virtualenvs/sapl/bin/activate + export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE + export PYTHONPATH=$DJANGODIR:$PYTHONPATH +fi + +# Create the run directory if it doesn't exist +RUNDIR=$(dirname $SOCKFILE) +test -d $RUNDIR || mkdir -p $RUNDIR + +# Start your Django Unicorn +# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon) +exec gunicorn ${DJANGO_WSGI_MODULE}:application \ + --name $NAME \ + --log-level debug \ + --timeout $TIMEOUT \ + --workers $NUM_WORKERS \ + --max-requests $MAX_REQUESTS \ + --user $USER \ + --access-logfile /var/log/gunicorn/sapl-access.log \ + --error-logfile /var/log/gunicorn/sapl-error.log \ + --bind=unix:$SOCKFILE +``` + +Criar o diretório para os logs: + +``` +sudo mkdir -p /var/log/gunicorn/ +sudo chown -R gunicorn\: /var/log/gunicorn/ +``` + +### SOLR + +Essa parte é opcional, mas vale a pena. + +Baixar e executar o `SOLR`: + +``` +cd /var/intelegis/sapl +curl -LO https://archive.apache.org/dist/lucene/solr/7.4.0/solr-7.4.0.tgz +tar xvzf solr-7.4.0.tgz +cd solr-7.4.0 +./bin/solr start -c +``` + +_O comando `./bin/solr start -c` deve ser executado novamente caso o servidor seja reiniciado._ + +Inserir as seguintes linhas no final do arquivo `sapl/.env`. + +``` +USE_SOLR = True +SOLR_COLLECTION = 'sapl' +SOLR_URL = 'http://localhost:8983' +``` + +Criar a coleção `sapl` no servidor `solr` + +``` +python solr_api.py -u http://localhost:8983 -c sapl -s 1 -rf 1 -ms 1 +``` + +Criar o indice: + +``` +./manage.py rebuild_index +``` + +### Let's Encrypt + ++ [https://letsencrypt.org/](https://letsencrypt.org/) + +As páginas servidas pelo `nginx` funcionam com o protocolo HTTPS, utilizando certificados emitidos pelo serviço de "CA", Autoridade Certificadora, Let's Encrypt. +Para que o processo de obtenção dos certificados funcione, antes de configurar os subdomínios é preciso instalar o **certbot**, que é recomendado na documentação de uso do Let's Encrypt [https://letsencrypt.org/getting-started/](https://letsencrypt.org/getting-started/). + +``` +sudo apt install certbot +sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 +``` + +O comando para renovar os certificados, que expiram a cada 3 meses, deve ser inserido no **crontab**. + +``` +sudo crontab -e +``` + +``` +45 3 * * * certbot renew --quiet +``` + +### Nginx + +Para instalar o _Nginx_ no sistema operacional _Ubuntu Server 18.04_ foi utilizado o repositório padrão da distribuição, portanto: + +``` +sudo apt install nginx +``` + +#### VHost padrão + +Aproveitamos a funcionalidade de "VirtualHosts". + +O arquivo `default` localizado no diretório `/etc/nginx/sites-available`, reposnável pelo "VirtualHosts" padrão do servidor `nginx` deve ser alterado conforme segue: + +``` +cd /etc/nginx/sites-available +sudo cp default default.dist +sudo vim default +``` + +```nginx +# +### default - server configuration +# + +server { + + ### HTTP ### + + ################################################################## + # Port that the web server will listen on. + ### + listen 80 default_server; + listen [::]:80 default_server; + ### + + ################################################################## + # Host that will serve this project. + ### + server_name _; + ### + + ################################################################## + # The location of our projects public directory. + ### + root /var/www/html; + ### + + ################################################################## + # Point index to the app front controller. + ### + index index.html index.htm index.nginx-debian.html; + ### + + ################################################################## + # Useful logfor debug. + ### + access_log /var/log/nginx/default.access.log; + error_log /var/log/nginx/default.error.log; + rewrite_log on; + ### + + ################################################################## + # Redirect to sapl.municipio.uf.leg.br + ### + return 301 https://sapl.municipio.uf.leg.br; + ### + +} +``` + +#### VHost sapl + +Copiar o diretório `DocumentRoot` do Vhost padrão do `nginx`: + +``` +sudo cp /var/www/html /var/www/sapl +sudo chown -R www-data\: /var/www/sapl +``` + +Criar o arquivo de configuração: + +``` +cd /etc/nginx/sites-available +sudo vim sapl.municipio.uf.leg.br.conf +``` + +Inicialmente o arquivo de configuração deve ser criado com o seguinte conteúdo: + +```nginx +# +## sapl.municipio.uf.leg.br - server configuration +# + +server { + + ### HTTP ### + + ################################################################## + # Port that the web server will listen on. + ### + listen 80; + listen [::]:80; + ### + + ################################################################## + # Host that will serve this project. + ### + server_name sapl.municipio.uf.leg.br; + ### + + ################################################################## + # The location of our projects public directory. + ### + root /var/www/sapl; + ### + + ################################################################## + # Point index to the app front controller. + ### + index index.html index.htm index.nginx-debian.html; + ### + + ################################################################## + # Useful logs for debug. + ### + access_log /var/log/nginx/sapl.municipio.uf.leg.br.access.log; + error_log /var/log/nginx/sapl.municipio.uf.leg.br.error.log; + rewrite_log on; + ### + +} +``` + +Assim, pode-se habilitar o Vhost `sapl.municipio.uf.leg.br`: + +``` +sudo ln -s /etc/nginx/sites-available/sapl.municipio.uf.leg.br.conf /etc/nginx/sites-enabled/sapl.municipio.uf.leg.br.conf +``` + +Na sequência, após checar se está tudo certo com a configuração dos Vhosts no `nginx`, + +``` +sudo nginx -t +``` + +o serviço deve ser reiniciado: + +``` +sudo systemctl restart nginx.service +``` + +Para obter o Certificado Let's Encrypt, rode o seguinte comando: + +``` +sudo certbot certonly --webroot -w /var/www/sapl -d sapl.municipio.uf.leg.br +``` + +Após a obtenção do certificado, altere a configuração do aquivo `/etc/nginx/sites-available/sapl.municipio.uf.leg.br.conf`, para o seguinte conteúdo: + +``` +sudo vim /etc/nginx/sites-available/vim sapl.municipio.uf.leg.br.conf +``` + +```nginx +# +## sapl.municipio.uf.leg.br - server configuration +# + +upstream sapl.municipio.uf.leg.br { + server unix:/var/interlegis/sapl/run/gunicorn.sock fail_timeout=0; +} + +server { + + ### HTTP ### + + ################################################################## + # Port that the web server will listen on. + ### + listen 80; + listen [::]:80; + ### + + ################################################################## + # Host that will serve this project. + ### + server_name sapl.municipio.uf.leg.br; + ### + + ################################################################## + # The location of our projects public directory. + ### + root /var/www/sapl; + ### + + ################################################################## + # Point index to the app front controller. + ### + index index.html index.htm index.nginx-debian.html; + ### + + ################################################################## + # Redirect to HTTPS + ### + return 301 https://$server_name$request_uri; + ### + + ################################################################## + # Useful logs for debug. + ### + access_log /var/log/nginx/sapl.municipio.uf.leg.br.access.log; + error_log /var/log/nginx/sapl.municipio.uf.leg.br.error.log; + rewrite_log on; + ### + +} + +server { + + ### HTTPS ### + + ################################################################## + # Port that the web server will listen on. + ### + listen 443 ssl; + listen [::]:443 ssl; + ### + + ################################################################## + # SSL configuration + ### + ssl_certificate /etc/letsencrypt/live/sapl.municipio.uf.leg.br/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/sapl.municipio.uf.leg.br/privkey.pem; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + ### + + ################################################################## + # Host that will serve this project. + ### + server_name sapl.municipio.uf.leg.br; + ### + + ################################################################## + # Redirect server error pages to the static page /50x.html + ### + error_page 500 502 503 504 /500.html; + location = /500.html { + root /var/interlegis/sapl/sapl/static/; + } + ### + + ################################################################## + # Point index to the app static files. + ### + location /static/ { + alias /var/interlegis/sapl/sapl/collected_static/; + } + ### + + ################################################################## + # Point index to the app media files. + ### + location /media/ { + alias /var/interlegis/sapl/sapl/media/; + } + ### + + ################################################################## + # URLs to attempt, including pretty ones. + ### + location / { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_redirect off; + if (!-f $request_filename) { + proxy_pass http://sapl.municipio.uf.leg.br; + break; + } + } + ### + + ################################################################## + # Max upload file size. + ### + client_max_body_size 4M; + ### + + ################################################################## + # Set header expirations + ### + add_header Strict-Transport-Security "max-age=63072000"; + ### + + ################################################################## + # Security + ### + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + ### + + ################################################################## + # Useful logfor debug. + ### + access_log /var/log/nginx/sapl.municipio.uf.leg.br.access.log; + error_log /var/log/nginx/sapl.municipio.uf.leg.br.error.log; + rewrite_log on; + ### + + ################################################################## + # Compressing. + ### + gzip on; + gzip_comp_level 5; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; + + gzip_types + application/atom+xml + application/javascript + application/json + application/ld+json + application/manifest+json + application/rss+xml + application/vnd.geo+json + application/vnd.ms-fontobject + application/x-font-ttservidores.legislativo + application/x-web-appservidores.legislativoanifest+json + application/xhtml+xmlservidores.legislativo + application/xml + font/opentype + image/bmp + image/svg+xml + image/x-icon + text/cache-manifest + text/css + text/plain + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + ### + +} +``` + +Por fim, cheque se está tudo certo com a configuração dos Vhosts no `nginx`, + +``` +sudo nginx -t +``` + +e reinicie o servidor: + +``` +sudo systemctl restart nginx.service +``` + +### Supervisor + +O `supervisor` fará com que o `gunicorn` seja executado de maneira automatica no servidor, mantendo o SAPL no ar mesmo que ocorram reinicializações do sistema operacional. + +``` +sudo apt install supervisor +cd /etc/supervisor/conf.d +sudo vim gunicorn.conf +``` + +``` +[program:gunicorn] +command = /var/interlegis/gunicorn-start.sh +process_name=%(program_name)s +directory = /var/interlegis/sapl +user = gunicorn +stdout_logfile = /var/log/gunicorn/sapl-std.log +stderr_logfile = /var/log/gunicorn/sapl-err.log +``` + +Reinicie o Supervisor + +``` +sudo systemctl restart supervisor.service +``` + +Autoria: Getulio Vinicius Teixeira da Silva +Câmara Municipal de Franca - São Paulo. \ No newline at end of file