Configurando servidor linux para hospedagem de sites

Ricardo Baltazar
Editora Globo
Published in
17 min readSep 9, 2018

Ubuntu 16, OpenSSH, Fail2Ban, UFW, Python 3.7, Django, Gunicorn, Supervisor, Nginx, Certbot, HTTP2, HTTPS. Como juntar tudo isso.

Photo by imgix on Unsplash

Sobre o texto

Esse post vai mostrar um serie de configurações que são o básico para criar um servidor simples de hospedagem de sites.

  • Estou ignorando alguns pontos importantes como a criação de usuário para logar no SO e desabilitar o root.
  • Também não entro no mérito de gerar uma chave SSH e fechar a conexão por senha.

Esses dois pontos são importantes e não devem ser negligenciados, eu costumo fazer isso no final de toda minha configuração. Como esse post está sendo escrito conforme eu vou configurando um novo servidor, então eu vou termina-lo antes dessas mudanças, realmente não sei quando vou faze-las.

Porque uma VPN e não um Cloud?

A primeira coisa que temos que avaliar é qual o seu objetivo? Criar um site para um "cliente" e não ter que se preocupar com hospedagem e apenas mandar o boleto para ele? Se for, coloca em um LocalWeb da vida e larga lá.

Se você quer aprender sobre infra e também quer conseguir um SEO decente, fazer http2, um https A+ e vai assumir a administração disso, que é o meu caso, você tem duas opções: Um Cloud da vida com Kubernets ou pegar um VPN.

Um VPN é muito mais barato, eu uso uma maquina da VPSDime, que foi o melhor custo benefício que achei. O Cloud se tonar muito caro, o problema do Cloud não é a máquina você vai pegar, o Load Balancing vai sair mais caro do que essa maquina que estou usando, procurem sobre o custo real de um serviço Kubernets, imagina toda a infraestrutura além do LB.

Outra coisa é tecnologia de ponta, por exemplo, o HTTP2 permite fazer push e até essa data que estou escrevendo o CDN da Azure não tem esse suporte.

Lógico que o Cloud tem MUITAS vantagens sobre um VPN, nem vou discutir isso, mas no meu caso que não tenho dinheiro, gosto de usar tudo de ponta, alem de conseguir aprender mais a fundo o que tem rodando por trás de tudo aí acabou então optando pela VPN.

Primeiro Login

Primeiro login no servidor

Firewall

Instalando e configurando o firewall

Execute sudo apt-get install ufw e espere ele terminar, aqui é só executar e esperar, assim que terminar verifique o status com ufw status e você verá Status: inactive . Ok, ufw instalado, vamos configurar.

Por padrão o ufw nega todas as conexões que chegam e autoriza todas as que saem, então, qualquer coisa que tentar conectar no servidor será negada, mas qualquer programa rodando dentro pode sair para se conectar ao mundo. Então, antes de você sair configurando é importante saber como seria possível resetar as configurações defaults dele, vai que fazemos alguma besteira, certo? Para fazer isso basta executar:

sudo ufw default deny incoming
sudo ufw default allow outgoing

Ou faça um sudo ufw reset que também funciona.

Vamos começar liberando apenas as conexões ssh , isso porque se você ligar o firewall e estiver negando todos de fora, você também não vai conseguir se conectar mais. Isso não é raro de acontecer entre os amadores, vai por mim, eu já fiz isso rsrs.

Uma coisa legal no ufw é que ele tem uma inteligência para criar regras baseada nas aplicações que você tem instaladas, execute ufw app list e se o servidor é novo como o meu, o resultado será igual a esse:

Para você entender melhor o que vai acontecer a seguir, execute ufw app info OpenSSHe veja que ele mostra 22/tcp que é o que o OpenSSH precisa para funcionar.

Agora vamos liberar a aplicação com sudo ufw allow OpenSSH e isso vai funcionar porque existe um profile com o nome OpenSSH já informando o que ele precisa que seja liberado / barrado para funcionar.

Precisamos ligar o firewall, execute sudo ufw enable , digite y e confirme.

Vamos verificar o status do firewall com ufw status

Podemos ver que o OpenSSH está liberado e com isso terminamos as configurações de firewall, mais tarde vamos voltar aqui e liberar a porta 80 e 443 para que possamos hospedar http e https aqui.

