Configuração ACME#

O módulo ACME no Angie permite a aquisição automática de certificados usando o protocolo ACME. O protocolo ACME suporta vários métodos de verificação de domínio (também chamados de "validação"); este módulo implementa validação HTTP, validação DNS e validação baseada em hooks através de um serviço externo personalizado.

Etapas de Configuração#

Etapas gerais para habilitar solicitações de certificado na configuração:

  • Configure um cliente ACME no bloco http usando a diretiva acme_client, que especifica um nome único de cliente e outros parâmetros. Múltiplos clientes ACME podem ser configurados.

  • Especifique os domínios para os quais os certificados são solicitados: Um único certificado será emitido para todos os nomes de domínio listados nas diretivas server_name dentro de todos os blocos server que usam diretivas acme apontando para o mesmo cliente ACME.

  • Configure o tratamento de solicitações e callbacks ACME: Isso é necessário para verificar a propriedade do domínio. A configuração depende do método de validação de domínio escolhido:

    Método

    Requisitos do Usuário

    Multi-domínio

    Domínios Wildcard

    Validação HTTP

    Abrir a porta 80 para conexões de entrada no servidor Angie.

    Validação DNS

    Abrir a porta 53 (ou a especificada em acme_dns_port) para conexões de entrada no servidor Angie.

    Definir um registro NS para o subdomínio _acme-challenge. apontando para seu servidor Angie.

    Validação por hook

    Criar um serviço externo (script ou aplicação) que possa, mediante solicitação do Angie, atualizar registros DNS ou servir uma resposta especial via servidor web.

  • Configure SSL usando o certificado e chave obtidos: O módulo torna certificados e chaves disponíveis como variáveis incorporadas que podem ser usadas na configuração para preencher ssl_certificate e ssl_certificate_key.

    Para instruções de configuração SSL, consulte Configuração SSL.

Dica

O processo de aquisição e renovação de certificados depende de muitos serviços e pode levar algum tempo. Seja paciente, e se encontrar problemas ou tiver dúvidas, verifique o log de debug.

Detalhes de Implementação#

Chaves de cliente e certificados são armazenados em codificação PEM dentro de subdiretórios do diretório especificado pela --http-acme-client-path opção de build:

$ ls /var/lib/angie/acme/example/

  account.key  certificate.pem  private.key

O cliente ACME requer uma conta no servidor CA. Para criar e gerenciar esta conta, o cliente usa uma chave privada (account.key). Se nenhuma chave existir, ela é gerada na inicialização. O cliente então usa esta chave para registrar a conta no servidor.

Nota

Se você já possui uma chave de conta, coloque-a no subdiretório do cliente antes de iniciar para reutilizar a conta. Alternativamente, especifique o arquivo de chave usando o parâmetro account_key em acme_client.

O cliente ACME também usa uma chave separada (private.key) para Solicitações de Assinatura de Certificado (CSRs). Esta chave de certificado é automaticamente criada na inicialização se necessário.

Na inicialização, o cliente solicita um certificado se um não existir, assinando e enviando um CSR para todos os domínios sob seu gerenciamento para o servidor CA. O servidor verifica a propriedade do domínio usando validação HTTP ou DNS e emite um certificado, que o cliente salva localmente (certificate.pem).

Como mencionado anteriormente, um único certificado cobre todos os nomes de domínio gerenciados pelo mesmo cliente ACME, potencialmente resultando em um certificado multi-domínio. A lista de todos os nomes cobertos pelo certificado pode ser encontrada na seção Subject Alternative Name (SAN) do certificado obtido. Para verificar isso pela linha de comando:

$ openssl x509 -in certificate.pem -noout -text | grep -A5 "Subject Alternative Name"

Quando um certificado está prestes a expirar ou a lista de domínios muda, o cliente assina e envia outro CSR para o servidor CA. O servidor re-verifica a propriedade e emite um novo certificado, que o cliente instala localmente, substituindo o anterior.

Na configuração, o certificado obtido e sua chave correspondente estão disponíveis através das variáveis de prefixo $acme_cert_<name> e $acme_cert_key_<name>. Seus valores são o conteúdo dos respectivos arquivos, que devem ser usados com as diretivas ssl_certificate e ssl_certificate_key:

server {

    listen 443 ssl;

    server_name example.com www.example.com;
    acme example;

    ssl_certificate $acme_cert_example;
    ssl_certificate_key $acme_cert_key_example;
}

