O WordPress é o CMS mais popular que existe – é um dos preferidos na hora de criar um blog ou até mesmo um site mais bem estruturado, como um portal ou um site institucional, e pode ser hospedado em qualquer servidor Linux bem configurado. Existem milhares de plugins e temas disponíveis (muitos deles gratuitos), o core em PHP também o torna acessível à maioria dos desenvolvedores e incontáveis tutoriais sobre como instalar e configurar o WordPress podem ser encontrados – e neste artigo vou mostrar como configurar um robusto WordPress na Amazon Web Services usando um Elastic Beanstalk com:
- Servidores Amazon Linux x64 com PHP 5.4
- Banco de dados RDS MySQL 5.3 em Multi-AZ
- Um bucket S3 para o armazenamento de arquivos estáticos (conteúdo multimídia, fotos, arquivos para download, etc)
- Plugins de segurança, SEO, cache, envio de e-mails via IMAP e vários outros para dar um up no CMS
- Ambientes de staging e produção espelhados – seguindo a filosofia Green-Blue
Passo 1: Preparando o S3 para armazenamento estático
Em vez de usar o diretório uploads do WordPress para armazenar a nossa biblioteca de mídia (fotos, vídeos, etc), vamos usar um bucket S3 porque o uso de volumes EC2 não se aplica ao nosso caso (um volume EC2 só pode estar conectado a uma única instância, a replicação desses volumes é complexa, e outros fatores) – para tanto, precisamos preparar o ambiente para que o WordPress tenha permissão de escrita e leitura em um bucket S3. O diretório uploads será meramente um espaço temporário de armazenamento de arquivos (uma área de transferência) entre o que for carregado através do backend do WordPress e o S3.
Faça login no AWS Management Console com o seu browser preferido, clique em S3 e crie um bucket para o seu WordPress.
Em seguida, no AWS Management Console, clique em IAM (que é onde criamos as contas de acesso ao ambiente). Uma vez lá, entre em IAM Resources e crie um usuário para o WordPress, com uma chave e uma senha – ambos são strings alfanuméricas longas e encontram-se em Security Credentials onde um arquivo CSV contendo essas strings pode ser baixado a partir dali mesmo.
Em seguida, crie uma policy de acesso completo a esse bucket para o usuário criado para o WordPress (você pode customizar ainda mais esta policy, usando o Policygen se preferir) – não esqueça de substituir a palavra chave-pública pela chave gerada no IAM:
{ "Statement": [ { "Action": "s3:*", "Effect": "Allow", "Resource": [ "arn:aws:s3:::nome-do-bucket", "arn:aws:s3:::nome-do-bucket/chave-publica”, ] } ] }
Passo 2: Preparando o Elastic Beanstalk do ambiente STAGING
Em linhas gerais, o Elastic Beanstalk é um produto da Amazon Web Services no qual que você lança um container onde sua aplicação (seja Python, PHP, Node.JS, Tomcat, etc) irá rodar. Ele pode contemplar instâncias de bancos de dados RDS multi-zonas para redundância e failover e, automaticamente, replica uma imagem AMI padrão de um servidor que você customiza com a sua aplicação, conforme os triggers (CPU, I/O, etc) que você definir, e um load balancer na frente de tudo isso para garantir que todos os servidores de aplicação respondam às requisições.
Vamos então lançar um Elastic Beanstalk para PHP – dentro do AWS Management Console com um browser e, no dashboard de aplicações, clique em Elastic Beanstalk e siga os passos abaixo:
- Crie a aplicação dando-lhe um nome;
- Crie inicialmente apenas um ambiente PHP contendo as instâncias de aplicação com o tamanho necessário, usando a configuração para “Sample Apllication”;
- Crie os bancos de dados MySQL com a capacidade (GB) e tamanho de instância necessários – dê preferência a Multi-AZ, porque o seu banco vai ser replicado em outra zona da Amazon.
Enquanto o Elastic Beanstalk é criado – o processo pode demorar uns quinze minutos para criar as instâncias EC2 e RDS, o Load Balancer e os Security Groups, vamos lançar uma instância EC2 para o ambiente de desenvolvimento – e para servir de base para as AMIs do Elastic Beanstalk.
Passo 3: Configurando o ambiente DEV
É inútil configurar o WordPress diretamente na instância do Elastic Beanstalk porque, mesmo usando volumes EBS, o Beanstalk vai usar a AMI (imagem) de deploy do ambiente “Sample Application” sempre que ele invocar outra instância para responder à demanda (ou mesmo se você der reboot na instância onde o WordPress foi configurado). E isso é o mesmo que enxugar gelo, porque o seu WordPress vai “sumir”. Para que isso não aconteça, é mandatório que use uma instância para configurar o seu WordPress inteiro e, a partir dela, criar uma AMI para depois reconstruir o seu Elastic Beanstalk (ou utilizá-la em um Cloud Formation, ou mesmo criar um template script para deploy rápido). Lance uma instância Amazon Linux (eu usei a imagem ami-35792c5c, um Amazon Linux x64 padrão), use um keypair já existente (ou crie um novo para seu WordPress) e coloque-a em um Security Group (não necessariamente o mesmo do Elastic Beanstalk). Atribua um Elastic IP a ela e, quando ela estiver online e respondendo (e assumindo que o Security Group no qual a instância está possui as portas TCP 22,80, 8080 e 3306, UDP 53 e ICMP ALL abertas), conecte-se via SSH através do usuário ec2-user e sua keypair, e vamos configurar a máquina com base nas recomendações da AWS:
sudo yum update –y sudo yum groupinstall -y "Web Server" "PHP Support" sudo service httpd start && sudo chkconfig httpd on sudo groupadd www && sudo usermod -a -G www ec2-user
Reinicie a instância (pela console da AWS ou simplesmente com sudo reboot) e prossiga com a configuração do ambiente via SSH para setar as permissões necessárias:
sudo chown -R root:www /var/www sudo chmod 2775 /var/www find /var/www -type d -exec sudo chmod 2775 {} + find /var/www -type f -exec sudo chmod 0664 {} +
Agora é necessário configurar os Security Groups ou, do contrário, não conseguiremos “amarrar” tudo como desejamos.
Passo 4: Configurando os security groups
O Elastic Beanstalk cria os security groups de EC2 e RDS, contudo, precisamos alterar algumas coisas para a instalação do WordPress e a configuração para que o ambiente de desenvolvimento (aquela instância EC2 onde estávamos agora mesmo) acesse o MySQL do Elastic Beanstalk.
- EC2: no security group do seu Elastic Beanstalk onde as instâncias EC2 vão rodar as portas 22 (SSH) e 80 (HTTP) estão liberadas por default, mas outras portas podem ser necessárias (como o IMAP/S 993 e HTPS 443 para o nosso exemplo);
- RDS: no security group da RDS criada pelo Beanstalk, adicione a regra 0.0.0.0/0 (opcional, somente se você for usar um MySQL Client como o MySQL Workbench, que facilita bastante a preparação do banco; esta regra DEVE ser removida depois que o seu WordPress estiver instalado); adicione também a regra com o Elastic IP da instância EC2 de desenvolvimento, onde instalamos o Apache (assim a instância de desenvolvimento terá acesso ao MySQL do Elastic Beanstalk, que é o que queremos).
Passo 5: Preparando o banco de dados MySQL
Acesse a instância RDS criada pelo Beanstalk – use o nome canônico da mesma (a porta é 3306 por default), o usuário e a senha são os mesmos utilizados na hora de configurar o ambiente no Elastic Beanstalk. Uma vez dentro do servidor de banco, crie o schema, o usuário e as permissões do mesmo dentro do schema – execute os comandos a seguir e o banco está pronto para receber as tabelas do WordPress:
use mysql; create database nomedobanco; grant usage on *.* to 'nomedousuario'@'localhost' identified by 'senhadousuario'; grant all privileges on nomedobanco.* to ' nomedousuario'@'localhost '; grant all privileges on nomedobanco.* to 'nomedousuario'@'%';
Agora que o ambiente está pronto para receber o WordPress, vamos instalá-lo.
Importante: as instruções a seguir referem-se às configurações default do Apache – por questões de segurança, é recomendável que o diretório raiz da aplicação seja diferente do default e para isso será necessário alterar as configurações no Apache (há documentação na internet para isso).
Passo 6: instalando o WordPress na instância DEV
Agora volte à instância EC2 de desenvolvimento (DEV) via SSH – vamos proceder algumas configurações básicas, que irão atualizar os pacotes e limpar a pasta /var/www/html para a instalação do WordPress:
sudo yum update –y cd /var/www/html sudo rm –rf *
Baixe e descompacte a última versão do WordPress (em inglês, o arquivo .po e .mo de tradução podem ser baixados e colocados depois, mas se preferir visite, o blog do WordPress em Português BR para baixar a última versão do WordPress BR, copiando o link de lá). Vamos usar a última versão disponível na data de criação deste artigo ( 3.7.1) em Português BR:
cd /usr/src sudo wget http://br.wordpress.org/wordpress-3.7.1-pt_BR.tar.gz sudo tar –zxvf wordpress-3.6.1-pt_BR.tar.gz cd wordpress sudo cp * /var/www/html
Agora que o seu WordPress foi baixado, descompactado e copiado para o diretório da aplicação web, acesse-o pelo endereço IP da instância DEV e prossiga com a instalação. Como não temos MySQL em localhost (está nas RDS do Elastic Beanstalk, lembram?), é necessário que informem o nome canônico da RDS do Elastic Beanstalk como hostname de banco, e o usuário e senha usados na criação do schema. De resto é instalação WordPress padrão – siga os passos e a aplicação estará instalada com sucesso, pronta para um “up” de plugins e o template – e o mais importante, a configuração de um bucket S3 como armazenamento de arquivos estáticos da biblioteca de mídia.
Importante: como não foi configurado FTP na instância – não é seguro e não será usado no Elastic Beanstalk, toda e qualquer alteração (instalação de plugins, templates, etc) deverá ser feita via SSH. Qualquer tentativa de instalação de plugins ou temas usando a interface admin do WordPress não funcionará. Além do mais, essas instalações só serão úteis no setup inicial do WordPress e se forem necessárias mudanças ou atualizações.
Passo 7: Conectando o WordPress no S3
Entre no diretório de plugins do WordPress para baixar os plugins de Amazon Web Services via SSH (wget):
cd /var/www/html/wp-content/plugins
Os plugins a serem baixados são Amazon Web Services e Amazon S3 and Cloudfront – o primeiro é um hook entre a Amazon e o WordPress, e o segundo é específico para uso do S3, como armazenamento de arquivos estáticos (biblioteca de mídia). Basta baixá-los com wget e descompactá-los dentro do diretório de plugins com o comando unzip nome-do-arquivo.zip – os paths são criados automaticamente. Em seguida, edite o arquivo wp-config.php para setar as chaves pública e privada do IAM para acesso ao S3.
sudo vim /var/www/html/wp-config.php
No final do conteúdo do arquivo, cole as seguintes linhas (substituindo as palavras chave-publica pela chave pública e chave-privada pela clave privada do usuário do WordPress (que estão naquele arquivo CSV, criado em IAM e previamente baixado):
define( 'AWS_ACCESS_KEY_ID', 'chave-publica' ); define( 'AWS_SECRET_ACCESS_KEY', chave-privada' );
Salve o arquivo com um wq! e crie um diretório uploads no path correto e atribua as permissões adequadas (ficará seguro contra escritas não autorizadas e ao mesmo tempo acessível ao WordPress):
cd /var/www/html/wp-content sudo mkdir uploads chmod –v 747 uploads
Agora, volte à interface admin do WordPress – na seção Plugins – e ative o Amazon Web Services primeiro, e depois o S3 and Cloudfront (este último deve ser configurado com o bucket que foi criado para o WordPress conforme a figura abaixo onde a caixa de seleção conterá o nome do seu bucket do WordPress). Configurações adicionais (como o uso em CloudFront, versionamento de araquivos, etc) podem ser obtidas no site do plugin. Após as alterações desejadas, salve-as e o seu WordPress agora estará armazenando o conteúdo de mídia no S3, utilizando o diretório uploads como temporário.
Agora é a parte onde você pode “viajar” à vontade, baixando e descompactando seus plugins preferidos. Recomendo que instale os seguintes:
- WP Maintenance Mode: permite que o usuário coloque o WordPress em modo “Estamos em Obras” – assim dá pra fazer todas as mudanças que se desejarem, fora das vistas do público;
- My WordPress Login Logo: personaliza o seu logo na área administrativa (backend) do site (e para o Maintenance Mode também, já que ele também usa o logo de login do backend);
- All in One Favicon: permite customizar os favicons padrão do WordPress (inclusive para Apple Touch), tanto do frontend como backend;
- W3 Total Cache: transforma as páginas em HTMLs estáticos, acelerando tremendamente o carregamento das mesmas e melhorando a experiência dos visitantes do site em WordPress;
- Better WP Security: plugin que lhe mostra aonde você deve mexer no seu servidor para que o WordPress torne-se mais seguro – ele também configura muitas coisas sozinho, e é uma mão na roda do admin;
- Ultimate TinyMCE: o melhor editor WYSIWYG para WordPress, substitui o (pobre) editor nativo.
Faça o mesmo com os templates – entre no diretório /var/www/html/wp-content/themes e baixe com wget o tema de sua preferência – eu costumo fazer um rm –rf nomedotema para “limpar” a instalação do WordPress e deixar só o tema que será usado, eliminando todos os outros.
Passo 8: Criando uma AMI e reconfigurando o Elastic Beanstalk
Terminou de instalar todos os plugins e o template? Agora é hora de criar uma imagem AMI para redeploy do Elastic Beanstalk – e fazer o seu WordPress rodar com esteroides em múltiplas instâncias! Na console de administração das instâncias EC2, clique com o botão direito sobre a instância de DEV e selecione a opção Create Image – coloque um nome para a sua imagem AMI e crie-a.
Assim que a imagem estiver criada, ela vai ganhar um nome – ami-codigoalfanumerico – copie esse código e vá até o painel administrativo do Elastic Beanstalk, clique na sua aplicação e, em seguida, no Elastic Beanstalk de STAGING. No menu à esquerda, clique em Configuration e no dashboard de configuração, clique em Instances. Role a tela até o campo com o nome da AMI em uso e substitua-o pelo nome da AMI que criou a partir da instância EC2 de desenvolvimento (DEV). Salve as configurações clicando em Rebuild e aguarde – o Elastic Beanstalk vai reconstruir suas instâncias EC2 internas de aplicação usando a sua imagem de deploy do WordPress. O rebuild do Elastic Beanstalk demora um tempo e passa por vários estados diferentes – aguarde até o final. Assim que o Elastic Beanstalk voltar ao status “Verde” (OK), e assim permanecer por alguns minutos, valide tudo e se estiver OK é só usar o seu WordPress!
Como é um ambiente de STAGING (também conhecido como “Azul”), você precisa criar um ambiente de PRODUÇÃO (também conhecido como “Verde”). Para tanto, crie um segundo Elastic Beanstalk (dentro da mesma aplicação). Você pode usar a mesma AMI customizada do WordPress – contudo, lembre-se que ela aponta para a RDS do ambiente de STAGING e qualquer alteração nesse ambiente afetará a exibição no Wordprerss de produção. Para evitar isso, é recomendável que crie uma nova instância EC2 lançada a partir da AMI customizada e edite o arquivo wp-config.php para apontar para a instância RDS do segundo Elastic Beanstalk. Para manter os schemas iguais, basta fazer um rebuild do Database do Elastic Beanstalk de produção usando o snapshot da RDS de staging. Agora você tem ambos os ambientes idênticos, cada um apontando para a sua base MySQL.
E para quê dois Elastic Beanstalk? É simples: qualquer alteração que for feita no ambiente de STAGING – e for validada para produção – é fácil de ser implementada e, em caso de problemas, o rollback é rápido e seguro. O Elastic Beanstalk é ideal para isso, pois permite alternar as URLs entre os dois ambientes com um clique e aplicar quase que imediatamente a mudança na aplicação – se algo der errado, basta reverter a alternância das URLs e a aplicação volta ao estado anterior.
No Elastic Beanstalk, dentro da aplicação (onde os dois ambientes estão rodando) existe um botão chamado Swap URLs – ao ser clicado, você define quais Elastic Beanstalk terão suas URLs trocadas entre si dentro do Route53. Isso significa que você coloca o site de staging em produção em poucos segundos e pode voltar atrás em caso de problemas. Esta filosofia é chamada de “Blue-Green” (“Verde-Azul”, daí as notações de nomes adotadas anteriormente) e nada mais é do que adotar a boa prática de ter dois ambientes idênticos: um Blue (Azul, de staging para os testes de mudanças e validação) e outro Green (Verde, de produção, que será acessado pelos visitantes do WordPress).
Passo 9: Usando recordsets no Route53 para o Elastic Beanstalk
Agora é só “amarrar” os dois Elastic Beanstalk no Route53 – o ambiente de STAGING ficará com a URL staging.meudominio.com.br e o ambiente de PRODUÇÃO com meudominio.com.br. Crie dois recordsets na sua DNS Zone do Route53 (uma para cada Elastic Beanstalk, respectivamente STAGING e PRODUÇÃO). Cada recordset aponta para o Load Balancer de cada Elastic Beanstalk – você pode encontrar qual Load Balancer pertence a qual Elastic Beanstalk indo no painel de administração das instâncias EC2 (no menu à esquerda vá até Load Balancers, identifique qual deles pertence a qual Elastic Beanstalk, copie o endpoint para seu respectivo recordset e está pronto).
Lembretes
Sempre que quiser realizar atualizações no WordPress ou instalar plugins:
- Atualize tudo que precisar na instância DEV;
- Crie uma nova imagem AMI;
- Faça o rebuild do Elastic Beanstalk de STAGING com essa nova AMI e valide as alterações;
- Alterne as URLs no dashboard da aplicação no Elastic Beanstalk;
- Descarte a AMI antiga.
Sempre que uma alteração de conteúdo for feita em STAGING, ao trocar as URLs ela se torna PRODUÇÃO (e a antiga PRODUÇÃO em STAGING). O conteúdo das bases de dados nas instâncias RDS em cada Beanstalk será diferente – assim, alguns processos devem ser adotados:
- Antes de alternar as URLs, crie um snapshot da instância RDS de cada ambiente (STAGING e PRODUÇÃO);
- Alterne as URLs entre os Elastic Beanstalk – o que era PRODUÇÃO agora é STAGING e vice versa – e agora faça um rebuild nas RDS de STAGING (ex-PRODUÇÃO) usando o snapshot da atual PRODUÇÃO (ex-STAGING);
- Se algo der errado, faça o rebuild com os snapshots anteriores à troca de URLs;
Importante: Tenha um controle rigoroso e documentado desses snapshots e AMIs ou, do contrário, você terá inúmeras versões de RDS e EC2 e não saberá qual delas é a que “está valendo”. Uma planilha serve bem para isso, mas se preferir pode usar algo mais sofisticado.
Conclusão
Parece algo um tanto complexo configurar este ambiente para WordPress, mas na verdade não é. Uma vez configurado – e com bastante atenção nos processos e sem pular etapas – é possível administrar o ambiente de forma bem simples. E via de regra, qualquer aplicação PHP que possua um plugin ou módulo para uso do S3 para armazenamento de arquivos estáticos (por exemplo Drupal ou Joomla) pode funcionar de maneira análoga.