Instalação e configuração do Strapi com Amazon Linux 2023
Tags: strapi, aws, linux, tutorial
Published: 2023-05-03 17:20:35

Nunca havia utilizado o Strapi de forma efetiva anteriormente, apenas realizei pequenos testes para tentar entender sua lógica. A instalação no ambiente local não oferece nenhum "desafio" por assim dizer, basta seguir a [documentação oficial](https://docs.strapi.io/dev-docs/installation/cli) e nenhum problema deve surgir.

A coisa começa a ganhar contornos complexos de fato, no ambiente de produção, que é o foco desta documentação que vos escrevo.

Como em produção trabalho constantemente com o ambiente da AWS, esta documentação é focada no [Amazon Linux 2023](https://aws.amazon.com/pt/linux/amazon-linux-2023/), que podemos simplesmente considerá-la como uma distribuição Linux desenvolvida pela AWS, bem como a Amazon Linux 2. São sistemas desenvolvidos para se integrarem de forma otimizada a serviços da AWS. Porém, nada impede que possamos utilizar esta documentação em outros ambientes como o Ubuntu, basta seguir a mesma lógica.

E preciso dizer que uma das maiores motivações que tive para escrever esta documentação, foi justamente a falta de uma documentação oficial bem detalhada focada em ambientes de produção. Chega a ser curioso e acredito não ser algo exclusivo do **Strapi**, mas me estranha uma ferramenta tão popular falhar nesse aspecto. Devemos lembrar que o Strapi possuí uma solução gerenciada, porém, os valores podem afastar e até assustar a maioria dos interessados.

## Preparação do ambiente

### Usuário

Vamos começar falando sobre o usuário. Na Amazon Linux 2023, bem como, na Amazon Linux 2 o usuário padrão é o "ec2-user" e é justamente com esse usuário que realizaremos todas as configurações, não sendo necessário mudar para o "root" ou criar algum outro usuário.

### Servidor Web

Aqui estamos utilizando o NGINX que pode ser facilmente instalado com o gerenciador de pacotes `dnf` :

```shell
sudo dnf install nginx
```

### Node.js

Vamos utilizar o Node.js que também pode ser facilmente instalado com o gerenciador de pacotes `dnf` :

```shell
sudo dnf install nodejs
``` 

### Estrutura de pastas

Tenho o costume de criar a estrutura de pastas para o NGINX em `/var/www` , porém, pode ser que você estruture em outro local. Caso queira utilizar a estrutura deste exemplo, basta seguir:

```shell
sudo mkdir /var/www
```

Agora podemos navegar até a pasta `www` :

```shell
cd /var/www
```

Vamos criar a pasta para nosso projeto:

```shell
sudo mkdir strapiapp.com.br
```

A aplicação será executada pelo usuário atual, porém, como estamos trabalhando com os diretórios de sistema, utilizamos o comando `sudo` para criar as pastas necessárias. Portanto, devemos alterar o `owner` do diretório do projeto para que todas as execuções não necessitem do comando `sudo` .

```shell
sudo chown ec2-user:ec2-user strapiapp.com.br
```

Também vamos definir permissões para o diretório do projeto:

```shell
sudo chmod 775 strapiapp.com.br
```

E finalmente navegamos até o diretório do projeto:

```shell
cd strapiapp.com.br
```

O resultado é a seguinte estrutura de diretórios: `/var/www/strapiapp.com.br` .

## Instalação do Strapi

Vamos instalar a última versão do Strapi a partir do diretório atual:

```shell
npx create-strapi-app@latest .

## Observer que não estamos utilizando o comando sudo

# 'npx' executa o comando de um pacote npm
# 'create-strapi-app' é o pacote Strapi
# '@latest' indica que vamos instalar a última versão do Strapi
# '.' informo que desejo utilizar o diretório atual para a instalação sem a necessidade de criar um novo diretório e informar o nome do projeto
```

Caso ainda não tenha o pacote create-strapi-app instalado, será informado que é necessário realizar sua instalação:

```shell
Need to install the following packages:
  create-strapi-app@4.10.2
Ok to proceed? (y)
```

Basta confirmar e seguir.

Após o processo de instalação do pacote ser finalizada, necessitamos informar as configurações do nosso projeto.

Para este projeto estou trabalhando com um Banco de Dados MySQL configurado e instalado em outro host. A primeira questão é referente ao modo de configuração, e aqui seleciono o modo "Custom (manual settings)", pois pretendo configurar esse projeto manualmente.

```shell
? Choose your installation type (Use arrow keys)
  Quickstart (recommended)
❯ Custom (manual settings)

# A diferença entre esses modos é que no "Quickstart (recommended)" uma base de dados (SQLite) é criada localmente para facilitar a criação do projeto. Porém, estamos falando de configurar um projeto em Produção e essa configuração básica não atende nossas necessidades.
```

Em seguida somos questionados sobre a nossa preferência de linguagem entre "Javascript" e "Typescript":

```shell
? Choose your preferred language
  JavaScript
❯ TypeScript

# Aqui estou selecionando Typescript por uma preferência estritamente pessoal, selecione a linguagem que lhe trouxer mais conforto.
```

Agora somos questionados sobre qual banco de dados vamos utilizar:

```shell
? Choose your default database client
  sqlite
  postgres
❯ mysql

# Como informei anteriormente, já possuo um cliente MySQL previamente configurado em outro host, então simplesmente seleciono a opção "mysql"
```

Informe o nome do seu banco de dados utilizado para o projeto:

```shell
? Database name: strapi_app

# Previamente criei uma base de dados com o nome "strapi_app"
```

Informe o host de seu banco de dados:

```shell
? Host: host.domain.us-east-1.rds.amazonaws.com

# Observe que o domínio "host.domain.us-east-1.rds.amazonaws.com" é apenas um exemplo, informe aqui o host do seu banco de dados.
```

Informe a porta de comunicação:

```shell
? Port: (3306)

# A porta de comunicação padrão é a 3306, informe outro valor caso seja o seu caso.
```

Agora informe o usuário de seu banco de dados:

```shell
? Username: admin

# Aqui informo que o nome do usuário é admin, informe o valor correto para seu caso.
```

Senha de acesso ao banco de dados:

```shell
? Password: ******
```

Informe se sua conexão de banco de dados possuí SSL:

```shell
? Enable SSL connection: (y/N) N

# No meu caso, não utilizo SSL para me comunicar com o bando de dados.
```

O processo de instalação será iniciado:

```shell
Creating a project with custom database options.
Creating a new Strapi application at /var/www/strapiapp.com.br.
Creating files.
```

Ao final do processo, caso tudo tenha transcorrido corretamente, receberemos a seguinte mensagem:

```shell
Dependencies installed successfully.
Initialized a git repository.


Your application was created at /var/www/strapiapp.com.br.

Available commands in your project:

  yarn develop
  Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)

  npm run start
  Start Strapi without watch mode.

  npm run build
  Build Strapi admin panel.

  npm run strapi
  Display all available commands.

You can start by doing:

  cd /var/www/strapiapp.com.br
  npm run develop
```

## Trabalhando com o Strapi

Algo que também me incomodou em relação a documentação e tutoriais espalhados pela internet é a falta de uma análise mais técnica em relação ao Strapi, ou seja, como de fato ele funciona, como ele pode me ajudar em um ambiente local, e principalmente como ele deve ser instalado e configurado em um ambiente de produção.

### Como o Strapi funciona?

De uma forma simples e direta, para que você consiga estruturar um projeto utilizando o Strapi, você sempre irá executá-lo no modo "develop" e após ter criado toda estrutura utilizando o "Content-Type Builder" é que vamos gerar o "Build" para enfim rodarmos em produção no modo "start".

Você não conseguirá criar nenhum "Content-Type" no modo "start", caso tente, receberá a seguinte mensagem:

```shell
The autoReload feature is required to use this plugin. Start your server with `strapi develop`
```

### Primeiros passos

Mesmo sem termos criado nenhum "Content-Type", podemos gerar o `build` inicial para termos acesso a área administrativa:

```shell
npm run build
``` 

E enfim, executamos o comando para executar de fato o Strapi:

```shell
npm run start
```

O Strapi será executado na porta `1337` .

### Configurando Proxy Reverso no NGINX

Aqui vou deixar um exemplo simples de como configurar um proxy reverso com redirecionamento automático para `https` .

```shell
server {
    listen 80;
    listen [::]:80;

    if ($host = 'strapiapp.com.br') {
        return 301 https://strapiapp.com.br$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name strapiapp.com.br;
    root /var/www/strapiapp.com.br;

    ssl_certificate "/etc/letsencrypt/live/strapiapp.com.br/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/strapiapp.com.br/privkey.pem";

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:1337;

    }
}
```

### Criando um serviço utilizando Systemd

Para que a execução do Strapi seja automática, ela deve ser controlada pelo sistema e não pela interação com o terminal de comandos, portanto, vou detalhar os passos para que seja criado um serviço "Systemd" que irá persistir mesmo após a reinicialização do sistema.

Diretório que armazena os serviços "Systemd":

```shell
/lib/systemd/system
```

Vamos navegar até esse diretório:

```shell
cd /lib/systemd/system
```

Vamos criar um arquivo para armazenar as informações de execução desse serviço:

```shell
sudo nano strapi_strapiapp-com-br.service
```

O arquivo deve conter as seguintes informações:

```shell
[Unit]
Description=Strapi systemd service for project: strapiapp-com-br
Documentation=https://docs.strapi.io/dev-docs/deployment

[Service]
Type=simple
WorkingDirectory=/var/www/strapiapp.com.br
User=ec2-user
Environment="NODE_ENV=production"
ExecStart=/usr/bin/npm run start
Environment=CI=true
Restart=always

[Install]
WantedBy=multi-user.target
```

Agora podemos ativar esse serviço para que sua execução seja persistente:

```shell
sudo systemctl enable strapi_strapiapp-com-br
```

E finalmente podemos excutar o Strapi através do "Systemd":

```shell
sudo systemctl start strapi_strapiapp-com-br
```

Finalizado!

Esta é uma documentação técnica que abrange os principais pontos para executar o Strapi em um ambiente de produção. Espero que tenha sido útil pra você, qualquer coisa me chama para um bate-papo!