<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Marllon Gomes</title>
    <description>The latest articles on Forem by Marllon Gomes (@marllongomes).</description>
    <link>https://forem.com/marllongomes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F229608%2F3acdf156-6197-4f7b-a253-e2c64be119ca.jpeg</url>
      <title>Forem: Marllon Gomes</title>
      <link>https://forem.com/marllongomes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/marllongomes"/>
    <language>en</language>
    <item>
      <title>SSL para SaaS com multiplos domínios usando Docker e Caddy</title>
      <dc:creator>Marllon Gomes</dc:creator>
      <pubDate>Mon, 26 Jun 2023 18:31:09 +0000</pubDate>
      <link>https://forem.com/marllongomes/ssl-para-saas-com-multiplos-dominios-usando-docker-e-caddy-6mi</link>
      <guid>https://forem.com/marllongomes/ssl-para-saas-com-multiplos-dominios-usando-docker-e-caddy-6mi</guid>
      <description>&lt;p&gt;&lt;strong&gt;Precisa fornecer automaticamente certificados SSL para os usuários do seu SaaS&lt;/strong&gt; (Software as a Service)? Pode parecer uma tarefa difícil à medida que você expande a quantidade de domínios. A boa notícia é que há uma solução viável e simples chamada &lt;strong&gt;Caddy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Claro que existem várias soluções pagas disponíveis no mercado, tipo &lt;strong&gt;&lt;a href="https://www.cloudflare.com/pt-br/ssl-for-saas-providers/"&gt;SSL para SaaS da Cloudflare&lt;/a&gt;&lt;/strong&gt;, que simplificam o processo. Só que os preços são salgados, especialmente para empresas que estão começando e ainda não podem fazer esse investimento.&lt;/p&gt;

&lt;p&gt;Depois de uma boa pesquisa e testes, descobri o Caddy, que oferece https on_demand, com validação de domínio. &lt;/p&gt;

&lt;p&gt;Vou te mostrar como implementei essa configuração usando Docker e Docker-compose.&lt;/p&gt;

&lt;p&gt;Considerando um docker-compose com a aplicação principal e um container caddy. No container caddy, temos 3 volumes mapeados: "caddydata", "caddycfg" e o Caddyfile (próximo parágrafo).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'

services:
  caddy:
    image: caddy:latest
    restart: always
    ports:
      - '80:80'
      - '443:443'
      - '443:443/udp'
    volumes:
      - caddydata:/data
      - caddycfg:/config
      - ./Caddyfile:/etc/caddy/Caddyfile
    depends_on:
      - app
    networks:
      - app

  app:
    build:
      context: .
      dockerfile: ./dockerassets/app/Dockerfile
    restart: always
    networks:
      - app

networks:
  app:

volumes:
  caddydataprod:
  caddycfgprod:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criando o Caddyfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    email email@suaempresa.com

    on_demand_tls {
        ask http://app/api/check-domain
        interval 2m
        burst 5
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No topo do arquivo, temos as configurações gerais do Caddy, incluindo o e-mail usado para emitir os certificados SSL e as configurações do on demand tls. No “on_demand_tls”, definimos a URL que responde com status 200, caso o domínio esteja cadastrado e ativo na sua aplicação, além do tempo de cache.&lt;/p&gt;

&lt;p&gt;Assim, sempre que uma requisição de um domínio que ainda não tem certificado chega no servidor, o Caddy envia uma requisição para a URL do parâmetro “ask”, com o domínio como parâmetro de URL. Por exemplo: &lt;strong&gt;&lt;a href="http://app/api/check-domain?domain=dominio.com"&gt;http://app/api/check-domain?domain=dominio.com&lt;/a&gt;&lt;/strong&gt;. (lembre-se do www).&lt;/p&gt;

&lt;p&gt;Aqui, temos o redirecionamento de http para https.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http:// {
    redir https://{host}{uri} permanent
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E finalmente, o proxy reverso com tls on demand para a aplicação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https:// {
    tls {
        on_demand
    }

    reverse_proxy app:80
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confira o Caddyfile completo com todas as configurações acima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    email email@suaempresa.com
    on_demand_tls {
        ask http://app/api/check-domain
        interval 2m
        burst 5
    }
}

http:// {
    redir https://{host}{uri} permanent
}

https:// {
    tls {
        on_demand
    }

    reverse_proxy app:80
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Com tudo configurado corretamente, basta um simples "&lt;strong&gt;docker compose up -d&lt;/strong&gt;" para que sua aplicação comece a fornecer certificados SSL para domínios apontados para o seu servidor.&lt;/p&gt;

</description>
      <category>security</category>
      <category>saas</category>
      <category>docker</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Entenda as vantagens de usar o Redis: Exemplo prático em Laravel</title>
      <dc:creator>Marllon Gomes</dc:creator>
      <pubDate>Mon, 16 Jan 2023 00:43:42 +0000</pubDate>
      <link>https://forem.com/marllongomes/entenda-as-vantagens-de-usar-o-redis-exemplo-pratico-em-laravel-5f9e</link>
      <guid>https://forem.com/marllongomes/entenda-as-vantagens-de-usar-o-redis-exemplo-pratico-em-laravel-5f9e</guid>
      <description>&lt;p&gt;Performance é um fator crítico em qualquer aplicação, especialmente em aplicações de alto tráfego. Bancos de dados comuns, como PostgreSQL, MySQL e Oracle, são amplamente utilizados e são projetados para gerenciar dados estruturados e relacionamentos entre tabelas.&lt;/p&gt;

&lt;p&gt;No entanto, esses bancos têm alguns limites de utilização tanto para leitura quanto para escrita, pois são gravados em disco nos servidores. Apesar das grandes melhorias trazidas pelos SSDs, ainda há gargalos quando se trata de milhões de requisições.&lt;/p&gt;

&lt;p&gt;Com o crescimento de toda aplicação, chega um momento em que apenas o banco de dados relacional com gravação em disco já não será suficiente para suportar toda a carga de acessos, o que leva à busca por soluções para este problema.&lt;/p&gt;

&lt;p&gt;Uma solução amplamente utilizada por grandes empresas é o Redis, que é um banco de dados NoSQL muito rápido devido à sua arquitetura, pois armazena os dados na memória RAM do servidor, permitindo que ele seja muito mais rápido do que os armazenamentos em disco.&lt;/p&gt;

&lt;p&gt;A velocidade de acesso à memória RAM é significativamente maior do que a velocidade de acesso ao disco. Isso se deve ao fato de que todos os bytes gravados na memória RAM podem ser acessados diretamente pelo processador em nanosegundos, enquanto os dados armazenados em disco precisam ser lidos através do trajeto: disco → memória RAM → processador, o que leva alguns milissegundos para ser processado.&lt;/p&gt;

&lt;p&gt;Veja abaixo um exemplo usando PHP e Laravel em que a leitura de todos os posts de uma determinada tabela passa de aproximadamente 300ms para apenas 10ms, simplesmente com a implementação do Redis. Essa diferença de 290ms pode parecer insignificante em aplicações pequenas, mas em 1 milhão de requisições representa uma diferença significativa de 80 horas para completar a mesma tarefa.&lt;/p&gt;

&lt;p&gt;Exemplo de código sem ache, com resposta média de 300ms&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplo de código com cache utilizando Redis, com resposta média de 10ms&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Http\Controllers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Http\Controllers\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Post&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostsController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$cacheKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'posts'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$cacheDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//in seconds&lt;/span&gt;
        &lt;span class="nv"&gt;$posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cacheKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$cacheDuration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Post&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$posts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>developer</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
