Skip to content

Commit baeef95

Browse files
committed
alpine&dep updates/changing must-staple&acme server now also effect renewals/change default mime types to download
1 parent 2bebb45 commit baeef95

File tree

14 files changed

+139
-46
lines changed

14 files changed

+139
-46
lines changed

backend/internal/certificate.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const internalAuditLog = require('./audit-log');
1616
const internalNginx = require('./nginx');
1717

1818
const certbotCommand = 'certbot';
19-
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'] : [])];
19+
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'] : [])];
2020

2121
function omissions() {
2222
return ['is_deleted', 'owner.is_deleted'];
@@ -42,7 +42,7 @@ const internalCertificate = {
4242
logger.info('Renewing TLS certs close to expiry...');
4343

4444
return utils
45-
.execFile(certbotCommand, [...certbotArgs, 'renew', '--quiet', '--no-random-sleep-on-renew'])
45+
.execFile(certbotCommand, [...certbotArgs, 'renew', '--server', process.env.ACME_SERVER, '--quiet', '--no-random-sleep-on-renew'])
4646
.then((result) => {
4747
if (result) {
4848
logger.info('Renew Result: ' + result);
@@ -761,7 +761,7 @@ const internalCertificate = {
761761
requestCertbot: (certificate) => {
762762
logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
763763

764-
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) => {
764+
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) => {
765765
logger.success(result);
766766
return result;
767767
});
@@ -787,7 +787,7 @@ const internalCertificate = {
787787
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 });
788788

789789
try {
790-
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]);
790+
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] : [])]);
791791
logger.info(result);
792792
return result;
793793
} catch (err) {
@@ -850,7 +850,7 @@ const internalCertificate = {
850850
const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']);
851851
logger.info(revokeResult);
852852

853-
const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']);
853+
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']);
854854
logger.info(renewResult);
855855

856856
return renewResult;
@@ -872,7 +872,7 @@ const internalCertificate = {
872872
const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']);
873873
logger.info(revokeResult);
874874

875-
const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']);
875+
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']);
876876
logger.info(renewResult);
877877

878878
return renewResult;
@@ -982,18 +982,18 @@ const internalCertificate = {
982982
} else if (result.error) {
983983
logger.info(`HTTP challenge test failed for domain ${domain} because error was returned: ${result.error.msg}`);
984984
return `other:${result.error.msg}`;
985-
} else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') {
985+
} else if (result.responsecode === '200' && result.htmlresponse === 'Success') {
986986
// Server exists and has responded with the correct data
987987
return 'ok';
988-
} else if (`${result.responsecode}` === '200') {
988+
} else if (result.responsecode === '200') {
989989
// Server exists but has responded with wrong data
990990
logger.info(`HTTP challenge test failed for domain ${domain} because of invalid returned data:`, result.htmlresponse);
991991
return 'wrong-data';
992-
} else if (`${result.responsecode}` === '404') {
992+
} else if (result.responsecode === '404') {
993993
// Server exists but responded with a 404
994994
logger.info(`HTTP challenge test failed for domain ${domain} because code 404 was returned`);
995995
return '404';
996-
} else if (`${result.responsecode}` === '0' || (typeof result.reason === 'string' && result.reason.toLowerCase() === 'host unavailable')) {
996+
} else if (result.responsecode === '0' || (typeof result.reason === 'string' && result.reason.toLowerCase() === 'host unavailable')) {
997997
// Server does not exist at domain
998998
logger.info(`HTTP challenge test failed for domain ${domain} the host was not found`);
999999
return 'no-host';

backend/templates/dead_host.conf

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ include conf.d/include/always.conf;
1515
{%- if use_default_location %}
1616
location / {
1717
include conf.d/include/always.conf;
18-
root /html/dead;
19-
try_files $uri /index.html;
18+
root /html/404deadpage;
19+
error_page 404 /404deadpage.html;
20+
return 404;
2021
}
2122
{%- endif %}
2223

backend/templates/default.conf

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ server {
2626
{%- if value == "404" %}
2727
location / {
2828
include conf.d/include/always.conf;
29-
root /html/dead;
30-
try_files $uri /index.html;
29+
root /html/404deadpage;
30+
error_page 404 /404deadpage.html;
31+
return 404;
3132
}
3233
{%- endif %}
3334

compose.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ services:
1111
environment:
1212
- "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
1313
- "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
14-
# - "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)
14+
# - "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)
1515
# - "ACME_EAB_KID=123456789abcdef" # Key Identifier for External Account Binding for the acme server
1616
# - "ACME_EAB_HMAC_KEY=123456789abcdef" # HMAC key for External Account Binding for the acme server
17-
# - "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
17+
# - "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
1818
# - "ACME_SERVER_TLS_VERIFY=false" # enables checking if ACME_SERVER has a valid TLS cert, default true
1919
# - "PUID=1000" # set group id, default 0 (root)
2020
# - "PGID=1000" # set user id, default 0 (root), requires PUID

frontend/js/app/nginx/certificates/form.ejs

-2
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@
105105
</div>
106106
107107
<!-- DNS propagation delay -->
108-
<!---
109108
<div class="row">
110109
<div class="col-sm-12 col-md-12">
111110
<div class="form-group mb-0">
@@ -125,7 +124,6 @@
125124
</div>
126125
</div>
127126
</div>
128-
--->
129127
</fieldset>
130128
</div>
131129

frontend/js/app/nginx/dead/form.ejs

-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@
144144
</div>
145145

146146
<!-- DNS propagation delay -->
147-
<!---
148147
<div class="row">
149148
<div class="col-sm-12 col-md-12">
150149
<div class="form-group mb-0">
@@ -164,7 +163,6 @@
164163
</div>
165164
</div>
166165
</div>
167-
--->
168166
</fieldset>
169167
</div>
170168

frontend/js/app/nginx/proxy/form.ejs

-2
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@
212212
</div>
213213

214214
<!-- DNS propagation delay -->
215-
<!---
216215
<div class="row">
217216
<div class="col-sm-12 col-md-12">
218217
<div class="form-group mb-0">
@@ -232,7 +231,6 @@
232231
</div>
233232
</div>
234233
</div>
235-
--->
236234
</fieldset>
237235
</div>
238236

frontend/js/app/nginx/redirection/form.ejs

-2
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@
193193
</div>
194194

195195
<!-- DNS propagation delay -->
196-
<!---
197196
<div class="row">
198197
<div class="col-sm-12 col-md-12">
199198
<div class="form-group mb-0">
@@ -213,7 +212,6 @@
213212
</div>
214213
</div>
215214
</div>
216-
--->
217215
</fieldset>
218216
</div>
219217

frontend/js/i18n/de-lang.json

+11-11
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"certificate": "Zertifikat",
5353
"created": "Erstellt {name}",
5454
"date": "Date",
55-
"dead-host": "404 Host",
55+
"dead-host": "Dead Host",
5656
"deleted": "Gelöscht {name}",
5757
"disabled": "Deaktiviert {name}",
5858
"empty": "Es gibt keine Protokolle.",
@@ -100,15 +100,15 @@
100100
"title": "Hallo {name}"
101101
},
102102
"dead-hosts": {
103-
"add": "404 Host hinzufügen",
104-
"delete": "404 Host löschen",
105-
"delete-confirm": "Sind Sie sicher, dass Sie diesen 404-Host löschen wollen?",
106-
"empty": "Es gibt keine 404 Hosts",
107-
"form-title": "{id, select, undefined{Neuer} other{Bearbeitung}} 404 Host",
108-
"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.",
109-
"help-title": "Was ist ein 404-Host?",
103+
"add": "Dead Host hinzufügen",
104+
"delete": "Dead Host löschen",
105+
"delete-confirm": "Sind Sie sicher, dass Sie diesen Dead-Host löschen wollen?",
106+
"empty": "Es gibt keine Dead Hosts",
107+
"form-title": "{id, select, undefined{Neuer} other{Bearbeitung}} Dead Host",
108+
"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.",
109+
"help-title": "Was ist ein Dead-Host?",
110110
"search": "Suche Host..",
111-
"title": "404 Hosts"
111+
"title": "Dead Hosts"
112112
},
113113
"footer": {
114114
"copy-npm": " - &copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM",
@@ -177,7 +177,7 @@
177177
},
178178
"settings": {
179179
"default-site": "Standard-Seite",
180-
"default-site-404": "404 Seite",
180+
"default-site-404": "Dead Seite",
181181
"default-site-444": "Verbindung abbrechen - erlaubt nur certbot dns-challenge",
182182
"default-site-congratulations": "Glückwunsch-Seite",
183183
"default-site-description": "Was angezeigt werden soll, wenn Nginx einen unbekannten Host antrifft",
@@ -256,7 +256,7 @@
256256
"no-wildcard-without-dns": "Zertifikat kann nicht für Wildcard-Domains angefordert werden, wenn keine DNS-Challenge verwendet wird",
257257
"none": "Nur HTTP",
258258
"other": "Individuell",
259-
"passphrase-protection-support-info": "Schlüsseldateien, die mit einer Passphrase geschützt sind, werden nicht unterstützt.",
259+
"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.",
260260
"processing-info": "Verarbeitung... Dies kann ein paar Minuten dauern.",
261261
"propagation-seconds": "Ausbreitung in Sekunden",
262262
"propagation-seconds-info": "Leer lassen, um den Standardwert des Plugins zu verwenden. Anzahl der Sekunden, die auf die DNS-Verbreitung gewartet werden soll.",

frontend/js/i18n/en-lang.json

+10-10
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"certificate": "Certificate",
5353
"created": "Created {name}",
5454
"date": "Date",
55-
"dead-host": "404 Host",
55+
"dead-host": "Dead Host",
5656
"deleted": "Deleted {name}",
5757
"disabled": "Disabled {name}",
5858
"empty": "There are no logs.",
@@ -100,15 +100,15 @@
100100
"title": "Hi {name}"
101101
},
102102
"dead-hosts": {
103-
"add": "Add 404 Host",
104-
"delete": "Delete 404 Host",
105-
"delete-confirm": "Are you sure you want to delete this 404 Host?",
106-
"empty": "There are no 404 Hosts",
107-
"form-title": "{id, select, undefined{New} other{Edit}} 404 Host",
108-
"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.",
109-
"help-title": "What is a 404 Host?",
103+
"add": "Add Dead Host",
104+
"delete": "Delete Dead Host",
105+
"delete-confirm": "Are you sure you want to delete this Dead Host?",
106+
"empty": "There are no Dead Hosts",
107+
"form-title": "{id, select, undefined{New} other{Edit}} Dead Host",
108+
"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.",
109+
"help-title": "What is a Dead Host?",
110110
"search": "Search Host…",
111-
"title": "404 Hosts"
111+
"title": "Dead Hosts"
112112
},
113113
"footer": {
114114
"copy-npm": " - &copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM",
@@ -256,7 +256,7 @@
256256
"no-wildcard-without-dns": "Cannot request Certificate for wildcard domains when not using DNS challenge",
257257
"none": "HTTP only",
258258
"other": "Custom",
259-
"passphrase-protection-support-info": "Key files protected with a passphrase are not supported.",
259+
"passphrase-protection-support-info": "Key files protected with a passphrase are not supported. OCSP Stapling is not supported on custom certificates.",
260260
"processing-info": "Processing... This might take a few minutes.",
261261
"propagation-seconds": "Propagation Seconds",
262262
"propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.",

rootfs/etc/certbot.ini

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ key-type = ecdsa
33
no-reuse-key = true
44
rsa-key-size = 4096
55
elliptic-curve = secp384r1
6+
7+
must-staple = true
+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Dead Host</title>
5+
<meta charset="UTF-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<meta name="application-name" content="NPMplus" />
8+
<meta name="author" content="ZoeyVid" />
9+
<meta name="description" content="Dead Host Page of NPMplus" />
10+
<meta name="keywords" content="NPMplus, dead, 404" />
11+
<!-- TODO: Icon -->
12+
<link rel="icon" type="image/webp" href="/favicon.webp" />
13+
</head>
14+
<body>
15+
<style>
16+
@media (prefers-color-scheme: dark) {
17+
body {
18+
background-color: rgb(17 24 39);
19+
color: white;
20+
}
21+
22+
#box {
23+
background-color: rgb(31 41 55);
24+
}
25+
}
26+
27+
@media (prefers-color-scheme: light) {
28+
body {
29+
background-color: white;
30+
color: black;
31+
}
32+
33+
#box {
34+
background-color: rgb(229 231 235);
35+
}
36+
}
37+
38+
body {
39+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
40+
text-align: center;
41+
}
42+
43+
#box {
44+
border-radius: 2rem;
45+
position: absolute;
46+
padding: 1rem;
47+
padding-right: 5rem;
48+
padding-left: 5rem;
49+
top: 50%;
50+
left: 50%;
51+
transform: translate(-50%, -50%);
52+
}
53+
54+
h1 {
55+
font-size: 64px;
56+
}
57+
58+
p {
59+
font-size: 24px;
60+
}
61+
62+
#notice {
63+
font-size: 12px;
64+
position: fixed;
65+
bottom: 0;
66+
left: 50%;
67+
transform: translateX(-50%);
68+
}
69+
70+
@media (max-width: 600px) {
71+
h1 {
72+
font-size: 32px;
73+
}
74+
75+
p {
76+
font-size: 16px;
77+
}
78+
79+
#box {
80+
padding-right: 2rem;
81+
padding-left: 2rem;
82+
}
83+
}
84+
</style>
85+
<div id="box">
86+
<h1>Dead Host</h1>
87+
</div>
88+
<p id="notice">Powered by <a href="https://github.com/ZoeyVid/NPMplus">NPMplus</a></p>
89+
</body>
90+
</html>

rootfs/html/dead/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<meta name="application-name" content="NPMplus" />
88
<meta name="author" content="ZoeyVid" />
99
<meta name="description" content="Dead Host Page of NPMplus" />
10-
<meta name="keywords" content="NPMplus, dead" />
10+
<meta name="keywords" content="NPMplus, dead, 404" />
1111
<!-- TODO: Icon -->
1212
<link rel="icon" type="image/webp" href="/favicon.webp" />
1313
</head>

rootfs/usr/local/bin/start.sh

+7
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,13 @@ fi
355355

356356

357357

358+
if [ "$ACME_MUST_STAPLE" = "true" ]; then
359+
sed -i "s|must-staple = .*|must-staple = true|g" /etc/certbot.ini
360+
else
361+
sed -i "s|must-staple = .*|must-staple = false|g" /etc/certbot.ini
362+
fi
363+
364+
358365
if [ "$PHP82" = "true" ]; then
359366

360367
apk add --no-cache php82-fpm

0 commit comments

Comments
 (0)