Zum Inhalt

acme: Automatische Bereitstellung von Let's Encrypt-Zertifikaten und Lua-Implementierung des ACMEv2-Protokolls

Installation

Wenn Sie das RPM-Repository noch nicht abonniert haben, melden Sie sich an. Dann können Sie mit den folgenden Schritten fortfahren.

CentOS/RHEL 7 oder Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-acme

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-acme

Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.

Dieses Dokument beschreibt lua-resty-acme v0.16.0, das am 01. September 2025 veröffentlicht wurde.


Automatische Bereitstellung von Let's Encrypt-Zertifikaten (RSA + ECC) und reine Lua-Implementierung des ACMEv2-Protokolls.

http-01 und tls-alpn-01 Herausforderungen werden unterstützt.

Build Status luarocks opm

简体中文

Beschreibung

Diese Bibliothek besteht aus zwei Teilen:

  • resty.acme.autossl: automatisches Lebenszyklusmanagement von Let's Encrypt-Zertifikaten
  • resty.acme.client: Lua-Implementierung des ACME v2-Protokolls

Installieren Sie mit opm:

opm install fffonion/lua-resty-acme

Alternativ, um mit luarocks zu installieren:

luarocks install lua-resty-acme
## manuell luafilesystem installieren
luarocks install luafilesystem

Bitte beachten Sie, dass Sie luafilesystem manuell installieren müssen, wenn Sie LuaRocks verwenden. Dies dient der Aufrechterhaltung der Abwärtskompatibilität.

Diese Bibliothek verwendet ein FFI-basiertes OpenSSL-Backend, das derzeit OpenSSL 1.1.1, 1.1.0 und 1.0.2 Serien unterstützt.

Zusammenfassung

Erstellen Sie den privaten Schlüssel des Kontos und Fallback-Zertifikate:

## Konto-Schlüssel erstellen
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out /etc/openresty/account.key
## Fallback-Zertifikat und -Schlüssel erstellen
openssl req -newkey rsa:2048 -nodes -keyout /etc/openresty/default.key -x509 -days 365 -out /etc/openresty/default.pem

Verwenden Sie die folgende Beispielkonfiguration:

events {}

http {
    resolver 8.8.8.8 ipv6=off;

    lua_shared_dict acme 16m;

    # erforderlich zur Überprüfung der Let's Encrypt API
    lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
    lua_ssl_verify_depth 2;

    init_by_lua_block {
        require("resty.acme.autossl").init({
            -- Einstellung der folgenden auf true
            -- impliziert, dass Sie https://letsencrypt.org/repository/ gelesen und akzeptiert haben
            tos_accepted = true,
            -- die folgende für die Ersteinrichtung auskommentieren
            -- staging = true,
            -- die folgende auskommentieren, um RSA + ECC-Doppelzertifikat zu aktivieren
            -- domain_key_types = { 'rsa', 'ecc' },
            -- die folgende auskommentieren, um die tls-alpn-01-Herausforderung zu aktivieren
            -- enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
            account_key_path = "/etc/openresty/account.key",
            account_email = "[email protected]",
            domain_whitelist = { "example.com" },
        })
    }

    init_worker_by_lua_block {
        require("resty.acme.autossl").init_worker()
    }

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

        # Fallback-Zertifikate, stellen Sie sicher, dass Sie sie vorher erstellt haben
        ssl_certificate /etc/openresty/default.pem;
        ssl_certificate_key /etc/openresty/default.key;

        ssl_certificate_by_lua_block {
            require("resty.acme.autossl").ssl_certificate()
        }

        location /.well-known {
            content_by_lua_block {
                require("resty.acme.autossl").serve_http_challenge()
            }
        }
    }
}

Beim Testen der Bereitstellung wird empfohlen, die staging = true auszukommentieren, um einen End-to-End-Test Ihrer Umgebung zu ermöglichen. Dies kann verhindern, dass Konfigurationsfehler zu zu vielen Anfragen führen, die die Ratenbegrenzung der Let's Encrypt API erreichen.

