Deploy de aplicações PHP e MySQL com Git e Github Actions

Eu sou um programador apaixonado por aprender e ensinar. Nos últimos 16 anos tenho focado minhas atenções ao desenvolvimento web Fullstack, mas sou bastante entusiasta das plataformas mobile.
Pronto, agora que já aprendemos como Criar um Droplet na DigitalOcean e como Configurar a pilha LAMP (Linux, Apache, MySQL e PHP), vamos agora realizar o Deploy de nossa aplicação. Para esse exemplo vamos usar o Freddy Gestor. O Freddy Gestor é uma aplicação simples de exemplo construída por mim, utilizando diversas bibliotecas PHP populares, com o intuito de apresentar como construir uma aplicação PHP moderna sem precisar de um framework de mercado.
Criando um Fork e Clonando o projeto
A primeira coisa que precisamos é criar um FORK do projeto e cloná-lo para a nossa máquina local. Para clonar navegue até um diretório de sua escolhe e execute o comando:
git clone git@github.com:PHPauloReis/freddy-gestor.git
Importante!!! No comando acima, “PHPauloReis” é o meu usuário no GitHub. Como você criou um Fork do projeto para a sua conta, lembre-se de alterar “PHPauloReis” para o seu usuário do GitHub.
Analisando os arquivos
Uma vez que você tenha clonado o projeto, abra-o em seu editor preferido. Você percebera a existência de um arquivo no caminho: “.github/workflows/deploy.yml“. Esse ponto (“.”), no início do nome github, não é um erro, é proposital e faz parte do nome do diretório.
O conteúdo desse arquivo é:
name: "Deploy para DigitalOcean"
on:
push:
branches:
- main
jobs:
build_deploy:
runs-on: ubuntu-latest
steps:
- name: "Baixar o código"
uses: actions/checkout@v4
- name: "Copiar arquivos para a Digital Ocean"
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "."
target: "/var/www/freddy"
- name: "Build da aplicação"
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/freddy
composer install --no-dev --no-progress -a
chown -R www-data:www-data .
As linhas que chamo a atenção nesse arquivo são:
on:
push:
branches:
- main
Isso indica que essa action (tarefa no github actions) será executada toda vez que rolar um push para a branch main.
- name: "Copiar arquivos para a Digital Ocean"
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "."
target: "/var/www/freddy"
No Linux existe um comando chamado scp (secure copy). Esse comando permite que você copie de maneira segura, arquivos e diretórios de um computador para outro por meio do protocolo SSH.
No exemplo acima, o “appleboy/scp-action@v0.1.7” é uma action do github actions que executa uma copia usando o comando scp de maneira automatizada. Basicamente você precisa informar o host, o nome do usuário, sua chave privada (note que aqui não estamos falando da chave pública que configuramos no tutorial: Como criar uma máquina Virtual (Droplet) na DigitalOcean?), diretório a partir do qual a copia será feita, nesse caso o “.” indica o diretório atual e o diretório alvo no servidor, nesse caso "/var/www/freddy".
Perceba que, no bloco acima, existem algumas “variáveis”. Isso é proposital. A ideia aqui é que você entenda que o nome do host, o usuário e a chave privada dão poderes a qualquer pessoa que possua esses dados para acessar, deletar, modificar etc. qualquer informação no servidor.
Logo, esses dados são sensíveis e não devem ser expostos no código, muito menos em um repositório do GitHub, mesmo que seja um repositório privado.
Daqui a pouco, ainda nesse tutorial, vamos ver como usar essas variáveis, por hora apenas entenda que elas existem e são importantes para segurança.
Um pouco mais abaixo temos esse outro trecho
- name: "Build da aplicação"
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/freddy
composer install --no-dev --no-progress -a
chown -R www-data:www-data public/uploads storage
Aqui temos “appleboy/ssh-action@v1.0.3”, uma outra action do Github Actions. Essa por sua vez se encarrega de acessar o nosso servidor, usando ssh, e executa alguns comandos pré-definidos.
cd /var/www/freddy
Acessa o diretório onde a nossa aplicação foi instalada
composer install --no-dev --no-progress -a
Executa a instalação das dependência usando o composer
O parâmetro
--no-devIndica ao composer para não instalar as dependências de desenvolvimento.O parâmetro
-aé um atalho para--optimize-autoloader, ele:Gera um autoloader otimizado
Melhora a performance da aplicação em produção
Reduz tempo de carregamento das classes
chown -R www-data:www-data public/uploads storageTransfere para o usuário e grupo www-data a propriedade dos diretórios public/uploads e storage, bem como todos os seus arquivos e subdiretórios.
Configurando variáveis de ambiente no Github
Agora que já entendemos o conteúdo do arquivo “.github/workflows/deploy.yml“ vamos obter a chave privada de nossa máquina para enviar para o Github.
No terminal do seu computador execute o comando:
cat ~/.ssh/id_ed25519
A saída gerada por esse comando será similar a:
-----BEGIN PGP PUBLIC KEY BLOCK-----
nCTRaDdRWBYJKwYBBAHaRw8BAQdA+ZCUXsxC8OxAw+ky6NIhf2xu/nwEXn64LigZ
+5JgFcy0FW5qZyA8bmpnQGVkMjU1MTkucHViTirABBMWCgA7FiEEjnU9tiCIddCF
rTyv7VgRDe9T4iQFAmg3UVgFAwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AA
CgkQ7VgRDe9T4iQw5QD/f8vLc7DmJHAVFU/OKOy7TqcyhlXoGaCCPCyktSi2v4QA
/RrUsqiJt9Kg/e6zFEG+dHTQe13M2x9EG+LdS385pQYJuDgEaDdRWBIKKwYBBAGX
VQEFAQEHQCkrr5tV9nW7RxjyFtYONqNC1rDuEnY2nbenAqlxpA4nAwEIB4h4BBgW
CgAgFiEEjnU9tiCIddCFrTyv7VgRDe9T4iQFAmg3UVgCGwwACgkQ7VgRDe9T4iSA
UgEAt2FjAhv4hq6W8/AjV4TZpSsS8KzdB/2rXg9FCpOH2PQBAK7g7TYj2UV4H5UX
BEARZX3bYK6DZJT28Kxx8zYm/BQP=1NdS
-----END PGP PUBLIC KEY BLOCK-----
Acesse o repositório que você “forkou” (em sua conta) e nele clique “Settings” (no menu superior). Uma nova página será aberta, nela clique no menu lateral esquerdo, na opção: “Secrets and variables“ e depois em “Actions“
A seguinte tela será exibida:

