Jekyll2022-09-26T21:16:34-03:00https://gabrielzuqueto.eti.br/feed.xmlGabriel Zuqueto AmaralBlog com dicas de programação, infra, jogos e tudo mais que eu gosto. :DGabriel Zuqueto AmaralComo hospedar site no Github Pages2019-11-20T19:00:00-03:002019-11-20T19:00:00-03:00https://gabrielzuqueto.eti.br/como-hospedar-site-no-github-pages<p>Nesse post mostro de forma bastante didática, como hospedar site no GitHub Pages totalmente de graça!</p>
<p>Sites estáticos estão cada vez mais em uso, não é sempre que precisamos utilizar um CMS (Content Management System) da vida, como o Wordpress, às vezes basta um serviço grátis de hospedagem de sites. Ainda mais se você tiver um SPA (Single Page Application) ou PWA (Progressive Web App), mas nada te impede de ter um site ou blog estático, como esse aqui.</p>
<p>Vamos lá :)</p>
<h2 id="o-que-é-github-pages">O que é GitHub Pages?</h2>
<p>O GitHub Pages é um serviço gratuito de hospedagem de site estático que recebe arquivos HTML, CSS e JavaScript diretamente de um repositório no <em>GitHub</em>.</p>
<p>Você pode hospedar seu site no próprio domínio do GitHub <em>(github.io)</em>, ou até mesmo utilizar seu próprio domínio para que fique mais profissional.</p>
<p>O GitHub Pages pode ser utilizado para hospedar seu site pessoal, organizacional, de algum projeto e até mesmo um blog. Sim, um blog estático gerado por exemplo pelo <a href="https://jekyllrb.com/" title="Jekyll - Simple, blog-aware, static sites" target="_blank">Jekyll</a>.</p>
<p>Porém, segundo as <a href="https://help.github.com/en/github/working-with-github-pages/about-github-pages#guidelines-for-using-github-pages" title="Guidelines for using GitHub Pages" target="_blank">diretrizes de utilização do GitHub Pages</a>, você não pode utilizá-lo para hospedar:</p>
<ul>
<li>
<p>Negócio online</p>
</li>
<li>
<p>Loja virtual</p>
</li>
<li>
<p>Site voltado para facilitar transações comerciais ou fornecimento de software como serviço (SaaS)</p>
</li>
</ul>
<p>Obviamente o GitHub Pages também não pode ser utilizado para hospedar conteúdo ilegal, violento, sexual, <em>SPAM</em>, entre outros. Para mais informações acesse: <a href="https://help.github.com/en/github/working-with-github-pages/about-github-pages#guidelines-for-using-github-pages" title="Guidelines for using GitHub Pages" target="_blank">Guidelines for using GitHub Pages</a></p>
<h2 id="vantagens-do-github-pages">Vantagens do GitHub Pages</h2>
<p>Sem sombra de dúvidas uma das vantagens é ser uma hospedagem de site gratuita, porém, podemos listar mais algumas:</p>
<ul>
<li>
<p>Alta disponibilidade</p>
</li>
<li>
<p>Baixo tempo de resposta</p>
</li>
<li>
<p>Responde por HTTP e HTTPS <em>(podemos forçar a responder sempre pelo segundo)</em></p>
</li>
<li>
<p>Publicação relativamente fácil</p>
</li>
</ul>
<p>Além disso, por utilizar <strong><em>git</em></strong> ganhamos controle de versão que ajuda muito na organização e manutenção do site, e facilita o trabalho em equipe.</p>
<h2 id="desvantagens-do-github-pages">Desvantagens do GitHub Pages</h2>
<p>Para alguns o fato de ter que utilizar <strong><em>Git</em></strong> e <strong><em>GitHub</em></strong>, pode ser uma desvantagem, porém conseguimos contornar com um <a href="https://gabrielzuqueto.eti.br/como-usar-github" title="Como usar GitHub" target="_blank">tutorial básico sobre Git e GitHub</a>.</p>
<p>Ademais temos as seguintes desvantagens:</p>
<ul>
<li>
<p>Limite de 100 MB por arquivo</p>
</li>
<li>
<p>Limite de 1 GB por repositório <em>(seu site só pode ocupar até 1 GB de espaço)</em></p>
</li>
<li>
<p>Limite de 100 GB de largura de banda por mês <em>(conseguimos contornar utilizando o CloudFlare)</em></p>
</li>
<li>
<p>Limite de 10 builds por hora</p>
</li>
</ul>
<p>O limite de builds será contabilizado caso utilize o próprio GitHub para gerar seu site estático, caso contrário não será um problema.</p>
<p>Sejamos honestos… Essas desvantagens não são nem tão ruins. A maioria dos sites não irão ultrapassar os limites do <em>GitHub</em> e <em>GitHub Pages</em>.</p>
<p>Uma conta rápida…100 GB <=> 104.857.600 KB, suponhamos que cada arquivo do seu site tenha 100 KB <em>(que é muita coisa)</em>, logo terá 1.048.576 de requests por mês. Agora imagine que cada página sua carregue 4 assets do seu próprio site, você poderá receber 209.715 visitas por mês. Isso sem contar com o cache do navegador…Sim, é possível chegar nesse número, porém, não será da noite para o dia, a menos que você invista em propaganda, pois via SEO <em>(Search Engine Optimization)</em>, não será.</p>
<p>Um detalhe importante é que o GitHub irá te avisar caso exceda ou esteja próximo de exceder algum dos limites.</p>
<h2 id="hospedando-seu-site-no-github-pages">Hospedando seu site no GitHub Pages</h2>
<p>Agora que já sabemos o que é GitHub Pages e quais são suas vantagens e desvantagens, podemos ver <strong>como hospedar site no GitHub Pages</strong>.</p>
<p>Por ser um serviço do GitHub, é obrigatório o cadastro no GitHub. Veja como se cadastrar em: <a href="https://gabrielzuqueto.eti.br/como-usar-github" title="Como usar GitHub" target="_blank">Como usar GitHub</a>.</p>
<p>Suponhando que já tenha feito o cadastro, vamos ao passo a passo.</p>
<h3 id="criando-o-repositório">Criando o repositório</h3>
<p>No canto superior direito de qualquer página, use o menu <code class="highlighter-rouge">+</code> e selecione <code class="highlighter-rouge">New repository</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-new-repository.png" alt="Screenshot Site GitHub Menu" title="Site GitHub Menu" class="lazy" /></center>
<p>Digite um nome para seu repositório. Se você estiver criando um site para o próprio usuário ou organização, seu repositório deverá ter o nome <code class="highlighter-rouge"><usuario>.github.io</code> ou <code class="highlighter-rouge"><organizacao>.github.io</code>.</p>
<p>Aconselho criar o repositório para o usuário GitHub, colocando o <code class="highlighter-rouge">.github.io</code>, pois a URL fica mais limpa. Caso ponha outro nome, a URL ficará <code class="highlighter-rouge"><usuario>.github.io/nomedorepo</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-tela-nome-repositorio.png" alt="Screenshot Site GitHub Novo Repositório" title="Site GitHub Novo Repositório" class="lazy" /></center>
<p>Escolha tornar o repositório público ou privado. Os repositórios públicos são visíveis ao público, enquanto os repositórios privados são acessíveis apenas a você e às pessoas com quem você o compartilha.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-tela-repositorio-publico-privado.png" alt="Screenshot Site GitHub Repositório Público/Privado" title="Site GitHub Repositório Público/Privado" class="lazy" /></center>
<p>O correto é sempre criar um repositório com o arquivo <code class="highlighter-rouge">README.md</code>, a menos que você vá importar um repositório existente, todavia fica ao seu critério.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-repositorio-readme.png" alt="Screenshot Site GitHub Repositório README.md" title="Site GitHub Repositório README.md" class="lazy" /></center>
<p>Após preencher o formulário, clique em <code class="highlighter-rouge">Create Repository</code>.</p>
<h3 id="publicando-o-site">Publicando o site</h3>
<p>Agora você está na página do seu repositório. Caso não esteja, vá até ela.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-repositorio.png" alt="Screenshot Site GitHub Página do Repositório" title="Site GitHub Página do Repositório" class="lazy" /></center>
<p>Logo abaixo do nome do repositório tem uma aba chamada <code class="highlighter-rouge">Setting</code>, clique nela e vamos ver as configurações do GitHub Pages.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-settings.png" alt="Screenshot Site GitHub Pages settings" title="Site GitHub Pages settings" class="lazy" /></center>
<p>Caso contrário terá que selecione o <code class="highlighter-rouge">Source</code>, pode por a <code class="highlighter-rouge">master</code> mesmo.</p>
<p>Repare que o <code class="highlighter-rouge">README.md</code> ficou como a index do site.</p>
<p>Agora vamos clonar o repositório, criar um arquivo chamado <code class="highlighter-rouge">index.html</code> e vamos fazer o push para a <code class="highlighter-rouge">master</code>.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><title></span>Exemplo GitHub Pages<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Apenas um exemplo de como utilizar o GitHub Pages<span class="nt"></h1></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-add-index.png" alt="Screenshot Site GitHub Pages index.html" title="Site GitHub Pages index.hmtl" class="lazy" /></center>
<p>Após fazer o <code class="highlighter-rouge">git push</code> com sucesso, pressione <code class="highlighter-rouge">F5</code> e verá o sua nova home.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-visualizando-index.png" alt="Screenshot Site GitHub Pages nova index.html" title="Site GitHub Pages nova index.hmtl" class="lazy" /></center>
<h3 id="customizando-a-página-404">Customizando a página 404</h3>
<p>Vamos experimentar solicitar uma página que sabemos que não existe.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-404.png" alt="Screenshot Site GitHub Pages 404" title="Site GitHub Pages 404" class="lazy" /></center>
<p>O retorno será a página 404 do GitHub.</p>
<p>Customizar a página 404 do GitHub Pages é muito simples. Basta criar um arquivo <code class="highlighter-rouge">404.html</code> ou <code class="highlighter-rouge">404.md</code>.</p>
<p>Caso tenha escolhido utilizar o formato markdown <code class="highlighter-rouge">(.md)</code>, não pode esquecer de por as seguintes linhas no começo do arquivo:</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">permalink</span><span class="pi">:</span> <span class="s">/404.html</span>
<span class="nn">---</span>
</code></pre></div></div>
<p>Para exemplificar melhor, vamos utilizar <code class="highlighter-rouge">404.md</code>.</p>
<p>Crie o arquivo <code class="highlighter-rouge">404.md</code> com conteúdo a seguir, após faça <code class="highlighter-rouge">commit</code> e <code class="highlighter-rouge">push</code> para a master.</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="na">permalink</span><span class="pi">:</span> <span class="s">/404.html</span>
<span class="nn">---</span>
<span class="gh"># Página não encontrada :(</span>
A página solicitada não foi encontrada.
</code></pre></div></div>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-push-404-page.png" alt="Screenshot Site GitHub Pages push custom 404" title="Site GitHub Pages push custom 404" class="lazy" /></center>
<p>Após pressione o <code class="highlighter-rouge">F5</code> e veremos a nova página. Caso não mude, é por causa do cache. Ponha outra página que não existe que verá a página 404 customizada.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-custom-404.png" alt="Screenshot Site GitHub Pages custom 404" title="Site GitHub Pages custom 404" class="lazy" /></center>
<h3 id="domínio-próprio-no-github-pages">Domínio próprio no GitHub Pages</h3>
<p>Utilizar domínio próprio no GitHub Pages é bastante simples.</p>
<p>O primeiro passo é criar um arquivo com o nome <code class="highlighter-rouge">CNAME</code> no repositório contendo o domínio ou subdomínio que deseja utilizar.</p>
<p>Em seguida basta fazer o push para a master.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/como-hospedar-site-no-github-pages-dominio-proprio.png" alt="Screenshot Site GitHub Pages configurar domínio próprio" title="Site GitHub Pages configurar domínio próprio" class="lazy" /></center>
<p>Após fazer o <code class="highlighter-rouge">push</code> a nova configuração de domínio pode ser vista clicando na aba <code class="highlighter-rouge">Settings</code>, na página do seu repositório, no campo <code class="highlighter-rouge">Custom Domain</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/github-pages-custom-domain.png" alt="Screenshot Site GitHub Pages custom domain" title="Site GitHub Pages custom domain" class="lazy" /></center>
<p>Pronto, o <strong>GitHub Pages</strong> está configurado.</p>
<p>Para finalizar, basta ir no gerenciador de DNS do seu domínio e criar uma entrada CNAME para o seu domínio ou subdomínio, apontando para o endereço do seu GitHub Pages.</p>
<p>Talvez fique mais claro com um exemplo…</p>
<p>O endereço do GitHub Pages desse tutorial é <code class="highlighter-rouge">gabrielzuqueto.github.io</code>, e quero que ele seja acessível através do endereço <code class="highlighter-rouge">github-pages.gabrielzuqueto.eti.br</code>, então configurei assim:</p>
<center><img src="/assets/1x1.png" data-src="/assets/2020/08/github-pages-custom-domain-cloudflare.png" alt="Screenshot Site GitHub Pages custom domain Cloudflare" title="Site GitHub Pages custom domain Cloudflare" class="lazy" /></center>
<p>É importante lembrar que uma alteração em seu DNS pode levar até 24 horas para acontecer, logo, tenha paciência.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2020/08/github-pages-custom-domain-screenshot.png" alt="Screenshot Site GitHub Pages custom domain index" title="Site GitHub Pages custom domain index" class="lazy" /></center>
<p><a href="https://github-pages.gabrielzuqueto.eti.br/" title="Exemplo em funcionamento" target="_blank">Veja o resultado :)</a></p>
<h2 id="conclusão">Conclusão</h2>
<p>O GitHub Pages é simples de utilizar, você não precisa comprar domínio, não precisa se preocupar com possíveis instabilidades ou quedas, e o melhor de tudo, não precisa contratar uma hospedagem. Você pode ter um site 100% gratuito.</p>
<p>O GitHub Pages é uma ótima alternativa para hospedagem de sites grátis.</p>
<p>Espero que tenha gostado. Se curtiu o conteúdo, compartilhe por favor.</p>Gabriel Zuqueto AmaralNeste post mostro de forma bem didática, como hospedar site no GitHub PagesGit: Como excluir branch local e remoto2019-11-17T10:00:00-03:002019-11-17T10:00:00-03:00https://gabrielzuqueto.eti.br/git-como-excluir-branch-local-e-remoto<p>Você já está há algum tempo trabalhando no mesmo repositório, já criou varios branchs locais e remotos e nunca os excluiu. Daí percebeu que o <code class="highlighter-rouge">git clone</code> cada vez demora mais e mais, também que o acesso local está demorando mais do que antes, e se perguntou como excluir os branchs que não são mais necessários?</p>
<p>Seguem algumas dicas de como fazer isso.</p>
<h2 id="1---excluir-branch-local-no-git">1 - Excluir branch local no Git</h2>
<p>Para excluir o branch local no Git, você pode escolher um desses dois comandos:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-d</span> nome_do_branch
git branch <span class="nt">-D</span> nome_do_branch
</code></pre></div></div>
<h3 id="11---diferença-entre-o-git-branch--d-e-o-git-branch--d">1.1 - Diferença entre o <code class="highlighter-rouge">git branch -d</code> e o <code class="highlighter-rouge">git branch -D</code></h3>
<p>A opção <code class="highlighter-rouge">-d</code> é um atalho para <code class="highlighter-rouge">--delete</code>, que irá excluir o branch local, apenas se você já tiver feito <code class="highlighter-rouge">push</code> ou <code class="highlighter-rouge">merge</code> com seu branch remoto.</p>
<p>A opção <code class="highlighter-rouge">-D</code> é um atalho para <code class="highlighter-rouge">--delete --force</code>, ou seja, exclui o branch independente de seu status de <code class="highlighter-rouge">push</code> ou <code class="highlighter-rouge">merge</code>, portanto, tenha cuidado ao utilizar essa opção.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/git-excluir-branch-local-terminal.png" alt="Screenshot do terminal com os comandos git para excluir branch local" title="Screenshot do terminal com os comandos git para excluir branch local" class="lazy" /></center>
<h2 id="2---excluir-branch-remoto-no-git">2 - Excluir branch remoto no Git</h2>
<p>Para excluir um branch remoto, você pode utilizar o seguinte comando:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin :nome_do_branch_remoto
</code></pre></div></div>
<p>Note que é obrigatório o <code class="highlighter-rouge">:</code> antes do nome do branch.</p>
<p>Como alternativa temos a opção a seguir:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin <span class="nt">--delete</span> nome_do_branch_remoto
</code></pre></div></div>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/git-excluir-branch-remoto-terminal.png" alt="Screenshot do terminal com os comandos git para excluir branch remoto" title="Screenshot do terminal com os comandos git para excluir branch remoto" class="lazy" /></center>
<p>Se você receber o erro <strong><em>error: unable to delete ‘nome_do_branch_remoto’: remote ref does not exist error: failed to push some refs to ‘git@repositorio’</em></strong>, é porquê alguém excluiu o branch antes de você.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/git-excluir-branch-remoto-terminal-erro.png" alt="Screenshot do terminal com o comando git para excluir branch remoto retornando erro" title="Screenshot do terminal com o comando git para excluir branch remoto retornando erro" class="lazy" /></center>
<h2 id="conclusão">Conclusão</h2>
<p>Vimos como é simples manter os repositórios limpos, excluindo os branchs que não necessitamos mais.</p>
<p>Note que é super importante mantermos apenas os branchs que iremos precisar, caso contrário, tanto o repositório local quanto remoto ficaram cheios de lixo.</p>Gabriel Zuqueto AmaralEste post explica de forma simples como excluir branch local e remota no GitGit: Como renomear branch local e remoto2019-11-17T10:00:00-03:002019-11-17T10:00:00-03:00https://gabrielzuqueto.eti.br/git-como-renomear-branch-local-e-remoto<p>Em algum momento já aconteceu de você ter criado um branch com o nome errado, seja porquê digitou errado, ou até mesmo não seguiu o padrão definido pela equipe ou projeto que trabalha. Para nossa alegria, o git permite que a gente altere não só o nome do branch local, como nome do remoto também.</p>
<h2 id="1---renomeando-o-branch-local">1 - Renomeando o branch local</h2>
<p>Caso esteja no branch, basta digitar o seguinte comando:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-m</span> nome-novo
</code></pre></div></div>
<p>Caso esteja em outro branch que não o que você quer renomear:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-m</span> nome-antigo nome-novo
</code></pre></div></div>
<h2 id="2---remova-o-branch-remoto-com-o-nome-antigo-e-crie-o-branch-novo">2 - Remova o branch remoto com o nome antigo e crie o branch novo</h2>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin :nome-antigo nome-novo
</code></pre></div></div>
<p>Note que é necessário o <code class="highlighter-rouge">:</code> antes do nome do branch antigo.</p>
<h2 id="3---redefina-o-branch-upstream-para-o-branch-local-nome-novo">3 - Redefina o branch upstream para o branch local nome-novo</h2>
<p>Caso não esteja no branch novo, faça checkout para ele:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout nome-novo
</code></pre></div></div>
<p>Após execute:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin <span class="nt">-u</span> nome-novo
</code></pre></div></div>
<center><img src="/assets/1x1.png" data-src="/assets/2019/11/git-como-renomear-branch-local-e-remoto-terminal.png" alt="Screenshot do terminal com os comandos git para renomear branch local e remoto" title="Screenshot do terminal com os comandos git para renomear branch local e remoto" class="lazy" /></center>
<h2 id="conclusão">Conclusão</h2>
<p>Branch faz parte do desenvolvimento de software e é um dos recursos mais poderosos do git.</p>
<p>Renomear um branch local é uma questão simples, porém, <code class="highlighter-rouge">renomear o branch remoto</code> trata-se de excluir o branch antigo e fazer <code class="highlighter-rouge">push</code> para o novo.</p>
<p>Caso tenha ficado alguma dúvida, deixe um comentário.</p>
<p>Se este post te ajudou, por favor, compartilhe nas suas redes sociais.</p>Gabriel Zuqueto AmaralEste post explica de forma simples como renomear branch locais e remotas no GitComo instalar Erlang e Elixir no CentOS 7 Minimal2019-09-29T17:00:00-03:002019-09-29T17:00:00-03:00https://gabrielzuqueto.eti.br/como-instalar-erlang-e-elixir-no-centos-7-minimal<p>Antes de iniciarmos a instalação do Erlang e Elixir no CentOS 7 Minimal, veremos uma breve explicação sobre essas linguagens.</p>
<h1 id="o-que-é-erlang">O que é Erlang?</h1>
<p><strong>Erlang</strong> é uma linguagem de programação criada pela <em>Ericsson Computer Science Laboratory</em>, com a finalidade de criar sistemas distribuídos, tolerantes a falhas, altamente escaláveis e que tenham como requisito a alta disponibilidade.</p>
<p>O <strong>Erlang</strong> conta também com o <em>OTP (Open Telecom Platform)</em>; uma coleção de middlewares e bibliotecas escritas nesta linguagem.</p>
<p>Para mais detalhes acesse o <a href="https://www.erlang.org/" title="Site do Erlang" target="_blank">site do Erlang</a></p>
<h1 id="o-que-é-elixir">O que é Elixir?</h1>
<p><strong>Elixir</strong> é uma linguagem dinâmica e funcional projetada para a criação de aplicações escaláveis e sustentáveis, criada pelo brasileiro <a href="https://github.com/josevalim" title="Github do José Valim" target="_blank">José Valim</a>.</p>
<p>O <strong>Elixir</strong> aproveita a <em>Erlang VM (BEAM)</em>, conhecida por executar sistemas de baixa latência, distribuídos e tolerantes a falhas, além de ser usada com sucesso no desenvolvimento web.</p>
<p>Para mais detalhes acesse o <a href="https://elixir-lang.org/" title="Site do Elixir" target="_blank">site do Elixir</a></p>
<p>Agora, vamos começar a instalar o Erlang e Elixir no CentOS 7 Minimal.</p>
<h2 id="pré-requisitos">Pré-requisitos</h2>
<p>Para facilitar a instalação, faça login como <code class="highlighter-rouge">root</code>, utilizando o seguinte comando:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>su root
</code></pre></div></div>
<p>Agora, antes de instalar o Erlang e o Elixir, certifique-se que seu CentOS 7 Minimal está atualizado, para isso execute:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum update -y && \
yum upgrade -y
</code></pre></div></div>
<p>Agora instale os pacotes <code class="highlighter-rouge">epel-release</code> e <code class="highlighter-rouge">wget</code>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum install epel-release wget -y
</code></pre></div></div>
<h2 id="instalando-o-erlang">Instalando o Erlang</h2>
<p>A forma mais simples de instalar o Erlang é através do seu repositório, então vamos adicioná-lo ao gerenciador de pacotes:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /tmp/ && \
wget http://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm && \
rpm -Uvh erlang-solutions-1.0-1.noarch.rpm && \
yum update -y && \
cd ~
</code></pre></div></div>
<p>Agora basta executar o seguinte comando para instalar o Erlang:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum install erlang -y
</code></pre></div></div>
<p>Pronto! A versão mais recente do Erlang foi instalada.</p>
<h2 id="verificando-a-instalação-do-erlang">Verificando a instalação do Erlang</h2>
<p>Execute o seguinte comando para verificar se o Erlang está instalado ou não:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>erl
</code></pre></div></div>
<p>Exemplo de retorno:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]
Eshell V10.5 (abort with ^G)
1>
</code></pre></div></div>
<center><img src="/assets/1x1.png" data-src="/assets/2019/09/centos7-erlang-shell.png" alt="Screenshot CentOS 7 Minimal Erlang Shell" title="Screenshot CentOS 7 Minimal Erlang Shell" class="lazy" /></center>
<p>Caso o prompt de comando do Erlang seja carregado, está funcionando! Para fechá-lo, basta pressionar Ctrl-C duas vezes.</p>
<h2 id="instalando-o-elixir">Instalando o Elixir</h2>
<p>O <strong>Elixir</strong> está disponível no repositório EPEL, mas está muito desatualizado. Portanto, para instalar a versão mais recente, vamos compilá-lo e instalá-lo a partir dos arquivos fonte.</p>
<p>Lembre-se de que antes de <strong>instalar o Elixir</strong>, você deve <strong>instalar o Erlang</strong> primeiro.</p>
<p>Para baixar a versão mais recente, <a href="https://github.com/elixir-lang/elixir/releases" title="Elixir Releases" target="_blank">acesse a página de releases</a>.</p>
<p>Hoje, <em>29/09/2019</em>, a versão mais recente é <code class="highlighter-rouge">1.9.1</code>.</p>
<p>Vamos baixar o fonte, descompactar, compilar e instalar o Elixir.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /tmp/ && \
wget https://github.com/elixir-lang/elixir/archive/v1.9.1.tar.gz && \
tar -xzvf v1.9.1.tar.gz && \
cd elixir-1.9.1 && \
make && \
make install && \
cd ~
</code></pre></div></div>
<h2 id="verificando-a-instalação-do-elixir">Verificando a instalação do Elixir</h2>
<p>Para verificar se o Elixir está instalado ou não, execute:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>iex
</code></pre></div></div>
<p>Exemplo de retorno:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]
Interactive Elixir (1.9.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>
</code></pre></div></div>
<center><img src="/assets/1x1.png" data-src="/assets/2019/09/centos7-elixir-shell.png" alt="Screenshot CentOS 7 Minimal Elixir Shell" title="Screenshot CentOS 7 Minimal Elixir Shell" class="lazy" /></center>
<p>Caso o prompt do Elixir carregue, parabéns, a instalação foi executada com sucesso!</p>
<p>Mais uma vez, para fechar o shell do Elixir, basta pressionar Ctrl-C duas vezes.</p>
<p>Para verificar a versão do Elixir, sem abrir abrir o <code class="highlighter-rouge">iex</code>, basta executar:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>elixir --version
</code></pre></div></div>
<p>Exemplo de retorno:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Elixir 1.9.1 (compiled with Erlang/OTP 22)
</code></pre></div></div>
<p>Pronto! Acabamos de instalar o Erlang e Elixir no CentOS 7 Minimal :D</p>
<h2 id="observação">Observação</h2>
<p>Os comandos deste post foram executados em uma instalação <em>Minimal do CentOS 7, Kernel 3.10.0-1062.el7.x86_64</em>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/09/centos7-version.png" alt="Screenshot CentOS 7 Minimal" title="Screenshot CentOS 7 Minimal" class="lazy" /></center>Gabriel Zuqueto AmaralNeste post iremos ver como instalar Erlang e Elixir no CentOS 7 Minimal.Como usar GitHub?2019-01-26T16:40:00-02:002019-01-26T16:40:00-02:00https://gabrielzuqueto.eti.br/como-usar-github<p>Por mais que o git seja uma ferramenta excelente para o versionamento e distribuição de códigos, muitos desenvolvedores não o conhecem ou não o utilizam. Este post tem como objetivo trazer os conhecimentos necessários para que a partir do zero, você possa dominar os conceitos gerais do <strong>git</strong>, e usar o <strong>github</strong> para guardar seus projetos na nuvem.</p>
<p class="h2" id="index">Índice</p>
<p><a href="#section1">1. O que é Git?</a></p>
<p><a href="#section2">2. O que é GitHub?</a></p>
<p><a href="#section3">3. Criando conta no GitHub</a></p>
<p><a href="#section4">4. Criando repositório no GitHub</a></p>
<p><a href="#section5">5. Adicionando chave SSH no GitHub</a></p>
<p><a href="#section6">6. Instalando Git</a></p>
<p><a href="#section7">7. Configurando git</a></p>
<p><a href="#section8">8. Clonando repositório do GitHub com git</a></p>
<p><a href="#section9">9. Fluxo de trabalho do git</a></p>
<p><a href="#section10">10. Comandos básicos do git</a></p>
<p><a href="#section11">11. Mãos à obra</a></p>
<p><a href="#section12">12. Errei o commit, como corrijo?</a></p>
<p><a href="#section13">13. Utilizando git pull</a></p>
<p><a href="#section14">14. Utilizando git branch</a></p>
<p><a href="#section15">15. Utilizando git merge</a></p>
<h2 id="section1">O que é git?</h2>
<p>Git é um sistema de controle de versão de arquivos, o qual permite o desenvolvimento de um projeto, por várias pessoas simultâneamente, sem o risco de uma alteração sobrescrever a outra sem ser indentificada.</p>
<p>Imagine o cenário no qual duas pessoas estão alterando um arquivo ao mesmo tempo, sem um sistema de versão isso seria um caos, certo?</p>
<p>Uma das funções do Git é justamente permitir que um arquivo possa ser editado por pessoas diferentes, ao mesmo tempo.</p>
<p>Outro aspecto interessante é a criação de <strong>branch</strong>, que nada mais é do que um <em>snapshot</em> do seu projeto.</p>
<p>Vamos supor que seu projeto seja um site HTML, e que você queira criar uma página nova, mas não quer que vá para produção, pois precisa testar bastante antes.</p>
<p>Nesse caso, você cria um <strong>branch</strong>, faz todas as alterações que desejar, testa, e quando estiver tudo certo, você faz um <strong>merge</strong> no <strong>branch</strong> oficinal — normalmente chamado de <em>master</em> — e sua página estará pronta para produção.</p>
<h2 id="section2">O que é GitHub?</h2>
<p>O GitHub é uma plataforma de hospedagem de código para controle de versão e colaboração. Ele permite que você e os outros trabalhem juntos em projetos de qualquer lugar do mundo.</p>
<h2 id="section3">Criando conta no GitHub</h2>
<p>Para criar uma conta no GitHub, acesse o site <a href="https://github.com/" title="Site GitHub" target="_blank">github.com</a> e preencha o formulário.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/criar-conta-github.png" alt="Screenshot Site GitHub" title="Site GitHub" class="lazy" /></center>
<p>Ponha um <strong><em>username</em></strong> legal, pois fica visível em todos os projetos que você trabalhar. Além disso, é ótimo para por no seu LinkedIn.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/criar-conta-github-formulario.png" alt="Screenshot Formulário GitHub" title="Formulário GitHub" class="lazy" /></center>
<p>Após preencher o formulário clique no botão <strong><em>Sign up for GitHub</em></strong>. Você será redirecionado para outra página para validar um captcha. Depois da validação, clique no botão <strong><em>Create an account</em></strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/criar-conta-github-step1.png" alt="Screenshot Formulário GitHub Step 1" title="Formulário GitHub Step 1" class="lazy" /></center>
<p>Agora será necessário escolher qual é o plano da conta que acabou de criar. Por padrão vem selecionado <strong><em>free</em></strong>, então basta clicar no botão <strong><em>Continue</em></strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/criar-conta-github-step2.png" alt="Screenshot Formulário GitHub Step 2" title="Formulário GitHub Step 2" class="lazy" /></center>
<p>A próxima tela é apenas um questionário de preferências, basta clicar no link <strong><em>skip this step</em></strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/criar-conta-github-step3.png" alt="Screenshot Formulário GitHub Step 3" title="Formulário GitHub Step 3" class="lazy" /></center>
<p>Sua conta já foi criada, porém você precisa validar seu e-mail.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/dashboard-github.png" alt="Screenshot Dashboard GitHub" title="Dashboard GitHub" class="lazy" /></center>
<p>O GitHub enviou uma mensagem para o e-mail que você escolheu para sua conta. Basta clicar no botão <strong><em>Verify email address</em></strong> e pronto.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/verificar-conta-github.png" alt="Screenshot Email GitHub" title="Email GitHub" class="lazy" /></center>
<h2 id="section4">Criando repositório no GitHub</h2>
<p>Agora que já tem uma conta criada e verificada no GitHub, vamos à criação do repositório do projeto. Para isso clique no link <a href="https://github.com/new" title="GitHub Criar Novo Repositório" target="_blank">Create a repository</a>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/novo-repositorio-github.png" alt="Screenshot Novo Repositório GitHub" title="Novo Repositório GitHub" class="lazy" /></center>
<p>Na imagem acima estamos criando um repositório público cujo nome é <em>tutorial-2019</em>, com o arquivo <strong>README.md</strong> embutido, o qual contém uma descrição do projeto. É super importante que você crie um repositório, para que possa fazer os testes contidos nesse post. Após preencher o formulário, clique em <strong>Create repository</strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/repositorio-github.png" alt="Screenshot Repositório GitHub" title="Repositório GitHub" class="lazy" /></center>
<p>O repositório ficará disponível no endereço https://github.com/<strong>username</strong>/<strong>reponame</strong>.</p>
<ul>
<li>
<p>username - É o nome do usuário que você escolheu quando foi criar a conta no GitHub</p>
</li>
<li>
<p>reponame - É o nome que você escolheu na criação do seu repositório</p>
</li>
</ul>
<p>No nosso exemplo: <strong>https://github.com/tutorialgithub2019/tutorial-2019</strong></p>
<h2 id="section5">Adicionando chave SSH no GitHub</h2>
<p>Para que não seja necessário digitar a senha toda vez que for fazer <strong>push</strong>, devemos adicionar nossa chave pública no GitHub, dessa forma o login será feito via SSH.</p>
<p>Primeiro copie sua chave pública. Em sistemas *UNIX e no Mac OS, execute o seguinte comando no terminal e depois copie o resultado:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cat</span> ~/.ssh/id_dsa.pub
</code></pre></div></div>
<p>Agora no GitHub, no canto superior direito de qualquer página, clique na foto do seu perfil e <a href="https://github.com/settings/profile" title="GitHub configurações" target="_blank">clique em Settings</a>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/configuracoes-github.png" alt="Screenshot Configurações GitHub" title="Configurações GitHub" class="lazy" /></center>
<p>Na barra lateral <strong>Personal settings</strong>, clique em <a href="https://github.com/settings/keys" title="GitHub Chaves SSH e GPG" target="_blank">SSH and GPG keys</a>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/chave-github.png" alt="Screenshot Menu GitHub" title="Menu GitHub" class="lazy" /></center>
<p>Clique em <a href="https://github.com/settings/ssh/new" title="GitHub Adicionar Chave SSH" target="_blank">New SSH key</a>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/configurar-chave-github.png" alt="Screenshot Configurar Chave SSH GitHub" title="Configurar Chave SSH GitHub" class="lazy" /></center>
<p>No campo <strong>Title</strong>, adicione uma descrição para a chave nova, e em <strong>Key</strong> cole sua chave pública.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/formulario-chave-github.png" alt="Screenshot Formulário Chave SSH GitHub" title="Formulário Chave SSH GitHub" class="lazy" /></center>
<p>Após preencher o fomulário, clique no botão <strong>Add SSH Key</strong>. Você será redirecionado para uma página na qual terá que digitar sua senha para confirmar a adição da sua chave pública.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/confirmar-chave-github.png" alt="Screenshot Confirmar Chave SSH GitHub" title="Confirmar Chave SSH GitHub" class="lazy" /></center>
<p>Caso você tenha sucesso, sua chave será adicionada à conta GitHub.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/sucesso-chave-github.png" alt="Screenshot Sucesso Chave SSH GitHub" title="Sucesso Chave SSH GitHub" class="lazy" /></center>
<h2 id="section6">Instalando Git</h2>
<p>Abaixo seguem as instruções para instalar o git, no sistema que você utiliza.</p>
<p><strong>RHEL / CentOS</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>yum <span class="nb">install</span> <span class="nt">-y</span> git
</code></pre></div></div>
<p><strong>Debian / Ubuntu</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> git
</code></pre></div></div>
<p><strong>Mac OS</strong></p>
<p><a href="https://git-scm.com/download/mac" title="Download Mac OS Download Git" target="_blank">Baixe o git para Mac OS</a></p>
<p><strong>Windows</strong></p>
<p><a href="https://git-scm.com/download/win" title="Windows Download Git" target="_blank">Baixe o git para Mac OS</a></p>
<h2 id="section7">Configurando git</h2>
<p>A configuração do git é muito simples, para isso abra o terminal e execute os sequintes comandos:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git config <span class="nt">--global</span> user.name <span class="s2">"YOUR NAME"</span>
<span class="nv">$ </span>git config <span class="nt">--global</span> user.email <span class="s2">"YOUR EMAIL ADDRESS"</span>
</code></pre></div></div>
<ul>
<li>
<p>YOUR NAME - É o nome que vai aparecer nos Commits e Pull Requests.</p>
</li>
<li>
<p>YOUR EMAIL ADDRESS - Deve preencher com o mesmo e-mail que você criou a conta no GitHub.</p>
</li>
</ul>
<p>No nosso caso…</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git config <span class="nt">--global</span> user.name <span class="s2">"Gabriel Z Amaral"</span>
<span class="nv">$ </span>git config <span class="nt">--global</span> user.email <span class="s2">"o9854467@nwytg.net"</span>
</code></pre></div></div>
<h2 id="section8">Clonando repositório do GitHub com git</h2>
<p>Chegou a grande hora, vamos clonar! O comando é simples <strong>git clone endereco_repo</strong>.</p>
<p>Se tiver configurado o acesso via SSH, o <strong>endereco_repo</strong> é: git@github.com:<strong>username</strong>/<strong>reponame</strong>.git</p>
<p>Caso contrário o <strong>endereco_repo</strong> é: https://github.com/<strong>username</strong>/<strong>reponame</strong>.git</p>
<p>Porém, há uma forma mais simples de obter o endereço do repo. Para isso vá à página do seu repositório e clique no botão <strong>Clone or download</strong>.</p>
<p>Por padrão vem a opção de clonar via HTTPS, porém se quiser ver o endereço SSH, clique em <strong>Use SSH</strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/clone-repo-https-github.png" alt="Screenshot Clone Repo HTTPS GitHub" title="Clone Repo HTTPS GitHub" class="lazy" /></center>
<p>E se estiver vendo o endereço SSH e quiser ver o HTTPS, clique em <strong>Use HTTPS</strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/clone-repo-ssh-github.png" alt="Screenshot Clone Repo SSH GitHub" title="Clone Repo SSH GitHub" class="lazy" /></center>
<p>No nosso caso os comandos seriam assim:</p>
<p><strong>Clonar via HTTPS</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/tutorialgithub2019/tutorial-2019.git
</code></pre></div></div>
<p><strong>Clonar via SSH</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com:tutorialgithub2019/tutorial-2019.git
</code></pre></div></div>
<p>Note que, se for a primeira vez que se conecta ao GitHub via SSH, uma mensagem de confirmação será exibida no terminal.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/confirmacao-clone-repo-ssh-github.png" alt="Screenshot Confirmação Repo SSH GitHub" title="Confirmação Repo SSH GitHub" class="lazy" /></center>
<p>Basta digitar <strong>yes</strong> e teclar <strong>ENTER</strong> para prosseguir.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/repo-clonado-ssh-github.png" alt="Screenshot Repo Clonado via SSH GitHub" title="Repo Clonado via SSH GitHub" class="lazy" /></center>
<p>Repare que, ao fazer o git clone, o projeto é baixado para a sua máquina, em um diterório com o nome do projeto.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/repo-clonado-diretorio.png" alt="Screenshot diteróio do projeto" title="Diteróio do projeto" class="lazy" /></center>
<p>Antes de prosseguirmos, é interessante sabermos qual é o fluxo que o git segue. Dessa forma será mais fácil entender o que está acontecendo.</p>
<h2 id="section9">Fluxo de trabalho do git</h2>
<p>Os repositórios locais consistem em três “árvores” manitdas pelo git.</p>
<p>1ª. Working Directory - Contém os arquivos atuais.</p>
<p>2ª. Index - É uma área entre o Working Directory e o HEAD. É utilizado para criar um conjunto de alterações para serem confirmadas.</p>
<p>3ª. HEAD - Aponta para a última confirmação (commit) que você fez.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-workflow.png" alt="Git Workflow" title="Git Workflow" class="lazy" /></center>
<p>Com o fluxo explanado, podemos passar para os comandos básicos do git.</p>
<h2 id="section10">Comandos básicos do git</h2>
<p>Estes são os 4 comandos básicos que iremos aprender a utilizar.</p>
<ul>
<li>
<p>git add <arquivos></arquivos></p>
<p>Este comando adiciona os arquivos no INDEX.</p>
</li>
<li>
<p>git commit -m “comentário sobre a alteração”</p>
<p>Este comando pega todos os arquivos adicionados no INDEX, cria uma revisão contendo um número e o comentário que você colocou.</p>
</li>
<li>
<p>git push</p>
<p>Este comando envia todos os commits para o GitHub.</p>
</li>
<li>
<p>git status</p>
<p>Exibe informações dos arquivos alterados (novos, editados, deletados) e se já foram adicionados no INDEX ou não.</p>
</li>
</ul>
<h2 id="section11">Mãos à obra</h2>
<p>Primeiro acesse o diretório do seu projeto</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">cd </span>tutorial-2019
</code></pre></div></div>
<p>Agora vamos criar um arquivo chamado <code class="highlighter-rouge">index.html</code> e vamos por o seguinte conteúdo:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><title></span>Tutorial GitHub<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Tutorial GitHub<span class="nt"></h1></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Agora vamos executar o comando <code class="highlighter-rouge">git status</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-status.png" alt="Terminal comando git status" title="Comando git status" class="lazy" /></center>
<p>Note que o nosso arquivo está na lista de <strong>Untracked files</strong>. Isso se dá pelo fato de ser um arquivo novo, que o git ainda não estar mapeando ele.</p>
<p>Vamos agora adicionar o arquivo ao INDEX, para isso iremos utilizar o comando <code class="highlighter-rouge">git add index.html</code>. Após, execute novamente o comando <code class="highlighter-rouge">git status</code> e veja que o arquivo estará na lista de arquivos a serem commitados.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-add-status.png" alt="Terminal comando git add + status" title="Comando git add + status" class="lazy" /></center>
<p>Agora vamos realizar o commit da alteração, para isso basta executar <code class="highlighter-rouge">git commit -m "index.html criado"</code>. Agora que já commitou, execute <code class="highlighter-rouge">git status</code> mais uma vez.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-commit-status.png" alt="Terminal comando git commit + status" title="Comando git commit + status" class="lazy" /></center>
<p>Note que não existem mais arquivos a serem commitados, isso se dá pelo fato de que as alterações já foram salvas local. Mas lembre-se de que ainda não estão no GitHub. Para que isso ocorra, devemos executar o comando <code class="highlighter-rouge">git push</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-push.png" alt="Terminal comando git push" title="Comando git push" class="lazy" /></center>
<p>Agora podemos ver a alteração no GitHub, basta atualizar a página do seu projeto.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-commit.png" alt="Screenshot GitHub commit" title="Screenshot GitHub commit" class="lazy" /></center>
<p>Aprendemos aqui 4 comandos básicos do git, com eles conseguimos compreender melhor como funciona esta ferramenta e o GitHub.</p>
<h2 id="section12">Errei o commit, como corrijo?</h2>
<p>Você errou a descrição do commit, ou quer adicionar novos arquivos? Se ainda não fez o <code class="highlighter-rouge">push</code> basta utilizar o comando <code class="highlighter-rouge">git commit --amend</code> para modificar o commit mais recente. Este comando cria um commit novo com as alterações que você realizou.</p>
<h2 id="section13">Utilizando git pull</h2>
<p>Este comando é muito importante quando se tem várias pessoas no mesmo projeto, ou caso você tenha seu repositório em dois computadores diferentes — casa e trabalho, por exemplo —, e precisa manter tudo atualizado.</p>
<p>Para exemplificar essa situação, iremos realizar uma alteração via GitHub e vamos puxá-la para o repositório local via <code class="highlighter-rouge">git pull</code>.</p>
<p>Vamos alterar o arquivo <code class="highlighter-rouge">README.md</code>, para isso clique no ícone de lápis.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-alterar-arquivo.png" alt="Screenshot GitHub alterar arquivo" title="Screenshot GitHub alterar arquivo" class="lazy" /></center>
<p>Adicione uma linha qualquer no arquivo, após preencha a descrição do commit e por fim, clique no botão <strong>Commit changes</strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-commitar-alteracoes.png" alt="Screenshot GitHub salvar alterações no arquivo" title="Screenshot GitHub salvar alterações no arquivo" class="lazy" /></center>
<p>Agora vá ao terminal e execute o comando <code class="highlighter-rouge">git pull</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-pull.png" alt="Terminal comando git pull" title="Terminal comando git pull" class="lazy" /></center>
<p>Note que a alteração foi puxada para o seu branch local.</p>
<h2 id="section14">Utilizando git branch</h2>
<p>Trabalhar com branch no git é muito simples, e facilita a vida do programador.</p>
<p>Imagine que você está trabalhando em um projeto tanto em sua casa, quanto no seu trabalho. Daí você fez algumas alterações no computador do trabalho, mas precisa continuar as alterações em casa, para isso, você precisa manter os repositórios atualizados em ambos os computadores.</p>
<p>Porém, você não pode por as alterações em produção sem finalizá-las e testá-las. Para isso existe o branch, você cria uma ramificação do seu repositório — como se fosse um espelho —, assim você pode trabalhar nesse código, sem se preocupar em quebrar produção.</p>
<p>Após finalizar todas as alterações, você pode juntar os códigos novamente no branch principal — normalmente o master.</p>
<p>Um branch pode ser criado direto no terminal utilizando o comando <code class="highlighter-rouge">git branch -b novo_branch</code>, porém, iremos criar via GitHub.</p>
<h3 id="criar-branch-no-github">Criar branch no GitHub</h3>
<p>Vá até a página do seu repositório e repare no dropdown escrito “Branch: <strong>master</strong>”. Isso quer dizer que até agora estamos trabalhando direto no <strong>master</strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-branch.png" alt="Screenshot GitHub branch" title="Screenshot GitHub branch" class="lazy" /></center>
<p>Vamos agora criar o branch cujo o nome será <em>novo_branch</em>, para isso clique no dropdown, preencha o campo com o nome do branch e clique em <em>Create branch: novo_branch</em>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-new-branch.png" alt="Screenshot GitHub Novo branch" title="Screenshot GitHub Novo branch" class="lazy" /></center>
<p>Agora que o branch foi criado no GitHub, vamos puxá-lo para o seu repositório local. Uma maneira simples é utilizando o comando <code class="highlighter-rouge">git pull</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-pull-branch.png" alt="Terminal git pull" title="Terminal git pull" class="lazy" /></center>
<p>Com o branch no seu repositório local, basta fazer o checkout para ele, para começar a trabalhar nele. Para isso execute o seguinte comando no terminal <code class="highlighter-rouge">git checkout novo_branch</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-checkout-branch.png" alt="Terminal git checkout" title="Terminal git checkout" class="lazy" /></center>
<p>Para saber em qual branch você está, basta executar o comando <code class="highlighter-rouge">git branch</code>, que todos os branchs locais serão exibidos e o que estiver selecionado, irá aparecer com um * ao lado do nome.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-branch-list.png" alt="Terminal git brach - lista de branchs" title="Terminal git brach - lista de branchs" class="lazy" /></center>
<p>Agora vamos alterar o arquivo <em>index.html</em> no branch novo.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><title></span>Tutorial GitHub<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Tutorial GitHub<span class="nt"></h1></span>
Alteração feita no branch novo.
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Após salvar o arquivo, adicione o mesmo ao INDEX, com o comando <code class="highlighter-rouge">git add index.html</code> e após faça um commit utilizando <code class="highlighter-rouge">git commit -m "linha nova adicionada"</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-commit-novo.png" alt="Terminal git commmit no branch novo" title="Terminal git commmit no branch novo" class="lazy" /></center>
<p>Vamos ao branch master — <code class="highlighter-rouge">git checkout master</code> — para que fique mais fácil de entender como funciona o conceito de branch.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-checkout-master.png" alt="Terminal git checkout master" title="Terminal git checkout master" class="lazy" /></center>
<p>Confira agora como está o arquivo <strong>index.html</strong>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/sublime-text-master-index.png" alt="Screenshot Sublime Text index.html master" title="Screenshot Sublime Text index.html master" class="lazy" /></center>
<p>Reparou que a linha que adicionamos não existe no arquivo? Relaxe, não perdemos as alterações. Volte para o branch <strong>novo_branch</strong> que irá ver as alterações lá.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-checkout-branch.png" alt="Terminal git checkout novo_branch" title="Terminal git checkout novo_branch" class="lazy" /></center>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/sublime-text-novo-index.png" alt="Screenshot Sublime Text index.html novo_branch" title="Screenshot Sublime Text index.html novo_branch" class="lazy" /></center>
<p>Faça o push do código novo e verifique no GitHub, as alterações no branch que criou.</p>
<p>Agora ficou tudo mais claro, concorda? Vamos então aprender a fazer merge (juntar um branch no outro)</p>
<h2 id="section15">Utilizando git merge</h2>
<p>Como dito anteriormente, o comando <strong>merge</strong> serve para mesclar um branch no outro. Vamos lá!</p>
<p>Faça checkout para o branch master <code class="highlighter-rouge">git checkout master</code>, após execute <code class="highlighter-rouge">git merge origin/novo_branch</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-merge.png" alt="Terminal git merge origin/novo_branch" title="Terminal git merge origin/novo_branch" class="lazy" /></center>
<p>Verifique que o arquivo index.html agora está com a linha que alteramos no outro branch.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/sublime-text-novo-index.png" alt="Screenshot Sublime Text index.html master" title="Screenshot Sublime Text index.html master" class="lazy" /></center>
<p>Agora vamos simular um <strong>merge com conflito</strong>, para que possamos saber como corrigir este problema e subir nosso código.</p>
<p>Ainda no branch master, altere o arquivo index.html, deixando-o assim:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><title></span>Tutorial GitHub<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Tutorial GitHub<span class="nt"></h1></span>
Alteração feita no branch novo.
<span class="nt"><p></span>Linha para conflitar<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Mais uma vez, adicione o arquivo e faça o commit.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git add index.html
<span class="nv">$ </span>git commit <span class="nt">-m</span> <span class="s2">"para fazer um merge com conflito"</span>
</code></pre></div></div>
<p>Agora vá para o outro branch <code class="highlighter-rouge">git checkout novo_branch</code> e altere o index.html:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><title></span>Tutorial GitHub<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Tutorial GitHub<span class="nt"></h1></span>
Alteração feita no branch novo.
<span class="nt"><p></span>Linha adicionada no branch novo para conflitar<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Agora faça o commit, o push e volte para o branch master.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git add index.html
<span class="nv">$ </span>git commit <span class="nt">-m</span> <span class="s2">"linha para conflitar"</span>
<span class="nv">$ </span>git push origin novo_branch
<span class="nv">$ </span>git checkout master
</code></pre></div></div>
<p>Chegou a hora de ver o conflito. Faça novamente o merge do branch novo, no master.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git merge origin/novo_branch
</code></pre></div></div>
<p>Voilà! Temos o nosso conflito.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-merge-conflito.png" alt="Terminal git merge com conflito" title="Terminal git merge com conflito" class="lazy" /></center>
<p>Abra novamente o <em>index.html</em> e veja como é representado o conflito.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/sublime-text-index-conflitado.png" alt="Screenshot Sublime Text index.html conflitado" title="Screenshot Sublime Text index.html conflitado" class="lazy" /></center>
<p>Podemos ver dois blocos de código. O que está no block HEAD, é o código do branch atual, o segundo bloco é o código que você quer mergear no branch atual.</p>
<p>Agora vamos resolver o conflito. No nosso caso, queremos os dois códigos, logo ficará assim:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><title></span>Tutorial GitHub<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>Tutorial GitHub<span class="nt"></h1></span>
Alteração feita no branch novo.
<span class="nt"><p></span>Linha para conflitar<span class="nt"></p></span>
<span class="nt"><p></span>Linha adicionada no branch novo para conflitar<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>Após a alteração, basta seguir os mesmo passos <code class="highlighter-rouge">git add</code>, <code class="highlighter-rouge">git commit</code> e <code class="highlighter-rouge">git push</code>.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/git-merge-conflito-corrigido.png" alt="Terminal git merge com conflito corrigido" title="Terminal git merge com conflito corrigido" class="lazy" /></center>
<p>Vá ao GitHub e confirme que o conflito foi corrigido e que o branch master está com o arquivo <em>index.html</em> atualizado com ambas as alterações.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-arquivo-atualizado.png" alt="Screenshot GitHub arquivo atualizado" title="Screenshot GitHub arquivo atualizado" class="lazy" /></center>
<h2 id="aprenda-mais-sobre-git">Aprenda mais sobre git</h2>
<p>Aproveite para aprender mais sobre git, lendo estes materiais adicionais.</p>
<p><a href="http://rogerdudler.github.io/git-guide/index.pt_BR.html" title="git - guia prático" target="_blank">git - guia prático</a></p>
<p><a href="http://marklodato.github.io/visual-git-guide/index-pt.html" title="Uma Referência Visual do Git" target="_blank">Uma Referência Visual do Git</a></p>
<p>Agora que chegamos ao final deste post, irei excluir a conta do GitHub, pois tenho a minha pessoal. Não é pelo fato de ser de graça, que devemos desperdiçar os recursos do GitHub.</p>
<center><img src="/assets/1x1.png" data-src="/assets/2019/01/github-account-excluida.png" alt="Screenshot GitHub conta excluída" title="Screenshot GitHub conta excluída" class="lazy" /></center>
<p>Espero ter ajudado de alguma forma. Qualquer crítica ou dúvida, deixe nos comentários.</p>Gabriel Zuqueto AmaralAprenda de forma prática como usar GitHub e git, a partir do zero. Você verá tudo o que precisa para dominar os conceitos gerais dessas ferramentas.Como instalar Docker no CentOS2018-12-31T17:00:00-02:002018-12-31T17:00:00-02:00https://gabrielzuqueto.eti.br/como-instalar-docker-no-centos<p>Esse post tem como objetivo ensinar de forma prática e simples, como instalar e utilizar o Docker no CentOS.</p>
<h2 id="o-que-é-docker">O que é Docker?</h2>
<p>De forma simples, Docker é uma ferramenta que permite empacotar sua aplicação e dependências de forma a garantir sua execução correta em qualquer ambiente Linux.</p>
<p>Garante também a flexibilidade, portabilidade e escalabilidade da sua aplicação, podendo ser executada em <a href="https://gabrielzuqueto.eti.br/cupom-de-25-em-creditos-na-digital-ocean" title="Cupom de $25 em créditos na Digital Ocean">nuvem pública</a>, nuvem privada, servidores bare-metal e até mesmo em máquinas virtuais.</p>
<h2 id="pré-requisitos-do-docker">Pré-Requisitos do Docker</h2>
<ol>
<li>
<p>Uma versão atualizada do CentOS 7</p>
<p>O Docker pode ser executado em qualquer Linux que utilize o Kernel 3.10 ou superior, porém, se tratando do CentOS, está claro no site do Docker que, versões antigas não são testadas ou suportadas.</p>
</li>
<li>
<p>O repositório <code class="highlighter-rouge">centos-extras</code> deve estar habilitado</p>
<p>Por padrão este repositório já vem habilitado, mas se você o desabilitou, lembre-se de habilitá-lo novamente.</p>
</li>
<li>
<p>512MB RAM</p>
<p>Sim, é possível executar o Docker em uma máquina com apenas 512MB RAM, contudo, você não conseguirá utilizar um grande número de containers, entre outros possíveis “problemas”.</p>
<p>Há quem diga que o mínimo confiável são 2GB RAM, porém hoje utilizo em produção máquinas com 1GB RAM e as aplicações rodam perfeitamente, ainda com muita folga de memória.</p>
<p>Cada caso é um caso, logo, vale a pena testar de acordo com a sua realidade. A mesma coisa vale para o processador.</p>
</li>
<li>
<p>É recomando o uso do drive de armazenamento <code class="highlighter-rouge">overlay2</code></p>
<p>Esse drive pode ser utilizado com o sistema de arquivos <code class="highlighter-rouge">ext4</code> (apenas RHEL 7.1), e com o <code class="highlighter-rouge">xfs</code> (RHEL 7.2 ou superior). O sistema de arquivos <code class="highlighter-rouge">xfs</code> precisa de algumas configurações a mais.</p>
<p>Mais detalhes em: <a href="https://docs.docker.com/storage/storagedriver/overlayfs-driver/">Use the OverlayFS storage driver</a></p>
</li>
</ol>
<h2 id="removendo-versões-antigas-do-docker">Removendo versões antigas do Docker</h2>
<p>Versões mais antigas do Docker eram chamadas <strong>docker</strong> ou <strong>docker-engine</strong>. Se estes estiverem instalados, desinstale-os, juntamente com as dependências associadas.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>yum remove docker <span class="se">\</span>
docker-client <span class="se">\</span>
docker-client-latest <span class="se">\</span>
docker-common <span class="se">\</span>
docker-latest <span class="se">\</span>
docker-latest-logrotate <span class="se">\</span>
docker-logrotate <span class="se">\</span>
docker-selinux <span class="se">\</span>
docker-engine-selinux <span class="se">\</span>
docker-engine
</code></pre></div></div>
<p>Tudo bem se o <code class="highlighter-rouge">yum</code> relatar que nenhum desses pacotes estão instalados.</p>
<p>O conteúdo de <strong><em>/var/lib/docker/</em></strong>, incluindo imagens, contêineres, volumes e redes, é preservado.</p>
<h2 id="instalando-o-docker-no-centos">Instalando o Docker no CentOS</h2>
<p>Existem várias maneiras de instalar o Docker:</p>
<ul>
<li>
<p>Através do repositório oficial</p>
</li>
<li>
<p>Baixando o pacote RPM, instalando e mantendo atualizado de forma manual. É útil em situações como a instalação do <strong>Docker</strong> em alguma máquina ou sistema sem acesso à internet.</p>
</li>
<li>
<p>Utilizando scripts de <strong>instalação do Docker</strong> <em>(recomendado apenas para ambientes de desenvolvimento e teste)</em></p>
</li>
</ul>
<p>Nós iremos instalar o <strong>Docker CE</strong> <em>(Community Edition)</em> através do repositório oficial.</p>
<h3 id="instalando-o-docker-através-do-repositório-oficial">Instalando o Docker através do repositório oficial</h3>
<p>Antes de instalar o <strong>Docker CE</strong> pela primeira vez em uma máquina host, é necessário configurar o repositório do Docker.</p>
<p>Após, você pode instalar e atualizar o Docker através do repositório.</p>
<h4 id="configurando-o-repositório">Configurando o repositório</h4>
<ol>
<li>
<p>Instale os pacotes necessários. <code class="highlighter-rouge">yum-utils</code> fornece o utilitário <code class="highlighter-rouge">yum-config-manager</code>, e <code class="highlighter-rouge">device-mapper-persistent-data</code> e <code class="highlighter-rouge">lvm2</code> são requeridos pelo driver de armazenamento <code class="highlighter-rouge">devicemapper</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">sudo </span>yum <span class="nb">install</span> <span class="nt">-y</span> yum-utils <span class="se">\</span>
device-mapper-persistent-data <span class="se">\</span>
lvm2
</code></pre></div> </div>
</li>
<li>
<p>Utilize o seguinte comando para configurar o repositório estável <em>(stable)</em>. Mesmo que queira instalar compilações <code class="highlighter-rouge">edge</code> ou <code class="highlighter-rouge">test</code>, você irá precisar do <code class="highlighter-rouge">stable</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">sudo </span>yum-config-manager <span class="se">\</span>
<span class="nt">--add-repo</span> <span class="se">\</span>
https://download.docker.com/linux/centos/docker-ce.repo
</code></pre></div> </div>
</li>
<li>
<p><strong>Opicional:</strong> Habilite os repositórios <code class="highlighter-rouge">edge</code> e <code class="highlighter-rouge">test</code>. Esses repositórios estão incluidos no arquivo <strong><em>docker.repo</em></strong> porém por padrão vêm desabilitados. Você pode habilitá-los junto com o repositório <code class="highlighter-rouge">stable</code>.</p>
<p>Para isso utilize os seguintes comandos:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">sudo </span>yum-config-manager <span class="nt">--enable</span> docker-ce-edge
</code></pre></div> </div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">sudo </span>yum-config-manager <span class="nt">--enable</span> docker-ce-test
</code></pre></div> </div>
<p>Se você quiser desabilitar esses repositórios basta executar o comando <code class="highlighter-rouge">yum-config-manager</code> com o argumento <code class="highlighter-rouge">--disable</code>. Para habilitá-los novamente utilize o argumento <code class="highlighter-rouge">--enable</code>.</p>
<p>Segue o comando para desabilitar o repositório <code class="highlighter-rouge">edge</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$ </span><span class="nb">sudo </span>yum-config-manager <span class="nt">--disable</span> docker-ce-edge
</code></pre></div> </div>
</li>
</ol>
<p><a href="https://docs.docker.com/install/">Leia mais sobre stable e edge</a></p>
<h4 id="instalando-o-docker-ce">Instalando o Docker CE</h4>
<p>Instale a última versão do Docker CE utilizando o seguinte comando:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>yum <span class="nb">install </span>docker-ce
</code></pre></div></div>
<p>Se for solicitado aceitar a GPG Key, verifique se o fingerprint é <code class="highlighter-rouge">060A 61C5 1B55 8A7F 742B 77AA C52F EB6B 621E 9F35</code>, se for, aceite.</p>
<p>O Docker será instalado mas não inicializado. Além disso, o grupo <code class="highlighter-rouge">docker</code> será criado porém, nenhum usuário é adicionado nele.</p>
<p>Mais para frente veremos como adicionar usuários nesse grupo, assim evitando a utilização do <code class="highlighter-rouge">sudo</code>.</p>
<p>Vamos agora executar o Docker utilizando o seguinte comando:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl start docker
</code></pre></div></div>
<p>Verifique se o Docker está instalado corretamente executando a imagem <code class="highlighter-rouge">hello-world</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>docker run hello-world
</code></pre></div></div>
<p>Esse comando faz o download de uma imagem de teste e a executa em um contêiner. Quando o contêiner é executado, ele imprime uma mensagem e sai.</p>
<p>O Docker CE está instalado e em execução, porém ainda é preciso utilizar o <code class="highlighter-rouge">sudo</code> para executar os comandos <code class="highlighter-rouge">docker</code>.</p>
<h2 id="utilizando-os-comandos-docker-sem-sudo">Utilizando os comandos docker sem sudo</h2>
<p>Para que não seja necessário utilizar <code class="highlighter-rouge">sudo</code> toda vez que for executar um comando <code class="highlighter-rouge">docker</code>, você deve adicionar o usuário ao grupo <code class="highlighter-rouge">docker</code>.</p>
<p>Esteja ciente de que o grupo <code class="highlighter-rouge">docker</code> dá acesso equivalente ao do usuário <code class="highlighter-rouge">root</code>.</p>
<p>Para adicionar o usuário atual ao grupo <code class="highlighter-rouge">docker</code> utilize o seguinte comando:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>usermod <span class="nt">-aG</span> docker <span class="nv">$USER</span>
</code></pre></div></div>
<p>Para adicionar qualquer outro usuário ao grupo <code class="highlighter-rouge">docker</code>, basta trocar <code class="highlighter-rouge">$USER</code> pelo nome do usuário desejado.</p>
<p>Após, efetue logout e login novamente para que sua associação ao grupo seja reavaliada.</p>
<p>Se estiver testando em uma máquina virtual, pode ser necessário reiniciar a máquina virtual para que as alterações entrem em vigor.</p>
<p>Em um ambiente Linux de desktop, como o X Windows, efetue logout de sua sessão completamente e, em seguida, efetue login novamente.</p>
<h2 id="inicializando-o-docker-no-boot">Inicializando o Docker no boot</h2>
<p>Para que o Docker inicialize junto com o sistema, basta executar:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl <span class="nb">enable </span>docker
</code></pre></div></div>
<p>Caso queira desabilitar a inicialização no boot:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">sudo </span>systemctl disable docker
</code></pre></div></div>
<p>Terminamos aqui o primeiro tutorial sobre Docker, deste blog. Espero ter ajudado. Qualquer dúvida, crítica ou sugestão deixe nos comentários.</p>
<p>Fontes:</p>
<p><a href="https://docs.docker.com/">Docker Docs</a></p>
<p><a href="https://forums.docker.com">Docker Community Forums</a></p>Gabriel Zuqueto AmaralNeste post mostro como instalar o Docker no CentOS Linux, além de mostrar como utilizar sem sudo.Como criar servidor para envio de e-mail em massa2017-08-26T21:23:44-03:002017-08-26T21:23:44-03:00https://gabrielzuqueto.eti.br/como-criar-servidor-para-envio-de-e-mail-em-massa<p>Hoje vou mostrar como criar servidor para envio de e-mail em massa, gastando apenas $5 por mês. Com seu próprio servidor de e-mail, você não irá precisar pagar muito para enviar alguns milhares de e-mails. Isso pode fazer com que suas campanhas fiquem bem mais baratas.</p>
<p>Vamos utilizar o CentOS como base do nosso servidor, por ser um sistema bem estável e robusto, como mencionei em outro post: <a href="https://gabrielzuqueto.eti.br/criar-servidor-ragnarok-centos" title="Servidor Ragnarok CentOS: Como criar?">Servidor Ragnarok CentOS: Como criar?</a>.</p>
<p>Montaremos nosso servidor utilizando a menor e mais barata instância da Digital Ocean, mas isso não quer dizer que nosso servidor de e-mail será ruim! Os $5 que falei no primeiro parágrafo é exatamente o custo deste droplet (apelido dado pela Digital Ocean às suas instâncias).</p>
<p>Caso ainda não tenha um droplet criado na Digital Ocean, confira este post: <a href="https://gabrielzuqueto.eti.br/como-criar-servidor-na-digital-ocean" title="Como criar servidor na Digital Ocean">Como criar servidor na Digital Ocean</a>.</p>
<p>Para que um servidor de e-mail seja válido, ou seja, para que as mensagens enviadas através dele cheguem aos destinatários, temos que configurar tudo com base nas boas práticas, caso contrário, suas mensagens ficaram pelo meio do caminho, nos filtros anti-spam da rede.</p>
<p>Se seu servidor estiver por trás de um IP doméstico, automaticamente seu servidor cairá na Blacklist, pois as faixas de IPs domésticos já se encontram nesta lista. Estando na Blacklist, seus e-mails não irão chegar aos destinatários. Por esse motivo que sugeri a <a href="https://gabrielzuqueto.eti.br/cupom-de-25-em-creditos-na-digital-ocean" title="Cupom de $25 em créditos na Digital Ocean">Digital Ocean</a>.</p>
<p>Mãos à obra!</p>
<h2 id="parte-1---instalando-e-configurando-o-postfix">Parte 1 - Instalando e configurando o Postfix</h2>
<p>Mas o que é Postfix? Vou responder a esta pergunta com uma definição clara e bem simples.</p>
<blockquote>
<p>Postfix é um agente de transferência de e-mails (MTA) livre e de código aberto que encaminha e entrega e-mails, e tem como objetivo ser uma alternativa segura ao Sendmail, muito utilizado em servidores UNIX.</p>
</blockquote>
<p><em>Fonte: <a href="https://pt.wikipedia.org/wiki/Postfix" title="Postfix">Wikipédia</a></em></p>
<h3 id="instalando-o-postfix">Instalando o Postfix</h3>
<p>Instalar o Postfix é bem simples, basta executar a seguinte linha de comando como usuário root:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum install postfix -y
</code></pre></div></div>
<p>Aguarde o fim da instalação e vamos para o próximo passo. Lembrando que o Postfix constuma vim instalado nos Droplets da Digital Ocean, porém não custa nada executar o comando pois vai que pare de vim instalado.</p>
<h3 id="configurando-o-postfix">Configurando o Postfix</h3>
<p>O arquivo de configuração do Postfix fica no seguinte caminho: <strong>/etc/postfix/main.cf</strong></p>
<p>Vamor definir as seguintes configurações:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mydomain = DOMINIO_DO_SERVIDOR
myhostname = NOME_COMPLETO_DO_SERVIDOR_INCLUINDO_DOMINIO
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
inet_interfaces = loopback-only
mailbox_size_limit = 0
</code></pre></div></div>
<ul>
<li>
<p>mydomain: é o domínio do servidor, exemplo: gabrielzuqueto.eti.br</p>
</li>
<li>
<p>myhostname: é o nome do servidor incluindo o domínio, exemplo: mail.gabrielzuqueto.eti.br</p>
</li>
<li>
<p>mydestination: indica quais nomes e domínio serão considerados endereços locais pelo servidor. Ou seja, se o nome do servidor é <strong>mail.gabrielzuqueto.eti.br</strong> e o domínio é <strong>gabrielzuqueto.eti.br</strong>, o servidor entenderá que tanto os e-mails endereçados a <strong>contato@mail.gabrielzuqueto.eti.br</strong> quanto, <strong>contato@localhost.gabrielzuquetoeti.br</strong>, <strong>contato@gabrielzuqueto.eti.br</strong> e <strong>contato@localhost</strong> são endereçados a ele mesmo.</p>
</li>
<li>
<p>inet_interfaces: define quais intefaces o servidor aceitará e-mails, definimos apenas local, logo, não iremos receber e-mails vindos de fora do servidor.</p>
</li>
<li>
<p>mailbox_size_limit: define o tamanho das caixas de e-mail, deixaremos zero pois não pretendemos receber e-mail algum.</p>
</li>
</ul>
<p>Vou usar o <strong>myhostname = gabrielzuqueto.eti.br</strong></p>
<p>Utilize o <strong>echo</strong> para adicionar as novas configurações no Postfix.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "mydomain = gabrielzuqueto.eti.br
myhostname = gabrielzuqueto.eti.br
mydestination = \$myhostname, localhost.\$mydomain, localhost, $mydomain
inet_interfaces = loopback-only
mailbox_size_limit = 0" >> /etc/postfix/main.cf
</code></pre></div></div>
<p>Agora precisamos habilitar o Postfix para enviar as mensagens pela porta 587, pois a <a href="http://www.antispam.br/" title="Antispam.br">Antispam.br</a> determinou que a partir de 01/01/2013 o envio pela porta 25 seria descontinuado, isso significa que, se você tentar usar a porta 25 para o envio de e-mails, sua mensagem nunca chegará ao destinatário.</p>
<p>A configuração é simples, basta editar o arquivo <strong>/etc/postfix/master.cf</strong> com o seu editor de texto preferido.</p>
<p>Ao abrir o arquivo <strong>/etc/postfix/master.cf</strong>, você verá algo como isso:</p>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-master-cf.png" alt="Como criar servidor para envio de e-mail em massa - Postfix master.cf" title="Como criar servidor para envio de e-mail em massa - Postfix master.cf" /></p>
<p>Devemos comentar a linha:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>smtp inet n - n - - smtpd
</code></pre></div></div>
<p>E descomentar a linha:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#submission inet n - n - - smtpd
</code></pre></div></div>
<p>No final ficará assim:</p>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-master-cf-2.png" alt="Como criar servidor para envio de e-mail em massa - Postfix master.cf" title="Como criar servidor para envio de e-mail em massa - Postfix master.cf" /></p>
<p>A linha comentada faz com que o Postfix não utilize mais a porta 25 e a linha que foi descomentada, faz com que ele utilize a porta 587.</p>
<h2 id="parte-2---spf-sender-policy-framework">Parte 2 - SPF (Sender Policy Framework)</h2>
<p>O que é SPF? Agora utilizarei as palavras do CGI.br</p>
<blockquote>
<p>SPF é uma tecnologia para combater a falsificação de endereços de retorno dos emails (return-path). O mecanismo permite ao administrador de um domínio definir e publicar uma política SPF, onde são designados os endereços das máquinas autorizadas a enviar mensagens em nome deste domínio.</p>
</blockquote>
<blockquote>
<p>Também permite ao administrador de um serviço de e-mail estabelecer critérios de aceitação de mensagens em função da checagem das políticas SPF publicadas para cada domínio.</p>
</blockquote>
<blockquote>
<p>O processo de publicação de uma política SPF é independente da implantação de checagem de SPF por parte do MTA, estes podem ou não ser feitos em conjunto.</p>
</blockquote>
<blockquote>
<p>Ao publicar uma política de SPF, o administrador de um domínio está autorizando determinados MTAs a enviar e-mails em nome deste domínio. O objetivo é evitar que terceiros enviem mensagem indevidamente em nome de seu domínio, e que mensagens de erro (bounces) causadas por spam com envelope falso sejam enviadas para o seu servidor.</p>
</blockquote>
<p><em>Fonte: <a href="http://www.antispam.br/admin/spf/" title="Antispam.br SPF">Antispam.br</a></em></p>
<h3 id="configurando-o-spf">Configurando o SPF</h3>
<p>O SPF é configurado diretamente nos registros do DNS, mas não se preocupe pois a configuração é bem simples:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>TXT @ "v=spf1 a mx -all"
</code></pre></div></div>
<ul>
<li>
<p>TXT: é tipo de registro da zona DNS. Os registros SPF são escritos como registros TXT.</p>
</li>
<li>
<p>@: em um arquivo DNS, o símbolo @ é um espaço reservado usado para representar o domínio atual</p>
</li>
<li>
<p>v=spf1: identifica o registro <strong>TXT</strong> como um registro SPF, utilizando o SPF Versão 1</p>
</li>
<li>
<p>a: autoriza o servidor definido nos registros <strong>A</strong> do DNS, a enviar e-mail</p>
</li>
<li>
<p>mx: autoriza os servidores definidos nos registros <strong>MX</strong> do DNS, a enviar e-mail</p>
</li>
<li>
<p>-all: retorna falha, caso nenhuma das opções SPF sejam satisfeitas, ou seja, se for um servidor que não esteja no registro <strong>A</strong> e nem nos registros <strong>MX</strong>, a mensagem será invalidada</p>
</li>
</ul>
<p>Daí você deve estar se perguntando: Mas meu servidor de e-mail não está listado em nenhum registro <strong>A</strong> ou <strong>MX</strong> do meu domínio, logo, como O SPF vai funcionar?</p>
<p>A resposta é simples! Crie um registro <strong>A</strong> dentro dos seus registros DNS e ponha o IP do seu servidor de e-mail. Após, crie uma entrada <strong>MX</strong> apontando para o registro <strong>A</strong> que acabou de criar. Você deve criar <strong>MX</strong> pois caso os servidores não encontrem este registro, iram perguntar aos <strong>A</strong> isso adiciona um delay a mais.</p>
<p>Vou exemplificar como fiz com o SPF:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A mail 165.227.0.178
MX @ mail.gabrielzuqueto.eti.br
</code></pre></div></div>
<p>No final, meus registros DNS ficaram assim:</p>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-dns.png" alt="Como criar servidor para envio de e-mail em massa - DNS" title="Como criar servidor para envio de e-mail em massa - DNS" /></p>
<p>Lembrando que seus servidores de e-mail podem estar por trás de outro DNS, se este é seu caso, ignore o registro do <strong>A</strong> e adicione diretamente o DNS no seu <strong>MX</strong>.</p>
<p>Exemplo, se o DNS do meu servidor de e-mail fosse gza.com.br, eu adicionaria:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>TXT @ "v=spf1 a mx -all"
MX @ gza.com.br
</code></pre></div></div>
<p>Repare que não registrei o <strong>A</strong> neste caso! :)</p>
<h2 id="parte-3---dkim-domain-keys-identified-mail">Parte 3 - DKIM (Domain Keys Identified Mail)</h2>
<p>O que é DKIM? Mais uma vez, vamos de CGI.br</p>
<blockquote>
<p>DKIM é uma especificação do IETF que define um mecanismo para autenticação de e-mail baseado em criptografia de chaves públicas. Através do uso do DKIM, uma organização assina digitalmente as mensagens que envia, permitindo ao receptor confirmar a autenticidade da mensagem. Para verificar a assinatura digital, a chave pública é obtida por meio de consulta ao DNS do domínio do assinante.</p>
</blockquote>
<blockquote>
<p>Ao contrário do SPF, que verifica somente o envelope, o DKIM verifica o cabeçalho da mensagem. Esta técnica acarreta um custo computacional adicional por mensagem, tanto para o MTA remetente quanto para o receptor.</p>
</blockquote>
<p><em>Fonte: <a href="http://www.antispam.br/admin/dkim/" title="Antispam.br DKIM">Antispam.br</a></em></p>
<h3 id="instalando-o-opendkim">Instalando o OpenDKIM</h3>
<p>Primeiramente devemos instalar o OpenDKIM, porém este pacote não está disponível nos repositórios que vêm como padrão no yum, mas está disponível nos repositórios do CentOS 7 EPEL.</p>
<p>Para habilitar o repositório EPEL, utilize o seguinte comando:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
</code></pre></div></div>
<p>Após o término da instalação do EPEL, podemos instalar o OpenDKIM:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum install opendkim -y
</code></pre></div></div>
<p>Vamos por o OpenDKIM para inicializar junto com o sistema:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chkconfig opendkim on
</code></pre></div></div>
<h3 id="configurando-o-opendkim">Configurando o OpenDKIM</h3>
<p>O arquivo de configuração do OpenDKIM fica no seguinte caminho: <strong>/etc/opendkim.conf</strong></p>
<p>Adicione as seguintes configurações no final do arquivo de configuração do OpenDKIM:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>AutoRestart Yes
AutoRestartRate 10/1h
UMask 002
Syslog yes
SyslogSuccess Yes
LogWhy Yes
Canonicalization relaxed/simple
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
InternalHosts refile:/etc/opendkim/TrustedHosts
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
Mode sv
PidFile /var/run/opendkim/opendkim.pid
SignatureAlgorithm rsa-sha256
UserID opendkim:opendkim
Socket inet:12301@localhost
</code></pre></div></div>
<ul>
<li>
<p>AutoRestart: reinicia automaticamente o filtro em caso de falhas.</p>
</li>
<li>
<p>AutoRestartRate: especifica a taxa de reinício máxima do filtro, se o reinício começar a ocorrer mais rapidamente do que essa taxa, o filtro será encerrado; 10/1h - 10 reinícios/hora serão permitidos no máximo.</p>
</li>
<li>
<p>UMask: dá todas as permissões de acesso ao grupo de usuários definido pelo UserID e permite que outros usuários leiam e executem arquivos, neste caso, permitirá a criação e modificação de um arquivo Pid.</p>
</li>
<li>
<p>Syslog, SyslogSuccess, *LogWhy: esses parâmetros permitem o log detalhado através de chamadas para o syslog.</p>
</li>
<li>
<p>Canonicalization: define os métodos de canonização utilizados na assinatura de mensagens, o método <strong>simple</strong> permite quase nenhuma modificação enquanto o <strong>relaxed</strong> tolera mudanças menores, como substituição de espaços em branco; <strong>relaxed/simple</strong> - o cabeçalho da mensagem será processado com o algoritmo <strong>relaxed</strong> eo corpo com o <strong>simple</strong>.</p>
</li>
<li>
<p>ExternalIgnoreList: especifica os hosts externos que podem enviar e-mails através do servidor como um dos domínios de assinatura sem credenciais.</p>
</li>
<li>
<p>InternalHosts: define uma lista de hosts internos cujo correio não deve ser verificado, mas assinado em vez disso.</p>
</li>
<li>
<p>KeyTable: mapeia nomes de chaves para assinar chaves</p>
</li>
<li>
<p>SigningTable: lista as assinaturas para aplicar a uma mensagem com base no endereço encontrado no campo From: do cabeçalho</p>
</li>
<li>
<p>Mode: declara os modos de operação; Neste caso, o milter age como um assinante (s) e um verificador (v).</p>
</li>
<li>
<p>PidFile: o caminho para o arquivo Pid que contém o número de identificação do processo.</p>
</li>
<li>
<p>SignatureAlgorithm: seleciona o algoritmo de assinatura a ser usado ao criar assinaturas.</p>
</li>
<li>
<p>UserID: o processo do opendkim é executado sob esse usuário e grupo.</p>
</li>
<li>
<p>Socket: o milter irá ouvir no socket especificado aqui, o Posfix enviará mensagens para o opendkim para assinar e verificar através deste soquete; 12301 @ localhost define um soquete TCP que escuta no localhost, porta 12301</p>
</li>
</ul>
<h4 id="configurando-o-par-de-chaves-públicaprivada">Configurando o par de chaves Pública/Privada</h4>
<p>Primeiramente devemos criar o diretório que guardará o par de chave para o nosso domínimo.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /etc/opendkim/keys/DOMINIO_DO_SERVIDOR
</code></pre></div></div>
<p>Com o diretório criado, podemos gerar o par de chaves:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>opendkim-genkey -D /etc/opendkim/keys/DOMINIO_DO_SERVIDOR/ -d DOMINIO_DO_SERVIDOR -s default
</code></pre></div></div>
<p>Agora devemos por o OpenDKIM como o proprietário do diretório das chaves:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chown -R opendkim: /etc/opendkim/keys/DOMINIO_DO_SERVIDOR
</code></pre></div></div>
<p>Agora vamos adicionar a chave ao mapeamento do OpenDKIM. Para isso adicione a seguinte linha em <strong>/etc/opendkim/KeyTable</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default._domainkey.DOMINIO_DO_SERVIDOR DOMINIO_DO_SERVIDOR:default:/etc/opendkim/keys/DOMINIO_DO_SERVIDOR/default.private
</code></pre></div></div>
<p>Agora vamos adicionar o domínio na tabela de assinatura. Para isso adicione a seguinte linha em <strong>/etc/opendkim/SigningTable</strong></p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*@DOMINIO_DO_SERVIDOR default._domainkey.DOMINIO_DO_SERVIDOR
</code></pre></div></div>
<p>Por fim, vamos adicionar o nosso IP local em <strong>/etc/opendkim/TrustedHosts</strong>. Para saber qual é o IP local da sua instância, utilize o seguinte comando:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ifconfig
</code></pre></div></div>
<p>Daí pegue o endereço IP (inet) da interface <strong>eth0</strong>.</p>
<p>Após, adicione no final do arquivo <strong>/etc/opendkim/TrustedHosts</strong>.</p>
<p>Agora temos que dizer ao Postfix que queremos usar o milter OpenDKIM. Edite /etc/postfix/main.cf e insira no final do arquivo:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>smtpd_milters = inet:127.0.0.1:12301
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
milter_protocol = 6
</code></pre></div></div>
<p>Agora reinicie o OpenDKIM e o Postfix</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>service opendkim reload
service postfix reload
</code></pre></div></div>
<p>O último passo é adicionar a nossa chave pública no registro do DNS. Execute o seguinte comando para pegar a chave pública OpenDKIM do seu domínio:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat /etc/opendkim/keys/DOMINIO_DO_SERVIDOR/default.txt
</code></pre></div></div>
<p>Irá retornar algo como isso aqui:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>default._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZfST+s+4xo4qOFrjn/xhDbP9gCfvHgpIqxeWtJrgOSLC9nlsmKlEBiuVZ4bcXolSDU8XmYmBGRvdtPcEerF0MpYgoK5St3xXinCayO0sy6F9rwzfkn06enXumQuN7Xgoio0a3G0K9xrjMmzt1pzmLlKC7x2wMA3l8oOgKdQQ/AwIDAQAB" ) ; ----- DKIM key default for gabrielzuqueto.eti.br
</code></pre></div></div>
<p>Vou tomar esse retorno aí como exemplo para montar o registro no DNS.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>TXT default._domainkey.gabrielzuqueto.eti.br "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZfST+s+4xo4qOFrjn/xhDbP9gCfvHgpIqxeWtJrgOSLC9nlsmKlEBiuVZ4bcXolSDU8XmYmBGRvdtPcEerF0MpYgoK5St3xXinCayO0sy6F9rwzfkn06enXumQuN7Xgoio0a3G0K9xrjMmzt1pzmLlKC7x2wMA3l8oOgKdQQ/AwIDAQAB"
</code></pre></div></div>
<p>Pronto! No final, meus registros DNS ficaram assim:</p>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-dns-2.png" alt="Como criar servidor para envio de e-mail em massa - DNS 2" title="Como criar servidor para envio de e-mail em massa - DNS 2" /></p>
<h2 id="testando-os-registros-dns">Testando os registros DNS</h2>
<p>Agora que terminamos de configurar tudo, utilizaremos o <a href="https://mxtoolbox.com/" title="MX Toolbox">MX Toolbox</a> para testar os registros do DNS.</p>
<h3 id="testando-o-registro-mx">Testando o registro MX</h3>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-mx.png" alt="Como criar servidor para envio de e-mail em massa - DNS MX" title="Como criar servidor para envio de e-mail em massa - DNS MX" /></p>
<h3 id="testando-o-registro-spf">Testando o registro SPF</h3>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-spf.png" alt="Como criar servidor para envio de e-mail em massa - DNS SPF" title="Como criar servidor para envio de e-mail em massa - DNS SPF" /></p>
<h3 id="testando-o-registro-dkim">Testando o registro DKIM</h3>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-dkim.png" alt="Como criar servidor para envio de e-mail em massa - DNS DKIM" title="Como criar servidor para envio de e-mail em massa - DNS DKIM" /></p>
<p>Parece que está tudo ok! Agora vamos testar o envio de e-mail.</p>
<h2 id="testando-o-envio-de-e-mail">Testando o envio de e-mail</h2>
<p>Primeiro teremos que instalarum cliente de e-mail:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum install mailx -y
</code></pre></div></div>
<p>Após a instalação, basta executar o seguinte comando:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>echo "Teste de envio de e-mail" | mail -s "Esse é apenas um teste" SEU_ENDERECO_DE_EMAIL_AQUI
</code></pre></div></div>
<p>Após execute o comando seguinte comando para ler os logs:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tail /var/log/maillog -f
</code></pre></div></div>
<p>Você terá algo como isso:</p>
<p><img src="assets/2017/08/como-criar-servidor-para-envio-de-e-mail-em-massa-log-envio.png" alt="Como criar servidor para envio de e-mail em massa - Log" title="Como criar servidor para envio de e-mail em massa - Log" /></p>
<p>Repare que o OpenDKIM assinou a mensagem:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Aug 27 15:17:52 centos-512mb-smtp1 opendkim[711]: 2FCAD4073C: DKIM-Signature field added (s=default, d=gabrielzuqueto.eti.br)
</code></pre></div></div>
<p>Porém, ele não consegue enviar a mensagem para o Gmail:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Aug 27 15:18:22 centos-512mb-smtp1 postfix/smtp[9639]: connect to gmail-smtp-in.l.google.com[74.125.28.26]:25: Connection timed out
</code></pre></div></div>
<p>Isso se dá por que a <a href="https://gabrielzuqueto.eti.br/cupom-de-25-em-creditos-na-digital-ocean" title="Cupom de $25 em créditos na Digital Ocean">Digital Ocean</a> por padrão bloqueia a porta 587, para diminuir a possibilidade de SPAM.</p>
<p>Para contornar isso, basta abrir um chamado pedindo para liberar a porta 587. Eles iram pedir que confirme sua identidade, e após a confirmação das informações com sucesso, a porta será liberada e seu servidor estará pronto para enviar e-mails.</p>
<p>Vou solicitar a liberção da porta a eles, e assim que eu tiver com a porta 587 liberada, atualizo este post mostrando que o servidor está funcionando corretamente.</p>
<p>Espero que tenham aprendido como criar servidor para envio de e-mail em massa. Qualquer dúvida, crítica ou sugestão, deixem nos comentários. Muito obrigado e até a próxima!</p>Gabriel Zuqueto AmaralNeste post mostro como criar servidor para envio de e-mail em massa, gastando apenas $5 por mês.Segurança de servidores na nuvem da Digital Ocean2017-07-23T12:26:59-03:002017-07-23T12:26:59-03:00https://gabrielzuqueto.eti.br/seguranca-servidores-nuvem-digital-ocean<p>Hoje irei mostrar como aplicar as configurações básicas de segurança em um servidor Linux.</p>
<p>A distro linux utilizada será o CentOS 7, porém as configurações de segurança apresentadas aqui podem ser aplicadas a qualquer disto. Dependendo da distro que você for utilizar, alguns detlahes como caminho de arquivos ou comandos podem ser diferentes.</p>
<p>Tomarei como base, que você já tenha um servidor e queira aplicar as configurações de segurança básica.
Caso ainda não tenha um servidor, confira: <a href="https://gabrielzuqueto.eti.br/como-criar-servidor-na-digital-ocean" title="Como criar servidor na Digital Ocean">Como criar um Droplet na Digital Ocean</a></p>
<h2>Acessando o droplet</h2>
<p>Nosso droplet está pronto para ser acessado! Levando em consideração que está utilizando uma distro Linux, copie o IP Address referente à instância que acabamos de subir e conecte-se a ela da seguinte forma:</p>
<pre class="lang:sh decode:true ">ssh root@IP_DA_INSTANCIA</pre>
<p>No caso do nosso tutorial fica assim:</p>
<pre class="lang:sh decode:true ">ssh root@138.68.247.213</pre>
<h2>Criando a senha do usuário root</h2>
<p>É importante cria uma senha para o root, pois mais para frente vamos desativar o acesso dele via ssh, porém teremos que deixar uma forma de atualizar o sistema ou instalar novos pacotes no nosso servidor. Mais para frente explico melhor.</p>
<p>Utilize o seguinte comando para criar a senha do root:</p>
<pre class="lang:sh decode:true ">passwd root</pre>
<p>Uma nova senha sera solicitada, logo digite uma e tecle ENTER. Após, será pedido que confirme a senha que acabou de digitar, então, repita a senha e tecle ENTER novamente.</p>
<p><img class="aligncenter wp-image-422 size-full" title="Segurança de servidores na nuvem da Digital Ocean - 5" src="assets/2017/06/digital-ocean-droplet-seguro-centos-5.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Ok! Agora que criamos uma senha para o root, vamos adicionar um usuário comum em nossa instância.</p>
<h2>Adicionando um usuário comum</h2>
<p>Um usuário comum é aquele que não tem os privilégios de root e nem permissão para executar comandos com sudo. Ou seja, este usuário não pode alterar que não seja dele ou seja público.</p>
<p>É super importante que as aplicações que ficaram ativas em nosso servidor, não estejam pelo usuário root ou por um usuário com poder de sudo. Isso nos dá uma camada a mais de segurança.</p>
<p>Para criar um novo usuário utilize o comando abaixo no terminal da instância e tecle ENTER:</p>
<pre class="lang:sh decode:true ">useradd NOME_DO_NOVO_USUARIO</pre>
<p>No caso do nosso tutorial:</p>
<pre class="lang:sh decode:true ">useradd gabriel</pre>
<p>Nenhum retorno será exibido. Agora vamos criar uma senha para o novo usuário.</p>
<pre class="lang:sh decode:true ">passwd NOME_DO_NOVO_USUARIO</pre>
<p>No caso do nosso tutorial:</p>
<pre class="lang:sh decode:true ">passwd gabriel</pre>
<p>Os passos são idênticos aos que utilizamos para por a senha no usuário root. E a saída será semelhante.</p>
<p><img class="aligncenter wp-image-423 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-6.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Tudo certo!</p>
<h2>Adicionando Autenticação de Chave Pública para o novo usuário</h2>
<p>O próximo passo é configurar uma chave pública de autenticação para o seu novo usuário, isso te proporciona uma camada de segurança, pois só conseguirá logar com este usuário via SSH, quem tive sua chave privada.</p>
<p>É importante fazer backup do seu par de chaves, pois se perder sua chave privada, não terá mais acesso ao seu servidor.</p>
<p>O ideal seria gerar um par de chaves novas para ter um pouco mais de segurança. Porém, neste tutorial vou utulizar a mesma chave pública que utilizamos para o usuário root.</p>
<p>Com a chave pública em mãos, vamos chavear para o novo usuário. Para isso digite o seguinte comando:</p>
<pre class="lang:sh decode:true ">su - NOME_DO_NOVO_USUARIO</pre>
<p>No caso do nosso tutorial:</p>
<pre class="lang:sh decode:true ">su - gabriel</pre>
<p>O <em>-</em> faz com que a gente vá para o diretório home do usuário.</p>
<p>Se você digitar o seguinte comando:</p>
<pre class="lang:sh decode:true ">pwd</pre>
<p>Verá que o retorno será <strong>/home/NOME_DO_NOVO_USUARIO</strong>, ou seja, não estamos no diretório <strong>/root</strong>, estamos na home do usuário.</p>
<p><img class="aligncenter wp-image-424 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-7.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Agora que estamos chaveado para o novo usuário, vamos adicionar a chave pública para ele.</p>
<p>Crie um novo diretório chamado <strong>.ssh</strong> e restrinja suas permissões com os seguintes comandos:</p>
<pre class="lang:sh decode:true ">mkdir .ssh
chmod 700 .ssh</pre>
<p>Agora crie um arquivo dentro do diretório <strong>.ssh</strong> chamado <strong>authorized_keys</strong> e adicione sua chave pública dentro dele.</p>
<p>Utilize o seguinte commando:</p>
<pre class="lang:sh decode:true ">echo "SUA_CHAVE_PUBLICA_AQUI" > .ssh/authorized_keys</pre>
<p>No caso do nosso tutorial fica assim:</p>
<pre class="lang:sh decode:true ">echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuNu6K/LblCPgWTpfv/QBbZh8W/DJmjIHs8s7KMiqWgqVD8RILZ5TnNSfrg+BwwW4P0KvRyBMVoJeeAy1Xeonh5Yn+KUQ/6OehCsc0OBYE+o+dnex6V5QNZS6VUIyewMHzTSSVRW2ZYlMQGFq4jtqV2xD4OOOYvQiR5ijWjkgRTdjtQBivZDgBrVy/QU97+ToBw4MQyWwNQpH8lrkBJtYYdwVkIC0/DGsq3BfzEcUCnNF+s7qbUKQ57zG2ic02yWQZlOkTumhs8PFNGj75o0z0tM0MDa/n1YypQRHxnB98UGF5Fz8mHebKCX6jEDorrbacKgkXXyJDNEeW+BeJsDGT gabriel@localhost.localdomain" > .ssh/authorized_keys</pre>
<p>Agora restrinja as permissões do arquivo <strong>authorized_keys</strong> com este comando:</p>
<pre class="lang:sh decode:true ">chmod 600 .ssh/authorized_keys</pre>
<p><img class="aligncenter wp-image-425 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-8.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>A partir de agora você pode efetuar login SSH como seu novo usuário, usando a chave privada como autenticação.</p>
<p>Digite o comando <strong>exit</strong> e tecle ENTER para sair do usuário atual e voltar para o root.</p>
<p><img class="aligncenter wp-image-426 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-9.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<h2>Configurando o servidor SSH</h2>
<p>Podemos proteger um pouco mais o nosso servidor, modificando a configuração padrão do SSH. As configurações ficam no seguinte caminho e arquivo:</p>
<pre class="lang:sh decode:true ">/etc/ssh/sshd_config</pre>
<p>Poderíamos utilizar qualquer editor de texto como vi, vim e nano, porém vou me ater a adicionar as novas configurações no final do arquivo de configuração do serviço SSH.</p>
<h3>Alterando a porta do serviço SSH</h3>
<p>Por padrão o serviço SSH vem configurado para responder na porta 22, por sem bem conhecida, o ideal é alterar esta configuração para diminuir o risco de um ataque no nosso servidor.</p>
<p>Podemos alterar a porta para algo entre 1025 e 65536, mas lembre-se de anotar para você não esquecer qual é a nova porta. Pois é através dela que você terá o acesso via SSH.</p>
<p>Vou utilizar a porta 2806 para o nosso tutorial. Utilize este comando para adicionar a nova configuração de porta:</p>
<pre class="lang:sh decode:true ">echo "Port 2806" >> /etc/ssh/sshd_config</pre>
<h3>Desabilitar o login remoto do root</h3>
<p>Por o usuário root também ser bastante conhecido, é fato que podem tentar atacar nosso servidor utilizando as credênciais do root, por isso, é mega importante desabilitar o acesso remoto do usuário root.</p>
<p>Não se preocupe, se você precisar utilizar o root, poderá chavear para ele como fez como usuário comum (<em>su - root</em>), bastando apenas digitar a senha root que será solicitada.</p>
<p>Para não permitir o acesso remoto do root, utilize o seguinte comando:</p>
<pre class="lang:sh decode:true ">echo "PermitRootLogin no" >> /etc/ssh/sshd_config</pre>
<h3>Reiniciar o serviço SSH</h3>
<p>Agora que já fizemos as configurações, devemos reiniciar o serviço SSH. Para isso utilize o seguinte comando:</p>
<pre class="lang:sh decode:true ">service sshd restart</pre>
<p><img class="aligncenter wp-image-427 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-10.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Agora, antes de sair do servidor, devemos testar nossa nova configuração. Não queremos desconectar antes que possamos confirmar que as novas conexões podem ser estabelecidas com sucesso.</p>
<p>Abra um novo terminal e digite o seguinte comando para se conectar ao servidor:</p>
<pre class="lang:sh decode:true ">ssh -p PORTA_NOVA NOME_DO_NOVO_USUARIO@IP_DA_INSTANCIA</pre>
<p>No caso do nosso tutorial, fica assim:</p>
<pre class="lang:sh decode:true ">ssh -p 2806 gabriel@138.68.247.213</pre>
<p>Se configurou tudo certo, verá que conectou no servidor com sucesso.</p>
<p><img class="aligncenter wp-image-428 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-11.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="541" /></p>
<p>Agora que verificamos que tudo ocorreu bem, podemos deslogar o usuário root do servidor. Para isso utilize ocomando <strong>exit</strong></p>
<p><img class="aligncenter wp-image-429 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-12.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>A partir de agora, se você tentar conectar na porta padrão (22) ou com o usuário root, não irá conseguir.</p>
<p><img class="aligncenter wp-image-430 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-13.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p><img class="aligncenter wp-image-431 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-14.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<h2>Atualizando os pacotes do servidor</h2>
<p>Acabamos decriar a nossa instância CentOS 7, logo, devemos atualizar seus pacotes.</p>
<p>Dado que não podemos mais acessar o nosso servidor via SSH com o usuário root, vamos acessá-lo com o usuário comum e depois a gente escala para o root.</p>
<p>Conectando ao servidor com o novo usuário:</p>
<pre class="lang:sh decode:true ">ssh -p 2806 gabriel@138.68.247.213</pre>
<p>Escalando para o usuário root:</p>
<pre class="lang:sh decode:true ">su root</pre>
<p>Ele vai pedir a senha, digite a senha do root e tecle ENTER.</p>
<p><img class="aligncenter wp-image-432 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-15.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Agora que estamos logados como root, vamos utilizar o seguinte comando para atualizar os pacotes do nosso servidor:</p>
<pre class="lang:sh decode:true ">yum update -y</pre>
<p><img class="aligncenter wp-image-433 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-16.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Ao término, teremos algo como este aqui:</p>
<p><img class="aligncenter wp-image-434 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-17.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="737" height="503" /></p>
<p>Pronto!</p>
<h2>Digital Ocean Firewall</h2>
<p>O Firewall é mais uma camada de segurança para o nosso servidor. A Digital Ocean tem o serviço de Firewall de graça. Vamos configurar o firewall básico para o nosso servidor.</p>
<p>Para isso vá até o painel da sua conta Digital Ocean, clique em Networking e depois em Firewall. Após clique em Create Firewall.</p>
<p><img class="aligncenter wp-image-435 size-large" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-18-1024x795.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="800" height="621" /></p>
<p>A seguinte tela irá ser carregada:</p>
<p><img class="aligncenter wp-image-436 size-large" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-19-845x1024.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="800" height="969" /></p>
<p>Em <strong>Name</strong> ponha um nova que vá te lembrar quais regras estaram na configuração de Firewall.</p>
<p>Exemplos: regras-servidor-lamp, regras-servidor-mysql, regras-servidor-apache, regras-servidor-nginx.</p>
<p>No nosso caso botarei: tutorial-seguranca-basica-servidor.</p>
<p><img class="aligncenter wp-image-437 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-20.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="680" height="180" /></p>
<p>Em <strong>Inbound Rules</strong> são as configurações para as conexões que vêm de fora para dentro do nosso servidor.</p>
<p>Podemos ver que a configuração SSH na porta 22 já está por padrão na regra do Firewall, porém nós alteramos o serviço SSH para a porta 2806, logo, devemos modificar o valor da porta na configuração do Firewall, caso contrário, não conseguiremos mais conectar no nosso servidor.</p>
<p>Altere o type de SSH para custom e digite 2806 no Port Range.</p>
<p><img class="aligncenter wp-image-438 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-21.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="1018" height="302" /></p>
<p>Lembre de adicionar todas as portas que você quiser expor. Exemplos: HTTP (80), HTTPS (443), MySQL (3306), …</p>
<p>Em <strong>Outbound Rules</strong> são as configurações para as conexões de dentro para fora do nosso servidor. Por padrão está liberado o protocolo ICMP e todas as porta utilizando tanto o protocolo TCP quanto o UDP.</p>
<p><img class="aligncenter wp-image-439 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-22.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="1018" height="463" /></p>
<p>Só altere estas configurações se tiver certeza do que está fazendo.</p>
<p>Em <strong>Apply to Droplets</strong> você irá selecionar quais instâncias (droplets) você quer quer recebam estas configurações de Firewall.</p>
<p>Ao começar a digitar o nome da instância, uma lista irá aparecer para você selecionar.</p>
<p><img class="aligncenter wp-image-440 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-23.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="1016" height="216" /></p>
<p>Após selecionar sua instância, clique no botão Create Firewall.</p>
<p><img class="aligncenter wp-image-441 size-full" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-24.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="1012" height="218" /></p>
<p>Pronto! Agora temos um Firewall básico em nossa droplet. :)</p>
<p><img class="aligncenter wp-image-442 size-large" title="Segurança de servidores na nuvem da Digital Ocean" src="assets/2017/06/digital-ocean-droplet-seguro-centos-25-1024x546.png" alt="Segurança de servidores na nuvem da Digital Ocean" width="800" height="427" /></p>
<p>Com estes cuidados básicos, estaremos bem mais protegido do que antes. Não podemos esquecer de sempre utilizar autenticação com chave pública em nossos servidores!</p>
<p>Confira <a title="Receber $ 25 em créditos na Digital Ocean + Bônus de $ 50" href="http://gabrielzuqueto.eti.br/cupom-de-25-em-creditos-na-digital-ocean/" target="_blank" rel="noopener">como receber $ 25 em créditos na Digital Ocean e caso seja um novo cadastro receberá um adicional de $ 50</a>, totalizando $ 75.</p>Gabriel Zuqueto AmaralNeste post iremos ver como aplicar segurança básica em servidores linux. Pormais que eu utilize a Digital Ocean e o CentOS, estas regras servem para qualquer *UNIXComo criar servidor na Digital Ocean2017-06-23T10:00:00-03:002017-06-23T10:00:00-03:00https://gabrielzuqueto.eti.br/como-criar-servidor-digital-ocean<p>Hoje vou mostrar como criar servidor na Digital Ocean de forma simples e direta. Seja para criar um <a href="https://gabrielzuqueto.eti.br/tag/servidor" title="Posts diversos sobre criação de servidores">servidor de jogo, e-mail, proxy ou até mesmo um LAMP para hospedar seu site</a>, o princípio da criação de servidor na Digital Ocean é o mesmo.</p>
<p>Na Digital Ocean, um servidor é chamado de Droplet que em português significa gotícula e faz total sentido uma vez que estamos em um Oceano Digital :P</p>
<p>Tenha em mente que servidor, VPS (Virtual Private Server), Instância, Cloud Server e Droplet, são a mesma coisa, no contexto de ter uma máquina virtual ligada na nuvem.</p>
<h2 id="primeiro-passo---login">Primeiro passo - Login</h2>
<p>Para criar seu primeiro servidor é necessário ter uma conta ativa na Digital Ocean. Caso ainda não tenha conta na <a href="https://m.do.co/c/9fe94b270974" title="Cadastre-se grátis e receba $100 de crédito.">Digital Ocean</a>, utilize este link para se registrar e ganhar $100 em créditos: <a href="https://m.do.co/c/9fe94b270974" title="Cadastre-se grátis e receba $100 de crédito.">https://m.do.co/c/9fe94b270974</a>. Após o cadastro, efetue login.</p>
<p>Assimq ue estiver logado, verá no canto superior direito um botão verde escrito <strong>Create</strong>, clique nele e um menu irá aparece, neste menu clique em <strong>Droplets</strong> para iniciar o guia de criação de um novo servidor.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-create-droplet.png" alt="Como criar servidor na Digital Ocean - Create Droplet" title="Como criar servidor na Digital Ocean - Create Droplet" /></p>
<h2 id="segundo-passo---escolha-a-distribuição-linux-do-seu-servidor">Segundo passo - Escolha a distribuição linux do seu servidor</h2>
<p>Agora você deve selecionar a distribuição linux que deseja instalar no seu servidor. Por padrão vem selecionado o Ubuntu, porém, o CentOS é uma cópia identica do Red Hat Enterprise, logo, seus servidores estaram utilizando uma distro Linux bem estável e segura.</p>
<p>Após selecionada a distribuição que você deseja utilizar, basta clicar na mesma e confirir que a sua caixa de seleção esteja azul, é isso que indica a correta seleção da distribuição.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-choose-an-image.png" alt="Como criar servidor na Digital Ocean - Choose an image" title="Como criar servidor na Digital Ocean - Choose an image" /></p>
<p>Você deve ter percebido a aba <strong>One-click apps</strong> nesta modalidade, a Digital Ocean já te entrega o servidor com a aplicação que você selecionou. Em um outro post entro mais a fundo nesta opção.</p>
<h2 id="terceiro-passo---escolha-o-tamanho-do-seu-servidor">Terceiro passo - Escolha o tamanho do seu servidor</h2>
<p>Neste passo, você vai decidir qual seráo tamanho do seu servidor em questão de memória RAM, CPU, Disco e banda. A Digital Ocean cobra por hora de uso, dessa forma você pode economizar bastante quando não estiver utilizando seu servidor, pois basta desligá-lo que a será encerrada a cobrança.</p>
<p>Dependendo da finalidade do seu servidor, o menor Droplet já é o suficiente. Isso é legal, pois se você se <a href="https://m.do.co/c/9fe94b270974" title="Cadastre-se grátis e receba $100 de crédito.">cadastrou pelo meu link</a>, recebeu $100 em créditos que equivale a mais de 16 meses (o preço atual do droplet é de $ 6 USD) de uso constante do seu servidor na Digital Ocean.</p>
<p>Para este post, selecionarei a menor instância da Digital Ocean.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-choose-a-size.png" alt="Como criar servidor na Digital Ocean - Choose a size" title="Como criar servidor na Digital Ocean - Choose a size" /></p>
<p>Mais abaixo você terá a opção de adicionar um disco a mais em seu servidor, porém, você pagará mais por isso. ara o servidor que estamos criando neste post, não vamos por nenhum disco a mais, porém seguem imagens de como funciona.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-block-storage.png" alt="Como criar servidor na Digital Ocean - Add block storage" title="Como criar servidor na Digital Ocean - Add block storage" /></p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-block-storage-2.png" alt="Como criar servidor na Digital Ocean - Add block storage" title="Como criar servidor na Digital Ocean - Add block storage" /></p>
<p>Caso tenha adicionado um block storage e queira remover, basta clicar no botão <strong>Remove Volume</strong>.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-block-storage-3.png" alt="Como criar servidor na Digital Ocean - Add block storage" title="Como criar servidor na Digital Ocean - Add block storage" /></p>
<h2 id="quarto-passo---escolha-a-região-do-datacenter-do-seu-servidor">Quarto passo - Escolha a região do datacenter do seu servidor</h2>
<p>Neste momento devemos escolher em qual datacenter o servidor irá ser criado. A Digital Ocean ainda não possui um datacenter aqui no Brasil, porém, das opções, a que mais fica próxima aqui é <strong>San Francisco</strong>, logo esta é a melhor opção caso você queira disponibilizar algum serviço para o público brasileiro.</p>
<p>A região, sempre deixo a cargo da Digital Ocean. Quase sempre vem com a <strong>região 2</strong> selecionada, porém você pode escolher outra se quiser.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-choose-datacenter-region.png" alt="Como criar servidor na Digital Ocean - Choose a datacenter region" title="Como criar servidor na Digital Ocean - Choose a datacenter region" /></p>
<h2 id="quinto-passo---escolha-as-opção-adicionais-do-seu-servidor">Quinto passo - Escolha as opção adicionais do seu servidor</h2>
<p>A Digital Ocean permite que você escolha algumas opções a mais para aplicar no seu servidor. Você pode escolher criar uma VPN (Virtual Private Network), habilitar IPv6, criar Backup (custará 20% no valor do Droplet), adicionar um monitoramento mais detalhado incluindo o envio de alertas por e-mail e até mesmo rodar um script na criação do seu servidor, selecionando a opção <strong>User data</strong>.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-select-additional-options.png" alt="Como criar servidor na Digital Ocean - Select additional options" title="Como criar servidor na Digital Ocean - Select additional options" /></p>
<p>Para o servidor deste post, não iremos selecionar nenhuma das opções.</p>
<h2 id="sexto-passo---adicionar-chave-ssh">Sexto passo - Adicionar chave SSH</h2>
<p>Ao adicionar sua chave pública ao servidor, você aumenta a segurança, uma vez que apenas quem contiver sua chave privada irá conseguir acessar seu servidor com o usuário <strong>root</strong>. <a href="https://gabrielzuqueto.eti.br/seguranca-servidores-nuvem-digital-ocean" title="Segurança de Servidores na nuvem">Neste outro post, abordo a questão de segurança básica em servidores</a>.</p>
<p>Para adicionar a sua chave pública, clique no botão <strong>New SSH Key</strong>, em seguida irá aparecer um formúlario contendo dois campos: <strong>SSH Key content</strong> e <strong>Name</strong>.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-ssh-keys.png" alt="Como criar servidor na Digital Ocean - Add your SSH Keys" title="Como criar servidor na Digital Ocean - Add your SSH Keys" /></p>
<p>Em <strong>SSH Key content</strong> você cola a sua chave pública e em <strong>Name</strong> você dá um apelido a ela.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-ssh-keys-2.png" alt="Como criar servidor na Digital Ocean - Add your SSH Keys" title="Como criar servidor na Digital Ocean - Add your SSH Keys" /></p>
<p>Com o formulário todo preenchido, o botão <strong>Add SSH Key</strong> ficará habilitado. Basta clicar nele e pronto, sua chave foi adicionada.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-ssh-keys-3.png" alt="Como criar servidor na Digital Ocean - Add your SSH Keys" title="Como criar servidor na Digital Ocean - Add your SSH Keys" /></p>
<p>Após o formulário fechar, você verá que a chave que adicionou está marcada.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-add-ssh-keys-4.png" alt="Como criar servidor na Digital Ocean - Add your SSH Keys" title="Como criar servidor na Digital Ocean - Add your SSH Keys" /></p>
<p>O legal é que fica salva na sua conta, logo, se precisar criar outro servidor depois, basta selecionar esta chave e já ficará configurado com ela.</p>
<p>Outra coisa, ao selecionar uma chave SSH, não será criada uma senha para o usuário <strong>root</strong>, logo, você não precisa aguardar o recebimento do e-mails da Digital Ocean, para acessar seu novo servidor.</p>
<h2 id="sétimo-passo---finalizar-a-criação">Sétimo passo - Finalizar a criação</h2>
<p>Neste passo, temos a opção de selecionar a quantidade de servidores (Droplets) que queremos criar com as configurações que fizemos. Além disso, temos a opção de dar nomes aos Droplets, caso selecione mais de um Droplet, você poderá alterar o nome dos demais também. Temos também aopção de por Tags para ajudar a indentificar melhor nossos servidores. Após configurar essas três coisas, clique no botão verde escrito <strong>Create</strong>.</p>
<p>Vou deixar apenas um servidor, com o nome padrão e sem tags.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-finalize-and-create.png" alt="Como criar servidor na Digital Ocean - Finalize and create" title="Como criar servidor na Digital Ocean - Finalize and create" /></p>
<p>Após você será redirecionado para a listagem de servidores (Droplets).</p>
<p>Note que ao lado do nome do seu servidor, tem uma barrinha azul.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-droplet-list.png" alt="Como criar servidor na Digital Ocean - Droplet list" title="Como criar servidor na Digital Ocean - Droplet list" /></p>
<p>Aguarde a barrinha chegar até o final e você estará pronto para acessar seu servidor.</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-droplet-list-2.png" alt="Como criar servidor na Digital Ocean - Droplet list" title="Como criar servidor na Digital Ocean - Droplet list" /></p>
<h2 id="oitavo-e-último-passo---acessar-seu-servidor">Oitavo e último passo - Acessar seu servidor</h2>
<p>Agora basta copiar o IP do seu servidor, abrir o temrinal e executar o seguinte comando:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@IP_DO_SEU_SERVIDOR
</code></pre></div></div>
<p>No caso deste post, o servidor tem o seguinte IP: 165.227.13.153, logo fica assim:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh root@165.227.13.153
</code></pre></div></div>
<p>Estamos conectados!</p>
<p><img src="assets/2017/06/como-criar-servidor-na-digital-ocean-droplet-access.png" alt="Como criar servidor na Digital Ocean - Droplet Access" title="Como criar servidor na Digital Ocean - Droplet Access" /></p>
<p>Chegamos ao final deste post! Qualquer dúvida, sugestão ou crítica, deixe nos comentários por favor. Muito obrigado pela sua atenção. Até a próxima! :)</p>Gabriel Zuqueto AmaralNeste post abordo como criar servidor na Digital Ocean. O mais legal é que você terá sua própria VPS.Abstrair AWS SQS no Ruby Parte 2: Criando testes automatizados2017-06-10T21:53:10-03:002017-06-10T21:53:10-03:00https://gabrielzuqueto.eti.br/aws-sqs-ruby-testes-automatizados<p>No <a title="Abstrair AWS SQS no Ruby" href="http://gabrielzuqueto.eti.br/abstrair-aws-sqs-no-ruby/" target="_blank" rel="noopener">post anterior escrevemos uma classe chamada QueueManager</a>, que é uma abstração do SDK da AWS para o SQS. Agora vamos ver como criar testes automatizados para a classe que criamos.</p>
<p>A primeira coisa que devemos fazer é alterar o arquivo <strong>spec_helper.rb</strong> para que consigamos criar os stubs para o AWS SQS. Além disso, devemos fazer o require tanto do <strong>aws-sdk</strong> quanto do <strong>queue_manager.rb</strong> para que os nossos testes automatizados funcionem.</p>
<p>Lembrando que estamos utilizando o <strong>Ruby 2.2.7</strong> e <strong>aws-sdk 2.9.11</strong>.</p>
<h2>Preparando o ambiente dos testes automatizados</h2>
<p>Dentro do diretório do nosso projeto, abra <strong>./spec/spec_helper.rb</strong> no seu editor de texto preferido e deixe o conteúdo da seguinte forma:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>require 'aws-sdk'
require 'queue_manager.rb'
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
expectations.syntax = [:should, :expect]
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
Aws.config.update(stub_responses: true)
end
</code></pre></div></div>
<p>Como foi dito logo no segundo parágrafo deste post, fizemos os requires necessários, após temos algumas configurações básicas do <strong>rspec</strong>, e na penúltima linha habilitamos o <strong>stub</strong> para o <strong>AWS SDK v2</strong>.</p>
<p>Feito isso, vamos para o próximo passo.</p>
<h2>Criando o esqueleto do arquivo dos testes automatizados</h2>
<p>Vamos começar criando o arquivo que conterá os testes. Para isso, dentro do diretório do projeto crie um arquivo com o nome de <strong>queue_manager_spec.rb</strong>, dentro do diretório <strong>spec</strong>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>touch spec/queue_manager_spec.rb
</code></pre></div></div>
<p>Abra o arquivo e ponha os seguintes comandos dentro dele e depois salve:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>require 'spec_helper.rb'
describe "QueueManager" do
let(:queue_url){"https://sqs.us-west-2.amazonaws.com/943154236803/gabrielzuqueto_eti_br"}
let(:queue_name){:gabrielzuqueto_eti_br}
let(:client_aws_sqs){Aws::SQS::Client.new}
before do
allow_any_instance_of(QueueManager).to receive(:client).and_return client_aws_sqs
end
end
</code></pre></div></div>
<p>Bem simples! Adicionamos o arquivo responsável pelas configurações globais dos nossos testes e depois iniciamos um bloco com a descrição do arquivo de teste. Na descrição botamos <strong>QueueManager</strong> para que fique claro que os testes sãopara esta classe.</p>
<p>Dentro criamos três métodos para nos auxiliar nos testes automatizados. O primeiro retorna a URL da fila, o segundo retorna o nome da fila e o terceiro retorna uma instância do client da AWS para SQS. Iremos utilizá-los nos stubs.</p>
<p>Por último dissemos para o teste que todas vez que o método client da classe QueueManager for chamado, ele irá retornar o client que iremos utilizar para configurar os stubs do SQS. Fizemos nosso primeiro stub!</p>
<p>Vamos aos testes!</p>
<h2>Primeiro e segundo teste automatizado</h2>
<p>Vamos testar a criação de uma instância da nossa classe e vamos verificar se os parâmetros que enviamos foram guardados nesta nova instância. Para isso faremos 2 testes, um com o valor default do parâmetro <strong>visibility_timeout</strong> e outro setando um novo valor para este argumento.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When try instance object" do
it "should return a new instance of QueueManager visibility_timeout=60" do
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.instance_eval{ queue_name } ).to eq(queue_name)
expect( queue_manager.instance_eval{ visibility_timeout } ).to eq(60)
end
it "with visibility_timeout arg equals 120 should return a new instance of QueueManager visibility_timeout=120" do
queue_manager = QueueManager.new(queue_name, 120)
expect( queue_manager.instance_eval{ queue_name } ).to eq(queue_name)
expect( queue_manager.instance_eval{ visibility_timeout } ).to eq(120)
end
end
</code></pre></div></div>
<p>Ponha este código antes do último end do arquivo, salve e vamos executar o teste para ver se está tudo Ok.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle exec rspec
</code></pre></div></div>
<p>Para a nossa surpresa, o primeiro teste quebrou!</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>F.
Failures:
1) QueueManager When try instance object should return a new instance of QueueManager visibility_timeout=60
Failure/Error:
def initialize(queue_name, visibility_timeout = 1.minutes)
@queue_name = queue_name
@visibility_timeout = visibility_timeout
end
NoMethodError:
undefined method `minutes' for 1:Fixnum
# ./lib/queue_manager.rb:2:in `initialize'
# ./spec/queue_manager_spec.rb:13:in `new'
# ./spec/queue_manager_spec.rb:13:in `block (3 levels) in <top (required)>'
Finished in 0.14077 seconds (files took 0.14085 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/queue_manager_spec.rb:12 # QueueManager When try instance object should return a new instance of QueueManager visibility_timeout=60
</code></pre></div></div>
<p>Isso aconteceu pois utilizamos o método <strong>minutes</strong> no valor default do<strong> visibility_timeout</strong>, no método <strong>initialize</strong> da class <strong>QueueManager</strong>. O problema é que o <strong>Rails</strong> é quem provê este método e nós estamos <strong>Ruby puro</strong>.</p>
<p>Reparou o quanto é importante ter testes automatizados? Se não fosse por ele, este código provavelmente iria para produção e quebraria a aplicação.</p>
<p>Vamos corrigir a classe QueueManager!</p>
<p>Abra <strong>lib/queue_manager.rb</strong> em seu editor de texto e na linha 2 altere <strong>visibility_timeout = 1.minutes</strong> por <strong>visibility_timeout = 60</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class QueueManager
def initialize(queue_name, visibility_timeout = 60)
@queue_name = queue_name
@visibility_timeout = visibility_timeout
end
...
</code></pre></div></div>
<p>Pronto! Salve o arquivo e execute os testes novamente.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>..
Finished in 0.15856 seconds (files took 0.1605 seconds to load)
2 examples, 0 failures
</code></pre></div></div>
<p>Corrigimos o bug! :D</p>
<h2>Terceiro teste automatizado</h2>
<p>Vamos testar o método <strong>client</strong> da classe <strong>QueueManager</strong>. Este método deve retornar uma instância da classe <strong>Aws::SQS::Client</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call client method" do
it "should return a instance of Aws::SQS::Client" do
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.instance_eval{ client } ).to be_instance_of(Aws::SQS::Client)
end
end
</code></pre></div></div>
<p>Adicione estas linhas antes do último <strong>end</strong> do nosso arquivo de teste, salve o arquivo e execute os testes.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
Finished in 0.13722 seconds (files took 0.14355 seconds to load)
3 examples, 0 failures
</code></pre></div></div>
<p>Tudo certo, vamos para o quarto teste.</p>
<h2>Quarto teste automatizado</h2>
<p>Vamos agora criar o teste para o método privador <strong>create_queue</strong> da classe <strong>QueueManager</strong>. Adicione estas linhas antes do último <strong>end</strong> do nosso arquivo de testes automatizados:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call create_queue method" do
it "should return the queue url" do
client_aws_sqs.stub_responses(:create_queue, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.instance_eval{ create_queue } ).to eq(queue_url)
end
end
</code></pre></div></div>
<p>Básicamente estamos criando um stub para o método <strong>create_queue</strong> da classe <strong>Aws::SQS::Client</strong>. Logo, se tudo estiver certo, ao chamar o <strong>create_queue</strong> da classe <strong>QueueManager</strong>, será retornada a URL da fila como esperamos. Salve o arquivo e execute os testes.</p>
<p>Mais uma vez, quebrou! O motivo é o mesmo: Utilizamos métodos providos pelo <strong>Rails</strong> em um projeto de <strong>Ruby puro</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...F
Failures:
1) QueueManager When create queue should return the queue url
Failure/Error: client.create_queue({queue_name: queue_name},{:http_open_timeout => 1.hours, :http_read_timeout => 1.hours, :logger => nil, :visibility_timeout => 1.minutes}).queue_url
NoMethodError:
undefined method `hours' for 1:Fixnum
# ./lib/queue_manager.rb:90:in `create_queue'
# ./spec/queue_manager_spec.rb:36:in `block (4 levels) in <top (required)>'
# ./spec/queue_manager_spec.rb:36:in `instance_eval'
# ./spec/queue_manager_spec.rb:36:in `block (3 levels) in <top (required)>'
Finished in 0.18209 seconds (files took 0.16784 seconds to load)
3 examples, 1 failure
Failed examples:
rspec ./spec/queue_manager_spec.rb:33 # QueueManager When create queue should return the queue url
</code></pre></div></div>
<p>Vamos corrigir!</p>
<p>Abra <strong>lib/queue_manager.rb</strong> em seu editor de texto e na linha 90 altere:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>client.create_queue({queue_name: queue_name},{:http_open_timeout => 1.hours, :http_read_timeout => 1.hours, :logger => nil, :visibility_timeout => 1.minutes}).queue_url
</code></pre></div></div>
<p>Por:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>client.create_queue({queue_name: queue_name},{:http_open_timeout => 3600, :http_read_timeout => 3600, :logger => nil, :visibility_timeout => 60}).queue_url
</code></pre></div></div>
<p>Salve o arquivo e rode os testes novamente.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>....
Finished in 0.22548 seconds (files took 0.14047 seconds to load)
4 examples, 0 failures
</code></pre></div></div>
<p>Mais um bug corrigido! Provavelmente teremos mais.</p>
<h2>Quinto e sexto teste automatizado</h2>
<p>Agora vamos criar os testes para o método <strong>get_queue_url</strong> da classe <strong>QueueManager</strong>. Precisamos de 2 testes, pois ele pergunta ao SQS a URL de fila e caso amesma não exista, ele a cria. logo, são 2 comportamentos que devemos testar.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call get_queue_url method" do
it "should return the queue url" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.instance_eval{ get_queue_url } ).to eq(queue_url)
end
it "if queue not exists should create queue and return your URL" do
client_aws_sqs.stub_responses(:get_queue_url, 'NonExistentQueue')
client_aws_sqs.stub_responses(:create_queue, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.instance_eval{ get_queue_url } ).to eq(queue_url)
end
end
</code></pre></div></div>
<p>No primeiro teste é como se a fila já existisse, logo ele retorna a URL de cara.</p>
<p>No segundo a gente criar o <strong>stub</strong> de erro de fila não existente para o método <strong>get_queue_url</strong> do <strong>Aws::SQS::Client</strong> e após a gente cria o <strong>stub</strong> de fila criada para o método <strong>create_queue</strong> da mesma classe dita anteriormente. Após a gente testa se a URL da fila foi retornada, assim garantindo que o método <strong>get_queue_url</strong> da classe <strong>QueueManager</strong> está funcionando!</p>
<p>Execute novamente os testes.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>......
Finished in 0.23801 seconds (files took 0.14207 seconds to load)
6 examples, 0 failures
</code></pre></div></div>
<p>Tudo correto, vamos para o próximo!</p>
<h2>Sétimo teste automatizado</h2>
<p>Agora iremos testar o método <strong>queue_url</strong> da classe <strong>QueueManager</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call queue_url method" do
it "should return the queue url" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.instance_eval{ queue_url } ).to eq(queue_url)
end
end
</code></pre></div></div>
<p>Mais uma vez adicione estas linhas antes do último <strong>end</strong> do nosso arquivo de teste, salve e execute os testes.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.......
Finished in 0.24331 seconds (files took 0.13894 seconds to load)
7 examples, 0 failures
</code></pre></div></div>
<p>Tudo certo! Próximo!</p>
<p>Agora que todos os métodos privados foram testados e o método público initialize também, iremos começar a testar os outros métodos públicos. Sim, todos os métodos privados foram testados, pois <strong>visibility_timeout</strong> e <strong>queue_name</strong> da classe <strong>QueueManager</strong> foram testados logo no primeiro teste.</p>
<h2>Oitavo teste automatizado</h2>
<p>Vamos testar o método send_message da classe QueueManager. Vamos verificar apenas se não houve erro ao chamar o método.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call send_message method" do
it "should not return error" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect { queue_manager.send_message("Something") }.to_not raise_error
end
end
</code></pre></div></div>
<p>Adicione estas linhas no arquivo de teste como fez com os outros, salve e execute os testes.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.......F
Failures:
1) QueueManager When call send_message method should not return error
Failure/Error: expect { queue_manager.send_message("Something") }.to_not raise_error
expected no Exception, got #<NameError: undefined local variable or method `data' for #<QueueManager:0x007f7d0c8bac00>> with backtrace:
# ./lib/queue_manager.rb:8:in `send_message'
# ./spec/queue_manager_spec.rb:67:in `block (4 levels) in <top (required)>'
# ./spec/queue_manager_spec.rb:67:in `block (3 levels) in <top (required)>'
# ./spec/queue_manager_spec.rb:67:in `block (3 levels) in <top (required)>'
Finished in 0.26467 seconds (files took 0.14186 seconds to load)
8 examples, 1 failure
Failed examples:
rspec ./spec/queue_manager_spec.rb:64 # QueueManager When call send_message method should not return error
</code></pre></div></div>
<p>Mais um bug! Em <strong>lib/queue_manager.rb:8</strong>, estamos tentando enviar o conteúdo da variável <strong>data</strong>, porém esta variável não existe. Altere para <strong>message_data</strong>, salve o arquivo.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class QueueManager
def initialize(queue_name, visibility_timeout = 60)
@queue_name = queue_name
@visibility_timeout = visibility_timeout
end
def send_message(message_data)
client.send_message({queue_url: queue_url, message_body: message_data })
end
...
</code></pre></div></div>
<p>Execute os testes e vamos em frente!</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>........
Finished in 0.24677 seconds (files took 0.14044 seconds to load)
8 examples, 0 failures
</code></pre></div></div>
<h2>Nono e décimo teste automatizado</h2>
<p>Vamos criar dois testes para o método <strong>receive_message</strong> da classe <strong>QueueManager</strong>: um para o caso de não existir mensagens na fila e o outro caso exista.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call receive_message method" do
before do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
end
it "and there is no message should return response with messages array empty" do
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.receive_message.messages.count ).to eq(0)
end
it "should return not empty message array" do
client_aws_sqs.stub_responses(:receive_message, messages: [
message_id: "Something",
receipt_handle: "Something",
body: {Something: "Something"}.to_json
])
expected_message = [Aws::SQS::Types::Message.new(message_id: "Something", receipt_handle: "Something", body: {"Something"=>"Something"}.to_json, attributes: {}, message_attributes: {})]
queue_manager = QueueManager.new(queue_name)
expect(queue_manager.receive_message.messages).to eq(expected_message)
end
end
</code></pre></div></div>
<p>Adicione ao seu arquivo de teste, salve e execute os <strong>testes automatizados</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>..........
Finished in 0.26132 seconds (files took 0.14142 seconds to load)
10 examples, 0 failures
</code></pre></div></div>
<h2>Décimo primeiro teste automatizado</h2>
<p>Vamos testar o método <strong>delete_message</strong> da classe <strong>QueueManager</strong>. Como no método <strong>send_message</strong>, iremos apenas testar se não ocorreu erro ao chamar o método do <strong>delete_message</strong> da classe <strong>Aws::SQS::Client</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call delete_message method" do
it "should not return error" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect { queue_manager.delete_message("Something") }.to_not raise_error
end
end
</code></pre></div></div>
<p>Já sabemos o que fazer a cada teste novo…</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...........
Finished in 0.26799 seconds (files took 0.1416 seconds to load)
11 examples, 0 failures
</code></pre></div></div>
<p>Tudo Ok! Próximo! :D</p>
<h2>Décimo segundo teste automatizado</h2>
<p>Vamos agora testar o método <strong>send_message_batch</strong> da classe <strong>QueueManager</strong>. O teste será parecido com os outros 2 anteriores.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call send_message_batch method" do
it "should not return error" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect { queue_manager.send_message_batch([{id: "1", message_body: "Something"},{id: "2", message_body: "Anything"}]) }.to_not raise_error
end
end
</code></pre></div></div>
<p>Note que é obrigatório enviar um ID no JSON da mensagem. Veja mais detalhes na <a title="Documentação Oficial SDK AWS v2" href="http://docs.aws.amazon.com/sdkforruby/api/Aws/SQS/Client.html#send_message_batch-instance_method" target="_blank" rel="noopener">documentação oficial do SDK AWS v2</a>.</p>
<p>Executando todos os testes temos:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>............
Finished in 0.50623 seconds (files took 0.21058 seconds to load)
12 examples, 0 failures
</code></pre></div></div>
<p>Perfeito!</p>
<h2>Décimo terceiro teste automatizado</h2>
<p>Agora vamos criar o teste do método <strong>receive_message_batch</strong> da classe <strong>QueueManager</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call receive_message_batch method" do
it "should return messages array" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
client_aws_sqs.stub_responses(:receive_message, messages: [
{message_id: "Something",
receipt_handle: "Something",
body: {Something: "Something"}.to_json},
{message_id: "Something_2",
receipt_handle: "Something_2",
body: {Something: "Something_2"}.to_json}
])
expected_message = [
Aws::SQS::Types::Message.new(message_id: "Something", receipt_handle: "Something", body: {"Something"=>"Something"}.to_json, attributes: {}, message_attributes: {}),
Aws::SQS::Types::Message.new(message_id: "Something_2", receipt_handle: "Something_2", body: {"Something"=>"Something_2"}.to_json, attributes: {}, message_attributes: {})
]
queue_manager = QueueManager.new(queue_name)
expect(queue_manager.receive_message_batch.messages).to eq(expected_message)
end
end
</code></pre></div></div>
<p>Ao executar os testes, teremos o seguinte resultado:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.............
Finished in 0.56844 seconds (files took 0.20844 seconds to load)
13 examples, 0 failures
</code></pre></div></div>
<h2>Décimo quarto teste automatizado</h2>
<p>Agora vamos testar a exclusão por batch. Para isso, vamos criar um teste para o método <strong>delete_message_batch</strong> da classe <strong>QueueManager</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call delete_message_batch method" do
it "should return messages array" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect { queue_manager.delete_message_batch([{id: "Something", receipt_handle: "Something"}]) }.to_not raise_error
end
end
</code></pre></div></div>
<p>Mais uma vez, vamos rodar novamente os teste.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>..............
Finished in 0.51683 seconds (files took 0.20637 seconds to load)
14 examples, 0 failures
</code></pre></div></div>
<h2>Décimo quinto teste automatizado</h2>
<p>Vamos criar o teste para o método <strong>purge_queue</strong> da classe <strong>QueueManager</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call purge_queue method" do
it "should return messages array" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect { queue_manager.purge_queue }.to_not raise_error
end
end
</code></pre></div></div>
<p>Ao executar novamente o arquivo de testes automatizados, temos:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...............
Finished in 0.51229 seconds (files took 0.23809 seconds to load)
15 examples, 0 failures
</code></pre></div></div>
<h2>Décimo sexto teste automatizado</h2>
<p>Estamos quase terminando a criação dos testes automatizados. Vamos criar o teste para o método <strong>delete_queue</strong> da classe <strong>QueueManager</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call delete_queue method" do
it "should return messages array" do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
queue_manager = QueueManager.new(queue_name)
expect { queue_manager.delete_queue }.to_not raise_error
expect( queue_manager.instance_eval{ @queue_url } ).to eq(nil)
end
end
</code></pre></div></div>
<p>Neste teste verificamos também a variável <strong>@queue_url</strong>, pois sabemos que ao excluir a fila, a gente seta esta variável com nulo.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>................
Finished in 0.54293 seconds (files took 0.19049 seconds to load)
16 examples, 0 failures
</code></pre></div></div>
<h2>Décimo sétimo, Décimo oitavo, Décimo novo e Vigésimo teste automatizado</h2>
<p>Vamos criar os testes que retornam a quantidade de mensagens na fila.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call " do
before do
client_aws_sqs.stub_responses(:get_queue_url, queue_url: queue_url)
client_aws_sqs.stub_responses(:get_queue_attributes, attributes: {
"ApproximateNumberOfMessages" => "1",
"ApproximateNumberOfMessagesNotVisible" => "1",
"ApproximateNumberOfMessagesDelayed" => "1"
})
end
it "queue_size method should return queue size" do
queue_manager = QueueManager.new(queue_name)
expect(queue_manager.queue_size).to eq(3)
end
it "queue_available_size method should return queue available size" do
queue_manager = QueueManager.new(queue_name)
expect(queue_manager.queue_available_size).to eq(1)
end
it "queue_unavailable_size method should return queue unavailable size" do
queue_manager = QueueManager.new(queue_name)
expect(queue_manager.queue_unavailable_size).to eq(1)
end
it "queue_waiting_size method should return queue waiting size" do
queue_manager = QueueManager.new(queue_name)
expect(queue_manager.queue_waiting_size).to eq(1)
end
end
</code></pre></div></div>
<p>A diferença neste teste é que criamos o stub para o método <strong>get_queue_attributes</strong> da classe <strong>Aws::SQS::Client</strong>.</p>
<p>Vamos executar os testes :)</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>....................
Finished in 0.58918 seconds (files took 0.20795 seconds to load)
20 examples, 0 failures
</code></pre></div></div>
<p>Tudo Ok. Agora vamos para o último teste da nossa classe.</p>
<h2>Vigésimo primeiro e último teste automatizado</h2>
<p>Este teste é bem simples. Verificamos apenas se o método <strong>poller</strong> da classe <strong>QueueManager</strong> retorna uma instância da classe <strong>Aws::SQS::QueuePoller</strong>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> describe "When call poller method" do
it "should return a instance of Aws::SQS::QueuePoller" do
queue_manager = QueueManager.new(queue_name)
expect( queue_manager.poller ).to be_instance_of(Aws::SQS::QueuePoller)
end
end
</code></pre></div></div>
<p>Rodando o teste, temos:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.....................
Finished in 0.53894 seconds (files took 0.2233 seconds to load)
21 examples, 0 failures
</code></pre></div></div>
<p> </p>
<p>Chegamos ao final deste post! Conseguimos cobrir 100% da nossa classe <strong>QueueManager</strong> por testes automatizados.</p>
<p>Pudemos ver na prática, como testes automatizados são importantes em um projeto. Encontramos bugs apenas rodando os testes.</p>
<p>Baixe o código-fonte: <a href="https://github.com/gabrielzuqueto/queue_manager_aws_sdk_v2_sqs_ruby" target="_blank" rel="noopener noreferrer">https://github.com/gabrielzuqueto/queue_manager_aws_sdk_v2_sqs_ruby</a></p>
<p><a href="http://gabrielzuqueto.eti.br/abstrair-aws-sqs-no-ruby/" target="_blank" rel="noopener">Confira aqui mais detalhes sobre como utilizar o Aws::SQS::QueuePoller</a></p>Gabriel Zuqueto AmaralEste post é a segunda parte do post Abstrair AWS SQS no Ruby. Nele mostro como criar testes automatizados para a classe que criamos (QueueManager)