Standardmäßig erstellt autossl nur RSA-Zertifikate. Um ECC-Zertifikate oder beide zu verwenden, kommentieren Sie domain_key_types = { 'rsa', 'ecc' } aus. Beachten Sie, dass mehrere Zertifikatsketten nur von NGINX 1.11.0 oder höher unterstützt werden.

Ein Zertifikat wird in die Warteschlange gestellt, um erstellt zu werden, nachdem NGINX eine Anfrage mit einem solchen SNI gesehen hat, was mehrere Sekunden dauern kann, um abzuschließen. In der Zwischenzeit werden Anfragen mit einem solchen SNI mit dem Fallback-Zertifikat beantwortet.

Beachten Sie, dass domain_whitelist oder domain_whitelist_callback so eingestellt sein muss, dass Ihre Domain, die Sie mit autossl bedienen möchten, enthalten ist, um potenziellen Missbrauch durch gefälschte SNI im SSL-Handshake zu verhindern.

domain_whitelist definiert eine Tabelle, die alle Domains enthält, die einbezogen werden sollen, und den CN, der zur Erstellung des Zertifikats verwendet werden soll. Nur ein einzelnes * ist als Platzhalter erlaubt.

domain_whitelist = { "domain1.com", "domain2.com", "domain3.com", "*.domain4.com" },

Wildcard-Zertifikate

Um dieser Bibliothek die Erstellung von Wildcard-Zertifikaten zu ermöglichen, müssen die folgenden Anforderungen erfüllt sein:

  • Die Wildcard-Domain erscheint genau als *.somedomain.com in domain_whitelist.
  • Die dns-01-Herausforderung ist aktiviert und ein DNS-Anbieter, der domains hat, die mit der Domain übereinstimmen, ist konfiguriert.

Andernfalls wird ein Nicht-Wildcard-Zertifikat als Fallback erstellt.

Standardmäßig erscheint die Wildcard-Domain *.example.com im Common Name. Wenn jedoch wildcard_domain_in_san auf true gesetzt ist, wird ein Zertifikat mit dem Common Name example.com und dem Subject Alternate Name *.example.com erstellt. Beachten Sie, dass sowohl *.example.com als auch example.com in dns_provider_accounts erscheinen sollten.

Erweiterte Nutzung

Verwenden Sie eine Funktion, um Domains einzuschließen

domain_whitelist_callback definiert eine Funktion, die die Domain als Parameter akzeptiert und einen booleschen Wert zurückgibt, um anzuzeigen, ob sie einbezogen werden sollte.

Um ein Muster in Ihrem Domainnamen zu überprüfen, z. B. alle Subdomains unter example.com, verwenden Sie:

domain_whitelist_callback = function(domain, is_new_cert_needed)
    return ngx.re.match(domain, [[\.example\.com$]], "jo")
end

Darüber hinaus, da die Überprüfung der Domain-Whitelist in der Zertifikatsphase erfolgt, ist es möglich, die Cosocket-API hier zu verwenden. Beachten Sie, dass dies die SSL-Handshake-Latenz erhöhen kann.

domain_whitelist_callback = function(domain, is_new_cert_needed)
    -- HTTP-Anfrage senden
    local http = require("resty.http")
    local res, err = httpc:request_uri("http://example.com")
    -- auf den Speicher zugreifen
    local acme = require("resty.acme.autossl")
    local value, err = acme.storage:get("key")
    -- Zertifikat aus dem resty LRU-Cache abrufen
    -- cached = { pkey, cert } oder nil, wenn das Zertifikat nicht im Cache ist
    local cached, staled, flags = acme.get_cert_from_cache(domain, "rsa")
    -- etwas tun, um die Domain zu überprüfen
    -- return is_domain_included
end

Die domain_whitelist_callback-Funktion erhält ein zweites Argument, das angibt, ob das Zertifikat bei einer eingehenden HTTP-Anfrage (false) bereitgestellt werden soll oder ob ein neues Zertifikat angefordert werden soll (true). Dies ermöglicht die Verwendung von zwischengespeicherten Werten im heißen Pfad (Anfragen bedienen), während frische Daten aus dem Speicher für neue Zertifikate abgerufen werden. Man kann auch unterschiedliche Logik implementieren, z. B. zusätzliche Überprüfungen durchführen, bevor ein neues Zertifikat angefordert wird.

