# Script de backup do Mysql e armazenamento no S3 da AWS

Fala pessoal tudo beleza?

Esse artigo é uma extensão de um artigo que escrevi há alguns anos, onde fiz a criação de um simples script de backup para bancos Mysql.

Hoje estarei refatorando aquele primeiro script e adicionando uma opção para poder armazenar o backup no S3 da AWS.

Caso queira ver o primeiro artigo que escrevi, [acesse aqui](https://aristides.dev/script-de-backup-de-banco-de-dados-mysql).

## Instalando AWS S3 CLI

Primeiro vamos instalar e configurar a ferramenta de CLI que a AWS fornece para podermos interagir com os recursos na nuvem.

A instalação será feita em um sistema Linux, para a instalação em outros sistemas, pode ser encontrado [nesse link](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html?ref=aristides.dev).

Execute os comandos:

```bash
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

$ unzip awscliv2.zip

$ sudo ./aws/install
```

Podemos confirmar se a instalação ocorreu com sucesso, com o comando:

```bash
$ aws --version

aws-cli/2.10.3 Python/3.9.11 Linux/5.10.0-21-amd64 exe/x86_64.debian.11 prompt/off
```

Caso já tenha o `aws-cli` instalado, poderá verificar se há alguma atualização para ser feita. No terceiro comando mostrado acima, pode usar a flag `--update` para atualizar para a versão mais recente.

```bash
$ sudo ./aws/install --update

You can now run: /usr/local/bin/aws --version
```

## Criando usuário na AWS

Agora é necessário configurar o `aws-cli` com as credenciais de um usuário, para isso é necessário ter uma conta na AWS.

Nesse artigo irei pressupor que você já tem uma conta na AWS, não irei abordar o processo de criação de conta, mas iremos passar pela criação de um usuário `programático` e gerar as credenciais.

Com o foco na segurança, esse usuário terá um permissão restrita a um determinado bucket no S3, podendo apenas realizar ações nesse bucket e não tendo acesso nenhum a outros bucket que não seja o que definimos.

Acesse o console da AWS e navegue até a sessão do IAM.

1. No menu esquerdo, clique em Usuários.
    
2. Na tela de listagem de usuários, clique em **Adicionar usuários**.
    
3. Informe o nome de usuário, nesse exemplo vamos criar um usuário chamado `backup-s3`. Clique em **Próximo**.
    
4. Nessa tela, iremos adicionar uma política ao usuário. Clique no card **Anexar políticas diretamente**.
    
5. Na listagem de políticas, clique em **Criar política**.
    
6. Na tela de criação, clique na aba **JSON** para informar a política manualmente.
    
7. Copie a seguinte política e cole no editor de política - *Altere o nome do bucket conforme sua preferência, nesse exemplo estou usando* `backups-aristides-dev`
    

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::backups-aristides-dev/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::backups-aristides-dev"
            ]
        }
    ]
}
```

8. Clique em **Próximo** duas vezes até chegar na tela para informar o nome da política.
    
9. Informe o nome `BackupS3ReadWriteAccess` e clique em **Criar política**.
    
10. Nesse ponto, a política foi criada. Volte para a aba inicial e procure na listagem a política que acabou de ser criada, selecione ela e clique em **Próximo**.
    
11. Revise os dados e clique em **Criar usuário**.
    

Até aqui acabamos de criar um usuário e anexamos uma política para que esse usuário tenha acesso somente a um bucket chamado `backups-aristides-dev`. Com essa política, o usuário poderá executar as ações de Leitura/Escrita/Remoção de arquivos dentro do bucket.

Para dar continuidade precisamos que o bucket já esteja criado. Para isso crie um bucket pela console da AWS com o mesmo nome que foi definido por você ao criar a política, no meu caso `backups-aristides-dev`. Não irei abordar a criação por se tratar de um passo simples, apenas informe o nome e deixe as opções padrões do bucket.

## Gerar credenciais de segurança

Após a criação do usuário e do bucket, acesse novamente a listagem de usuários do IAM e clique sobre o usuário `backup-s3` que acabamos de criar.

1. Na aba Credenciais de segurança, na sessão Chaves de acesso, clique em **Criar chave de acesso**.
    
2. Selecione a opção **Command Line Interface (CLI)**, marque o checkbox **Compreendo a recomendação acima e quero prosseguir para criar uma chave de acesso.** e clique em **Próximo**.
    
3. Caso queira deixar alguma descrição (essa informação é opcional), informe na caixa de texto e clique em **Criar chave de acesso**.
    
4. Esse passo é muito importante, as chaves geradas serão mostradas apenas uma vez na tela. Clique em **Baixar arquivo .csv** e salve em um lugar seguro as credenciais.
    
5. Após baixar o arquivo .csv, clique em **Concluído**.
    

## Configurando AWS S3 CLI

Após todo os passos acima de criação de usuário e geração das chaves de acesso, devemos configurar a ferramente de CLI para podermos interagir com o S3.

Execute o comando abaixo para configurar o acesso e informe as credenciais do usuário criado.

```bash
$ aws configure

AWS Access Key ID [None]: <access-key-id>
AWS Secret Access Key [None]: <secret-access-key>
Default region name [None]: us-east-1
Default output format [None]: json
```

Para validarmos o acesso, vamos copiar um arquivo para o bucket e em seguida listarmos.

```bash
# Cria um arquivo de teste com conteúdo
$ touch teste.txt && echo "Backup Mysql" > teste.txt

# Copia o arquivo criado para o bucket
$ aws s3 cp teste.txt s3://backups-aristides-dev/
upload: ./teste.txt to s3://backups-aristides-dev/teste.txt