Fail2Ban

Bom, abrindo a porta 22 para conexões ssh nós criamos um problema, o que impediria de alguém ficar batendo infinitamente nessa porta tentando pegar a sua senha.

Para impedir esse tipo de coisa vamos utilizar o Fail2ban . Ele é um sistema que fica monitorando os principais logs do seu servidor buscando por ataques automatizados e adicionando / removendo regras no seu iptable para bloquear / desbloquear IPs. Tudo isso é configurável, mas vamos com o default mesmo.

É importante que você use o Fail2Ban como um segurança a mais no servidor, ele não substitui nenhum outro sistema de segurança.

Instale executando o comando apt-get install fail2ban e espere, aqui também não tem nada de mais, é uma instalação simples.

Ele primeiro lê as configurações do arquivo .conf primeiro e depois do .local e se existir a mesma configuração nos dois arquivos ele vai usar o que tem no arquivo .local .

Como o seguro morreu de velho, vamos fazer uma cópia do arquivo .conf e mudar o nome dele para .local e alterar somente o .local . Com isso, qualquer problema basta deletar esse arquivo e ainda vamos ter o .conf com tudo configurado com o default.

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Bom, como eu sou um dos milhões que o SO já ajuda a sair do Vim , eu resolvi usar alguma coisa mais simples como nano para editar os meus arquivos no servidor. E essa é a hora que vamos configurar nosso arquivo .local . Execute nano /etc/fail2ban/jail.local e procure, logo no início a linha #enable = true , remova essa # e salve o arquivo.

Use o comando tail -f /var/log/fail2ban.log e tente conectar de outro lugar no seu servidor errando a senha. Não use a sua wi-fi para não banir o seu IP. Você verá um log parecido com o abaixo:

Da para ver o ban executado na penultima linha ali.

Voltando no dia seguinte e olhando o log, já da para ver que algum outro IP tentou se conectar ao servidor:

Isso vai acontecer até a eternidade, por isso é importante a configuração do Fail2Ban.

Python 3.7

Como é um servidor novo, vamos instalar um Python novo, nada mais justo, certo? Para instalar o python 3.7 nessa versão de Ubuntu basta seguir esse script:

# Install requirements
apt-get install -y build-essential
apt-get install -y checkinstall
apt-get install -y libreadline-gplv2-dev
apt-get install -y libncursesw5-dev
apt-get install -y libssl-dev
apt-get install -y libsqlite3-dev
apt-get install -y tk-dev
apt-get install -y libgdbm-dev
apt-get install -y libc6-dev
apt-get install -y libbz2-dev
apt-get install -y zlib1g-dev
apt-get install -y openssl
apt-get install -y libffi-dev
apt-get install -y python3-dev
apt-get install -y python3-setuptools
apt-get install -y wget
apt-get install -y libmysqlclient-dev
# Prepare to build
mkdir /tmp/Python37
cd /tmp/Python37

# Pull down Python 3.7, build, and install
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
tar xvf Python-3.7.0.tar.xz
cd /tmp/Python37/Python-3.7.0
./configure
make altinstall

Foi retirado dessa resposta do SO.

Nginx

Vamos agora configurar o nosso Nginx. A ideia aqui é a hospedagem de múltiplos sites e por isso vamos configurar cada site em um config diferente.

Para instalar basta executar sudo apt-get install nginx e esperar. Lembra do nosso firewall? Agora vamos liberar o Nginx para que o mundo possa ver nossas portas 80e 443.

Execute ufw app list para ver como agora existe uma nova app nos profiles:

Como eu quero configurar ambas as portas, vamos habilitar Nginx Full com o comando sudo ufw allow 'Nginx Full'

sudo ufw status para verificar se correu tudo bem, podemo ver agora o Nginx Full na lista como ALLOW .

Agora vamos ver se o Nginx está funcionando. Use systemctl status nginx e procure por Active: active (running) . Se está assim, podemos continuar.

Ah, acesse o seu navegado com o IP do seu servidor e veja o resultado:

Para ver um domínio funcionando basta configurar o seu DNS agora, eu configurei um subdomínio no meu domínio para fazer o teste. Usei o nome de test e apontei para o meu IP, no GoDaddy ficou como a imagem abaixo:

Agora ao acessar o subdomínio aparece o mesmo Nginx:

Mas nesse caso, o nosso Nginx ainda está respondendo com o arquivo de configuração default dele. Antes de criar um novo arquivo de configuração, vamos terminar de configurar o servidor e no momento que tivermos um Django rodando já conectado no MySQL voltamos no Nginx.

MySQL

Para instalar o MySQL execute sudo apt-get install mysql-server , durante a instalação ele vai exibir a imagem abaixo pedindo a senha do usuário root . Escolha a senha e não a perca, você vai precisar.

Agora execute mysql_secure_installation , isso vai configurar o servidor para que ele fique mais seguro. Você vai precisar informar a senha do root. Ele vai te fazer várias perguntas, você pode dar y para tudo, menos para mudar a senha do root porque você acabou de escolher uma.

Você pode verificar o status do serviço com o comando systemctl status mysql.service :

Para verificar a versão e outros dados do servidor execute mysqladmin -p -u root version , ele vai te pedir a senha e depois vai te retornar a versão:

Vamos criar um banco e um usuário para o nosso site. Esse processo deve ser feito toda vez que você for hospedar um site novo, a ideia é que cada site seu se conecte com um usuário próprio que tenha apenas permissões para um único banco.

Primeiro, vamos conectar no MySql: mysql -u root -p

Crie um novo banco de dados create database seu-banco; e depois veja os existentes show databases;

Agora vamos criar o usuário e dar os devidos acessos:

CREATE USER 'criatorio'@'localhost' IDENTIFIED BY 'SENHA_DO_USU';
GRANT ALL ON criatorio.* TO 'criatorio'@'localhost';
FLUSH PRIVILEGES;

Os comandos acima fizeram:

1 — Criar um usuário chamado criatorio que pode acessar via localhost com a senha SENHA_DO_USU

2 — Garantimos todos ALL acesso a todas as tabelas do banco de dados criatorio ( criatorio.* ) ao usuário criatorio@localhost .

3 — Atualizamos os privilégios para ele começarem a funcionar.

Django

Criando a estrutura onde ele será hospedado no servidor:

Basta rodar o seguinte script:

mkdir /var/www/criatorio
cd /var/www/criatorio
python3.7 -m venv .venv

Crie um arquivo chamado my.cnf na raiz do projeto com o seguinte conteúdo:

[client]
database = criatorio
user = criatorio
password = 'SENHA_DO_USU'
default-character-set = utf8

Vamos apontar o settings do Django para ler esse arquivo na hora de se conectar no banco de dados, isso vai facilitar os deploys no seu dia-a-dia. Aqui não adianta usar variável de ambiente, como se faz em ambientes de containers porque teremos vários sites dividindo o mesmo SO.

Na sua máquina agora, vamos atualizar seu django com pip install -U django . Criar um novo projeto com django-admin startproject criatorio entrar no projeto criado cd criatorio e executa-lo python manage.py runserver . Agora entre em localhost:8000 e você vai ver o seu site rodando. Bom, qualquer dúvida com esses passo você pode tirar na documentação oficial.

Ah, crie também um arquivo com o nome requirements.txt com o seguinte conteúdo:

django==2.1.1
mysqlclient==1.3.13
gunicorn==19.9.0

Vamos mudar algumas configurações no seu settings.py :

Procure por ALLOWED_HOSTS e mude para:

ALLOWED_HOSTS = ['seudominio.com', 'www.seudominio.com']

Agora o seu DATABASES deve ser apontado para o seu arquivo my.cnf :

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': '/var/www/criatorio/my.cnf',
},
}
}

Adicione essa linha:

STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), "criatorio/static")

Agora que estamos dentro da pasta do seu projeto rodando vamos enviar os arquivos para o servidor, eu vou usar o scp para isso. Abaixo existem três comandos, o primeiro copia apenas o arquivo manage.py para o diretório do servidor, o segundo copia o arquivo requirements.txt e o terceiro copia a pasta criatorio com todos os arquivos dentro.

scp manage.py root@SEU_IP:/var/www/criatorio/
scp requirements.txt root@SEU_IP:/var/www/criatorio/
scp -r criatorio root@SEU_IP:/var/www/criatorio/

Voltando ao servidor temos nosso site devidamente organizado:

Agora é ativar o ambiente virtual e rodar a instalação do requirements.txt :