Definieren Sie die Abkühlzeit bei Fehlern

Im Falle eines Fehlers bei der Zertifikatsanforderung möchte man möglicherweise verhindern, dass der ACME-Client sofort ein weiteres Zertifikat anfordert. Standardmäßig ist die Abkühlzeit auf 300 Sekunden (5 Minuten) eingestellt. Sie kann mit failure_cooloff oder mit der Funktion failure_cooloff_callback angepasst werden, z. B. um exponentielles Backoff zu implementieren.

    failure_cooloff_callback = function(domain, count)
      if count == 1 then
        return 600 -- 10 Minuten
      elseif count == 2 then
        return 1800 -- 30 Minuten
      elseif count == 3 then
        return 3600 -- 1 Stunde
      elseif count == 4 then
        return 43200 -- 12 Stunden
      elseif count == 5 then
        return 43200 -- 12 Stunden
      else
        return 86400 -- 24 Stunden
      end
    end

tls-alpn-01 Herausforderung

Die tls-alpn-01-Herausforderung wird derzeit auf Openresty 1.15.8.x, 1.17.8.x und 1.19.3.x unterstützt.

Klicken Sie hier, um die Beispielkonfiguration zu erweitern
events {}

http {
    resolver 8.8.8.8 ipv6=off;

    lua_shared_dict acme 16m;

    # erforderlich zur Überprüfung der Let's Encrypt API
    lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
    lua_ssl_verify_depth 2;

    init_by_lua_block {
        require("resty.acme.autossl").init({
            -- Einstellung der folgenden auf true
            -- impliziert, dass Sie https://letsencrypt.org/repository/ gelesen und akzeptiert haben
            tos_accepted = true,
            -- die folgende für die Ersteinrichtung auskommentieren
            -- staging = true,
            -- die folgende auskommentieren, um RSA + ECC-Doppelzertifikat zu aktivieren
            -- domain_key_types = { 'rsa', 'ecc' },
            -- die folgende auskommentieren, um die tls-alpn-01-Herausforderung zu aktivieren
            enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
            account_key_path = "/etc/openresty/account.key",
            account_email = "[email protected]",
            domain_whitelist = { "example.com" },
            storage_adapter = "file",
        })
    }
    init_worker_by_lua_block {
        require("resty.acme.autossl").init_worker()
    }

    server {
        listen 80;
        listen unix:/tmp/nginx-default.sock ssl;
        # listen unix:/tmp/nginx-default.sock ssl proxy_protocol;
        server_name example.com;

        # set_real_ip_from unix:;
        # real_ip_header proxy_protocol;

        # Fallback-Zertifikate, stellen Sie sicher, dass Sie sie vorher erstellt haben
        ssl_certificate /etc/openresty/default.pem;
        ssl_certificate_key /etc/openresty/default.key;

        ssl_certificate_by_lua_block {
            require("resty.acme.autossl").ssl_certificate()
        }

        location /.well-known {
            content_by_lua_block {
                require("resty.acme.autossl").serve_http_challenge()
            }
        }
    }
}

stream {
    init_worker_by_lua_block {
        require("resty.acme.autossl").init({
            -- Einstellung der folgenden auf true
            -- impliziert, dass Sie https://letsencrypt.org/repository/ gelesen und akzeptiert haben
            tos_accepted = true,
            -- die folgende für die Ersteinrichtung auskommentieren
            -- staging = true,
            -- die folgende auskommentieren, um RSA + ECC-Doppelzertifikat zu aktivieren
            -- domain_key_types = { 'rsa', 'ecc' },
            -- die folgende auskommentieren, um die tls-alpn-01-Herausforderung zu aktivieren
            enabled_challenge_handlers = { 'http-01', 'tls-alpn-01' },
            account_key_path = "/etc/openresty/account.key",
            account_email = "[email protected]",
            domain_whitelist = { "example.com" },
            storage_adapter = "file"
        })
        require("resty.acme.autossl").init_worker()
    }

    map $ssl_preread_alpn_protocols $backend {
        ~\bacme-tls/1\b unix:/tmp/nginx-tls-alpn.sock;
        default unix:/tmp/nginx-default.sock;
    }

    server {
            listen 443;
            listen [::]:443;

            ssl_preread on;
            proxy_pass $backend;

            # proxy_protocol on;
    }

    server {
            listen unix:/tmp/nginx-tls-alpn.sock ssl;
            # listen nix:/tmp/nginx-tls-alpn.sock ssl proxy_protocol;
            ssl_certificate certs/default.pem;
            ssl_certificate_key certs/default.key;

            # erfordert --with-stream_realip_module
            # set_real_ip_from unix:;

            ssl_certificate_by_lua_block {
                    require("resty.acme.autossl").serve_tls_alpn_challenge()
            }

            content_by_lua_block {
                    ngx.exit(0)
            }
    }
}

In der obigen Beispielkonfiguration haben wir einen HTTP-Server und zwei Stream-Server eingerichtet.

Der ganz vorne stehende Stream-Server hört auf Port 443 und leitet basierend auf dem Client-ALPN an verschiedene Upstreams weiter. Der tls-alpn-01-Responder hört auf unix:/tmp/nginx-tls-alpn.sock. Der gesamte normale HTTPS-Verkehr hört auf unix:/tmp/nginx-default.sock.

                                                [Stream-Server unix:/tmp/nginx-tls-alpn.sock ssl]
                                            Y /
[Stream-Server 443] --- ALPN ist acme-tls ?
                                            N \
                                                [HTTP-Server unix:/tmp/nginx-default.sock ssl]
  • Die Konfiguration, die an require("resty.acme.autossl").init in beiden Subsystemen übergeben wird, sollte so ähnlich wie möglich gehalten werden.
  • Der tls-alpn-01-Herausforderungs-Handler benötigt keine Drittanbieterabhängigkeiten.
  • Sie können die http-01- und tls-alpn-01-Herausforderungs-Handler gleichzeitig aktivieren.
  • Die http- und stream-Subsysteme teilen sich kein shm, daher sollten Sie in Betracht ziehen, einen anderen Speicher als shm zu verwenden. Wenn Sie shm verwenden müssen, müssen Sie diesen Patch anwenden.

dns-01 Herausforderung

Die DNS-01-Herausforderung wird in lua-resty-acme > 0.13.0 unterstützt. Derzeit werden folgende DNS-Anbieter unterstützt:

  • cloudflare: Cloudflare
  • dynv6: Dynv6
  • dnspod-intl: Dnspod International (nur Dnspod-Token wird unterstützt und verwenden Sie id,token im geheimen Feld)

Um zu erfahren, wie Sie einen neuen DNS-Anbieter für die Verwendung mit der dns-01-Herausforderung erweitern können, siehe DNS-Anbieter.

Ein Beispielkonfiguration zur Verwendung der dns-01-Herausforderung wäre:

require("resty.acme.autossl").init({
  -- Einstellung der folgenden auf true
  -- impliziert, dass Sie https://letsencrypt.org/repository/ gelesen und akzeptiert haben
  tos_accepted = true,
  -- die folgende für die Ersteinrichtung auskommentieren
  -- staging = true,
  -- die folgende auskommentieren, um RSA + ECC-Doppelzertifikat zu aktivieren
  -- domain_key_types = { 'rsa', 'ecc' },
  -- setzen Sie `http-01` oder `tls-alpn-01` nicht, wenn Sie nur planen, dns-01 zu verwenden.
  enabled_challenge_handlers = { 'dns-01' },
  account_key_path = "/etc/openresty/account.key",
  account_email = "[email protected]",
  domain_whitelist = { "example.com", "subdomain.anotherdomain.com" },

  dns_provider_accounts = {
    {
      name = "cloudflare_prod",
      provider = "cloudflare",
      secret = "apikey von cloudflare",
      domains = { "example.com" },
    },
    {
      name = "dynv6_staging",
      provider = "dynv6",
      secret = "apikey von dynv6",
      domains = { "*.anotherdomain.com" },
    },
  },
  -- die folgende auskommentieren, um anotherdomain.com im CN und *.anotherdomain.com im SAN zu erstellen
  -- wildcard_domain_in_san = true,
})