Validação HTTP#

A validação é tratada automaticamente. O processo envolve o servidor ACME, ao receber uma solicitação, recuperar um arquivo de token especial via HTTP do cliente no endereço /.well-known/acme-challenge/<TOKEN>. Nosso módulo ACME rastreia e processa tais solicitações automaticamente. Quando a resposta esperada com o conteúdo correto é recebida, o servidor ACME confirma que o domínio pertence ao cliente.

Exemplo de Configuração#

Neste exemplo, o cliente ACME chamado example gerencia certificados para example.com e www.example.com (note que certificados wildcard não são suportados com validação HTTP):

http {

    resolver 127.0.0.53; # Necessário para a diretiva 'acme_client'

    acme_client example https://acme-v02.api.letsencrypt.org/directory;

    server {

        listen 80; # Pode residir em um bloco 'server' diferente
        # com uma lista de domínios diferente
        # ou mesmo sem uma

        listen 443 ssl;

        server_name example.com www.example.com;
        acme example;

        ssl_certificate $acme_cert_example;
        ssl_certificate_key $acme_cert_key_example;
    }
}

Como observado anteriormente, a porta 80 deve estar aberta para tratar chamadas HTTP ACME. No entanto, como mostrado neste exemplo, a diretiva listen para esta porta pode ser colocada em um bloco server separado. Se nenhum bloco existente com esta diretiva estiver presente, você pode limitar o novo bloco apenas para chamadas ACME:

server {

    listen 80;
    return 444; # Sem resposta, conexão fechada
}

Por que isso funciona? O módulo intercepta solicitações para /.well-known/acme-challenge/<TOKEN> após ler os cabeçalhos mas antes de selecionar um servidor virtual e processar as diretivas rewrite e location. Tais solicitações interceptadas são processadas se o valor <TOKEN> corresponder ao valor esperado para a chamada específica. Nenhum acesso a diretório ocorre; a solicitação é tratada inteiramente pelo módulo.

Validação DNS#

A validação é tratada automaticamente. Ao processar uma solicitação de certificado, o servidor ACME executa uma consulta DNS especial para o subdomínio _acme-challenge. do domínio sendo verificado. Uma vez que a resposta esperada é recebida, o servidor ACME confirma que o domínio pertence ao cliente.

Nosso módulo ACME rastreia e processa tais solicitações automaticamente, desde que seus registros DNS estejam configurados adequadamente para designar o servidor Angie como o servidor de nomes autoritativo para o subdomínio _acme-challenge..

Por exemplo, para verificar o domínio example.com usando um servidor Angie no endereço IP 93.184.215.14, a configuração DNS do seu domínio deve incluir os seguintes registros:

_acme-challenge.example.com. 60    IN      NS       ns.example.com.
             ns.example.com. 60    IN       A       93.184.215.14

Esta configuração delega a resolução DNS para _acme-challenge.example.com para ns.example.com, garantindo que ns.example.com seja acessível mapeando-o para o endereço IP (93.184.215.14).

Este método permite solicitar certificados wildcard, por exemplo, um certificado que inclui a entrada *.example.com na seção Subject Alternative Name (SAN). Para solicitar explicitamente um certificado para um subdomínio, como www.example.com, você deve verificar separadamente esse subdomínio usando o método descrito acima.

Aviso

A aplicabilidade deste cenário depende amplamente das capacidades fornecidas pelo seu provedor DNS; alguns provedores não permitem tais configurações.

Exemplo de Configuração#

No geral, a configuração é similar ao exemplo da seção anterior. Não há necessidade de configurações específicas do HTTP; em vez disso, é suficiente definir challenge=dns para a diretiva acme_client.

Neste exemplo, o cliente ACME chamado example gerencia certificados para example.com e *.example.com:

http {

    resolver 127.0.0.53;

    acme_client example https://acme-v02.api.letsencrypt.org/directory
        challenge=dns;

    server {

        server_name example.com *.example.com;
        acme example;

        ssl_certificate $acme_cert_example;
        ssl_certificate_key $acme_cert_key_example;
    }
}

Validação Baseada em Hooks#