source .venv/bin/activate
pip install -r requirements.txt

Depois dele instalado vamos rodar para ver se ele funciona python manage.py runserver :

A mensagem em vermelho é porque não executamos o migrations ainda. Aperte Control C para parar e agora vamos executar tudo o que precisamos para criar nossas tabelas e o super usuário:

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
python manage.py collectstatic

Gunicorn

Gunicorn é um dos servidores mais indicados para colocar uma aplicação Python rodando. Vamos configura-lo agora.

Crie um arquivo chamado gunicorn-start.sh na raiz do projeto com o seguinte conteúdo:

#!/bin/bashNAME="criatorio"                                # Name of the application
DJANGODIR=/var/www/criatorio/ # Django project directory
SOCKFILE=/var/www/criatorio/run/gunicorn.sock # we will communicate using this unix socket
USER=www-data # The user to run as
GROUP=www-data # The group to run as
NUM_WORKERS=2 # How many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=criatorio.settings # Which settings file should Django use
DJANGO_WSGI_MODULE=criatorio.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"# Activate the virtual environment
cd $DJANGODIR
source /var/www/criatorio/.venv/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user $USER \
--bind=unix:$SOCKFILE

Agora vamos +x para tornar o arquivo executável.

chmod +x gunicorn-start.sh

Execute o arquivo e veja se a sua aplicação será executada:

./gunicorn-start.sh

Supervisor

Esse cara é quem vai manter o seu site rodando, se alguma coisa acontecer no servidor, ele reiniciar, der algum erro ou qualquer outra coisa que faça o seu processo parar o supervisor vai colocar ele para rodar novamente.

Se você está seguindo passo-a-passo que estou fazendo, vai precisar mudar o dono da pasta run, rode o segundo comando:

sudo chown -R www-data:www-data /var/www/criatorio/run

Primeiro, vamos instalar com sudo apt-get install supervisor . É uma instalação simples, basta esperar terminar. Para verificar se está tudo certo execute sudo service supervisor status:

Primeiro crie o seguinte diretório: mkdir /var/www/criatorio/logs .

Agora crie um arquivo de configuração no diretório do supervisor: nano /etc/supervisor/conf.d/criatorio.conf . O conteúdo deve ser:

[program:criatorio]
command = /var/www/criatorio/gunicorn-start.sh ; Start app
user = www-data ; User to run as
stdout_logfile = /var/www/criatorio/logs/gunicorn-supervisor.log ; Where to write log messages
redirect_stderr = true

Agora execute os dois comandos abaixo:

sudo supervisorctl reread
sudo supervisorctl update

Agora sempre que quiser verificar o status do seus sites digite sudo supervisorctl status :

Certbot

Esse é o cara que vai fazer nosso HTTPS. Vamos instalar:

sudo apt-get update
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install -y python-certbot-nginx

Confirme o que precisar confirmar e deixa ele instalar normalmente.

Certbot e Nginx

O Certbot vem com um plugin do Nginx, basta usar --nginx na hora de gerar o certificado, aqui vamos utilizar esse plugin e para funcionar vamos precisar fazer um novo arquivo de configuração:

nano /etc/nginx/sites-available/criatorioimperiodasaves.com

Agora use a configuração abaixo:

upstream criatorio_app_server {
server unix:/var/www/criatorio/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name criatorioimperiodasaves.com;
return 301 $scheme://www.criatorioimperiodasaves.com$request_uri;
}
server {listen 80;server_name www.criatorioimperiodasaves.com;client_max_body_size 3m;access_log /var/www/criatorio/logs/nginx-access.log;
error_log /var/www/criatorio/logs/nginx-error.log;
location /static/ {
autoindex off;
alias /var/www/criatorio/static/;
}
location /media/ {
autoindex off;
alias /var/www/criatorio/media/;
}
location / {
try_files $uri @criatorio_backend;
}
location @criatorio_backend {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://criatorio_app_server;
}
}

Vamos criar o link para sites-enabled e reiniciar o Nginx, após isso verifique o status:

sudo ln -s /etc/nginx/sites-available/criatorioimperiodasaves.com /etc/nginx/sites-enabled/
sudo service nginx restart
systemctl status nginx.service

Bom, esse domínio que eu coloquei no nome do arquivo e nas configurações é um domínio do meu irmão que estou usando para esse post, estou escrevendo conforme vou executando a configuração.

