webmoney/ROTEIRO_INSTALACAO_SERVIDOR.md
marco 54cccdd095 refactor: migração para desenvolvimento direto no servidor
- Removido README.md padrão do Laravel (backend)
- Removidos scripts de deploy (não mais necessários)
- Atualizado copilot-instructions.md para novo fluxo
- Adicionada documentação de auditoria do servidor
- Sincronizado código de produção com repositório

Novo workflow:
- Trabalhamos diretamente em /root/webmoney (symlink para /var/www/webmoney)
- Mudanças PHP são instantâneas
- Mudanças React requerem 'npm run build'
- Commit após validação funcional
2025-12-19 11:45:32 +01:00

55 KiB
Executable File

🚀 ROTEIRO DE INSTALAÇÃO DO SERVIDOR - WEBMoney/ConneXiFly

Versão: 2.0.0
Data: 7 de Dezembro de 2025
Servidor: 213.165.93.60
Domínio: cnxifly.com
Senha Padrão: M@ster9354

⚠️ IMPORTANTE: Este roteiro deve ser executado COMANDO A COMANDO manualmente.
Não usar scripts automatizados. Verificar cada passo antes de prosseguir.


📦 VERSÕES INSTALADAS (Dezembro 2025)

Software Versão Fonte
Ubuntu Server 24.04.3 LTS ISO oficial
Nginx 1.29.3 (mainline) Repo oficial Nginx
PHP 8.4.15 PPA ondrej/php
MariaDB 11.4.9 LTS Repo oficial MariaDB
Node.js 22.21.0 LTS NodeSource
PM2 6.0.14 npm
Redis 7.0.15 Repo Ubuntu
Postfix 3.8.6 Repo Ubuntu
Dovecot 2.3.21 Repo Ubuntu
OpenDKIM 2.11.x Repo Ubuntu
Certbot 5.2.1 Snap
Composer 2.9.2 getcomposer.org
PostfixAdmin 3.3.x GitHub
Roundcube 1.6.11 GitHub
phpMyAdmin 5.2.x Repo Ubuntu

📋 ÍNDICE

  1. Pré-requisitos e Preparação
  2. Fase 1: Sistema Base
  3. Fase 2: Firewall e Segurança
  4. Fase 3: MariaDB 11.4 LTS
  5. Fase 4: PHP 8.4
  6. Fase 5: Nginx Mainline
  7. Fase 6: SSL/Let's Encrypt
  8. Fase 7: Postfix + Dovecot + OpenDKIM
  9. Fase 8: PostfixAdmin + Roundcube + phpMyAdmin
  10. Fase 9: Node.js 22 LTS
  11. Fase 10: Deploy WEBMoney
  12. Fase 11: Otimização de Desempenho
  13. Fase 12: Validação Final
  14. Comandos de Verificação
  15. Referência Rápida

1. PRÉ-REQUISITOS E PREPARAÇÃO

Informações do Projeto

Item Valor
IP do Servidor 213.165.93.60
IPv6 2001:ba0:268:ab00::1
Domínio Principal cnxifly.com
Subdomínios webmoney, mail, webmail, phpmyadmin
Timezone Europe/Madrid
Locale es_ES.UTF-8
Senha Única M@ster9354

Estrutura de Subdomínios Final

cnxifly.com              → Redirect para webmoney
www.cnxifly.com          → Redirect para webmoney
webmoney.cnxifly.com     → Aplicação WEBMoney (Laravel+React)
mail.cnxifly.com         → PostfixAdmin (admin email)
webmail.cnxifly.com      → Roundcube (webmail usuários)
phpmyadmin.cnxifly.com   → phpMyAdmin (admin BD)

DNS Necessários (verificar antes de começar)

# No painel DNS do registrador (UI-DNS), garantir:
dig cnxifly.com A +short              # → 213.165.93.60
dig mail.cnxifly.com A +short         # → 213.165.93.60
dig webmoney.cnxifly.com A +short     # → 213.165.93.60
dig webmail.cnxifly.com A +short      # → 213.165.93.60
dig phpmyadmin.cnxifly.com A +short   # → 213.165.93.60
dig cnxifly.com MX +short             # → 10 mail.cnxifly.com
dig cnxifly.com TXT +short            # → v=spf1 mx a ip4:213.165.93.60 -all

2. FASE 1: SISTEMA BASE (~15 min)

2.1 Conectar ao Servidor

ssh root@213.165.93.60

Senha: Master9354

2.2 Verificar Versão do Sistema

cat /etc/os-release

Deve mostrar: Ubuntu 24.04.x LTS

2.3 Atualizar Sistema Completamente

apt update
apt upgrade -y
apt dist-upgrade -y
apt autoremove -y

2.4 Instalar Pacotes Essenciais

apt install -y software-properties-common apt-transport-https ca-certificates curl wget gnupg lsb-release git unzip zip htop net-tools dnsutils vim nano

2.5 Configurar Timezone (CRÍTICO - FAZER PRIMEIRO)

timedatectl set-timezone Europe/Madrid

Verificar:

timedatectl

Deve mostrar: Time zone: Europe/Madrid

2.6 Configurar Locale UTF-8 (CRÍTICO - FAZER PRIMEIRO)

apt install -y locales
sed -i '/es_ES.UTF-8/s/^# //g' /etc/locale.gen
locale-gen es_ES.UTF-8
update-locale LANG=es_ES.UTF-8 LC_ALL=es_ES.UTF-8

Aplicar imediatamente na sessão atual:

export LANG=es_ES.UTF-8
export LC_ALL=es_ES.UTF-8

Verificar:

locale

2.7 Criar arquivo /etc/environment

cat > /etc/environment << 'EOF'
LANG=es_ES.UTF-8
LC_ALL=es_ES.UTF-8
LC_CTYPE=es_ES.UTF-8
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
EOF

2.8 Configurar Hostname

hostnamectl set-hostname mail.cnxifly.com
echo "213.165.93.60 mail.cnxifly.com mail" >> /etc/hosts

Verificar:

hostname -f

Deve mostrar: mail.cnxifly.com

2.9 Reiniciar para Aplicar Todas as Configurações

reboot

Aguardar 30 segundos e reconectar:

ssh root@213.165.93.60

3. FASE 2: FIREWALL E SEGURANÇA (~5 min)

3.1 Configurar UFW

apt install -y ufw

# Regras básicas
ufw default deny incoming
ufw default allow outgoing

# SSH
ufw allow 22/tcp

# HTTP/HTTPS
ufw allow 80/tcp
ufw allow 443/tcp

# Email
ufw allow 25/tcp    # SMTP
ufw allow 465/tcp   # SMTPS
ufw allow 587/tcp   # Submission
ufw allow 143/tcp   # IMAP
ufw allow 993/tcp   # IMAPS

# Ativar
ufw --force enable
ufw status verbose

3.2 Criar Usuário Admin (opcional mas recomendado)

adduser admin
# Senha: M@ster9354
usermod -aG sudo admin

4. FASE 3: MARIADB 11.4 LTS (~10 min)

4.1 Adicionar Repositório Oficial MariaDB 11.4

curl -fsSL https://mariadb.org/mariadb_release_signing_key.pgp | gpg --dearmor -o /usr/share/keyrings/mariadb-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/mariadb-keyring.gpg] https://dlm.mariadb.com/repo/mariadb-server/11.4/repo/ubuntu noble main" > /etc/apt/sources.list.d/mariadb.list
apt update

4.2 Instalar MariaDB 11.4

apt install -y mariadb-server mariadb-client

Verificar versão:

mariadb --version

Deve mostrar: mariadb Ver 15.1 Distrib 11.4.x

4.3 Habilitar e Iniciar

systemctl enable mariadb
systemctl start mariadb
systemctl status mariadb

4.4 Configurar Charset UTF-8 e Performance

cat > /etc/mysql/mariadb.conf.d/99-custom.cnf << 'EOF'
[mysqld]
# Charset
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
skip-character-set-client-handshake

# InnoDB Performance
innodb_buffer_pool_size = 256M
innodb_log_file_size = 64M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT

# Query Cache (deprecated but still useful)
query_cache_type = 1
query_cache_size = 32M
query_cache_limit = 2M

# Connections
max_connections = 100
wait_timeout = 600
interactive_timeout = 600

# Temp tables
tmp_table_size = 64M
max_heap_table_size = 64M

# Logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4
EOF
systemctl restart mariadb

4.5 Executar Segurança Inicial

mariadb-secure-installation

Responder:

  • Enter current password for root: (pressionar Enter, está vazio)
  • Switch to unix_socket authentication: n
  • Change the root password: Y → Digite: M@ster9354
  • Remove anonymous users: Y
  • Disallow root login remotely: Y
  • Remove test database: Y
  • Reload privilege tables: Y

4.6 Criar Usuários e Bancos

mariadb -u root -p'M@ster9354'

Dentro do MariaDB, executar cada comando:

-- Usuário admin geral
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'M@ster9354';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;

-- Banco WEBMoney
CREATE DATABASE webmoney CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'webmoney'@'localhost' IDENTIFIED BY 'M@ster9354';
GRANT ALL PRIVILEGES ON webmoney.* TO 'webmoney'@'localhost';

-- Banco PostfixAdmin
CREATE DATABASE postfixadmin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'postfixadmin'@'localhost' IDENTIFIED BY 'M@ster9354';
GRANT ALL PRIVILEGES ON postfixadmin.* TO 'postfixadmin'@'localhost';

-- Banco Roundcube
CREATE DATABASE roundcube CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'M@ster9354';
GRANT ALL PRIVILEGES ON roundcube.* TO 'roundcube'@'localhost';

-- Banco phpMyAdmin
CREATE DATABASE phpmyadmin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'phpmyadmin'@'localhost' IDENTIFIED BY 'M@ster9354';
GRANT ALL PRIVILEGES ON phpmyadmin.* TO 'phpmyadmin'@'localhost';

FLUSH PRIVILEGES;
EXIT;

4.7 Verificar

mariadb -u admin -p'M@ster9354' -e "SHOW DATABASES;"
mariadb -u admin -p'M@ster9354' -e "SHOW VARIABLES LIKE 'character%';"
mariadb -u admin -p'M@ster9354' -e "SELECT VERSION();"

5. FASE 4: PHP 8.4 (~10 min)

5.1 Adicionar Repositório PHP (ondrej/php)

add-apt-repository -y ppa:ondrej/php
apt update

5.2 Instalar PHP 8.4 e Extensões

apt install -y php8.4-fpm php8.4-cli php8.4-common
apt install -y php8.4-mysql php8.4-pgsql php8.4-sqlite3
apt install -y php8.4-curl php8.4-gd php8.4-mbstring php8.4-xml php8.4-zip
apt install -y php8.4-bcmath php8.4-intl php8.4-soap php8.4-imap
apt install -y php8.4-ldap php8.4-imagick php8.4-redis php8.4-opcache

Verificar versão:

php -v

Deve mostrar: PHP 8.4.x

5.3 Configurar PHP-FPM (php.ini)

sed -i 's/;date.timezone =/date.timezone = Europe\/Madrid/' /etc/php/8.4/fpm/php.ini
sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 64M/' /etc/php/8.4/fpm/php.ini
sed -i 's/post_max_size = 8M/post_max_size = 64M/' /etc/php/8.4/fpm/php.ini
sed -i 's/memory_limit = 128M/memory_limit = 256M/' /etc/php/8.4/fpm/php.ini
sed -i 's/max_execution_time = 30/max_execution_time = 300/' /etc/php/8.4/fpm/php.ini
sed -i 's/;max_input_vars = 1000/max_input_vars = 5000/' /etc/php/8.4/fpm/php.ini

5.4 Configurar PHP CLI

sed -i 's/;date.timezone =/date.timezone = Europe\/Madrid/' /etc/php/8.4/cli/php.ini

5.5 Configurar OPcache para Performance

cat > /etc/php/8.4/mods-available/opcache-custom.ini << 'EOF'
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.enable_cli=0
opcache.jit=1255
opcache.jit_buffer_size=128M
EOF
ln -sf /etc/php/8.4/mods-available/opcache-custom.ini /etc/php/8.4/fpm/conf.d/99-opcache-custom.ini

5.6 Configurar PHP-FPM Pool para Performance

sed -i 's/pm = dynamic/pm = ondemand/' /etc/php/8.4/fpm/pool.d/www.conf
sed -i 's/pm.max_children = 5/pm.max_children = 20/' /etc/php/8.4/fpm/pool.d/www.conf
sed -i 's/;pm.process_idle_timeout = 10s/pm.process_idle_timeout = 10s/' /etc/php/8.4/fpm/pool.d/www.conf

5.7 Habilitar e Reiniciar PHP-FPM

systemctl enable php8.4-fpm
systemctl restart php8.4-fpm
systemctl status php8.4-fpm

5.8 Instalar Composer (Última Versão)

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

Verificar:

composer --version

Deve mostrar: Composer version 2.8.x


6. FASE 5: NGINX MAINLINE (~10 min)

6.1 Remover Nginx do Repo Ubuntu (se existir)

apt remove --purge -y nginx nginx-common nginx-full 2>/dev/null || true

6.2 Adicionar Repositório Oficial Nginx (Mainline)

curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /usr/share/keyrings/nginx-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] http://nginx.org/packages/mainline/ubuntu noble nginx" > /etc/apt/sources.list.d/nginx.list
apt update

6.3 Instalar Nginx Mainline

apt install -y nginx

Verificar versão:

nginx -v

Deve mostrar: nginx version: nginx/1.27.x

6.4 Criar Estrutura de Diretórios

mkdir -p /etc/nginx/sites-available
mkdir -p /etc/nginx/sites-enabled
mkdir -p /var/www/webmoney/public
mkdir -p /var/www/html
chown -R www-data:www-data /var/www

6.5 Configuração Base Nginx (Otimizada)

cat > /etc/nginx/nginx.conf << 'EOF'
user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log warn;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

http {
    # Basic
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;
    
    # MIME
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # Charset UTF-8
    charset utf-8;
    charset_types text/html text/xml text/plain text/css text/javascript application/json application/javascript;
    
    # SSL Global Settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
    
    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_min_length 256;
    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-ttf
        application/x-web-app-manifest+json
        application/xhtml+xml
        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
        text/xml;
    
    # Buffers
    client_body_buffer_size 10K;
    client_header_buffer_size 1k;
    client_max_body_size 64M;
    large_client_header_buffers 4 32k;
    
    # Timeouts
    client_body_timeout 12;
    client_header_timeout 12;
    send_timeout 10;
    
    # FastCGI Cache
    fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=FASTCGI:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    
    # Open File Cache
    open_file_cache max=10000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
    
    # Logging
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time"';
    access_log /var/log/nginx/access.log main;
    
    # Rate Limiting
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    # Includes
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
EOF

6.6 Criar Diretório de Cache

mkdir -p /var/cache/nginx
chown -R www-data:www-data /var/cache/nginx

6.7 Criar Vhost Temporário (para Certbot)

cat > /etc/nginx/sites-available/temp-http.conf << 'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name cnxifly.com www.cnxifly.com webmoney.cnxifly.com mail.cnxifly.com webmail.cnxifly.com phpmyadmin.cnxifly.com;
    root /var/www/html;
    
    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }
    
    location / {
        return 200 'Server ready for SSL';
        add_header Content-Type text/plain;
    }
}
EOF
ln -sf /etc/nginx/sites-available/temp-http.conf /etc/nginx/sites-enabled/

6.8 Testar e Iniciar Nginx

nginx -t
systemctl enable nginx
systemctl start nginx
systemctl status nginx

7. FASE 6: SSL/LET'S ENCRYPT (~5 min)

7.1 Instalar Certbot via Snap (Última Versão)

apt install -y snapd
snap install core
snap refresh core
snap install --classic certbot
ln -sf /snap/bin/certbot /usr/bin/certbot

Verificar versão:

certbot --version

7.2 Obter Certificado (todos os domínios)

certbot certonly --webroot -w /var/www/html \
    -d cnxifly.com \
    -d www.cnxifly.com \
    -d webmoney.cnxifly.com \
    -d mail.cnxifly.com \
    -d webmail.cnxifly.com \
    -d phpmyadmin.cnxifly.com \
    --email admin@cnxifly.com \
    --agree-tos \
    --no-eff-email

7.3 Verificar Certificado

certbot certificates

7.4 Configurar Renovação Automática

systemctl enable snap.certbot.renew.timer
systemctl start snap.certbot.renew.timer

7.5 Testar Renovação

certbot renew --dry-run

7.6 Criar Hook para Reload do Nginx

cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx
EOF
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

7.7 Remover Vhost Temporário

rm /etc/nginx/sites-enabled/temp-http.conf

8. FASE 7: POSTFIX + DOVECOT + OPENDKIM (~25 min)

8.1 Pré-configurar Postfix (evitar prompts)

debconf-set-selections <<< "postfix postfix/mailname string cnxifly.com"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"

8.2 Instalar Postfix

apt install -y postfix postfix-mysql

Verificar versão:

postconf mail_version

8.3 Instalar Dovecot

apt install -y dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-pop3d

Verificar versão:

dovecot --version

8.4 Instalar OpenDKIM

apt install -y opendkim opendkim-tools

Verificar versão:

opendkim -V

8.5 Configurar OpenDKIM

Criar diretórios:

mkdir -p /etc/opendkim/keys/cnxifly.com

Gerar chaves DKIM (2048 bits):

opendkim-genkey -b 2048 -d cnxifly.com -D /etc/opendkim/keys/cnxifly.com -s default -v

Ajustar permissões:

chown -R opendkim:opendkim /etc/opendkim
chmod 600 /etc/opendkim/keys/cnxifly.com/default.private

Configurar opendkim.conf:

cat > /etc/opendkim.conf << 'EOF'
Syslog                  yes
SyslogSuccess           yes
LogWhy                  yes
Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no
OversignHeaders         From
AutoRestart             yes
AutoRestartRate         10/1M
Background              yes
DNSTimeout              5
SignatureAlgorithm      rsa-sha256

KeyTable                /etc/opendkim/key.table
SigningTable            refile:/etc/opendkim/signing.table
ExternalIgnoreList      /etc/opendkim/trusted.hosts
InternalHosts           /etc/opendkim/trusted.hosts

Socket                  local:/var/spool/postfix/opendkim/opendkim.sock
PidFile                 /run/opendkim/opendkim.pid
UMask                   007
UserID                  opendkim
EOF

Criar key.table:

cat > /etc/opendkim/key.table << 'EOF'
default._domainkey.cnxifly.com cnxifly.com:default:/etc/opendkim/keys/cnxifly.com/default.private
EOF

Criar signing.table:

cat > /etc/opendkim/signing.table << 'EOF'
*@cnxifly.com default._domainkey.cnxifly.com
EOF

Criar trusted.hosts:

cat > /etc/opendkim/trusted.hosts << 'EOF'
127.0.0.1
localhost
cnxifly.com
mail.cnxifly.com
EOF

Criar diretório do socket:

mkdir -p /var/spool/postfix/opendkim
chown opendkim:postfix /var/spool/postfix/opendkim
chmod 750 /var/spool/postfix/opendkim
usermod -aG opendkim postfix

Iniciar OpenDKIM:

systemctl enable opendkim
systemctl restart opendkim
systemctl status opendkim

8.6 Mostrar Chave DKIM para DNS

echo "============================================"
echo "ADICIONAR ESTE REGISTRO TXT NO DNS:"
echo "============================================"
echo "Nome: default._domainkey.cnxifly.com"
echo "Tipo: TXT"
echo "Valor:"
cat /etc/opendkim/keys/cnxifly.com/default.txt
echo "============================================"

⚠️ IMPORTANTE: Copie o conteúdo e adicione no painel DNS AGORA. A propagação pode levar até 24h.

8.7 Configurar Postfix main.cf

cat > /etc/postfix/main.cf << 'EOF'
# Basic
smtpd_banner = $myhostname ESMTP
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 3.6

# Hostname
myhostname = mail.cnxifly.com
mydomain = cnxifly.com
myorigin = $mydomain
mydestination = localhost
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128

# Virtual mailbox
virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf
virtual_transport = lmtp:unix:private/dovecot-lmtp

# TLS Incoming
smtpd_tls_cert_file = /etc/letsencrypt/live/cnxifly.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/cnxifly.com/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

# TLS Outgoing
smtp_tls_security_level = may
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1

# SASL Auth
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname

# Restrictions
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

# OpenDKIM
milter_default_action = accept
milter_protocol = 6
smtpd_milters = unix:/var/spool/postfix/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

# Limits
mailbox_size_limit = 0
message_size_limit = 52428800
recipient_delimiter = +

# Queue
maximal_queue_lifetime = 1d
bounce_queue_lifetime = 1d
EOF

8.8 Configurar Postfix MySQL Maps

Criar mysql-virtual-mailbox-domains.cf:

cat > /etc/postfix/mysql-virtual-mailbox-domains.cf << 'EOF'
user = postfixadmin
password = M@ster9354
hosts = localhost
dbname = postfixadmin
query = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
EOF

Criar mysql-virtual-mailbox-maps.cf:

cat > /etc/postfix/mysql-virtual-mailbox-maps.cf << 'EOF'
user = postfixadmin
password = M@ster9354
hosts = localhost
dbname = postfixadmin
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
EOF

Criar mysql-virtual-alias-maps.cf:

cat > /etc/postfix/mysql-virtual-alias-maps.cf << 'EOF'
user = postfixadmin
password = M@ster9354
hosts = localhost
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
EOF

Ajustar permissões:

chmod 640 /etc/postfix/mysql-*.cf
chown root:postfix /etc/postfix/mysql-*.cf

8.9 Configurar Postfix master.cf (submission/smtps)

cat >> /etc/postfix/master.cf << 'EOF'

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_auth_only=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

smtps     inet  n       -       y       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_reject_unlisted_recipient=no
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
EOF

8.10 Configurar Dovecot

Criar usuário e diretório de mail:

mkdir -p /var/mail/vhosts/cnxifly.com
groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /var/mail/vhosts -s /usr/sbin/nologin
chown -R vmail:vmail /var/mail/vhosts

Configurar dovecot.conf:

cat > /etc/dovecot/dovecot.conf << 'EOF'
protocols = imap lmtp pop3
listen = *, ::
dict {
}
!include conf.d/*.conf
EOF

Configurar 10-auth.conf:

cat > /etc/dovecot/conf.d/10-auth.conf << 'EOF'
disable_plaintext_auth = yes
auth_mechanisms = plain login
!include auth-sql.conf.ext
EOF

Configurar 10-mail.conf:

cat > /etc/dovecot/conf.d/10-mail.conf << 'EOF'
mail_location = maildir:/var/mail/vhosts/%d/%n
mail_uid = vmail
mail_gid = vmail
mail_privileged_group = vmail
first_valid_uid = 5000
last_valid_uid = 5000
EOF

Configurar 10-master.conf:

cat > /etc/dovecot/conf.d/10-master.conf << 'EOF'
service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
  }
  user = dovecot
}

service auth-worker {
  user = vmail
}

service stats {
  unix_listener stats-reader {
    user = vmail
    group = vmail
    mode = 0660
  }
  unix_listener stats-writer {
    user = vmail
    group = vmail
    mode = 0660
  }
}
EOF

Configurar 10-ssl.conf:

cat > /etc/dovecot/conf.d/10-ssl.conf << 'EOF'
ssl = required
ssl_cert = </etc/letsencrypt/live/cnxifly.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/cnxifly.com/privkey.pem
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
EOF

Configurar auth-sql.conf.ext:

cat > /etc/dovecot/conf.d/auth-sql.conf.ext << 'EOF'
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
EOF

Configurar dovecot-sql.conf.ext:

cat > /etc/dovecot/dovecot-sql.conf.ext << 'EOF'
driver = mysql
connect = host=localhost dbname=postfixadmin user=postfixadmin password=M@ster9354
default_pass_scheme = SHA512-CRYPT
password_query = SELECT username AS user, password FROM mailbox WHERE username = '%u' AND active = '1'
user_query = SELECT CONCAT('/var/mail/vhosts/', maildir) AS home, 5000 AS uid, 5000 AS gid FROM mailbox WHERE username = '%u' AND active = '1'
iterate_query = SELECT username AS user FROM mailbox WHERE active = '1'
EOF

Ajustar permissões:

chmod 600 /etc/dovecot/dovecot-sql.conf.ext
chown root:root /etc/dovecot/dovecot-sql.conf.ext

Permitir www-data usar doveadm (para PostfixAdmin):

usermod -aG dovecot www-data

8.11 Iniciar Serviços de Email

systemctl enable dovecot
systemctl restart dovecot
systemctl status dovecot
systemctl restart postfix
systemctl status postfix

9. FASE 8: POSTFIXADMIN + ROUNDCUBE + PHPMYADMIN (~20 min)

9.1 Instalar PostfixAdmin

apt install -y postfixadmin

Durante a instalação, se aparecer prompt do dbconfig:

  • Configure database: Yes
  • Database type: mysql
  • Password: M@ster9354

Criar link simbólico:

ln -sf /usr/share/postfixadmin/public /var/www/postfixadmin

9.2 Configurar PostfixAdmin

Gerar hash da senha de setup:

SETUP_HASH=$(php -r "echo password_hash('M@ster9354', PASSWORD_BCRYPT);")
echo $SETUP_HASH

Criar config.local.php:

cat > /etc/postfixadmin/config.local.php << 'EOFPHP'
<?php
$CONF['configured'] = true;
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'M@ster9354';
$CONF['database_name'] = 'postfixadmin';

$CONF['admin_email'] = 'admin@cnxifly.com';
$CONF['encrypt'] = 'dovecot:SHA512-CRYPT';
$CONF['dovecotpw'] = '/usr/bin/doveadm pw';

$CONF['default_aliases'] = array(
    'abuse' => 'admin@cnxifly.com',
    'hostmaster' => 'admin@cnxifly.com',
    'postmaster' => 'admin@cnxifly.com',
    'webmaster' => 'admin@cnxifly.com'
);

$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';

$CONF['forgotten_admin_password_reset'] = false;
$CONF['alias_domain'] = 'YES';

$CONF['password_validation'] = array(
    '/^.{8,}$/' => 'password_too_short 8'
);

$CONF['default_language'] = 'es';
EOFPHP

Agora adicionar o hash de setup (copie o valor de $SETUP_HASH):

echo "\$CONF['setup_password'] = '$(php -r "echo password_hash('M@ster9354', PASSWORD_BCRYPT);")'; " >> /etc/postfixadmin/config.local.php

Ajustar permissões:

chown root:www-data /etc/postfixadmin/config.local.php
chmod 640 /etc/postfixadmin/config.local.php

9.3 Instalar Roundcube

apt install -y roundcube roundcube-mysql roundcube-plugins

Durante a instalação, se aparecer prompt do dbconfig:

  • Configure database: Yes
  • Database type: mysql
  • Password: M@ster9354

9.4 Configurar Roundcube

Gerar chave aleatória:

DES_KEY=$(openssl rand -base64 24)
echo "DES_KEY gerada: $DES_KEY"

Criar configuração (substituir DES_KEY pelo valor gerado):

cat > /etc/roundcube/config.inc.php << 'EOF'
<?php
$config = array();

// Database
$config['db_dsnw'] = 'mysql://roundcube:M@ster9354@localhost/roundcube';

// IMAP
$config['default_host'] = 'localhost';
$config['default_port'] = 143;
$config['imap_auth_type'] = 'PLAIN';
$config['imap_conn_options'] = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
    ),
);

// SMTP
$config['smtp_server'] = 'localhost';
$config['smtp_port'] = 587;
$config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p';
$config['smtp_auth_type'] = 'PLAIN';
$config['smtp_conn_options'] = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false,
    ),
);

// General
$config['product_name'] = 'WEBMoney Mail';
$config['skin'] = 'elastic';
$config['language'] = 'es_ES';
$config['timezone'] = 'Europe/Madrid';

// Plugins
$config['plugins'] = array(
    'archive',
    'zipdownload',
    'password',
);

// Misc
$config['draft_autosave'] = 60;
$config['enable_spellcheck'] = false;
$config['mail_pagesize'] = 50;
$config['addressbook_pagesize'] = 50;
EOF

Adicionar DES_KEY (substitua pelo valor gerado):

echo "\$config['des_key'] = '$(openssl rand -base64 24)';" >> /etc/roundcube/config.inc.php

Ajustar permissões:

chown root:www-data /etc/roundcube/config.inc.php
chmod 640 /etc/roundcube/config.inc.php

9.5 Instalar phpMyAdmin

Pré-configurar para evitar prompts:

debconf-set-selections <<< "phpmyadmin phpmyadmin/dbconfig-install boolean true"
debconf-set-selections <<< "phpmyadmin phpmyadmin/mysql/admin-pass password M@ster9354"
debconf-set-selections <<< "phpmyadmin phpmyadmin/mysql/app-pass password M@ster9354"
debconf-set-selections <<< "phpmyadmin phpmyadmin/reconfigure-webserver multiselect none"
apt install -y phpmyadmin

9.6 Configurar phpMyAdmin

Gerar blowfish_secret:

BLOWFISH=$(openssl rand -base64 32)
echo "Blowfish Secret: $BLOWFISH"

Criar configuração:

cat > /etc/phpmyadmin/config.inc.php << 'EOF'
<?php
$i = 0;
$i++;

$cfg['Servers'][$i]['auth_type'] = 'cookie';
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;

$cfg['Servers'][$i]['controlhost'] = 'localhost';
$cfg['Servers'][$i]['controluser'] = 'phpmyadmin';
$cfg['Servers'][$i]['controlpass'] = 'M@ster9354';

$cfg['Servers'][$i]['pmadb'] = 'phpmyadmin';
$cfg['Servers'][$i]['bookmarktable'] = 'pma__bookmark';
$cfg['Servers'][$i]['relation'] = 'pma__relation';
$cfg['Servers'][$i]['table_info'] = 'pma__table_info';
$cfg['Servers'][$i]['table_coords'] = 'pma__table_coords';
$cfg['Servers'][$i]['pdf_pages'] = 'pma__pdf_pages';
$cfg['Servers'][$i]['column_info'] = 'pma__column_info';
$cfg['Servers'][$i]['history'] = 'pma__history';
$cfg['Servers'][$i]['tracking'] = 'pma__tracking';
$cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
$cfg['Servers'][$i]['recent'] = 'pma__recent';
$cfg['Servers'][$i]['favorite'] = 'pma__favorite';
$cfg['Servers'][$i]['users'] = 'pma__users';
$cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
$cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
$cfg['Servers'][$i]['savedsearches'] = 'pma__savedsearches';
$cfg['Servers'][$i]['central_columns'] = 'pma__central_columns';
$cfg['Servers'][$i]['designer_settings'] = 'pma__designer_settings';
$cfg['Servers'][$i]['export_templates'] = 'pma__export_templates';

$cfg['UploadDir'] = '';
$cfg['SaveDir'] = '';
$cfg['TempDir'] = '/tmp';
EOF

Adicionar blowfish_secret (substitua pelo valor gerado):

echo "\$cfg['blowfish_secret'] = '$(openssl rand -base64 32)';" >> /etc/phpmyadmin/config.inc.php

Importar tabelas de controle:

mysql -u phpmyadmin -p'M@ster9354' phpmyadmin < /usr/share/phpmyadmin/sql/create_tables.sql 2>/dev/null || true

9.7 Criar Vhosts Nginx Finais

webmoney.cnxifly.com (Aplicação principal):

cat > /etc/nginx/sites-available/webmoney.cnxifly.com << 'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name webmoney.cnxifly.com cnxifly.com www.cnxifly.com;
    return 301 https://webmoney.cnxifly.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name webmoney.cnxifly.com cnxifly.com www.cnxifly.com;
    
    root /var/www/webmoney/public;
    index index.php index.html;
    
    ssl_certificate /etc/letsencrypt/live/cnxifly.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cnxifly.com/privkey.pem;
    
    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }
    
    location ~ /\.(?!well-known).* {
        deny all;
    }
}
EOF

mail.cnxifly.com (PostfixAdmin):

cat > /etc/nginx/sites-available/mail.cnxifly.com << 'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name mail.cnxifly.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name mail.cnxifly.com;
    
    root /usr/share/postfixadmin/public;
    index index.php;
    
    ssl_certificate /etc/letsencrypt/live/cnxifly.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cnxifly.com/privkey.pem;
    
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    location ~ /\.(?!well-known).* {
        deny all;
    }
}
EOF

webmail.cnxifly.com (Roundcube):

cat > /etc/nginx/sites-available/webmail.cnxifly.com << 'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name webmail.cnxifly.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name webmail.cnxifly.com;
    
    root /usr/share/roundcube;
    index index.php;
    
    ssl_certificate /etc/letsencrypt/live/cnxifly.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cnxifly.com/privkey.pem;
    
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    location ~ /\.(?!well-known).* {
        deny all;
    }
    
    location ~ ^/(config|temp|logs)/ {
        deny all;
    }
}
EOF

phpmyadmin.cnxifly.com:

cat > /etc/nginx/sites-available/phpmyadmin.cnxifly.com << 'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name phpmyadmin.cnxifly.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name phpmyadmin.cnxifly.com;
    
    root /usr/share/phpmyadmin;
    index index.php;
    
    ssl_certificate /etc/letsencrypt/live/cnxifly.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cnxifly.com/privkey.pem;
    
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    location ~ /\.(?!well-known).* {
        deny all;
    }
}
EOF

9.8 Ativar Sites Nginx

ln -sf /etc/nginx/sites-available/webmoney.cnxifly.com /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/mail.cnxifly.com /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/webmail.cnxifly.com /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/phpmyadmin.cnxifly.com /etc/nginx/sites-enabled/

Testar e recarregar Nginx:

nginx -t
systemctl reload nginx

9.9 Criar Admin PostfixAdmin

Primeiro, acessar setup.php para criar tabelas:

curl -s https://mail.cnxifly.com/setup.php > /dev/null

Criar admin via SQL (mais confiável):

ADMIN_HASH=$(doveadm pw -s SHA512-CRYPT -p 'M@ster9354')
echo "Hash gerado: $ADMIN_HASH"
mysql -u postfixadmin -p'M@ster9354' postfixadmin << EOSQL
INSERT INTO admin (username, password, superadmin, created, modified, active)
VALUES ('admin@cnxifly.com', '$(doveadm pw -s SHA512-CRYPT -p "M@ster9354")', 1, NOW(), NOW(), 1)
ON DUPLICATE KEY UPDATE password='$(doveadm pw -s SHA512-CRYPT -p "M@ster9354")', active=1;
EOSQL

Desativar setup.php por segurança:

mv /usr/share/postfixadmin/public/setup.php /usr/share/postfixadmin/public/setup.php.disabled 2>/dev/null || true

10. FASE 9: NODE.JS 22 LTS + DEPLOY WEBMONEY (~15 min)

10.1 Instalar Node.js 22 LTS (Última Versão LTS)

Adicionar repositório oficial NodeSource:

curl -fsSL https://deb.nodesource.com/setup_22.x | bash -

Instalar Node.js:

apt install -y nodejs

Verificar versões:

node --version

Deve mostrar: v22.x.x

npm --version

10.2 Preparar Estrutura de Diretórios

mkdir -p /var/www/webmoney/public
mkdir -p /var/www/webmoney/storage/logs
mkdir -p /var/www/webmoney/storage/framework/{sessions,views,cache}
mkdir -p /var/www/webmoney/bootstrap/cache
chown -R www-data:www-data /var/www/webmoney

10.3 Deploy Backend (Laravel)

Na máquina de desenvolvimento:

Criar .env.production:

cd /workspaces/webmoney/backend
cat > .env.production << 'EOF'
APP_NAME=WEBMoney
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_TIMEZONE=Europe/Madrid
APP_URL=https://webmoney.cnxifly.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=webmoney
DB_USERNAME=webmoney
DB_PASSWORD=M@ster9354

MAIL_MAILER=smtp
MAIL_HOST=localhost
MAIL_PORT=587
MAIL_USERNAME=no-reply@cnxifly.com
MAIL_PASSWORD=M@ster9354
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=no-reply@cnxifly.com
MAIL_FROM_NAME="${APP_NAME}"
EOF

Enviar arquivos para o servidor:

rsync -avz --exclude='.git' --exclude='node_modules' --exclude='vendor' \
    ./ root@213.165.93.60:/var/www/webmoney/

No servidor (via SSH):

ssh root@213.165.93.60
cd /var/www/webmoney
cp .env.production .env
composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
chown -R www-data:www-data /var/www/webmoney
chmod -R 755 /var/www/webmoney
chmod -R 775 /var/www/webmoney/storage
chmod -R 775 /var/www/webmoney/bootstrap/cache

10.4 Deploy Frontend (React + Vite)

Na máquina de desenvolvimento:

cd /workspaces/webmoney/frontend
npm install
npm run build

Enviar build para o servidor:

rsync -avz ./dist/ root@213.165.93.60:/var/www/webmoney/public/

No servidor:

chown -R www-data:www-data /var/www/webmoney/public

11. FASE 10: VALIDAÇÃO FINAL (~5 min)

11.1 Criar Domínio e Mailbox no PostfixAdmin

Acessar PostfixAdmin:

URL: https://mail.cnxifly.com/login.php
Login: admin@cnxifly.com
Senha: M@ster9354
  1. Criar Domínio:

    • Menu: "Lista de Domínios" → "Novo Domínio"
    • Domínio: cnxifly.com
    • Caixas de Correio: 100
    • Aliases: 100
    • Guardar
  2. Criar Mailboxes:

    • Menu: "Lista Virtual" → "Adicionar Caixa de Correio"
    • admin@cnxifly.com / M@ster9354
    • no-reply@cnxifly.com / M@ster9354
    • support@cnxifly.com / M@ster9354

11.2 Testar Envio de Email

echo "Teste de email do servidor" | mail -s "Teste SMTP $(date)" admin@cnxifly.com

11.3 Verificar Status dos Serviços

systemctl status nginx
systemctl status php8.4-fpm
systemctl status mariadb
systemctl status postfix
systemctl status dovecot
systemctl status opendkim

11.4 Testar Configurações

nginx -t
postfix check
doveconf -n | head -20

11.5 Verificar Portas Abertas

ss -tlnp | grep -E ':(22|25|80|143|443|465|587|993)'

11.6 Testar DKIM

opendkim-testkey -d cnxifly.com -s default -vvv

11.7 Verificar DNS

dig cnxifly.com MX +short
dig cnxifly.com TXT +short
dig default._domainkey.cnxifly.com TXT +short
dig _dmarc.cnxifly.com TXT +short

11.8 Checklist Final

Verificação Status
https://webmoney.cnxifly.com carrega [ ]
https://mail.cnxifly.com login funciona [ ]
https://webmail.cnxifly.com login funciona [ ]
https://phpmyadmin.cnxifly.com login funciona [ ]
SSL válido em todos os subdomínios [ ]
Email enviado chega no inbox (não spam) [ ]
DKIM/SPF/DMARC pass [ ]

12. FASE 11: OTIMIZAÇÃO DE DESEMPENHO 🚀 (~20 min)

Esta é a fase final de otimização para máximo desempenho do servidor.

12.1 Otimização do Kernel (sysctl.conf)

cat >> /etc/sysctl.conf << 'EOF'

# ============================================
# WEBMONEY SERVER PERFORMANCE TUNING
# ============================================

# Network Performance
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15

# TCP Buffer Sizes
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 262144 16777216
net.ipv4.tcp_wmem = 4096 262144 16777216

# Enable TCP Fast Open
net.ipv4.tcp_fastopen = 3

# File Descriptors
fs.file-max = 2097152
fs.nr_open = 2097152

# Virtual Memory
vm.swappiness = 10
vm.dirty_ratio = 60
vm.dirty_background_ratio = 5

# Security (já ativo por padrão mas bom garantir)
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
EOF

Aplicar configurações:

sysctl -p

12.2 Aumentar Limites de Arquivos Abertos

cat >> /etc/security/limits.conf << 'EOF'

# WEBMONEY Performance Limits
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
www-data soft nofile 65535
www-data hard nofile 65535
mysql soft nofile 65535
mysql hard nofile 65535
EOF

12.3 Otimização do PHP-FPM (Pool Dedicado)

Criar pool otimizado para produção:

cat > /etc/php/8.4/fpm/pool.d/webmoney.conf << 'EOF'
[webmoney]
user = www-data
group = www-data

listen = /run/php/php8.4-fpm-webmoney.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Process Manager - ondemand para economia de recursos
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
pm.max_requests = 500

; Status e Logs
pm.status_path = /status
ping.path = /ping
ping.response = pong

; Slow log para debug
slowlog = /var/log/php8.4-fpm-webmoney-slow.log
request_slowlog_timeout = 5s

; Limites
request_terminate_timeout = 300s
rlimit_files = 65535
rlimit_core = 0

; Environment
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

; PHP Settings
php_admin_value[error_log] = /var/log/php8.4-fpm-webmoney-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/sessions
EOF

12.4 Otimização Avançada do OPcache

cat > /etc/php/8.4/mods-available/opcache-production.ini << 'EOF'
; OPcache Production Settings
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.max_wasted_percentage=10
opcache.revalidate_freq=0
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.fast_shutdown=1
opcache.file_cache=/tmp/opcache
opcache.file_cache_only=0
opcache.file_cache_consistency_checks=1

; JIT (PHP 8+)
opcache.jit=1255
opcache.jit_buffer_size=256M
EOF

Criar diretório de cache:

mkdir -p /tmp/opcache
chown www-data:www-data /tmp/opcache

Ativar configuração:

rm -f /etc/php/8.4/fpm/conf.d/99-opcache-custom.ini
ln -sf /etc/php/8.4/mods-available/opcache-production.ini /etc/php/8.4/fpm/conf.d/99-opcache-production.ini

12.5 Otimização do MariaDB

cat > /etc/mysql/mariadb.conf.d/99-performance.cnf << 'EOF'
[mysqld]
# InnoDB Settings
innodb_buffer_pool_size = 512M
innodb_buffer_pool_instances = 4
innodb_log_file_size = 128M
innodb_log_buffer_size = 16M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
innodb_read_io_threads = 4
innodb_write_io_threads = 4

# Query Cache (deprecated in MySQL 8, still works in MariaDB)
query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 2M

# Connections
max_connections = 200
max_connect_errors = 100000
wait_timeout = 600
interactive_timeout = 600

# Buffers
join_buffer_size = 4M
sort_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 2M

# Table Cache
table_open_cache = 4000
table_definition_cache = 2000

# Temp Tables
tmp_table_size = 64M
max_heap_table_size = 64M

# Binary Log (para replicação futura)
# log_bin = mysql-bin
# binlog_format = ROW
# expire_logs_days = 7

# Slow Query Log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

# Thread Pool
thread_handling = pool-of-threads
thread_pool_size = 4
EOF

12.6 Otimização do Nginx (Produção)

Atualizar nginx.conf com configurações de produção:

cat > /etc/nginx/conf.d/performance.conf << 'EOF'
# Additional Performance Settings

# Proxy Cache
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=PROXY:10m inactive=60m max_size=1g;

# Static File Caching
map $sent_http_content_type $expires {
    default                    off;
    text/html                  epoch;
    text/css                   1M;
    application/javascript     1M;
    ~image/                    1M;
    ~font/                     1M;
    application/font-woff      1M;
    application/font-woff2     1M;
}

# Brotli Compression (se disponível)
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css application/json application/javascript text/xml application/xml;
EOF

Criar diretório de cache do proxy:

mkdir -p /var/cache/nginx/proxy
chown -R www-data:www-data /var/cache/nginx

12.7 Configurar Cache de Sessão PHP com Arquivos

mkdir -p /var/lib/php/sessions
chown -R www-data:www-data /var/lib/php/sessions
chmod 1733 /var/lib/php/sessions

12.8 Instalar e Configurar Redis (Cache Opcional)

Instalar Redis:

apt install -y redis-server

Configurar Redis:

sed -i 's/^# maxmemory .*/maxmemory 128mb/' /etc/redis/redis.conf
sed -i 's/^# maxmemory-policy .*/maxmemory-policy allkeys-lru/' /etc/redis/redis.conf

Habilitar e iniciar:

systemctl enable redis-server
systemctl start redis-server

Verificar:

redis-cli ping

Deve retornar: PONG

12.9 Atualizar Vhosts para Usar Pool Dedicado

Atualizar webmoney.cnxifly.com para usar o novo pool:

sed -i 's|php8.4-fpm.sock|php8.4-fpm-webmoney.sock|g' /etc/nginx/sites-available/webmoney.cnxifly.com

12.10 Reiniciar Todos os Serviços

systemctl restart php8.4-fpm
systemctl restart mariadb
systemctl restart nginx
systemctl restart redis-server

12.11 Verificar Otimizações

Verificar OPcache:

php -i | grep -i opcache

Verificar limites de arquivo:

ulimit -n

Verificar conexões MariaDB:

mysql -u root -p'M@ster9354' -e "SHOW VARIABLES LIKE 'max_connections';"

Verificar buffer pool:

mysql -u root -p'M@ster9354' -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"

12.12 Benchmark Simples

Testar resposta do servidor:

curl -w "@-" -o /dev/null -s "https://webmoney.cnxifly.com" << 'EOF'
     time_namelookup:  %{time_namelookup}s\n
        time_connect:  %{time_connect}s\n
     time_appconnect:  %{time_appconnect}s\n
    time_pretransfer:  %{time_pretransfer}s\n
       time_redirect:  %{time_redirect}s\n
  time_starttransfer:  %{time_starttransfer}s\n
                     ----------\n
          time_total:  %{time_total}s\n
EOF

13. COMANDOS DE VERIFICAÇÃO E MONITORAMENTO

Status dos Serviços

systemctl status nginx php8.4-fpm mariadb postfix dovecot opendkim redis-server

Testar Configurações

nginx -t
postfix check
doveconf -n

Verificar Portas

ss -tlnp | grep -E ':(22|25|80|143|443|465|587|993|6379)'

Testar DKIM

opendkim-testkey -d cnxifly.com -s default -vvv

Verificar DNS

dig cnxifly.com MX +short
dig cnxifly.com TXT +short
dig default._domainkey.cnxifly.com TXT +short
dig _dmarc.cnxifly.com TXT +short

Monitorar Logs em Tempo Real

tail -f /var/log/nginx/error.log
tail -f /var/log/mail.log
tail -f /var/log/php8.4-fpm-webmoney-error.log
tail -f /var/log/mysql/slow.log

Testar Email via Terminal

echo "Teste de configuração SMTP" | mail -s "Teste SMTP" admin@cnxifly.com

Verificar Uso de Recursos

htop
free -h
df -h

14. REFERÊNCIA RÁPIDA

Credenciais Unificadas

Serviço Usuário Senha
SSH root root Master9354
SSH admin admin M@ster9354
MariaDB root root M@ster9354
MariaDB admin admin M@ster9354
PostfixAdmin admin@cnxifly.com M@ster9354
phpMyAdmin admin M@ster9354
Email (criar) admin@cnxifly.com M@ster9354