Diferentemente dos métodos anteriores, esta validação requer esforço adicional. O servidor ACME executa validação HTTP padrão ou validação DNS, mas em vez de interagir diretamente com o servidor Angie, ele se comunica com um serviço externo gerenciado pelo servidor Angie usando chamadas de hook (acme_hook). Este serviço configura um servidor DNS ou HTTP separado onde o servidor ACME envia suas solicitações.

Uma vez que o servidor ACME recebe a resposta esperada do servidor DNS ou HTTP configurado, ele confirma a propriedade do domínio.

O Angie invoca o serviço externo quando atualizações de certificado são necessárias via o protocolo ACME. As chamadas são feitas proxy de solicitações e dados para FastCGI, SCGI, e servidores similares usando diretivas como fastcgi_pass, scgi_pass, etc.

O serviço deve retornar um código de status 2xx, que pode ser enviado via o cabeçalho Status. Qualquer outro código é tratado como um erro, e a renovação do certificado é interrompida. A saída do serviço é ignorada.

Exemplo de Configuração#

Neste exemplo, o cliente ACME example está configurado para verificação de domínio usando callbacks DNS, indicado pelo parâmetro challenge=dns na diretiva acme_client.

O bloco server se aplica a todos os subdomínios de example.com (por exemplo, *.example.com) e usa o cliente ACME example para gerenciar certificados, conforme especificado pela diretiva acme.

Um bloco location nomeado é configurado para lidar com chamadas de serviço externo para verificação DNS. A diretiva acme_hook vincula o servidor ao cliente ACME example. As solicitações são proxy para um servidor FastCGI local rodando na porta 9000 usando a diretiva fastcgi_pass. As diretivas fastcgi_param passam dados sobre o cliente ACME, hook, tipo de desafio, domínio, token e autorização de chave para o serviço externo.

acme_client example https://acme-v02.api.letsencrypt.org/directory
    challenge=dns;

server {

    listen 80;

    server_name *.example.com;

    acme example;

    ssl_certificate $acme_cert_example;
    ssl_certificate_key $acme_cert_key_example;

    location @acme_hook_location {

        acme_hook example;

        fastcgi_pass localhost:9000;

        fastcgi_param ACME_CLIENT $acme_hook_client;
        fastcgi_param ACME_HOOK $acme_hook_name;
        fastcgi_param ACME_CHALLENGE $acme_hook_challenge;
        fastcgi_param ACME_DOMAIN $acme_hook_domain;
        fastcgi_param ACME_TOKEN $acme_hook_token;
        fastcgi_param ACME_KEYAUTH $acme_hook_keyauth;

        include fastcgi.conf;
    }
}

O seguinte script Perl demonstra um serviço FastCGI externo correspondente:

#!/usr/bin/perl

use strict; use warnings;

use FCGI;

my $socket = FCGI::OpenSocket(":9000", 5);
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket);

while ($request->Accept() >= 0) {
    print "\r\n";

    my $client =    $ENV{ACME_CLIENT};
    my $hook =      $ENV{ACME_HOOK};
    my $challenge = $ENV{ACME_CHALLENGE};
    my $domain =    $ENV{ACME_DOMAIN};
    my $token =     $ENV{ACME_TOKEN};
    my $keyauth =   $ENV{ACME_KEYAUTH};

    if ($hook eq 'add') {

        DNS_set_TXT_record("_acme-challenge.$domain.", $keyauth);

    } elsif ($hook eq 'remove') {

        DNS_clear_TXT_record("_acme-challenge.$domain.");
    }
};

FCGI::CloseSocket($socket);

Aqui, DNS_set_TXT_record() e DNS_clear_TXT_record() são funções assumidas para adicionar e remover registros TXT na configuração de um servidor DNS externo que o servidor ACME consulta. Estes registros devem conter os dados fornecidos pelo servidor Angie para permitir que o servidor DNS externo passe com sucesso na validação, similar ao processo descrito em Validação DNS. Os detalhes de implementação de tais funções estão além do escopo deste guia; por exemplo, parâmetros também podem ser passados através da URI da solicitação:

# ...

location @acme_hook_location {

    acme_hook example uri=/acme_hook/$acme_hook_name?domain=$acme_hook_domain&key=$acme_hook_keyauth;

    fastcgi_pass localhost:9000;

    fastcgi_param REQUEST_URI $request_uri;
    fastcgi_param ACME_CLIENT $acme_hook_client;
    fastcgi_param ACME_CHALLENGE $acme_hook_challenge;
    fastcgi_param ACME_TOKEN $acme_hook_token;

    include fastcgi.conf;
}

