Criando um ambiente de desenvolvimento com Nix
Tags: nix, flakes, environment, portuguese
Published: 2022-07-09 06:50:15

---
title: Criando um ambiente de desenvolvimento com Nix
published: true
description: Vamos descobrir como podemos criar um ambiente reprodutível de forma simples e rápida com Nix
tags: nix, flakes, environment, portuguese
cover_image: https://cdn.pixabay.com/photo/2015/12/04/14/05/code-1076536_1280.jpg
# Use a ratio of 100:42 for best results.
series: Nix
---

## O que é nix?

Se você não sabe o que é Nix, eu escrevi um [artigo sobre como usá-lo como um gerenciador de pacotes](https://dev.to/dmass/o-que-e-nix-e-como-utiliza-lo-como-seu-gerenciador-de-pacotes-2dcb) onde eu falo sobre o que é Nix.

Para continuar a leitura desse artigo, eu recomendo que você leia o outro, pois vamos utilizar alguns conceitos explicados lá.

## Preparação

Nesse artigo, vamos usar o *flakes*, assim como no artigo passado.

Se você usa o Nix como seu gerenciador de pacotes, da forma que expliquei no outro artigo, você pode pular para a próxima seção.

Caso contrário, você precisa habilitar o uso do *flakes* pelo Nix. Para isso, basta criar o arquivo `~/.config/nix/nix.conf` com o conteúdo:

`experimental-features = nix-command flakes`

Isso diz ao Nix para habilitar o *flakes* sem precisar passar uma *flag*.

Agora, vamos em frente!

## O que é um ambiente de desenvolvimento?

Um ambiente de desenvolvimento é um "ambiente" onde todas as ferramentas necessárias para desenvolver um projeto estão disponíveis.

Com o Nix, conseguimos utilizar pacotes sem instalá-los no nosso sistema, através de um arquivo declarativo.

Ou seja, conseguimos criar um arquivo com todos os pacotes que queremos e o Nix se encarrega de disponibilizá-los temporariamente para nós.

Isso é ótimo, pois, além de não precisarmos instalar ferramentas na nossa máquina para projetos específicos, se subirmos esse arquivo para o repositório do projeto, toda a equipe pode ter o mesmo ambiente sem precisar instalar nada (além do Nix, é claro)!

## Criando seu ambiente

O que vamos fazer para criar um ambiente é, na verdade, bem parecido com o que você viu no outro artigo.

Vamos supor que eu quero fazer uns exercícios de Rust no [Exercism](https://exercism.org/), mas não quero instalar nada de Rust na minha máquina, nem quero instalar o exercism.

Vou começar criando uma pasta `Exercism` na minha pasta *HOME*:

```sh
mkdir Exercism
```

Dentro dessa pasta, vou criar um arquivo `flake.nix` com o conteúdo:

```nix
{
  description = "Ambiente para exercícios de Rust";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs { inherit system; };
      in {
        devShell = with pkgs; mkShell {
          packages = [
            exercism
            cargo
            libiconv
          ];
        };
      }
    );
}
```

Começamos definindo o campo `description` com uma descrição do que se trata esse arquivo.

Depois definimos nossas dependências no campo `inputs`, que são:
1. O repositório do *nixpkgs*
2. Um utilitário chamado *flake-utils*, que vamos utilizar para criar um ambiente que suporte várias plataformas

No `outputs` chamamos a função `eachDefaultSystem` do *flake-utils*. Essa função recebe um *callback* onde recebemos o `system`. O que essa função faz é chamar esse *callback* para todas as plataformas que o Nix suporta (Linux, Mac e Windows) passando o `system` desta plataforma.

Nós definimos a variável `pkgs` com o valor resultante do `nixpkgs` configurado com o `system` que recebemos. Assim, os pacotes instalados serão da plataforma correta.

Por fim, definimos o campo `devShell`, que se refere ao *shell* que vamos criar, o valor vai ser o retorno da função `mkShell`. Nós passamos para essa função um `set` com um único campo `packages`, que é a lista de pacotes que queremos disponíveis no nosso *shell*.

No nosso caso, vamos precisar de 3 pacotes, o `exercism` que vai servir para baixar os exercícios e enviar o resultado, o `cargo` para rodar os testes em *Rust* e o `libiconv` que é necessário para o `cargo` rodar.

Agora, vamos rodar o comando:

```sh
nix develop
```

E é aqui que a mágica acontece!

O Nix vai baixar os pacotes e torná-los disponíveis para a gente em um *shell*.

```sh
exercism version
> exercism version 3.0.13

cargo -V
> cargo 1.61.0
```

Isso significa que eu posso baixar um exercício executando, por exemplo:

```sh
exercism download --exercise=reverse-string --track=rust
```

E ele vai criar a pasta `rust/reverse-string` dentro da pasta `Exercism` que estamos.

Eu posso ir até essa pasta e rodar os testes usando o `cargo`:

```sh
cd rust/reverse-string
cargo test
```

Quando eu terminar, é só eu sair do *shell* com `exit` e os pacotes que estavam disponíveis não estão mais.

```sh
exercism version             
> zsh: command not found: exercism

cargo -V   
> zsh: command not found: cargo
```

Sistema limpo! ✨

## Conclusão

Esse foi um exemplo bem bobo, mas deu para ter um gosto do que é capaz de fazer.

Você pode colocar qualquer ferramenta, como formatadores de código, *language-servers* etc.

No final, você vai ter o seu arquivo `flake.nix` e outro arquivo, criado pelo Nix, chamado `flake.lock`, esse último contém a versão de todos os pacotes baixados, assim, sempre que você ou uma pessoa da sua equipe rodar o `nix develop`, o ambiente vai ser o mesmo até na versão dos pacotes utilizados.

Espero que esse artigo tenha sido útil!

Boa sorte criando seus ambientes!

Até a próxima! 👋