URLs Finais

Serviço URL
WEBMoney App https://webmoney.cnxifly.com
PostfixAdmin https://mail.cnxifly.com
Roundcube https://webmail.cnxifly.com
phpMyAdmin https://phpmyadmin.cnxifly.com
API https://webmoney.cnxifly.com/api

Arquivos de Configuração Importantes

Arquivo Propósito
/etc/nginx/nginx.conf Nginx principal
/etc/nginx/sites-available/* Vhosts Nginx
/etc/php/8.4/fpm/pool.d/webmoney.conf PHP-FPM Pool
/etc/php/8.4/mods-available/opcache-production.ini OPcache
/etc/mysql/mariadb.conf.d/99-performance.cnf MariaDB tuning
/etc/postfix/main.cf Postfix config
/etc/dovecot/dovecot.conf Dovecot config
/etc/opendkim.conf DKIM config
/etc/postfixadmin/config.local.php PostfixAdmin
/etc/roundcube/config.inc.php Roundcube
/var/www/webmoney/.env Laravel env

Versões Instaladas

Software Versão
Ubuntu 24.04 LTS
PHP 8.4.x
MariaDB 11.4 LTS
Nginx 1.27.x (Mainline)
Node.js 22.x LTS
Composer 2.8.x
Postfix 3.9.x
Dovecot 2.3.x
Redis 7.x

Registro DNS DKIM (adicionar no painel)

Nome: default._domainkey.cnxifly.com
Tipo: TXT
Valor: [Usar o conteúdo de /etc/opendkim/keys/cnxifly.com/default.txt]

Registro DNS DMARC (adicionar no painel)

Nome: _dmarc.cnxifly.com
Tipo: TXT
Valor: v=DMARC1; p=quarantine; rua=mailto:postmaster@cnxifly.com; ruf=mailto:postmaster@cnxifly.com; fo=1; sp=quarantine; adkim=s; aspf=s; pct=100

Registro DNS SPF (adicionar no painel)

Nome: cnxifly.com (ou @)
Tipo: TXT
Valor: v=spf1 mx a ip4:213.165.93.60 -all

15. TROUBLESHOOTING COMUM

Nginx não inicia

nginx -t
journalctl -xeu nginx

PHP-FPM erro de socket

ls -la /run/php/
systemctl restart php8.4-fpm

MariaDB não aceita conexão

systemctl status mariadb
journalctl -xeu mariadb
mysql -u root -p'M@ster9354' -e "SELECT 1;"

Email não enviado

tail -50 /var/log/mail.log
postqueue -p
postfix check

Dovecot não autentica

doveconf -n | grep auth
tail -50 /var/log/mail.log | grep dovecot

SSL não funciona

certbot certificates
nginx -t
openssl s_client -connect webmoney.cnxifly.com:443 -servername webmoney.cnxifly.com

Laravel erro 500

tail -50 /var/www/webmoney/storage/logs/laravel.log
php artisan config:clear
php artisan cache:clear
chown -R www-data:www-data /var/www/webmoney/storage

Tempo Total Estimado: ~120 minutos (com otimização de desempenho)

Autor: GitHub Copilot
Data: 7 de Dezembro de 2025
Versão: 2.0.0 - Manual Completo com Otimização