Standardmäßig versucht diese Bibliothek bis zu 5 Minuten auf die DNS-Propagation. Wenn die Standard-TTL für den DNS-Anbieter länger ist, möchte der Benutzer möglicherweise challenge_start_delay manuell anpassen, um länger zu warten.

resty.acme.autossl

Eine Konfigurationstabelle kann an resty.acme.autossl.init() übergeben werden, die Standardwerte sind:

default_config = {
  -- akzeptieren Sie die Nutzungsbedingungen https://letsencrypt.org/repository/
  tos_accepted = false,
  -- wenn die Let's Encrypt-Staging-API verwendet wird
  staging = false,
  -- der Pfad zum privaten Schlüssel des Kontos im PEM-Format
  account_key_path = nil,
  -- die E-Mail-Adresse des Kontos zur Registrierung
  account_email = nil,
  -- Anzahl der Zertifikats-Cache pro Typ
  cache_size = 100,
  domain_key_paths = {
    -- der globale Domain-RSA-Private-Key
    rsa = nil,
    -- der globale Domain-ECC-Private-Key
    ecc = nil,
  },
  -- der zu verwendende private Schlüsselalgorithmus, kann einer oder beide sein
  -- 'rsa' und 'ecc'
  domain_key_types = { 'rsa' },
  -- die Registrierung neuer Zertifikate nur auf Domains beschränken, die in dieser Tabelle definiert sind
  domain_whitelist = nil,
  -- die Registrierung neuer Zertifikate nur auf Domains beschränken, die von dieser Funktion überprüft werden
  domain_whitelist_callback = nil,
  -- Intervall, um vor dem erneuten Versuch nach einer fehlgeschlagenen Zertifikatsanforderung zu warten
  failure_cooloff = 300,
  -- Funktion, die das Intervall zurückgibt, um vor dem erneuten Versuch nach einer fehlgeschlagenen Zertifikatsanforderung zu warten
  failure_cooloff_callback = nil,
  -- die Schwelle zur Erneuerung eines Zertifikats, bevor es abläuft, in Sekunden
  renew_threshold = 7 * 86400,
  -- Intervall zur Überprüfung der Zertifikatserneuerung, in Sekunden
  renew_check_interval = 6 * 3600,
  -- die Zertifikate speichern
  storage_adapter = "shm",
  -- die Speicherconfig, die an den Speicheradapter übergeben wird
  storage_config = {
    shm_name = 'acme',
  },
  -- die aktivierten Herausforderungsarten
  enabled_challenge_handlers = { 'http-01' },
  -- Zeit, um zu warten, bevor das ACME-Server zur Validierung signalisiert wird, in Sekunden
  challenge_start_delay = 0,
  -- wenn true, wartet die Anfrage an nginx, bis das Zertifikat generiert wurde und sofort verwendet wird
  blocking = false,
  -- wenn true, wird das Zertifikat für Domains, die nicht in der Whitelist sind, aus dem Speicher gelöscht
  enabled_delete_not_whitelisted_domain = false,
  -- das Verzeichnis der DNS-Anbieter, jeder Anbieter sollte die folgende Struktur haben:
  -- {
  --   name = "prod_account",
  --   provider = "provider_name", -- "cloudflare" oder "dynv6"
  --   secret  = "der API-Schlüssel oder Token",
  --   domains = { "example.com", "*.example.com" }, -- die Liste der Domains, die mit diesem Anbieter verwendet werden können
  -- }
  dns_provider_accounts = {},
  -- wenn aktiviert, werden Wildcard-Domains wie *.example.com als SAN erstellt und CN wird example.com sein
  wildcard_domain_in_san = false,
}

Wenn account_key_path nicht angegeben ist, wird bei jedem Nginx-Konfigurationsneuladen ein neuer Kontoschlüssel erstellt. Beachten Sie, dass dies New Account Ratenbegrenzung auf der Let's Encrypt API auslösen kann.

Wenn domain_key_paths nicht angegeben ist, wird für jedes Zertifikat ein neuer privater Schlüssel generiert (4096-Bit RSA und 256-Bit prime256v1 ECC). Beachten Sie, dass die Generierung eines solchen Schlüssels den Worker blockiert und insbesondere auf VMs, bei denen die Entropie niedrig ist, auffällig sein wird.

Übergeben Sie die Konfigurationstabelle direkt als zweiten Parameter an den ACME-Client. Das folgende Beispiel zeigt, wie man einen CA-Anbieter verwendet, der nicht Let's Encrypt ist, und auch die bevorzugte Kette festlegt.

resty.acme.autossl.init({
    tos_accepted = true,
    account_email = "[email protected]",
  }, {
    api_uri = "https://acme.otherca.com/directory",
    preferred_chain = "OtherCA PKI Root CA",
  }
)

Siehe auch Speicheradapter unten.

Bei der Verwendung von verteilten Speichertypen ist es nützlich, challenge_start_delay zu erhöhen, um Änderungen im Speicher zu propagieren. Wenn challenge_start_delay auf 0 gesetzt ist, wird vor dem Start der Validierung der Herausforderungen keine Wartezeit eingehalten.

autossl.get_certkey

Syntax: certkey, err = autossl.get_certkey(domain, type?)

Gibt das PEM-kodierte Zertifikat und den privaten Schlüssel für domain aus dem Speicher zurück. Akzeptiert optional einen type-Parameter, der "rsa" oder "ecc" sein kann; wenn er weggelassen wird, wird der type standardmäßig auf "rsa" gesetzt.

resty.acme.client

client.new

Syntax: c, err = client.new(config)

Erstellt einen ACMEv2-Client.

Standardwerte für config sind:

default_config = {
  -- der ACME v2 API-Endpunkt, der verwendet werden soll
  api_uri = "https://acme-v02.api.letsencrypt.org/directory",
  -- die E-Mail-Adresse des Kontos zur Registrierung
  account_email = nil,
  -- der Kontoschlüssel im PEM-Format
  account_key = nil,
  -- die Kontokennung (als URL)
  account_kid = nil,
  -- externe Kontobindungsschlüssel-ID
  eab_kid = nil,
  -- externer Kontobindungshmac-Schlüssel, base64url-kodiert
  eab_hmac_key = nil,
  -- externer Kontoregistrierungs-Handler
  eab_handler = nil,
  -- Speicher für Herausforderungen
  storage_adapter = "shm",
  -- die Speicherconfig, die an den Speicheradapter übergeben wird
  storage_config = {
    shm_name = "acme"
  },
  -- die aktivierten Herausforderungsarten, Auswahl von `http-01` und `tls-alpn-01`
  enabled_challenge_handlers = {"http-01"},
  -- wähle den bevorzugten Root-CA-Aussteller-Common-Name, falls zutreffend
  preferred_chain = nil,
  -- Callback-Funktion, die es ermöglicht, zu warten, bevor das ACME-Server zur Validierung signalisiert wird
  challenge_start_callback = nil,
  -- das Verzeichnis der DNS-Anbieter, jeder Anbieter sollte die folgende Struktur haben:
  dns_provider_accounts = {},
}

Wenn account_kid weggelassen wird, muss der Benutzer client:new_account() aufrufen, um ein neues Konto zu registrieren. Beachten Sie, dass bei Verwendung des gleichen account_key client:new_account() die gleiche kid zurückgibt, die zuvor registriert wurde.

Wenn die CA External Account Binding erfordert, kann der Benutzer eab_kid und eab_hmac_key festlegen, um ein vorhandenes Konto zu laden, oder account_email und eab_handler festlegen, um ein neues Konto zu registrieren. eab_hmac_key muss base64 url kodiert sein. Im späteren Fall muss der Benutzer client:new_account() aufrufen, um ein neues Konto zu registrieren. eab_handler muss eine Funktion sein, die die account_email als Parameter akzeptiert und eab_kid, eab_hmac_key und Fehler, falls vorhanden, zurückgibt.

