alpine&dep updates/changing must-staple&acme server now also effect renewals/change default mime types to download

This commit is contained in:
Zoey 2024-12-14 18:13:49 +01:00
parent 2bebb45baa
commit baeef95a5f
No known key found for this signature in database
GPG key ID: 02A3919EB4F67328
14 changed files with 139 additions and 46 deletions

View file

@ -16,7 +16,7 @@ const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx'); const internalNginx = require('./nginx');
const certbotCommand = 'certbot'; const certbotCommand = 'certbot';
const certbotArgs = ['--logs-dir', '/tmp/certbot-log', '--work-dir', '/tmp/certbot-work', '--config-dir', '/data/tls/certbot', '--config', '/etc/certbot.ini', '--agree-tos', '--non-interactive', '--no-eff-email', '--register-unsafely-without-email', ...(process.env.ACME_MUST_STAPLE === 'false' ? [] : ['--must-staple']), ...(process.env.ACME_SERVER_TLS_VERIFY === 'false' ? ['--no-verify-ssl'] : [])]; const certbotArgs = ['--logs-dir', '/tmp/certbot-log', '--work-dir', '/tmp/certbot-work', '--config-dir', '/data/tls/certbot', '--config', '/etc/certbot.ini', '--agree-tos', '--non-interactive', '--no-eff-email', '--register-unsafely-without-email', ...(process.env.ACME_SERVER_TLS_VERIFY === 'false' ? ['--no-verify-ssl'] : [])];
function omissions() { function omissions() {
return ['is_deleted', 'owner.is_deleted']; return ['is_deleted', 'owner.is_deleted'];
@ -42,7 +42,7 @@ const internalCertificate = {
logger.info('Renewing TLS certs close to expiry...'); logger.info('Renewing TLS certs close to expiry...');
return utils return utils
.execFile(certbotCommand, [...certbotArgs, 'renew', '--quiet', '--no-random-sleep-on-renew']) .execFile(certbotCommand, [...certbotArgs, 'renew', '--server', process.env.ACME_SERVER, '--quiet', '--no-random-sleep-on-renew'])
.then((result) => { .then((result) => {
if (result) { if (result) {
logger.info('Renew Result: ' + result); logger.info('Renew Result: ' + result);
@ -761,7 +761,7 @@ const internalCertificate = {
requestCertbot: (certificate) => { requestCertbot: (certificate) => {
logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
return utils.execFile(certbotCommand, [...certbotArgs, 'certonly', '--cert-name', `npm-${certificate.id}`, '--domains', `${certificate.domain_names.join(',')}`, '--server', `${process.env.ACME_SERVER}`, '--authenticator', 'webroot', '--webroot-path', '/tmp/acme-challenge']).then((result) => { return utils.execFile(certbotCommand, [...certbotArgs, 'certonly', '--cert-name', `npm-${certificate.id}`, '--domains', certificate.domain_names.join(','), '--server', process.env.ACME_SERVER, '--authenticator', 'webroot', '--webroot-path', '/tmp/acme-challenge']).then((result) => {
logger.success(result); logger.success(result);
return result; return result;
}); });
@ -787,7 +787,7 @@ const internalCertificate = {
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 }); fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 });
try { try {
const result = await utils.execFile(certbotCommand, [...certbotArgs, 'certonly', '--cert-name', `npm-${certificate.id}`, '--domains', `${certificate.domain_names.join(',')}`, '--server', `${process.env.ACME_SERVER}`, '--authenticator', dnsPlugin.full_plugin_name, `--${dnsPlugin.full_plugin_name}-credentials`, credentialsLocation]); const result = await utils.execFile(certbotCommand, [...certbotArgs, 'certonly', '--cert-name', `npm-${certificate.id}`, '--domains', certificate.domain_names.join(','), '--server', process.env.ACME_SERVER}, '--authenticator', dnsPlugin.full_plugin_name, `--${dnsPlugin.full_plugin_name}-credentials`, credentialsLocation, ...(certificate.meta.propagation_seconds !== undefined ? [`--${dnsPlugin.full_plugin_name}-propagation-seconds`] : []), ...(certificate.meta.propagation_seconds !== undefined ? [certificate.meta.propagation_seconds] : [])]);
logger.info(result); logger.info(result);
return result; return result;
} catch (err) { } catch (err) {
@ -850,7 +850,7 @@ const internalCertificate = {
const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']); const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']);
logger.info(revokeResult); logger.info(revokeResult);
const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']); const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--server', process.env.ACME_SERVER, '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']);
logger.info(renewResult); logger.info(renewResult);
return renewResult; return renewResult;
@ -872,7 +872,7 @@ const internalCertificate = {
const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']); const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']);
logger.info(revokeResult); logger.info(revokeResult);
const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']); const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--server', process.env.ACME_SERVER, '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']);
logger.info(renewResult); logger.info(renewResult);
return renewResult; return renewResult;
@ -982,18 +982,18 @@ const internalCertificate = {
} else if (result.error) { } else if (result.error) {
logger.info(`HTTP challenge test failed for domain ${domain} because error was returned: ${result.error.msg}`); logger.info(`HTTP challenge test failed for domain ${domain} because error was returned: ${result.error.msg}`);
return `other:${result.error.msg}`; return `other:${result.error.msg}`;
} else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') { } else if (result.responsecode === '200' && result.htmlresponse === 'Success') {
// Server exists and has responded with the correct data // Server exists and has responded with the correct data
return 'ok'; return 'ok';
} else if (`${result.responsecode}` === '200') { } else if (result.responsecode === '200') {
// Server exists but has responded with wrong data // Server exists but has responded with wrong data
logger.info(`HTTP challenge test failed for domain ${domain} because of invalid returned data:`, result.htmlresponse); logger.info(`HTTP challenge test failed for domain ${domain} because of invalid returned data:`, result.htmlresponse);
return 'wrong-data'; return 'wrong-data';
} else if (`${result.responsecode}` === '404') { } else if (result.responsecode === '404') {
// Server exists but responded with a 404 // Server exists but responded with a 404
logger.info(`HTTP challenge test failed for domain ${domain} because code 404 was returned`); logger.info(`HTTP challenge test failed for domain ${domain} because code 404 was returned`);
return '404'; return '404';
} else if (`${result.responsecode}` === '0' || (typeof result.reason === 'string' && result.reason.toLowerCase() === 'host unavailable')) { } else if (result.responsecode === '0' || (typeof result.reason === 'string' && result.reason.toLowerCase() === 'host unavailable')) {
// Server does not exist at domain // Server does not exist at domain
logger.info(`HTTP challenge test failed for domain ${domain} the host was not found`); logger.info(`HTTP challenge test failed for domain ${domain} the host was not found`);
return 'no-host'; return 'no-host';

View file

@ -15,8 +15,9 @@ include conf.d/include/always.conf;
{%- if use_default_location %} {%- if use_default_location %}
location / { location / {
include conf.d/include/always.conf; include conf.d/include/always.conf;
root /html/dead; root /html/404deadpage;
try_files $uri /index.html; error_page 404 /404deadpage.html;
return 404;
} }
{%- endif %} {%- endif %}

View file

@ -26,8 +26,9 @@ server {
{%- if value == "404" %} {%- if value == "404" %}
location / { location / {
include conf.d/include/always.conf; include conf.d/include/always.conf;
root /html/dead; root /html/404deadpage;
try_files $uri /index.html; error_page 404 /404deadpage.html;
return 404;
} }
{%- endif %} {%- endif %}

View file

@ -11,10 +11,10 @@ services:
environment: environment:
- "TZ=your-timezone" # set timezone, required, set it to one of the values from the "TZ identifier" https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List - "TZ=your-timezone" # set timezone, required, set it to one of the values from the "TZ identifier" https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
- "ACME_EMAIL=your-email" # email address which should be used for acme, currently optional, may be required in the future, so I recommend you to enter your email here - "ACME_EMAIL=your-email" # email address which should be used for acme, currently optional, may be required in the future, so I recommend you to enter your email here
# - "ACME_SERVER=https://acme.zerossl.com/v2/DV90" # acme server to use for NEW certificates, default is (currently, may change later) set to: https://acme-v02.api.letsencrypt.org/directory (letsencrypt) # - "ACME_SERVER=https://dv.acme-v02.api.pki.goog/directory" # acme server to used when requesting/renewing certs using certbot, default is (currently, may change later) set to: https://acme-v02.api.letsencrypt.org/directory (letsencrypt)
# - "ACME_EAB_KID=123456789abcdef" # Key Identifier for External Account Binding for the acme server # - "ACME_EAB_KID=123456789abcdef" # Key Identifier for External Account Binding for the acme server
# - "ACME_EAB_HMAC_KEY=123456789abcdef" # HMAC key for External Account Binding for the acme server # - "ACME_EAB_HMAC_KEY=123456789abcdef" # HMAC key for External Account Binding for the acme server
# - "ACME_MUST_STAPLE=false" # enables must-staple, default true, please only disable it if you get this error MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING in Firefox, see https://github.com/ZoeyVid/NPMplus/discussions/1249, after changing this option you need to recreate (not renew) your certs # - "ACME_MUST_STAPLE=false" # enables must-staple, default true (will change soon, see https://github.com/ZoeyVid/NPMplus/discussions/1285), I recommend you to enable this if your CA supports it
# - "ACME_SERVER_TLS_VERIFY=false" # enables checking if ACME_SERVER has a valid TLS cert, default true # - "ACME_SERVER_TLS_VERIFY=false" # enables checking if ACME_SERVER has a valid TLS cert, default true
# - "PUID=1000" # set group id, default 0 (root) # - "PUID=1000" # set group id, default 0 (root)
# - "PGID=1000" # set user id, default 0 (root), requires PUID # - "PGID=1000" # set user id, default 0 (root), requires PUID

View file

@ -105,7 +105,6 @@
</div> </div>
<!-- DNS propagation delay --> <!-- DNS propagation delay -->
<!---
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
@ -125,7 +124,6 @@
</div> </div>
</div> </div>
</div> </div>
--->
</fieldset> </fieldset>
</div> </div>

View file

@ -144,7 +144,6 @@
</div> </div>
<!-- DNS propagation delay --> <!-- DNS propagation delay -->
<!---
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
@ -164,7 +163,6 @@
</div> </div>
</div> </div>
</div> </div>
--->
</fieldset> </fieldset>
</div> </div>

View file

@ -212,7 +212,6 @@
</div> </div>
<!-- DNS propagation delay --> <!-- DNS propagation delay -->
<!---
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
@ -232,7 +231,6 @@
</div> </div>
</div> </div>
</div> </div>
--->
</fieldset> </fieldset>
</div> </div>

View file

@ -193,7 +193,6 @@
</div> </div>
<!-- DNS propagation delay --> <!-- DNS propagation delay -->
<!---
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<div class="form-group mb-0"> <div class="form-group mb-0">
@ -213,7 +212,6 @@
</div> </div>
</div> </div>
</div> </div>
--->
</fieldset> </fieldset>
</div> </div>

View file

@ -52,7 +52,7 @@
"certificate": "Zertifikat", "certificate": "Zertifikat",
"created": "Erstellt {name}", "created": "Erstellt {name}",
"date": "Date", "date": "Date",
"dead-host": "404 Host", "dead-host": "Dead Host",
"deleted": "Gelöscht {name}", "deleted": "Gelöscht {name}",
"disabled": "Deaktiviert {name}", "disabled": "Deaktiviert {name}",
"empty": "Es gibt keine Protokolle.", "empty": "Es gibt keine Protokolle.",
@ -100,15 +100,15 @@
"title": "Hallo {name}" "title": "Hallo {name}"
}, },
"dead-hosts": { "dead-hosts": {
"add": "404 Host hinzufügen", "add": "Dead Host hinzufügen",
"delete": "404 Host löschen", "delete": "Dead Host löschen",
"delete-confirm": "Sind Sie sicher, dass Sie diesen 404-Host löschen wollen?", "delete-confirm": "Sind Sie sicher, dass Sie diesen Dead-Host löschen wollen?",
"empty": "Es gibt keine 404 Hosts", "empty": "Es gibt keine Dead Hosts",
"form-title": "{id, select, undefined{Neuer} other{Bearbeitung}} 404 Host", "form-title": "{id, select, undefined{Neuer} other{Bearbeitung}} Dead Host",
"help-content": "Ein 404-Host ist einfach eine Host-Einrichtung, die eine 404-Seite anzeigt.\nDies kann nützlich sein, wenn Ihre Domain in Suchmaschinen gelistet ist und Sie eine schönere Fehlerseite bereitstellen wollen oder um den Suchindexierern mitzuteilen, dass die Domain-Seiten nicht mehr existieren.\nEin weiterer Vorteil dieses Hosts besteht darin, dass man die Logs der Zugriffe auf ihn verfolgen und die Verweiser einsehen kann.", "help-content": "Ein Dead-Host ist einfach eine Host-Einrichtung, die eine 404-Seite anzeigt.\nDies kann nützlich sein, wenn Ihre Domain in Suchmaschinen gelistet ist und Sie eine schönere Fehlerseite bereitstellen wollen oder um den Suchindexierern mitzuteilen, dass die Domain-Seiten nicht mehr existieren.\nEin weiterer Vorteil dieses Hosts besteht darin, dass man die Logs der Zugriffe auf ihn verfolgen und die Verweiser einsehen kann.",
"help-title": "Was ist ein 404-Host?", "help-title": "Was ist ein Dead-Host?",
"search": "Suche Host..", "search": "Suche Host..",
"title": "404 Hosts" "title": "Dead Hosts"
}, },
"footer": { "footer": {
"copy-npm": " - &copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM", "copy-npm": " - &copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM",
@ -177,7 +177,7 @@
}, },
"settings": { "settings": {
"default-site": "Standard-Seite", "default-site": "Standard-Seite",
"default-site-404": "404 Seite", "default-site-404": "Dead Seite",
"default-site-444": "Verbindung abbrechen - erlaubt nur certbot dns-challenge", "default-site-444": "Verbindung abbrechen - erlaubt nur certbot dns-challenge",
"default-site-congratulations": "Glückwunsch-Seite", "default-site-congratulations": "Glückwunsch-Seite",
"default-site-description": "Was angezeigt werden soll, wenn Nginx einen unbekannten Host antrifft", "default-site-description": "Was angezeigt werden soll, wenn Nginx einen unbekannten Host antrifft",
@ -256,7 +256,7 @@
"no-wildcard-without-dns": "Zertifikat kann nicht für Wildcard-Domains angefordert werden, wenn keine DNS-Challenge verwendet wird", "no-wildcard-without-dns": "Zertifikat kann nicht für Wildcard-Domains angefordert werden, wenn keine DNS-Challenge verwendet wird",
"none": "Nur HTTP", "none": "Nur HTTP",
"other": "Individuell", "other": "Individuell",
"passphrase-protection-support-info": "Schlüsseldateien, die mit einer Passphrase geschützt sind, werden nicht unterstützt.", "passphrase-protection-support-info": "Schlüsseldateien, die mit einer Passphrase geschützt sind, werden nicht unterstützt. OCSP Stapling wird bei Custom Zertifikaten nicht untersützt.",
"processing-info": "Verarbeitung... Dies kann ein paar Minuten dauern.", "processing-info": "Verarbeitung... Dies kann ein paar Minuten dauern.",
"propagation-seconds": "Ausbreitung in Sekunden", "propagation-seconds": "Ausbreitung in Sekunden",
"propagation-seconds-info": "Leer lassen, um den Standardwert des Plugins zu verwenden. Anzahl der Sekunden, die auf die DNS-Verbreitung gewartet werden soll.", "propagation-seconds-info": "Leer lassen, um den Standardwert des Plugins zu verwenden. Anzahl der Sekunden, die auf die DNS-Verbreitung gewartet werden soll.",

View file

@ -52,7 +52,7 @@
"certificate": "Certificate", "certificate": "Certificate",
"created": "Created {name}", "created": "Created {name}",
"date": "Date", "date": "Date",
"dead-host": "404 Host", "dead-host": "Dead Host",
"deleted": "Deleted {name}", "deleted": "Deleted {name}",
"disabled": "Disabled {name}", "disabled": "Disabled {name}",
"empty": "There are no logs.", "empty": "There are no logs.",
@ -100,15 +100,15 @@
"title": "Hi {name}" "title": "Hi {name}"
}, },
"dead-hosts": { "dead-hosts": {
"add": "Add 404 Host", "add": "Add Dead Host",
"delete": "Delete 404 Host", "delete": "Delete Dead Host",
"delete-confirm": "Are you sure you want to delete this 404 Host?", "delete-confirm": "Are you sure you want to delete this Dead Host?",
"empty": "There are no 404 Hosts", "empty": "There are no Dead Hosts",
"form-title": "{id, select, undefined{New} other{Edit}} 404 Host", "form-title": "{id, select, undefined{New} other{Edit}} Dead Host",
"help-content": "A 404 Host is simply a host setup that shows a 404 page.\nThis can be useful when your domain is listed in search engines and you want to provide a nicer error page or specifically to tell the search indexers that the domain pages no longer exist.\nAnother benefit of having this host is to track the logs for hits to it and view the referrers.", "help-content": "A Dead Host is simply a host setup that shows a 404 page.\nThis can be useful when your domain is listed in search engines and you want to provide a nicer error page or specifically to tell the search indexers that the domain pages no longer exist.\nAnother benefit of having this host is to track the logs for hits to it and view the referrers.",
"help-title": "What is a 404 Host?", "help-title": "What is a Dead Host?",
"search": "Search Host…", "search": "Search Host…",
"title": "404 Hosts" "title": "Dead Hosts"
}, },
"footer": { "footer": {
"copy-npm": " - &copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM", "copy-npm": " - &copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM",
@ -256,7 +256,7 @@
"no-wildcard-without-dns": "Cannot request Certificate for wildcard domains when not using DNS challenge", "no-wildcard-without-dns": "Cannot request Certificate for wildcard domains when not using DNS challenge",
"none": "HTTP only", "none": "HTTP only",
"other": "Custom", "other": "Custom",
"passphrase-protection-support-info": "Key files protected with a passphrase are not supported.", "passphrase-protection-support-info": "Key files protected with a passphrase are not supported. OCSP Stapling is not supported on custom certificates.",
"processing-info": "Processing... This might take a few minutes.", "processing-info": "Processing... This might take a few minutes.",
"propagation-seconds": "Propagation Seconds", "propagation-seconds": "Propagation Seconds",
"propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.", "propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.",

View file

@ -3,3 +3,5 @@ key-type = ecdsa
no-reuse-key = true no-reuse-key = true
rsa-key-size = 4096 rsa-key-size = 4096
elliptic-curve = secp384r1 elliptic-curve = secp384r1
must-staple = true

View file

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<title>Dead Host</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="application-name" content="NPMplus" />
<meta name="author" content="ZoeyVid" />
<meta name="description" content="Dead Host Page of NPMplus" />
<meta name="keywords" content="NPMplus, dead, 404" />
<!-- TODO: Icon -->
<link rel="icon" type="image/webp" href="/favicon.webp" />
</head>
<body>
<style>
@media (prefers-color-scheme: dark) {
body {
background-color: rgb(17 24 39);
color: white;
}
#box {
background-color: rgb(31 41 55);
}
}
@media (prefers-color-scheme: light) {
body {
background-color: white;
color: black;
}
#box {
background-color: rgb(229 231 235);
}
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
text-align: center;
}
#box {
border-radius: 2rem;
position: absolute;
padding: 1rem;
padding-right: 5rem;
padding-left: 5rem;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
h1 {
font-size: 64px;
}
p {
font-size: 24px;
}
#notice {
font-size: 12px;
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
@media (max-width: 600px) {
h1 {
font-size: 32px;
}
p {
font-size: 16px;
}
#box {
padding-right: 2rem;
padding-left: 2rem;
}
}
</style>
<div id="box">
<h1>Dead Host</h1>
</div>
<p id="notice">Powered by <a href="https://github.com/ZoeyVid/NPMplus">NPMplus</a></p>
</body>
</html>

View file

@ -7,7 +7,7 @@
<meta name="application-name" content="NPMplus" /> <meta name="application-name" content="NPMplus" />
<meta name="author" content="ZoeyVid" /> <meta name="author" content="ZoeyVid" />
<meta name="description" content="Dead Host Page of NPMplus" /> <meta name="description" content="Dead Host Page of NPMplus" />
<meta name="keywords" content="NPMplus, dead" /> <meta name="keywords" content="NPMplus, dead, 404" />
<!-- TODO: Icon --> <!-- TODO: Icon -->
<link rel="icon" type="image/webp" href="/favicon.webp" /> <link rel="icon" type="image/webp" href="/favicon.webp" />
</head> </head>

View file

@ -355,6 +355,13 @@ fi
if [ "$ACME_MUST_STAPLE" = "true" ]; then
sed -i "s|must-staple = .*|must-staple = true|g" /etc/certbot.ini
else
sed -i "s|must-staple = .*|must-staple = false|g" /etc/certbot.ini
fi
if [ "$PHP82" = "true" ]; then if [ "$PHP82" = "true" ]; then
apk add --no-cache php82-fpm apk add --no-cache php82-fpm