Commit 45ff0a53 authored by nanahira's avatar nanahira

Update src/site.ts, views/nginx.conf.mustache, src/acme.ts, index.ts, views/entrypoint.sh files

parent 98968f34
Pipeline #40868 canceled with stages
in 7 minutes and 46 seconds
...@@ -2,19 +2,50 @@ import * as fs from 'fs'; ...@@ -2,19 +2,50 @@ import * as fs from 'fs';
import Mustache from 'mustache'; import Mustache from 'mustache';
import path from 'path'; import path from 'path';
import { getData } from './src/site'; import { getData } from './src/site';
import { execFile as _execFile } from 'child_process';
import { promisify } from 'util';
const execFile = promisify(_execFile);
async function reloadNginx() {
console.error('[nginx] Reloading...');
try {
const { stdout, stderr } = await execFile('nginx', ['-s', 'reload']);
if (stdout?.trim()) console.error('[nginx][stdout]', stdout.trim());
if (stderr?.trim()) console.error('[nginx][stderr]', stderr.trim());
console.error('[nginx] Reloaded.');
} catch (err: any) {
console.error('[nginx] Reload failed:', err?.stderr || err?.message || err);
throw err;
}
}
async function main() { async function main() {
console.log( try {
Mustache.render( if (process.argv[2] === 'renewCert') {
fs.readFileSync( console.error('[acme] Signing start');
await getData(process.env as any, 61000);
console.error('[acme] Signing done');
await reloadNginx();
} else {
console.error('[render] Nginx config render start');
const parsed = await getData(process.env as any);
console.error('[render] parsed');
const tpl = fs.readFileSync(
path.join(__dirname, '..', 'views', 'nginx.conf.mustache'), path.join(__dirname, '..', 'views', 'nginx.conf.mustache'),
'utf8', 'utf8',
),
await getData(process.env),
undefined,
{ escape: (v) => v },
),
); );
const rendered = Mustache.render(tpl, parsed, undefined, {
escape: (v) => v,
});
console.log(rendered);
console.error('[render] Nginx config render done');
}
process.exit(0); process.exit(0);
} catch (e) {
console.error('[main] Error:', e);
process.exit(1);
}
} }
main(); main();
...@@ -20,7 +20,7 @@ export async function addSignCert(domains: string[], payload: string) { ...@@ -20,7 +20,7 @@ export async function addSignCert(domains: string[], payload: string) {
return domainsToBeSigned[0]; return domainsToBeSigned[0];
} }
export async function runSignCert() { export async function runSignCert(signCertPort = 80) {
if (!domainsToBeSigned.length) { if (!domainsToBeSigned.length) {
return; return;
} }
...@@ -61,7 +61,7 @@ export async function runSignCert() { ...@@ -61,7 +61,7 @@ export async function runSignCert() {
`${req.socket.remoteAddress}: Serving token for ${token}: ${content}`, `${req.socket.remoteAddress}: Serving token for ${token}: ${content}`,
); );
res.end(content); res.end(content);
}).listen(80); }).listen(signCertPort);
const certDir = `/etc/nginx/certs/${domainsToBeSigned[0]}`; const certDir = `/etc/nginx/certs/${domainsToBeSigned[0]}`;
const accountFile = path.join(certDir, 'account.pem'); const accountFile = path.join(certDir, 'account.pem');
const fullchainFile = path.join(certDir, 'fullchain.pem'); const fullchainFile = path.join(certDir, 'fullchain.pem');
......
...@@ -29,6 +29,7 @@ export interface SiteRenderData { ...@@ -29,6 +29,7 @@ export interface SiteRenderData {
locationExtraPre?: string; locationExtraPre?: string;
htpasswd?: string; htpasswd?: string;
cors?: boolean; cors?: boolean;
acme?: boolean;
} }
export interface ProxyRenderData extends SiteRenderData { export interface ProxyRenderData extends SiteRenderData {
...@@ -90,6 +91,7 @@ export interface RenderData { ...@@ -90,6 +91,7 @@ export interface RenderData {
nginxExtra?: string; nginxExtra?: string;
httpExtraPre?: string; httpExtraPre?: string;
nginxExtraPre?: string; nginxExtraPre?: string;
acme?: boolean,
} }
export interface Upstream { export interface Upstream {
...@@ -226,18 +228,20 @@ async function getSiteData( ...@@ -226,18 +228,20 @@ async function getSiteData(
? `/etc/nginx/generated/htpasswd-${domain}` ? `/etc/nginx/generated/htpasswd-${domain}`
: undefined, : undefined,
cors: parser.getBoolean('CORS'), cors: parser.getBoolean('CORS'),
acme: httpsCert?.startsWith('acme://'),
...specificRenderData, ...specificRenderData,
}; };
} }
export async function getData( export async function getData(
input: Record<string, string> = process.env, input: Record<string, string> = process.env,
signCertPort = 80,
): Promise<RenderData> { ): Promise<RenderData> {
const parser = new Parser('', input); const parser = new Parser('', input);
const sites = await Promise.all( const sites = await Promise.all(
getSiteNames().map((domain) => getSiteData(domain, input)), getSiteNames().map((domain) => getSiteData(domain, input)),
); );
await runSignCert(); await runSignCert(signCertPort);
return { return {
purgeAllowed: parser.getArray('PURGE_ALLOWED'), purgeAllowed: parser.getArray('PURGE_ALLOWED'),
externalRealIp: parser.getBoolean('EXTERNAL_REAL_IP'), externalRealIp: parser.getBoolean('EXTERNAL_REAL_IP'),
...@@ -256,5 +260,6 @@ export async function getData( ...@@ -256,5 +260,6 @@ export async function getData(
nginxExtra: parser.getString('NGINX_EXTRA'), nginxExtra: parser.getString('NGINX_EXTRA'),
httpExtraPre: parser.getString('HTTP_EXTRA_PRE'), httpExtraPre: parser.getString('HTTP_EXTRA_PRE'),
nginxExtraPre: parser.getString('NGINX_EXTRA_PRE'), nginxExtraPre: parser.getString('NGINX_EXTRA_PRE'),
acme: sites.some(s => s.acme),
}; };
} }
#!/bin/sh #!/bin/sh
set -e
node dist > /etc/nginx/nginx.conf node dist > /etc/nginx/nginx.conf
"$@" if grep -q 'acme_required' /etc/nginx/nginx.conf; then
\ No newline at end of file echo "[entrypoint] ACME required detected, scheduling daily renewCert task" >&2
(
while true; do
sleep 86400 # 24h
echo "[entrypoint] Running daily cert renewal..." >&2
node dist renewCert || echo "[entrypoint] renewCert failed" >&2
echo "[entrypoint] Daily cert renewal finished." >&2
done
) &
fi
exec "$@"
...@@ -230,6 +230,12 @@ http { ...@@ -230,6 +230,12 @@ http {
{{.}} {{.}}
{{/serverExtra}} {{/serverExtra}}
{{#acme}}
location /.well-known/acme-challenge/ {
proxy_pass http://localhost:61000;
}
{{/acme}}
location / { location / {
{{#locationExtraPre}} {{#locationExtraPre}}
{{.}} {{.}}
...@@ -343,3 +349,7 @@ stream { ...@@ -343,3 +349,7 @@ stream {
{{#nginxExtra}} {{#nginxExtra}}
{{.}} {{.}}
{{/nginxExtra}} {{/nginxExtra}}
{{#acme}}
# acme_required
{{/acme}}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment