One place for hosting & domains

      Objeto

      SOLID: os primeiros 5 princípios do design orientado a objeto


      Introdução

      SOLID é uma sigla para os primeiros cinco princípios do design orientado a objeto (OOD) criada por Robert C. Martin (também conhecido como Uncle Bob).

      Nota: embora esses princípios sejam aplicáveis a várias linguagens de programação, o código de amostra contido neste artigo usará o PHP.

      Esses princípios estabelecem práticas que contribuem para o desenvolvimento de software com considerações de manutenção e extensão à medida que o projeto cresce. A adoção dessas práticas também pode contribuir para evitar problemas de código, refatoração de código e o desenvolvimento ágil e adaptativo de software.

      SOLID significa:

      Neste artigo, cada princípio será apresentado individualmente para que você compreenda como o SOLID pode ajudá-lo(a) a melhorar como desenvolvedor(a).

      Princípio da responsabilidade única

      O Princípio da responsabilidade única (SRP) declara:

      Uma classe deve ter um e apenas um motivo para mudar, o que significa que uma classe deve ter apenas uma função.

      Por exemplo, considere um aplicativo que recebe uma coleção de formas — círculos e quadrados — e calcula a soma da área de todas as formas na coleção.

      Primeiramente, crie as classes de formas e faça com que os construtores configurem os parâmetros necessários.

      Para quadrados, será necessário saber o length (comprimento) de um lado:

      class Square
      {
          public $length;
      
          public function construct($length)
          {
              $this->length = $length;
          }
      }
      

      Para os círculos, será necessário saber o radius (raio):

      class Circle
      {
          public $radius;
      
          public function construct($radius)
          {
              $this->radius = $radius;
          }
      }
      

      Em seguida, crie a classe AreaCalculator e então escreva a lógica para somar as áreas de todas as formas fornecidas. A área de um quadrado é calculada pelo quadrado do comprimento. A área de um círculo é calculada por pi multiplicado pelo quadrado do raio.

      class AreaCalculator
      {
          protected $shapes;
      
          public function __construct($shapes = [])
          {
              $this->shapes = $shapes;
          }
      
          public function sum()
          {
              foreach ($this->shapes as $shape) {
                  if (is_a($shape, 'Square')) {
                      $area[] = pow($shape->length, 2);
                  } elseif (is_a($shape, 'Circle')) {
                      $area[] = pi() * pow($shape->radius, 2);
                  }
              }
      
              return array_sum($area);
          }
      
          public function output()
          {
              return implode('', [
                '',
                    'Sum of the areas of provided shapes: ',
                    $this->sum(),
                '',
            ]);
          }
      }
      

      Para usar a classe AreaCalculator, será necessário criar uma instância da classe, passar uma matriz de formas e exibir o resultado no final da página.

      Aqui está um exemplo com uma coleção de três formas:

      • um círculo com um raio de 2
      • um quadrado com um comprimento de 5
      • um segundo quadrado com um comprimento de 6
      $shapes = [
        new Circle(2),
        new Square(5),
        new Square(6),
      ];
      
      $areas = new AreaCalculator($shapes);
      
      echo $areas->output();
      

      O problema com o método de saída é que o AreaCalculator manuseia a lógica para gerar os dados.

      Considere um cenário onde o resultado deve ser convertido em outro formato, como o JSON.

      Toda a lógica seria manuseada pela classe AreaCalculator. Isso violaria o princípio da responsabilidade única. A classe AreaCalculator deve estar preocupada somente com a soma das áreas das formas fornecidas. Ela não deve se importar se o usuário quer JSON ou HTML.

      Para resolver isso, crie uma classe separada chamada SumCalculatorOutputter e use essa nova classe para lidar com a lógica necessária para gerar os dados para o usuário:

      class SumCalculatorOutputter
      {
          protected $calculator;
      
          public function __constructor(AreaCalculator $calculator)
          {
              $this->calculator = $calculator;
          }
      
          public function JSON()
          {
              $data = [
                'sum' => $this->calculator->sum(),
            ];
      
              return json_encode($data);
          }
      
          public function HTML()
          {
              return implode('', [
                '',
                    'Sum of the areas of provided shapes: ',
                    $this->calculator->sum(),
                '',
            ]);
          }
      }
      

      A classe SumCalculatorOutputter funcionaria da seguinte forma:

      $shapes = [
        new Circle(2),
        new Square(5),
        new Square(6),
      ];
      
      $areas = new AreaCalculator($shapes);
      $output = new SumCalculatorOutputter($areas);
      
      echo $output->JSON();
      echo $output->HTML();
      

      Agora, a lógica necessária para gerar os dados para o usuário é manuseada pela classe SumCalculatorOutputter.

      Isso satisfaz o princípio da responsabilidade única.

      Princípio do aberto-fechado

      O Princípio do aberto-fechado (S.R.P.) declara:

      Os objetos ou entidades devem estar abertos para extensão, mas fechados para modificação.

      Isso significa que uma classe deve ser extensível sem que seja modificada.

      Vamos revisitar a classe AreaCalculator e focar no método sum(soma):

      class AreaCalculator
      {
          protected $shapes;
      
          public function __construct($shapes = [])
          {
              $this->shapes = $shapes;
          }
      
          public function sum()
          {
              foreach ($this->shapes as $shape) {
                  if (is_a($shape, 'Square')) {
                      $area[] = pow($shape->length, 2);
                  } elseif (is_a($shape, 'Circle')) {
                      $area[] = pi() * pow($shape->radius, 2);
                  }
              }
      
              return array_sum($area);
          }
      }
      

      Considere um cenário onde o usuário deseja a sum de formas adicionais, como triângulos, pentágonos, hexágonos, etc. Seria necessário editar constantemente este arquivo e adicionar mais blocos de if/else. Isso violaria o princípio do aberto-fechado.

      Uma maneira de tornar esse método sum melhor é remover a lógica para calcular a área de cada forma do método da classe AreaCalculator e anexá-la à classe de cada forma.

      Aqui está o método area definido em Square:

      class Square
      {
          public $length;
      
          public function __construct($length)
          {
              $this->length = $length;
          }
      
          public function area()
          {
              return pow($this->length, 2);
          }
      }
      

      E aqui está o método area definido em Circle:

      class Circle
      {
          public $radius;
      
          public function construct($radius)
          {
              $this->radius = $radius;
          }
      
          public function area()
          {
              return pi() * pow($shape->radius, 2);
          }
      }
      

      O método sum para AreaCalculator pode então ser reescrito como:

      class AreaCalculator
      {
          // ...
      
          public function sum()
          {
              foreach ($this->shapes as $shape) {
                  $area[] = $shape->area();
              }
      
              return array_sum($area);
          }
      }
      

      Agora, é possível criar outra classe de formas e a passar ao calcular a soma sem quebrar o código.

      No entanto, outro problema surge. Como saber que o objeto passado para o AreaCalculator é na verdade uma forma ou se a forma possui um método chamado area?

      Programar em uma interface é uma parte integral do SOLID.

      Crie uma ShapeInterface que suporte area:

      interface ShapeInterface
      {
          public function area();
      }
      

      Modifique suas classes de formas para implement (implementar) a ShapeInterface.

      Aqui está a atualização para Square:

      class Square implements ShapeInterface
      {
          // ...
      }
      

      E aqui está a atualização para Circle:

      class Circle implements ShapeInterface
      {
          // ...
      }
      

      No método sum para AreaCalculator, verifique se as formas fornecidas são na verdade instâncias de ShapeInterface; caso contrário, lance uma exceção:

       class AreaCalculator
      {
          // ...
      
          public function sum()
          {
              foreach ($this->shapes as $shape) {
                  if (is_a($shape, 'ShapeInterface')) {
                      $area[] = $shape->area();
                      continue;
                  }
      
                  throw new AreaCalculatorInvalidShapeException();
              }
      
              return array_sum($area);
          }
      }
      

      Isso satisfaz o princípio do aberto-fechado.

      Princípio da substituição de Liskov

      O Princípio da substituição de Liskov declara:

      Seja q(x) uma propriedade demonstrável sobre objetos de x do tipo T. Então q(y) deve ser demonstrável para objetos y do tipo S onde S é um subtipo de T.

      Isso significa que cada subclasse ou classe derivada deve ser substituível pela classe sua classe base ou pai.

      Analisando novamente a classe de exemplo AreaCalculator, considere uma nova classe VolumeCalculator que estende a classe AreaCalculator:

      class VolumeCalculator extends AreaCalculator
      {
          public function construct($shapes = [])
          {
              parent::construct($shapes);
          }
      
          public function sum()
          {
              // logic to calculate the volumes and then return an array of output
              return [$summedData];
          }
      }
      

      Lembre-se que a classe SumCalculatorOutputter se assemelha a isto:

      class SumCalculatorOutputter {
          protected $calculator;
      
          public function __constructor(AreaCalculator $calculator) {
              $this->calculator = $calculator;
          }
      
          public function JSON() {
              $data = array(
                  'sum' => $this->calculator->sum();
              );
      
              return json_encode($data);
          }
      
          public function HTML() {
              return implode('', array(
                  '',
                      'Sum of the areas of provided shapes: ',
                      $this->calculator->sum(),
                  ''
              ));
          }
      }
      

      Se você tentar executar um exemplo como este:

      $areas = new AreaCalculator($shapes);
      $volumes = new VolumeCalculator($solidShapes);
      
      $output = new SumCalculatorOutputter($areas);
      $output2 = new SumCalculatorOutputter($volumes);
      

      Quando chamar o método HTML no objeto $output2, você irá obter um erro E_NOTICE informando uma conversão de matriz em string.

      Para corrigir isso, em vez de retornar uma matriz do método de soma de classe VolumeCalculator, retorne $summedData:

      class VolumeCalculator extends AreaCalculator
      {
          public function construct($shapes = [])
          {
              parent::construct($shapes);
          }
      
          public function sum()
          {
              // logic to calculate the volumes and then return a value of output
              return $summedData;
          }
      }
      

      O $summedData pode ser um float, duplo ou inteiro.

      Isso satisfaz o princípio da substituição de Liskov.

      Princípio da segregação de interfaces

      O Princípio da segregação de interfaces declara:

      Um cliente nunca deve ser forçado a implementar uma interface que ele não usa, ou os clientes não devem ser forçados a depender de métodos que não usam.

      Ainda utilizando o exemplo anterior do ShapeInterface, você precisará suportar as novas formas tridimensionais Cuboid e Spheroid, e essas formas também precisarão ter o volume calculado.

      Vamos considerar o que aconteceria se você modificasse a ShapeInterface para adicionar outro contrato:

      interface ShapeInterface
      {
          public function area();
      
          public function volume();
      }
      

      Agora, qualquer forma criada deve implementar o método volume, mas você sabe que os quadrados são formas planas que não têm volume, de modo que essa interface forçaria a classe Square a implementar um método sem utilidade para ela.

      Isso violaria o princípio da segregação de interfaces. Ao invés disso, você poderia criar outra interface chamada ThreeDimensionalShapeInterface que possui o contrato volume e as formas tridimensionais poderiam implementar essa interface:

      interface ShapeInterface
      {
          public function area();
      }
      
      interface ThreeDimensionalShapeInterface
      {
          public function volume();
      }
      
      class Cuboid implements ShapeInterface, ThreeDimensionalShapeInterface
      {
          public function area()
          {
              // calculate the surface area of the cuboid
          }
      
          public function volume()
          {
              // calculate the volume of the cuboid
          }
      }
      

      Essa é uma abordagem muito mais vantajosa, mas uma armadilha a ser observada é quando sugerir o tipo dessas interfaces. Ao invés de usar uma ShapeInterface ou uma ThreeDimensionalShapeInterface, você pode criar outra interface, talvez ManageShapeInterface, e implementá-la tanto nas formas planas quanto tridimensionais.

      Dessa forma, é possível ter uma única API para gerenciar todas as formas:

      interface ManageShapeInterface
      {
          public function calculate();
      }
      
      class Square implements ShapeInterface, ManageShapeInterface
      {
          public function area()
          {
              // calculate the area of the square
          }
      
          public function calculate()
          {
              return $this->area();
          }
      }
      
      class Cuboid implements ShapeInterface, ThreeDimensionalShapeInterface, ManageShapeInterface
      {
          public function area()
          {
              // calculate the surface area of the cuboid
          }
      
          public function volume()
          {
              // calculate the volume of the cuboid
          }
      
          public function calculate()
          {
              return $this->area();
          }
      }
      

      Agora, na classe AreaCalculator, substitua a chamada do método area por calculate e verifique se o objeto é uma instância da ManageShapeInterface e não da ShapeInterface.

      Isso satisfaz o princípio da segregação de interfaces.

      Princípio da inversão de dependência

      O princípio da inversão de dependência declara:

      As entidades devem depender de abstrações, não de implementações. Ele declara que o módulo de alto nível não deve depender do módulo de baixo nível, mas devem depender de abstrações.

      Esse princípio permite a desestruturação.

      Aqui está um exemplo de um PasswordReminder que se conecta a um banco de dados MySQL:

      class MySQLConnection
      {
          public function connect()
          {
              // handle the database connection
              return 'Database connection';
          }
      }
      
      class PasswordReminder
      {
          private $dbConnection;
      
          public function __construct(MySQLConnection $dbConnection)
          {
              $this->dbConnection = $dbConnection;
          }
      }
      

      Primeiramente, o MySQLConnection é o módulo de baixo nível, enquanto o PasswordReminder é de alto nível. No entanto, de acordo com a definição de D em SOLID, que declara Dependa de abstrações e não de implementações, Esse trecho de código acima viola esse princípio, uma vez que a classe PasswordReminder está sendo forçada a depender da classe MySQLConnection.

      Mais tarde, se você alterasse o mecanismo do banco de dados, também teria que editar a classe PasswordReminder e isso violaria o princípio do aberto-fechado.

      A classe PasswordReminder não deve se importar com qual banco de dados seu aplicativo usa. Para resolver esses problemas, programe em uma interface, uma vez que os módulos de alto e baixo nível devem depender de abstrações:

      interface DBConnectionInterface
      {
          public function connect();
      }
      

      A interface possui um método de conexão e a classe MySQLConnection implementa essa interface. Além disso, em vez de sugerir o tipo diretamente da classe MySQLConnection no construtor do PasswordReminder, você sugere o tipo de DBConnectionInterface. Sendo assim, independentemente do tipo de banco de dados que seu aplicativo usa, a classe PasswordReminder poderá se conectar ao banco de dados sem problemas e o princípio do aberto-fechado não será violado.

      class MySQLConnection implements DBConnectionInterface
      {
          public function connect()
          {
              // handle the database connection
              return 'Database connection';
          }
      }
      
      class PasswordReminder
      {
          private $dbConnection;
      
          public function __construct(DBConnectionInterface $dbConnection)
          {
              $this->dbConnection = $dbConnection;
          }
      }
      

      Esse código estabelece que tanto os módulos de alto quanto de baixo nível dependem de abstrações.

      Conclusão

      Neste artigo, os cinco princípios do Código SOLID foram-lhe apresentados. Projetos que aderem aos princípios SOLID podem ser compartilhados com colaboradores, estendidos, modificados, testados e refatorados com menos complicações.

      Continue seu aprendizado lendo sobre outras práticas para o desenvolvimento de software ágil e adaptativo.



      Source link

      Como Configurar um Servidor de Armazenamento de Objeto Usando o Minio no Ubuntu 18.04


      O autor escolheu o Open Internet/Free Speech Fund para receber uma doação como parte do programa Write for DOnations.

      Introdução

      De soluções de backup baseadas na nuvem até a alta disponibilidade redes de entrega de conteúdo (CDNs), a capacidade de armazenar blobs não estruturados de dados de objetos e torná-los acessíveis por meio de APIs HTTP, conhecidas como armazenamento de objeto ou object storage, tornou-se parte integrante do cenário da tecnologia moderna.

      O Minio é um popular servidor de armazenamento de objetos open-source compatível com o Serviço de armazenamento em nuvem Amazon S3. As aplicações que foram configuradas para conversar com o Amazon S3 também podem ser configuradas para conversar com o Minio, permitindo que o Minio seja uma alternativa viável ao S3 se você quiser ter mais controle sobre o servidor de armazenamento de objetos. O serviço armazena dados não estruturados como fotos, vídeos, arquivos de log, backups e imagens de container/VM, e pode até mesmo fornecer um servidor de armazenamento de objeto único que agrupa várias unidades espalhadas por muitos servidores.

      O Minio é escrito em Go, vem com um cliente de linha de comando mais uma interface web, e suporta serviço de enfileiramento simples para alvos com o protocolo Advanced Message Queuing (AMQP), Elasticsearch, Redis, NATS. Por todos esses motivos, aprender a configurar um servidor de armazenamento de objetos Minio pode adicionar uma ampla variedade de flexibilidade e utilidade ao seu projeto.

      Neste tutorial, você irá:

      • Instalar o servidor Minio no seu servidor Ubuntu 18.04 e configurá-lo como um serviço systemd.

      • Configurar um certificado SSL/TLS usando o Let’s Encrypt para proteger a comunicação entre o servidor e o cliente.

      • Acessar a interface web do Minio via HTTPS para usar e administrar o servidor.

      Pré-requisitos

      Para concluir este tutorial, você precisará de:

      • Um servidor Ubuntu 18.04 configurado seguindo nosso tutorial de Configuração Inicial de servidor com Ubuntu 18.04, incluindo um usuário sudo não-root e um firewall.

      • Um nome de domínio totalmente qualificado. Você pode comprar um em Namecheap ou obter um gratuitamente em Freenom. Neste tutorial, seu domínio será representado como seu_domínio.

      • Os seguintes registros DNS configurados para o seu servidor Minio. Você pode seguir nossa documentação sobre registros DNS para obter detalhes sobre como adicioná-los a um Droplet da DigitalOcean.

        • Um registro A com o nome do servidor (exemplo: minio-server.seu_domínio) apontando para o endereço IPv4 do servidor de objetos.
        • (Opcional) Se você deseja que seu servidor seja acessível via IPv6, será necessário um registro AAAA com o nome do seu servidor apontando para o endereço IPv6 do servidor de objetos.

      Passo 1 — Instalando e Configurando o Servidor Minio

      Você pode instalar o servidor Minio compilando o código fonte ou através de um arquivo binário. Para instalá-lo a partir da fonte, você precisa ter pelo menos o Go 1.12 instalado em seu sistema.

      Neste passo, você instalará o servidor através do binário pré-compilado e configurará o servidor Minio posteriormente.

      Primeiro, efetue login no seu servidor, substituindo sammy pelo seu nome de usuário e ip_do_seu_servidor pelo endereço IP do seu servidor Ubuntu 18.04:

      • ssh sammy@ip_do_seu_servidor

      Se você não atualizou o banco de dados de pacotes recentemente, atualize-o agora:

      Em seguida, baixe o arquivo binário do servidor Minio do site oficial:

      • wget https://dl.min.io/server/minio/release/linux-amd64/minio

      Você receberá uma saída semelhante à seguinte:

      Output

      --2019-08-27 15:08:49-- https://dl.min.io/server/minio/release/linux-amd64/minio Resolving dl.min.io (dl.min.io)... 178.128.69.202 Connecting to dl.min.io (dl.min.io)|178.128.69.202|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 44511616 (42M) [application/octet-stream] Saving to: ‘minio’ minio 100%[===================>] 42.45M 21.9MB/s in 1.9s 2019-08-27 15:08:51 (21.9 MB/s) - ‘minio’ saved [44511616/44511616]

      Depois que o download terminar, um arquivo chamado minio estará no seu diretório de trabalho. Use o seguinte comando para torná-lo executável:

      Agora, mova o arquivo para o diretório /usr/local/bin, onde o script de inicialização systemd do Minio espera encontrá-lo:

      • sudo mv minio /usr/local/bin

      Isso nos permitirá escrever um arquivo de unidade de serviço posteriormente neste tutorial para executar automaticamente o Minio na inicialização.

      Por motivos de segurança, é melhor evitar a execução do servidor Minio como root. Isso limitará os danos que podem ser causados ao seu sistema se ele for comprometido. Como o script systemd que você usará no Passo 2 procura uma conta de usuário e um grupo chamado minio-user, crie um novo usuário com este nome:

      • sudo useradd -r minio-user -s /sbin/nologin

      Neste comando, você usou a flag -s para definir /sbin/nologin como o shell para minio-user. Este é um shell que não permite o login do usuário, o que não é necessário para o minio-user.

      Em seguida, altere a propriedade do binário do Minio para minio-user:

      • sudo chown minio-user:minio-user /usr/local/bin/minio

      Em seguida, você criará um diretório onde o Minio armazenará arquivos. Este será o local de armazenamento para os buckets que você usará posteriormente para organizar os objetos que você armazena no servidor Minio. Este tutorial nomeará o diretório como minio:

      • sudo mkdir /usr/local/share/minio

      Dê a propriedade desse diretório para o minio-user:

      • sudo chown minio-user:minio-user /usr/local/share/minio

      A maioria dos arquivos de configuração do servidor é armazenada no diretório /etc, então crie seu arquivo de configuração do Minio lá:

      Dê a propriedade desse diretório para o minio-user também:

      • sudo chown minio-user:minio-user /etc/minio

      Use o Nano ou seu editor de texto favorito para criar o arquivo de ambiente necessário para modificar a configuração padrão:

      • sudo nano /etc/default/minio

      Depois que o arquivo estiver aberto, adicione as seguintes linhas para definir algumas variáveis de ambiente importantes no seu arquivo de ambiente:

      /etc/default/minio

      MINIO_ACCESS_KEY="minio"
      MINIO_VOLUMES="/usr/local/share/minio/"
      MINIO_OPTS="-C /etc/minio --address ip_do_seu_servidor:9000"
      MINIO_SECRET_KEY="miniostorage"
      

      Vamos dar uma olhada nessas variáveis e nos valores que você define:

      • MINIO_ACCESS_KEY: Isso define a access key que você usará para acessar a interface web de usuário do Minio.
      • MINIO_SECRET_KEY: Isso define a chave privada que você usará para completar suas credenciais de login na interface do Minio. Este tutorial configurou o valor para miniostorage, mas recomendamos que você escolha uma senha diferente e mais complexa para proteger seu servidor.
      • MINIO_VOLUMES: Isso identifica o diretório de armazenamento que você criou para seus buckets.
      • MINIO_OPTS: Isso muda onde e como o servidor serve os dados. A flag -C aponta o Minio para o diretório de configuração que ele deve usar, enquanto a flag --address informa ao Minio o endereço IP e a porta na qual se conectar. Se o endereço IP não for especificado, o Minio será vinculado a todos os endereços configurados no servidor, incluindo localhost e quaisquer endereços IP relacionados ao Docker, portanto, é recomendável especificar diretamente o endereço IP aqui. A porta padrão 9000 pode ser alterada se você desejar.

      Por fim, salve e feche o arquivo de ambiente quando terminar de fazer as alterações.

      Agora você instalou o Minio e definiu algumas variáveis de ambiente importantes. Em seguida, você configurará o servidor para ser executado como um serviço do sistema.

      Passo 2 — Instalando o Script de Inicialização Systemd do Minio

      Neste passo, você configurará o servidor Minio para ser gerenciado como um serviço systemd.

      Primeiro, faça o download do arquivo descritor de serviço oficial do Minio usando o seguinte comando.

      • curl -O https://raw.githubusercontent.com/minio/minio-service/master/linux-systemd/minio.service

      Você receberá uma saída semelhante à seguinte:

      Output

      % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 835 100 835 0 0 6139 0 --:--:-- --:--:-- --:--:-- 6139

      Após o término do download, um arquivo chamado minio.service estará no seu diretório de trabalho.

      Para auditar o conteúdo do arquivo minio.service antes de aplicá-lo, abra-o em um editor de texto para visualizar seu conteúdo:

      Isso mostrará o seguinte:

      /etc/systemd/system/minio.service

      [Unit]
      Description=MinIO
      Documentation=https://docs.min.io
      Wants=network-online.target
      After=network-online.target
      AssertFileIsExecutable=/usr/local/bin/minio
      
      [Service]
      WorkingDirectory=/usr/local/
      
      User=minio-user
      Group=minio-user
      
      EnvironmentFile=/etc/default/minio
      ExecStartPre=/bin/bash -c "if [ -z "${MINIO_VOLUMES}" ]; then echo "Variable MINIO_VOLUMES not set in /etc/default/minio"; exit 1; fi"
      
      ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
      
      # Let systemd restart this service always
      Restart=always
      
      # Specifies the maximum file descriptor number that can be opened by this process
      LimitNOFILE=65536
      
      # Disable timeout logic and wait until process is stopped
      TimeoutStopSec=infinity
      SendSIGKILL=no
      
      [Install]
      WantedBy=multi-user.target
      
      # Built for ${project.name}-${project.version} (${project.name})
      

      Este arquivo de unidade de serviço inicia o servidor Minio usando o usuário minio-user que você criou anteriormente. Ele também implementa as variáveis de ambiente definidas no último passo e faz o servidor executar automaticamente na inicialização. Para mais informações sobre arquivos de unidades do systemd, consulte nosso guia Understanding Systemd Units and Unit Files.

      Depois de examinar o conteúdo do script, feche o seu editor de texto.

      O Systemd requer que os arquivos de unidade sejam armazenados no diretório de configuração systemd, então mova o minio.service para lá:

      • sudo mv minio.service /etc/systemd/system

      Em seguida, execute o seguinte comando para recarregar todas as unidades systemd:

      • sudo systemctl daemon-reload

      Por fim, habilite o Minio para iniciar na inicialização:

      • sudo systemctl enable minio

      Isso dará a seguinte saída:

      Output

      Created symlink from /etc/systemd/system/multi-user.target.wants/minio.service to /etc/systemd/system/minio.service.

      Agora que o script systemd está instalado e configurado, é hora de iniciar o servidor.

      Passo 3 — Iniciando o Servidor Minio

      Neste passo, você iniciará o servidor e modificará o firewall para permitir o acesso através da interface web.

      Primeiro, inicie o servidor Minio:

      • sudo systemctl start minio

      Em seguida, verifique o status do Minio, o endereço IP ao qual está vinculado, seu uso de memória e muito mais executando este comando:

      • sudo systemctl status minio

      Você obterá a seguinte saída:

      Output

      ● minio.service - MinIO Loaded: loaded (/etc/systemd/system/minio.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2019-12-09 21:54:02 UTC; 46s ago Docs: https://docs.min.io Process: 3405 ExecStartPre=/bin/bash -c if [ -z "${MINIO_VOLUMES}" ]; then echo "Variable MINIO_VOLUMES not set in /etc/default/minio"; exit 1; fi (code=exited, status=0/SUCCES Main PID: 3407 (minio) Tasks: 7 (limit: 1152) CGroup: /system.slice/minio.service └─3407 /usr/local/bin/minio server -C /etc/minio --address your_server_IP:9000 /usr/local/share/minio/ Dec 09 21:54:02 cart-Minion-Object-1804-1 systemd[1]: Started MinIO. Dec 09 21:54:03 cart-Minion-Object-1804-1 minio[3407]: Endpoint: http://your_server_IP:9000 Dec 09 21:54:03 cart-Minion-Object-1804-1 minio[3407]: Browser Access: Dec 09 21:54:03 cart-Minion-Object-1804-1 minio[3407]: http://your_server_IP:9000 ...

      Em seguida, habilite o acesso através do firewall ao servidor Minio na porta configurada. Neste tutorial, essa é a porta 9000.

      Primeiro adicione a regra:

      Em seguida, ative o firewall:

      Você receberá o seguinte prompt:

      Output

      Command may disrupt existing ssh connections. Proceed with operation (y|n)?

      Pressione y e ENTER para confirmar. Você obterá a seguinte saída:

      Output

      Firewall is active and enabled on system startup

      O Minio agora está pronto para aceitar tráfego, mas antes de se conectar ao servidor, você protegerá a comunicação instalando um certificado SSL/TLS.

      Neste passo, você protegerá o acesso ao seu servidor Minio usando uma chave privada e um certificado público que foram obtidos de uma autoridade de certificação (CA), neste caso Let’s Encrypt. Para obter um certificado SSL gratuito, você usará o Certbot.

      Primeiro, permita o acesso HTTP e HTTPS através do seu firewall. Para fazer isso, abra a porta 80, que é a porta para HTTP:

      Em seguida, abra a porta 443 para HTTPS:

      Depois de adicionar essas regras, verifique o status do seu firewall com o seguinte comando:

      Você receberá uma saída semelhante à seguinte:

      Output

      Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22/tcp (OpenSSH) ALLOW IN Anywhere 9000 ALLOW IN Anywhere 443 ALLOW IN Anywhere 80 ALLOW IN Anywhere 22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6) 9000 (v6) ALLOW IN Anywhere (v6) 443 (v6) ALLOW IN Anywhere (v6) 80 (v6) ALLOW IN Anywhere (v6)

      Isso confirma que as portas 80 e 443 estão abertas, garantindo que o servidor aceite solicitações da Internet.

      Em seguida, você instalará o Certbot. Como o Certbot mantém um repositório PPA separado, você primeiro precisará adicioná-lo à sua lista de repositórios antes de instalar o Certbot, como mostrado:

      Para se preparar para adicionar o repositório PPA, primeiro instale software-properties-common, um pacote para o gerenciamento de PPAs:

      • sudo apt install software-properties-common

      Este pacote fornece alguns scripts úteis para adicionar e remover PPAs em vez de fazê-lo manualmente.

      Agora adicione o repositório Universe:

      • sudo add-apt-repository universe

      Este repositório contém software livre e de código aberto mantido pela comunidade Ubuntu, mas não é oficialmente mantido pela Canonical, os desenvolvedores do Ubuntu. É aqui que encontraremos o repositório do Certbot.

      Em seguida, adicione o repositório do Certbot:

      • sudo add-apt-repository ppa:certbot/certbot

      Você receberá a seguinte saída:

      Output

      This is the PPA for packages prepared by Debian Let's Encrypt Team and backported for Ubuntu(s). More info: https://launchpad.net/~certbot/+archive/ubuntu/certbot Press [ENTER] to continue or ctrl-c to cancel adding it

      Pressione ENTER para aceitar.

      Atualize a lista de pacotes:

      Finalmente, instale o certbot:

      Em seguida, você usará o certbot para gerar um novo certificado SSL.

      Como o Ubuntu 18.04 ainda não suporta a instalação automática, você usará o comando certonly e --standalone para obter o certificado:

      • sudo certbot certonly --standalone -d minio-server.seu_domínio

      --standalone significa que este certificado é para um servidor web interno independente. Para mais informações sobre isso, consulte nosso tutorial How To Use Certbot Standalone Mode to Retrieve Let’s Encrypt SSL Certificates on Ubuntu 18.04.

      Você receberá a seguinte saída:

      Output

      Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator standalone, Installer None Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel):

      Adicione seu email e pressione ENTER.

      O Certbot solicitará que você se registre no Let’s Encrypt:

      Output

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must agree in order to register with the ACME server at https://acme-v02.api.letsencrypt.org/directory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (A)gree/(C)ancel:

      Digite A e pressione ENTER para concordar.

      Em seguida, você será perguntado se deseja compartilhar seu e-mail com a Electronic Frontier Foundation:

      Output

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o:

      Depois de responder Y ou N, suas chaves públicas e privadas serão geradas e salvas no diretório /etc/letsencrypt/live/minio-server.seu_domínio.

      Em seguida, copie esses dois arquivos (privkey.pem e fullchain.pem) para o diretório certs na pasta de configuração do servidor Minio, que é /etc/minio para este tutorial. Use o seguinte para copiar privkey.pem e renomear o arquivo private.key:

      • sudo cp /etc/letsencrypt/live/minio-server.seu_domínio/privkey.pem /etc/minio/certs/private.key

      Em seguida, faça o mesmo para fullchain.pem, nomeando o resultado como public.crt:

      • sudo cp /etc/letsencrypt/live/minio-server.seu_domínio/fullchain.pem /etc/minio/certs/public.crt

      Agora, altere a propriedade dos arquivos para minio-user. Primeiro, faça isso para private.key:

      • sudo chown minio-user:minio-user /etc/minio/certs/private.key

      Em seguida, public.crt:

      • sudo chown minio-user:minio-user /etc/minio/certs/public.crt

      Reinicie o servidor Minio, para que ele fique ciente do certificado e comece a usar HTTPS:

      • sudo systemctl restart minio

      Os certificados Let’s Encrypt são válidos apenas por noventa dias. Isso é para incentivar os usuários a automatizar seu processo de renovação de certificado. O pacote Certbot que você instalou adiciona automaticamente um script novo ao /etc/cron.d. Esse script é executado duas vezes por dia e renova automaticamente qualquer certificado que esteja dentro de trinta dias da expiração.

      Com isso, a conexão do Minio agora está segura e o certificado SSL/TLS será renovado automaticamente para você. No próximo passo, você se conectará ao Minio através do navegador para usar o servidor.

      Passo 5 — Conexão Segura à Interface Web do Minio Usando HTTPS

      Neste passo, você se conectará com segurança à interface web do Minio via HTTPS e, em seguida, criará buckets e fará o upload de objetos para eles.

      Acesse a interface web apontando o navegador para https://minio-server.seu_domínio:9000.

      Você verá a tela de login do servidor Minio:

      Minio login screen

      Agora, faça login na interface principal inserindo suas credenciais. Para Access Key, digite a MINIO_ACCESS_KEY que você definiu no arquivo de ambiente /etc/default/minio no Passo 1. Para Secret Key, digite a MINIO_SECRET_KEY que você definiu nesse mesmo arquivo. Depois de inserir as credenciais, clique no botão redondo com a seta, diretamente abaixo dos campos de entrada.

      Você será apresentado à interface de usuário do Minio. Para criar um novo bucket no qual você pode armazenar objetos, clique no botão vermelho claro + no canto inferior direito da interface principal para exibir dois botões amarelos adicionais.

      Minio's main interface

      Clique no botão amarelo do meio e digite um nome para o seu novo bucket no prompt, pressionando a tecla ENTER para salvar sua resposta. Seu novo bucket está pronto para ser usado para armazenamento.

      Nota: Ao nomear seu bucket no Minio, verifique se o seu nome contém apenas letras minúsculas, números ou hífens. O Minio limita as convenções de nomenclatura de buckets para ser compatível com os padrões do AWS S3.

      Quando você quiser adicionar objetos ao seu bucket, clique no mesmo botão vermelho claro de antes e clique no botão amarelo superior para abrir um prompt de upload de arquivo.

      Neste ponto, você trabalhou em toda a interface web básica para criar buckets e fazer upload de objetos.

      Conclusão

      Agora você tem seu próprio servidor Minio de armazenamento de objetos ao qual pode se conectar com segurança a partir da interface web usando um certificado Let’s Encrypt SSL/TLS. Opcionalmente, você pode querer olhar para o Minio desktop clients para FreeBSD, Linux, Mac, e Windows como uma maneira alternativa de usar e administrar seu servidor de armazenamento de objetos.

      Além disso, se você quiser aumentar a capacidade de armazenamento da sua instalação do Minio para além do tamanho do disco do servidor, use o Serviço de armazenamento em bloco da DigitalOcean para anexar um volume ao seu servidor, estendendo a capacidade de armazenamento em até 80 TB.

      Mais informações sobre o Minio estão disponíveis no site de documentação do projeto. Se você quiser saber mais sobre armazenamento de objetos, navegue em Tutoriais sobre armazenamento de objetos.



      Source link