Mantenha selecionada a aba “Secrets” e clique em “New repository secret”
Observação!!!
Repository secrets: Valem para todo o repositório
Environment secrets: Associados a um environment específico (ex: staging, production)
Como não teremos vários servidores de homologação, teste, etc… vamos pegar a opção mais genérica.
Cadastre o seu HOST (Lembre-se que aqui é o IP do seu Droplet)

Cadastre o seu USERNAME: root
Cadastre sua SSH_PRIVATE_KEY: Chave privada obtida no terminal
No final você terá isso:

Prontinho. Para testarmos, vamos realizar um novo push para o nosso repositório. Nesse exemplo vou mudar um arquivo aleatório. Abra o arquivo .env.example e informe a senha DATABASE_PASSWORD=secret (Lembrando que isso é só um teste). Faça um commit e um push.
git add .
git commit -m "Troca a senha do banco de dados"
git push
Acesse o repositório do seu projeto no Github e clique Actions (no menu superior), você verá algo como:

Quando o JOB for concluído, esse ícone amarelo ficará verde.
Vamos agora acessar novamente o nosso Droplet via SSH e executar o comando:
ls /var/www/
Perceba que a resposta será algo como:
freddy html
O que comprova que nossa aplicação foi copiada corretamente para o nosso Droplet 😊
Configurando um Virtual Host
Crie um novo arquivo de configuração com o nome freddy.conf.
sudo nano /etc/apache2/sites-available/freddy.conf
O conteúdo desse arquivo deve ser:
<VirtualHost *:80>
ServerName 159.89.159.105
ServerAdmin webmaster@localhost
DocumentRoot /var/www/freddy/public
<Directory /var/www/freddy/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Após a alteração, tecle: CONTROL + O e na sequência pressione Enter, para salvar as alterações. E logo após tecle: CONTROL + X para sair do nano.
Execute o comando abaixo para habilitar o seu novo Virtual Host:
sudo a2ensite freddy
Para evitar conflitos, vamos desativar o nosso site default:
sudo a2dissite 000-default
Também para evitar problemas, vamos verificar a integridade e a sintaxe do nosso arquivo de configuração:
sudo apache2ctl configtest
E por fim vamos reiniciar o nosso Apache:
sudo systemctl reload apache2
Agora precisamos configurar o acesso ao banco de dados.
No diretório raiz de nossa aplicação temos um arquivo chamado .env.example, vamos criar um novo arquivo chamado .env, usando esse arquivo como base:
cp /var/www/freddy/.env.example /var/www/freddy/.env
Importando o banco de dados
Note que no diretório raiz do nosso projeto tem um arquivo chamado freddy.sql, vamos importá-lo para o nosso MySQL:
mysql -u seu_usuario_do_mysql -p < /var/www/freddy/freddy.sql
O comando acima solicitará a senha do seu usuário, informe-a e tecle Enter. Lembre-se que por segurança o Ubuntu não exibe a senha, nem asteriscos, nem nada do tipo.
Por fim, ative o mod_rewrite no Apache:
sudo a2enmod rewrite
sudo systemctl reload apache2
E tente acessar a aplicação no IP do seu Droplet, a saída deve ser:

O usuário e senha são:
Usuário: admin@freddy.com
Senha: password