eab_handler = function(account_email)
  -- etwas tun, um ein Konto mit account_email zu registrieren
  -- wenn err dann
  --  return nil, nil, err
  -- end
  return eab_kid, eab_hmac_key
end

Der folgende EAB-Handler des CA-Anbieters wird von lua-resty-acme unterstützt, und der Benutzer muss seinen eigenen eab_handler nicht implementieren:

preferred_chain wird verwendet, um eine Kette mit übereinstimmendem Common Name in ihrer Root-CA auszuwählen. Zum Beispiel kann der Benutzer "ISRG Root X1" verwenden, um die neue Standardkette in Let's Encrypt zu erzwingen. Wenn kein Wert konfiguriert ist oder der konfigurierte Name in keiner Kette gefunden wird, wird die Standardkette verwendet.

challenge_start_callback ist eine Callback-Funktion, die es dem Client ermöglicht, zu warten, bevor das ACME-Server zur Validierung der Herausforderung signalisiert wird. Dies ist nützlich in einer verteilten Umgebung, in der Herausforderungen Zeit benötigen, um sich zu propagieren. challenge_start_callback akzeptiert challenge_type und challenge_token. Der Client ruft diese Funktion jede Sekunde auf, bis sie true zurückgibt, was anzeigt, dass die Herausforderung gestartet werden sollte; wenn dieser challenge_start_callback nicht gesetzt ist, wird keine Wartezeit eingehalten.

challenge_start_callback = function(challenge_type, challenge_token)
  -- hier etwas tun
  -- wenn wir gut sind
  return true
end

Siehe auch Speicheradapter unten.

client:init

Syntax: err = client:init()

Initialisiert den Client, erfordert die Verfügbarkeit der Cosocket-API. Diese Funktion wird ein Konto anmelden oder registrieren.

client:order_certificate

Syntax: err = client:order_certificate(domain,...)

Erstellt ein Zertifikat mit einer oder mehreren Domains. Beachten Sie, dass Wildcard-Domains nicht unterstützt werden, da sie nur durch die dns-01 Herausforderung überprüft werden können.

client:serve_http_challenge

Syntax: client:serve_http_challenge()

Bedient die http-01 Herausforderung. Ein gängiger Anwendungsfall wäre, dies als content_by_* Block für den /.well-known-Pfad zu setzen.

client:serve_tls_alpn_challenge

Syntax: client:serve_tls_alpn_challenge()

Bedient die tls-alpn-01 Herausforderung. Siehe diesen Abschnitt zur Verwendung dieses Handlers.

Speicheradapter

Speicheradapter werden in autossl oder dem ACME client verwendet, um temporäre oder persistente Daten zu speichern. Abhängig von der Bereitstellungsumgebung stehen derzeit fünf Speicheradapter zur Auswahl. Um einen benutzerdefinierten Speicheradapter zu implementieren, siehe dieses Dokument.

file

Dateisystembasierter Speicher. Beispielkonfiguration:

storage_config = {
    dir = '/etc/openresty/storage',
}
Wenn dir weggelassen wird, wird das temporäre Verzeichnis des Betriebssystems verwendet.

luafilesystem oder luafilesystem-ffi wird benötigt, wenn der file-Speicher für Erneuerungen verwendet wird.

shm

Speicher auf Basis des Lua Shared Dict. Beachten Sie, dass dieser Speicher zwischen NGINX-Neustarts (nicht -Neuladen) volatil ist. Beispielkonfiguration:

storage_config = {
    shm_name = 'dict_name',
}

redis

Redis-basierter Speicher. Die Standardkonfiguration ist:

storage_config = {
    host = '127.0.0.1',
    port = 6379,
    database = 0,
    -- Redis-Authentifizierungsschlüssel
    auth = nil,
    ssl = false,
    ssl_verify = false,
    ssl_server_name = nil,
    -- Namespace als Präfix des Schlüssels
    namespace = "",
}