# Lista o conteúdo do bucket
$ aws s3 ls s3://backups-aristides-dev/
2023-03-11 18:45:18          13 teste.txt
```

Podemos validar também se o nosso usuário tem acesso para visualizar outros buckets:

```bash
# Para listar todos os bucket no S3
$ aws s3 ls
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied

# Copiando um arquivo para outro bucket
$ aws s3 cp teste.txt s3://meu-bucket-pessoal/       
upload failed: ./teste.txt to s3://meu-bucket-pessoal/teste.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
```

Show de bola, como visto acima o usuário criado tem acesso somente a um determinado bucket. Com isso nós garantimos uma segurança a mais para o nosso script de backup.

## Script de backup Mysql

Nesse script, deixei toda parte do código comentado para um melhor entendimento de cada linha. Mas em resumo o script executará os seguintes passos:

1. Define algumas variáveis que serão usadas durante a execução do script.
    
2. Define o nome dos bancos de dados que devem ser realizado o backup.
    
3. Verifica se o diretório de armazenamento dos arquivos e do log existem, caso não, serão criados.
    
4. Faz um loop nos bancos de dados para realizar o backup, compactar e sincronizar com o S3.
    
5. O script irá sincronizar todo o conteúdo do diretório de backup, caso um arquivo já exista no S3, esse não será enviado novamente.
    
6. Remove arquivos de backups antigos conforme a quantidade de dias determinada. Essa remoção será somente do servidor, no S3 os arquivos irão ser mantidos normalmente.
    

Abaixo segue todo o código de backup:

```sh
#!/bin/bash
# 
# Autor: Aristides Neto
# Email: falecom@aristides.dev
#
# Data: 11/03/2023
#
# Realiza o backup de bancos de dados MySQL
# Sincroniza com o S3 da AWS
#

# Define usuario e senha do banco
USER='root'
PASS='root'

# Datas
DIA=`date +%d`
MES=`date +%m`
ANO=`date +%Y`
DATA_ATUAL=`date +%Y-%m-%d-%H-%M`

# Data de Inicio do Backup
DATA_INICIO=`date +%d/%m/%Y-%H:%M:%S`

# Caminho do arquivo de log
LOG_DIR=/var/log/backup
LOG=$LOG_DIR/backup_db_$ANO$MES$DIA.log

# Diretorio onde serão salvos os backups
DIR_BK=/backups/mysql

# Lista dos bancos de dados que serão realizados o backup
DATABASES=(banco01 banco02)

# Verifica se existe o diretorio para armazenar os logs
if [ ! -d $LOG_DIR ]; then
    mkdir $LOG_DIR
fi

# Verifica se existe o diretorio para o backup
if [ ! -d $DIR_BK ]; then
    mkdir -p $DIR_BK
fi

# Inicio do backup
echo -e "MYSQLDUMP Iniciado em $DATA_INICIO\n" >> $LOG

# Loop para backupear todos os bancos
for db in "${DATABASES[@]}"; do
    # Mysql DUMP
    # Para backupear procedures e functions foi adicionado o --routines
    echo "...Realizando backup do banco ...........................[ $db ]" >> $LOG
    mysqldump --routines -u$USER -p$PASS $db > $DIR_BK/$db'_'$DATA_ATUAL.sql

    # Compacta o arquivo sql em BZ2
    echo "...Compactando arquivo de backup ........................[ $db ]" >> $LOG
    bzip2 $DIR_BK/$db'_'$DATA_ATUAL.sql

    # Sincroniza o diretório local com o bucket S3
    aws s3 sync $DIR_BK s3://backups-aristides-dev
    echo "...Sincronização do diretório de backup com S3 ..........[ OK ]" >> $LOG
done

DATA_FINAL=`date +%d/%m/%Y-%H:%M:%S`
echo -e "\nMYSQLDUMP Finalizado em $DATA_FINAL\n" >> $LOG

# Remove arquivos de backups antigos - 5 dias
find $DIR_BK -type f -mtime +5 -exec rm -rf {} \;
```

Para executar esse script recomendo que seja feito com o usuário `root`, pois serão criados diretórios e arquivos em locais que serão necessárias permissões de super usuário. Caso deseja executar com um usuário não root, certifique que terá as permissões corretas.

## Log de execução do script

Ao executar o script, será criado um arquivo de log no caminho definido na variável `LOG => /var/log/backup` que conterá informações do banco backupeado e sincronização com o S3.

Esse é um arquivo bem simples, mas é uma forma de monitorar o andamento do backup.

```bash
MYSQLDUMP Iniciado em 11/03/2023-19:00:34

...Realizando backup do banco ...........................[ banco01 ]
...Compactando arquivo de backup ........................[ banco01 ]
...Sincronização do diretório de backup com S3 ..........[ OK ]

...Realizando backup do banco ...........................[ banco02 ]
...Compactando arquivo de backup ........................[ banco02 ]
...Sincronização do diretório de backup com S3 ..........[ OK ]

MYSQLDUMP Finalizado em 11/03/2023-19:04:14
```

## Conclusão

Esse é um script simples, que não contém validações em caso de possíveis erros nos comandos executados. É uma boa prática e recomendado adicionar validações nos comandos executados e validar se foi executado com sucesso ou não.

Não será o foco desse artigo essa implementação, mas recomendo que tenha validações e em casos de erros tenha um alerta, seja o envio de um e-mail ou uma notificação em um canal como o Slack, Microsoft Teams ou outro. Esses programas disponibilizam um webhook para esses casos que irá te ajudar a enviar as notificações.

Espero que seja útil esse script e qualquer dúvida, melhorias ou comentários, não deixe de comentar abaixo.

Até a próxima.