Outro exemplo usando PHP-FPM:

location @acme_hook_location {

    acme_hook example;
    root /var/www/dns;
    fastcgi_pass unix:/run/php-fpm/php-dns.sock;
    fastcgi_index hook.php;
    fastcgi_param SCRIPT_FILENAME /var/www/dns/hook.php;
    include fastcgi_params;

    fastcgi_param ACME_CLIENT $acme_hook_client;
    fastcgi_param ACME_HOOK $acme_hook_name;
    fastcgi_param ACME_CHALLENGE $acme_hook_challenge;
    fastcgi_param ACME_DOMAIN $acme_hook_domain;
    fastcgi_param ACME_TOKEN $acme_hook_token;
    fastcgi_param ACME_KEYAUTH $acme_hook_keyauth;
}
[dns]
listen = /run/php-fpm/php-dns.sock
listen.mode = 0666
user = angie
group = angie
chdir = /var/www/dns
# ...

Parâmetros passados podem ser acessados em PHP via $_SERVER['...'].

ACME no Módulo Stream#

O módulo stream ACME permite emissão automatizada de certificados e uso para tráfego TCP. Para operação adequada, o equivalente HTTP deve ser configurado primeiro: o cliente ACME deve ser declarado no contexto http, e o bloco stream deve ser colocado após o bloco http na configuração.

Exemplo de Configuração#

Por padrão, a validação HTTP é usada para obter certificados. Como mencionado em Validação HTTP, isso requer um servidor HTTP escutando na porta 80:

# Seção HTTP
http {

    resolver 127.0.0.53;

    # Cliente ACME para seção stream
    acme_client example https://acme-v02.api.letsencrypt.org/directory;

    # Servidor para validação HTTP
    server {

        listen 80;
        return 444;
    }
}

# Seção Stream
stream {

    server {

        listen 12345 ssl;
        proxy_pass backend_upstream;

        ssl_certificate $acme_cert_example;
        ssl_certificate_key $acme_cert_key_example;

        server_name example.com www.example.com;
        acme example; # referência ao cliente ACME definido na seção HTTP
    }

    upstream backend_upstream {

        server 127.0.0.1:54321;
    }
}

A validação DNS também pode ser usada configurando challenge=dns na diretiva acme_client; neste caso, o servidor não é necessário.

Migrando do certbot#

Se você usou anteriormente o certbot para obter e renovar certificados SSL do Let's Encrypt antes de migrar do nginx para o Angie, siga estes passos para fazer a transição para usar o módulo ACME.

Suponha que você configurou inicialmente os certificados com o seguinte comando:

$ sudo certbot --nginx -d example.com -d www.example.com

A configuração criada automaticamente pelo certbot está tipicamente localizada em /etc/nginx/sites-available/example.conf e se parece com algo assim:

server {

    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {

    listen 443 ssl;
    server_name example.com www.example.com;

    root /var/www/example;
    index index.html;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {

        try_files $uri $uri/ =404;
    }
}

No exemplo acima, as linhas destacadas devem ser modificadas. Dependendo das suas circunstâncias e preferências, configure a validação HTTP ou a validação DNS usando o módulo ACME.

A configuração do Angie resultante pode se parecer com isto:

http {

    resolver 127.0.0.53;

    acme_client example https://acme-v02.api.letsencrypt.org/directory;

    server {

        listen 80;
        server_name example.com www.example.com;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;
        server_name example.com www.example.com;

        root /var/www/example;
        index index.html;

        acme                 example;

        ssl_certificate      $acme_cert_example;
        ssl_certificate_key  $acme_cert_key_example;

        location / {
            try_files $uri $uri/ =404;
        }
    }
}

Lembre-se de recarregar a configuração após fazer as alterações:

$ sudo kill -HUP $(cat /run/angie.pid)

Uma vez que você tenha verificado que esta configuração funciona, você pode deletar os certificados do certbot e desabilitar ou remover o certbot inteiramente do servidor se ele não for mais usado em outro lugar, por exemplo:

$ sudo rm -rf /etc/letsencrypt

$ sudo systemctl stop certbot.timer
$ sudo systemctl disable certbot.timer
$ # -- ou --
$ sudo rm /etc/cron.d/certbot

$ sudo apt remove certbot
$ # -- ou --
$ sudo dnf remove certbot