Montando Servidor PHP, Mysql e NodeJs
Estou trazendo esse topico por alguns motivos:
- Manter um histórico para que futuramente as vezes eu possa necessitar
- Caso alguem necessite =)
- Redução de custos e escabilidade
- Dificuldade encontradas no balanceamento do Nginx, Mysql e PHP-FPM
Hoje o cenário é que possuo vários sistemas todos na Hostinger porem esbarrei com algumas restrições que não foi tão agradavel, não falando mal apenas parou de atender o que eu precisava fiquei quase 4 anos com eles sem nenhum problema porem o projeto cresceu. As LandsPages e gerenciamento de DNS continuam na Hostinger.
Os serviços englobam:
- Servidor de PHP
- Servidor Mysql
- Servidor NodeJs rodando Biblioteca WhatsApp - Baileys
- Sistema de Cobranças com ASAAS
- Sistema de Envio de mensagens
- Sistema e-commerce Local
- Servidor de DNS
- Servidor de CRON
As configurações foram
- Servidor dedicado da Contaboo (não me julguem hehe) 20 CPU e 256 GB Memoria R$ 800/Mês
- Nginx
- PHP-FPM 7.4
- Mysql
- UFW
- GIT
- NPM
- PM2
- CERTBOT
As configurações abaixo faz as instalações das bibliotecas e através do UFW faz a segurança de tudo liberando acesso apenas pelo http, https e SSH
sudo apt update
sudo apt upgrade
sudo apt install nginx
sudo apt install mysql-server
sudo apt install php-fpm
sudo apt install php7.4-fpm
sudo apt install phpmyadmin
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt install nodejs
sudo apt install ufw ##Firewall ufw, liberar https, http, e SSH
sudo ufw allow http
sudo ufw allow https
sudo ufw allow ssh
sudo ufw enable
sudo apt install git
sudo apt install npm
npm install pm2 -g
sudo apt install python3-certbot-nginx
Gerenciamento de DNS na Hostigner
- No painel administrativo ir até "Avançado"
- Editor de Zona DNS
- Apontar um subdominio para o servidor da Contabo
Tipo: A
Name: api.SITE.com.br
Aponta para: Servidor Contabo xxx.xxx.xxx.xxx
TTL: 14400
Configurações do NGINX e CERTBOT
- Apontamento das requisições para suas pastas
- Configuração do Nginx.conf
Item 1 - /etc/nginx/sites-available
sudo nano api
server {
server_name api.SITE.com.br;
root /var/www/api; # Diretório onde você vai armazenar seus arquivos PHP
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
# Configuração para capturar todas as solicitações PHP dentro do diretório svFrontend
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.4-fpm.sock; # Verifique o caminho do socket PHP-FPM
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Aumentar o tempo limite para 2 minutos (120 segundos)
fastcgi_read_timeout 120s;
}
}
Agora cria uma copia da API na pasta sites-enabled
sudo ln -s /etc/nginx/sites-available/api /etc/nginx/sites-enabled
Confere configuração
sudo nginx -t
Reinicia Nginx
sudo service nginx restart
Roda o Certbot no Nginx
sudo certbot --nginx
Item 2 configurando o Nginx.conf OBS: Foi aqui um dos maiores problemas enfrentados pois as configurações que estavam estava barrando as novas requisições
worker_processes 1024;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 8192;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 120;
types_hash_max_size 2048;
server_tokens off;
client_max_body_size 20M;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
}
Configurações do PHP-FPM
- Configuração do php.ini
- Configuração do usuário do PHP-FPM
Item 1 - PHP.INI
max_execution_time = 120
max_input_time = 120
memory_limit = 20GB ; aqui separei do servidor até 20 GB para trabalhar com o PHP
Item 2 - Configuração do Usuário
user = www-data
group = www-data
listen = /run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 500
pm.start_servers = 100
pm.min_spare_servers = 70
pm.max_spare_servers = 200
pm.max_requests = 650
php_admin_value[memory_limit] = 256M
Configuração do Servidor Mysql Vídeo tutorial - AQUI
- Configuração dos limites
- Criação do usuário root
Item 1 - Configuração dos limites - Separei 100 GB para o BD
cd/etc/mysql/mysql.conf.d
sudo nano mysqld.cnf
bind-address = 127.0.0.1
mysqlx-bind-address = 127.0.0.1
key_buffer_size = 64M
innodb_buffer_pool_size = 100G
max_allowed_packet = 64M
myisam-recover-options = BACKUP
max_connections = 1000
max_binlog_size = 100M
*Item 2 - Criação do usuário *
sudo apt install mysql-server
sudo apt install phpmyadmin
mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'SENHA';
exit
mysql -u root -p
CREATE USER 'usuario'@'xxx.xxx.xxx.xxx' IDENTIFIED BY 'SENHA';
#aqui vai liberar que o usuário acesse somente pelo servidor especifico e abaixo da todos os privilégios para ele
GRANT ALL PRIVILEGES ON *.* TO 'usuario'@'xxx.xxx.xxx.xx' WITH GRANT OPTION;
flush privileges;
exit
Servidor NodeJS - WhatsApp
- Instalação da biblioteca open source WhatsApp
- PM2 para rodar a instância
- Configuração para reiniciar o servidor Node caso Servidor da Contaboo reinicie.
Neste caso o servidor esta rodando na porta 16001, pelo DNS da hostinger criei um subdominio servidor01.SITE.com.br apontando para Contaboo, e do Nginx quando tiver requisição através do servidor01.site.com.br apontará para o servidor localhost:16001.
Item 1 - Instalação da biblioteca open source WhatsApp
cd /home
git clone https://github.com/WhiskeySockets/Baileys.git servidor
cd servidor
npm install
Item 2 - Startar pelo Pm2
pm2 start disp1.js --name '16001-disparador' --watch 'watch/servidor_1' --cron-restart='*/7 * * * *'
Item 3 - Reinicio automático
pm2 save
pm2 startup
As configurações para rodar o servidor manualmente foram estas baseadas na capacidade do meu servidor.
Para cada novo sistema basta apontar o DNS para o servidor da contaboo , e no nginx apontar para pasta onde o sistema estará rodando.
Bom sucesso
Achei muito massa eu estava usando a vps na hostinger e comecei a ter problemas também com crecimento do meu projeto caso queira ver Criativo Dahora, porem eu preferi usar a Hetzner só que eu contratei um servidor dedicado e não achei muito caro, instalei o panel administrador aapanel muito simples a instalação e faço o gerenciamento na Cloudflare
Dado seu cenário, eu sugiro que você use Kubernetes, mais espeficicamente o microk8s da Canonical mantenedora do Ubuntu. E o porquê disso? A instalação é bem mais simples e já te dá acesso ao HPA (Horizontal Pod Autoscaling) que é um recurso chave e muito fantástico pra escalar seu ambiente.
Eu, por exemplo, utilizo 3 servidores dedicados (bare metal) em cluster utilizando DRDB pra persistencia de dados e quase todas minhas aplicações com MinIO - que me ajuda muito a manter, migrar ou repatriar dados.
Na minha stack quase sempre utilizo Redis e RabbitMQ, então uma parte da aplicação vai virar fila persistente ou fila em memória, que depois vai ser descarregada pra uma 1 ou N bancos (Por ex: uma parte pode ser escrita no Postgres ou MySQL e outra parte também ser escrita no MongoDB ou ScyllaDB). Num cenário hipotético pra ilustar: tenho um cliente que faz uma live, abertura de carrinho, enfim, ele gera uma concentração muito grande de usuários e direciona pra uma página de vendas, captura de leads etc e geralmente não dá tempo pro servidor escalar no método tradicional - e é ai que vem a sacada.
No meu caso eu rodo um script que monitora o tamanho da fila, e como eu já fiz teste de carga e eu sei exatamente a quantidade de usuários que cada parte vai segurar, então o HPA do Kubernetes basicamente dispara via API a requisição pra subir mais uma instância pra plugar mais um nó de worker ao cluster, só que agora essa isntância não é dedicada e sim VPS (EC2 da AWS, Droplet da Digital Ocean, VM da OCI, Cloud da Hetzner, etc aonde fizer sentido). Eu só imponho um limite pra ele não escalar ao infinito e além por prevenção caso haja algum bug.
Outra detalhe importante que eu ia me esquecendo de mencionar: uma parte da aplicação (Geralmetne a camada estática e uma parte de roteamento entre os serviços) é serverless - que me garante que mesmo que uma quantidade absurda de usuários entrem me dê tempo pra aplicação tratar o erro de too many conections, por exemplo, de forma bonitinha sem o usuário saber que o backend tá morrendo lá atrás. Mesmo que você use um Aurora da AWS com um banco serverless, ele não segura esses estouros de conexão, ele demora pra escalar inclusive (E aqui é a vantagem principal do HPA, pois se eu tenho 50k usuários concorrentes eu já sei o tamanho que a minha infra precisa escalar, e no Aurora e RDS por exemplo, você é meio que forçado a subir o número de instâncias um passo de cada vez. As vezes o simples fato da sua aplicação morrer ou estourar um erro na cara do usuário, faz os usuários a ficarem clicando em refresh sem parar e piorar o cenário gerando um DoS (Denial of Service).
Então o HPA do Kubernetes tb é responsável por gerenciar o warmup e cooldown pra instanciar mais rápido que a forma convencional (eu não espero a máquina chegar em 80% de consumo de recurso ou beirar o esgotamento) e não liberar as máquinas de forma prematura (Por ex: passou a rajada de conexõs iniciais eu sei que o provedor vai me cobrar em blocos de X intervalos de tempo, nesse caso eu crio um script que segura a instancia ao limite do que já será cobrado ou se o tráfego já reduziu ao limite do cooldown e se manteve sem acionar o gatilho de warmup nenhuma vez durante 15 minutos ai sim libera a instância do worker.
Pra reduzir ainda mais o custo, você pode utilizar round robin se for complicado você colocar um load balancer de borda (Nem toda topologia de rede favorece isso, principalmente se seus servidores tiverem geograficamente separados - que é meu caso). Então eu uso via API da CloudFlare um health-check que a cada 5 segundos faz detach do nó com falha, e nesse caso eu só posso ter failover de 1 servidor dedicado.
No caso dos bare metal eu tenho tolerância de 1 falha, pra suporar 2 falhas eu teria que ter 5 dedicados. Na real é um algoritmo de consenso tb pra evitar que fiquem números pares de servidores, mas o limite mínimo é de 2, isso pq os bancos de dados relacionais também tem replicação em um nível que quando o bloco fica par, ele força um a eleger um master, só funcionando master-master em nível impar (Com o objetivo de evitar split brain). Isso é um assunto gigante, mas quase tudo que tem replicação horizontal sofre esse problema. Cada serviço tem seu jeito de trabalhar horizontalmente, Postgres, MySQL, Mongo, Redis. Cada um dos que citei tem várias formas de configurar horizontalmente e trabalhar diferentes. Redis tem sentinela e cluster que é um assunto fantástico também. Enfim, subiu as réplicas em Kubernetes o serviço tem que ter a sua estratégia de replicar os dados dos pods entre si.
Sei que parece complicado, mas acredite é a forma mais simples de você conseguir escalar seu ambiente low-cost. Se tiver dúvidas, manda ai que respondo na medida do possível.
É ótimo ver que você está explorando e configurando seu próprio ambiente de servidor para atender às necessidades de seus projetos. Parece que você está bem encaminhado com a configuração do seu servidor, incluindo Nginx, PHP-FPM, MySQL e Node.js.
Aqui estão alguns pontos que você mencionou e algumas dicas adicionais:
Limites de Recursos do Servidor MySQL: Configurar limites de recursos adequados para o MySQL é importante para garantir um desempenho estável. Certifique-se de ajustar esses limites com base na carga de trabalho e nos recursos disponíveis no seu servidor.
Segurança: Certifique-se de manter sua configuração de segurança atualizada, incluindo firewalls, atualizações regulares de software e configuração segura de senhas.
Backup e Monitoramento: Implemente um plano de backup eficaz para seus dados e monitore a saúde do servidor e do banco de dados regularmente. Existem várias ferramentas de monitoramento disponíveis para ajudar nesse aspecto.
Escalabilidade: Considere como o seu sistema irá dimensionar conforme a demanda cresce. Isso pode envolver a adição de servidores adicionais, balanceamento de carga e outros ajustes de infraestrutura.
Automatização: Para facilitar a manutenção do servidor, você pode considerar a automação de tarefas rotineiras usando ferramentas como Ansible ou scripts personalizados.
Segurança do Node.js: Certifique-se de que seu servidor Node.js está devidamente protegido contra ataques e vulnerabilidades comuns do lado do servidor. Mantenha todas as dependências atualizadas e siga práticas recomendadas de segurança.
Documentação: Mantenha uma documentação detalhada de todas as configurações e procedimentos de manutenção. Isso será útil para futuras referências e para outros membros da equipe, se houver.
Testes de Recuperação: Realize testes de recuperação de desastres para garantir que seus backups sejam confiáveis e que você possa restaurar seu sistema em caso de falha.
Lembre-se de que a administração de servidores é uma tarefa contínua, e é importante manter-se atualizado sobre as melhores práticas e as últimas atualizações de segurança. Boa sorte com seus projetos!
Tenho essa mesma configuração PHP + mariaDb + node no mesmo servidor e na contabo.
Esse site de um amigo: https://shareallfiles.net/ esta lá!
Não tem motivo para ter vergonha de usar a contabo. Uso deles tem 10 anos. Caiu umas 2 vezes meu server.
Uso cloudflare para SSL(facil e sem problemas) uso Full (strict)
Pq vc quis o baileys e não o whatsapp-web.js?
Abraços