Agora, com a configuração atual, se você abrir direto o IP do servidor ele vai abrir a página do Nginx e se vc abrir o domínio criatorioimperiodasaves.com ele vai abrir a home do Django.

Isso acontece porque o arquivo default de configuração do Nginx ainda está na pasta sites-enabled , a ideia é o acesso via IP não mostrar essa página, para isso, vamos remover esse link:

rm /etc/nginx/sites-enabled/default
sudo service nginx restart

Agora tente acessar via IP novamente e ele vai redirecionar para o Django, isso porque o Django é o único que existe.

Vamos agora configurar o HTTPS, com o comando abaixo ele vai gerar o certificado e também configurar o nosso Nginx para funcionar.

sudo certbot --nginx -d criatorioimperiodasaves.com -d www.criatorioimperiodasaves.com

Veja abaixo o log de execução do comando.

root@ricardo:~# sudo certbot --nginx -d criatorioimperiodasaves.com -d www.criatorioimperiodasaves.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): ricardobchaves6@gmail.com
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Starting new HTTPS connection (1): supporters.eff.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for criatorioimperiodasaves.com
http-01 challenge for www.criatorioimperiodasaves.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/criatorioimperiodasaves.com
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/criatorioimperiodasaves.com
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/criatorioimperiodasaves.com
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/criatorioimperiodasaves.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled
https://criatorioimperiodasaves.com and https://www.criatorioimperiodasaves.com
You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=criatorioimperiodasaves.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.criatorioimperiodasaves.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/criatorioimperiodasaves.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/criatorioimperiodasaves.com/privkey.pem
Your cert will expire on 2018-12-08. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

Atualizando o site agora, seremos direcionados para HTTPS:

Para verificar se o renew do certificado vai funcionar digite sudo certbot renew --dry-run e veja que ele vai conseguir simular o renew com sucesso.

HTTP2

Já existe um issue aberto no GitHub para adicionar suporte ao http2 no Certbot, enquanto isso não acontece, vamos precisar configurar na mão.

Edite o arquivo de configuração:

nano /etc/nginx/sites-available/criatorioimperiodasaves.com

Procure pelas duas linhas assim:

listen 443 ssl; # managed by Certbot

E mude para:

listen 443 ssl http2; # managed by Certbot

Restar o Nginx:

sudo service nginx restart

Você pode agora testar o seu http2 nessa ferramenta:

Vamos agora testar nosso HTTPS nessa ferramenta, e veremos que ganhamos um A, parece bom, mas bom mesmo é um A+:

Antes do passo abaixo, saiba que algumas coisa da home do Django vão quebrar porque ele vai incluir o Content-Security-Policy e se você não quiser lidar com isso agora pare por aqui, porque não vou falar sobre a correção desse problema, mas caso queira um certificado A+ e depois resolve o resto então siga em frente.

Para ganhar um A+ vamos trocar o conteúdo do arquivo /etc/letsencrypt/options-ssl-nginx.conf :

Para esse conteúdo, basta editar, apagar tudo e colocar o conteúdo abaixo:

ssl_session_cache shared:le_nginx_SSL:1m;
ssl_session_timeout 1d;
ssl_session_tickets off;

ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;

ssl_stapling on;
ssl_stapling_verify on;

add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload;";
add_header Content-Security-Policy "default-src 'none'; frame-ancestors 'none'; script-src 'self'; img-src 'self'; style-src 'self'; base-uri 'self'; form-action 'self';";
add_header Referrer-Policy "no-referrer, strict-origin-when-cross-origin";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";

Faça o teste novamente e está lá! Nosso A+.

Bom pessoal, agora para adicionar outros sites basta seguir os passos descritos acima novamente.

Ficou um pouco extenso, mas a ideia era dar um overview de como seria um servidor para hospedagem.

Mais uma vez lembrando, sou backend e nunca trabalhei profissionalmente com infra, mas é uma área que eu gosto e conhecer servidor faz parte de ser um backend na minha opinião.

Bom, tudo isso aí eu peguei de uma serie de artigos da DigitalOcean, Linode entre outros, vale muito a pena ler tudo o que eles tem lá.

Faltou falar sobre como lidar com logs, fiz outro post sobre isso, leia aqui.

Grande abraços para todos.

--

--