Redis >= 2.6.12 ist erforderlich, da dieser Speicher SET EX benötigt.

vault

Hashicorp Vault basierter Speicher. Nur KV V2 Backend wird unterstützt. Die Standardkonfiguration ist:

storage_config = {
    host = '127.0.0.1',
    port = 8200,
    -- Geheimnisse kv-Präfixpfad
    kv_path = "acme",
    -- Timeout in ms
    timeout = 2000,
    -- HTTPS verwenden
    https = false,
    -- TLS-Überprüfung aktivieren
    tls_verify = true,
    -- SNI, das in der Anfrage verwendet wird, standardmäßig auf Host gesetzt, wenn weggelassen
    tls_server_name = nil,
    -- Authentifizierungsmethode, standardmäßig auf Token, kann "token" oder "kubernetes" sein
    auth_method = "token",
    -- Vault-Token
    token = nil,
    -- Authentifizierungspfad von Vault, der verwendet werden soll
    auth_path = "kubernetes",
    -- Die Rolle, die versucht wird zuzuweisen
    auth_role = nil,
    -- Der Pfad zum JWT
    jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",
    -- Vault-Namespace
    namespace = nil,
}

Unterstützung für verschiedene Authentifizierungsmethoden

  • Token: Dies ist die Standardmethode und ermöglicht es, ein wörtliches "Token" in der Konfiguration zu übergeben.
  • Kubernetes: Über diese Methode kann man die integrierte Authentifizierungsmethode von Vault für Kubernetes nutzen. Was dies im Wesentlichen tut, ist, das Token des Dienstkontos zu nehmen und zu validieren, dass es von der Kubernetes-CA signiert wurde. Der Hauptvorteil hier ist, dass Konfigurationsdateien Ihr Token nicht mehr offenlegen.

Die folgenden Konfigurationen gelten hier: lua -- Authentifizierungspfad von Vault, der verwendet werden soll auth_path = "kubernetes", -- Die Rolle, die versucht wird zuzuweisen auth_role = nil, -- Der Pfad zum JWT jwt_path = "/var/run/secrets/kubernetes.io/serviceaccount/token",

consul

Hashicorp Consul basierter Speicher. Die Standardkonfiguration ist:

storage_config = {
    host = '127.0.0.1',
    port = 8500,
    -- kv-Präfixpfad
    kv_path = "acme",
    -- Consul ACL-Token
    token = nil,
    -- Timeout in ms
    timeout = 2000,
}

etcd

etcd basierter Speicher. Derzeit wird nur das v3-Protokoll unterstützt, und die etcd-Serverversion sollte >= v3.4.0 sein. Die Standardkonfiguration ist:

storage_config = {
    http_host = 'http://127.0.0.1:4001',
    key_prefix = '',
    timeout = 60,
    ssl_verify = false,
}

Etcd-Speicher erfordert die Bibliothek lua-resty-etcd, die installiert werden muss. Sie kann manuell mit opm install api7/lua-resty-etcd oder luarocks install lua-resty-etcd installiert werden.

DNS-Anbieter

Um einen benutzerdefinierten DNS-Anbieter zu erstellen, befolgen Sie diese Schritte:

  • Erstellen Sie eine Datei wie route53.lua unter lib/resty/acme/dns_provider
  • Implementieren Sie die folgende Funktionssignatur
function _M.new(token)
  -- ... 
  return self
end

function _M:post_txt_record(fqdn, content)
  return ok, err
end

function _M:delete_txt_record(fqdn)
  return ok, err
end

Dabei ist token der API-Schlüssel, fqdn der DNS-Datensatzname, um den Datensatz festzulegen, und content der Wert des Datensatzes.

Testen

Richten Sie die End-to-End-Testumgebung ein, indem Sie bash t/fixtures/prepare_env.sh ausführen.

Führen Sie dann cpanm install Test::Nginx::Socket aus und anschließend prove -r t.

Siehe auch

GitHub

Sie finden zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-acme.