diff --git a/Dockerfile b/Dockerfile index 21ec40f52..19ac4f0a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,6 +57,7 @@ RUN apk upgrade --no-cache -a && \ mv crowdsec-nginx-bouncer-* crowdsec-nginx-bouncer && \ sed -i "/lua_package_path/d" /src/crowdsec-nginx-bouncer/nginx/crowdsec_nginx.conf && \ sed -i "s|/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf|/data/etc/crowdsec/crowdsec.conf|g" /src/crowdsec-nginx-bouncer/nginx/crowdsec_nginx.conf && \ + sed -i "s|crowdsec-nginx-bouncer|crowdsec-npmplus-bouncer|g" /src/crowdsec-nginx-bouncer/nginx/crowdsec_nginx.conf && \ sed -i "s|API_KEY=.*|API_KEY=|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \ sed -i "s|ENABLED=.*|ENABLED=false|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \ sed -i "s|API_URL=.*|API_URL=http://127.0.0.1:8080|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \ @@ -70,10 +71,10 @@ RUN apk upgrade --no-cache -a && \ sed -i "s|APPSEC_PROCESS_TIMEOUT=.*|APPSEC_PROCESS_TIMEOUT=10000|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf -FROM zoeyvid/nginx-quic:347-python +FROM zoeyvid/nginx-quic:349-python SHELL ["/bin/ash", "-eo", "pipefail", "-c"] COPY rootfs / -COPY --from=zoeyvid/certbot-docker:58 /usr/local /usr/local +COPY --from=zoeyvid/certbot-docker:59 /usr/local /usr/local COPY --from=zoeyvid/curl-quic:420 /usr/local/bin/curl /usr/local/bin/curl ARG CRS_VER=v4.7.0 @@ -81,7 +82,7 @@ RUN apk upgrade --no-cache -a && \ apk add --no-cache ca-certificates tzdata tini \ nodejs \ bash nano \ - logrotate apache2-utils \ + logrotate \ lua5.1-lzlib lua5.1-socket \ coreutils grep findutils jq shadow su-exec \ luarocks5.1 lua5.1-dev lua5.1-sec build-base git yarn && \ @@ -123,7 +124,8 @@ ENV NODE_ENV=production \ # until https://github.com/certbot/certbot/issues/9967 is closed ENV PYTHONWARNINGS=ignore -ENV PUID=0 \ +ENV ACME_SERVER="https://acme-v02.api.letsencrypt.org/directory" \ + PUID=0 \ PGID=0 \ NIBEP=48693 \ GOAIWSP=48683 \ diff --git a/README.md b/README.md index 4e4f02cd0..d3b40dc13 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ running at home or otherwise, including free TLS, without having to know too muc **Note: ModSecurity overblocking (403 Error)? Please see `/opt/npm/etc/modsecurity`, if you also use CRS please see [here](https://coreruleset.org/docs/concepts/false_positives_tuning).**
**Note: Other Databases like MariaDB may work, but are unsupported.**
**Note: access.log/stream.log, logrotate and goaccess are NOT enabled by default bceuase of GDPR, you can enable them in the compose.yaml.**
-**Note: if you remove a cert, which is still used by a host, NPM/NPMplus will crash.**
## Project Goal @@ -97,6 +96,28 @@ so that the barrier for entry here is low. - if you have a healthcheck defined in your compose yaml file, remove it - this fork defines its own healthcheck in the Dockerfile, so you don't need to have it in compose anymore - please report all migration issues you have +# Quick Setup +1. Install Docker and Docker Compose (or portainer) +- [Docker Install documentation](https://docs.docker.com/engine) +- [Docker Compose Install documentation](https://docs.docker.com/compose/install/linux) +2. Create a compose.yaml file similar to [this](https://github.com/ZoeyVid/NPMplus/blob/develop/compose.yaml) (or use it as a portainer stack): +3. Bring up your stack by running (or deploy your portainer stack) +```bash +docker compose up -d +``` +4. Log in to the Admin UI +When your docker container is running, connect to it on port `81` for the admin interface. +Sometimes this can take a little bit because of the entropy of keys. +You may need to open port 81 in your firewall. +You may need to use another IP-Address. +[https://127.0.0.1:81](https://127.0.0.1:81) +Default Admin User: +``` +Email: admin@example.org +Password: iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi +``` +Immediately after logging in with this default user you will be asked to modify your details and change your password. + # Crowdsec 1. Install crowdsec using this compose file: https://github.com/ZoeyVid/NPMplus/blob/develop/compose.crowdsec.yaml and enable LOGROTATE 2. open `/opt/crowdsec/conf/acquis.d/npmplus.yaml` and fill it with: @@ -175,34 +196,6 @@ location / { } ``` -# custom acme server -1. Open this file: `nano` `/opt/npm/ssl/certbot/config.ini` -2. uncomment the server line and change it to your acme server -3. maybe set eab keys -4. create your cert using the npm web ui - -# Quick Setup -1. Install Docker and Docker Compose (or portainer) -- [Docker Install documentation](https://docs.docker.com/engine) -- [Docker Compose Install documentation](https://docs.docker.com/compose/install/linux) -2. Create a compose.yaml file similar to [this](https://github.com/ZoeyVid/NPMplus/blob/develop/compose.yaml) (or use it as a portainer stack): -3. Bring up your stack by running (or deploy your portainer stack) -```bash -docker compose up -d -``` -4. Log in to the Admin UI -When your docker container is running, connect to it on port `81` for the admin interface. -Sometimes this can take a little bit because of the entropy of keys. -You may need to open port 81 in your firewall. -You may need to use another IP-Address. -[https://127.0.0.1:81](https://127.0.0.1:81) -Default Admin User: -``` -Email: admin@example.org -Password: iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi -``` -Immediately after logging in with this default user you will be asked to modify your details and change your password. - ### prerun scripts (EXPERT option) - if you don't know what this is, ignore it run order: entrypoint.sh (prerun scripts) => start.sh => launch.sh
if you need to run scripts before NPMplus launches put them under: `/opt/npm/etc/prerun/*.sh` (please add `#!/bin/sh` / `#!/bin/bash` to the top of the script)
@@ -221,6 +214,4 @@ If you want to sponsor them, please see [here](https://github.com/NginxProxyMana ## Getting Support 1. [Found a bug?](https://github.com/ZoeyVid/NPMplus/issues) 2. [Discussions](https://github.com/ZoeyVid/NPMplus/discussions) - +3. [Reddit](https://reddit.com/r/NPMplus) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index 838837724..f406eee6b 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -1,5 +1,6 @@ const _ = require('lodash'); const fs = require('fs'); +const md5 = require('apache-md5'); const batchflow = require('batchflow'); const logger = require('../logger').access; const error = require('../lib/error'); @@ -483,15 +484,17 @@ const internalAccessList = { if (typeof item.password !== 'undefined' && item.password.length) { logger.info('Adding: ' + item.username); - utils - .execFile('htpasswd', ['-b', htpasswd_file, item.username, item.password]) - .then((/* result */) => { - next(); - }) - .catch((err) => { - logger.error(err); - next(err); - }); + try { + const hashedPassword = md5(item.password); + fs.appendFileSync(htpasswd_file, `${item.username}:${hashedPassword}\n`, { encoding: 'utf8' }); + next(); + } catch (err) { + logger.error(err); + next(err); + } + } else { + // Proceed to next if no password + next(); } }) .error((err) => { diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index db4a15749..240f38106 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -15,7 +15,8 @@ const dnsPlugins = require('../certbot-dns-plugins.json'); const internalAuditLog = require('./audit-log'); const internalNginx = require('./nginx'); -const certbotCommand = 'certbot --logs-dir /tmp/certbot-log --work-dir /tmp/certbot-work --config-dir /data/tls/certbot --agree-tos -non-interactive --config /etc/tls/certbot.ini'; +const certbotCommand = 'certbot'; +const certbotArgs = ['--logs-dir', '/tmp/certbot-log', '--work-dir', '/tmp/certbot-work', '--config-dir', '/data/tls/certbot', '--config', '/etc/tls/certbot.ini', '--agree-tos', '--non-interactive', '--no-eff-email', '--register-unsafely-without-email']; function omissions() { return ['is_deleted', 'owner.is_deleted']; @@ -40,10 +41,8 @@ const internalCertificate = { internalCertificate.intervalProcessing = true; logger.info('Renewing TLS certs close to expiry...'); - const cmd = '${certbotCommand} renew --quiet'; - return utils - .exec(cmd) + .execFile(certbotCommand, [...certbotArgs, 'renew', '--quiet', '--no-random-sleep-on-renew']) .then((result) => { if (result) { logger.info('Renew Result: ' + result); @@ -498,7 +497,6 @@ const internalCertificate = { * @param {Object} data * @param {Array} data.domain_names * @param {String} data.meta.letsencrypt_email - * @param {Boolean} data.meta.letsencrypt_agree * @returns {Promise} */ createQuickCertificate: (access, data) => { @@ -619,7 +617,7 @@ const internalCertificate = { reject(new error.ValidationError('Result Validation Error: Validation timed out. This could be due to the key being passphrase-protected.')); }, 10000); utils - .exec('openssl pkey -in ' + filepath + ' -check -noout 2>&1 ') + .execFile('openssl', ['pkey', '-in', filepath, '-check', '-noout']) .then((result) => { clearTimeout(failTimeout); if (!result.toLowerCase().includes('key is valid')) { @@ -670,7 +668,7 @@ const internalCertificate = { const certData = {}; return utils - .exec('openssl x509 -in ' + certificate_file + ' -subject -noout') + .execFile('openssl', ['x509', '-in', certificate_file, '-subject', '-noout']) .then((result) => { const regex = /(?:subject=)?[^=]+=\s*(\S+)/gim; const match = regex.exec(result); @@ -679,7 +677,7 @@ const internalCertificate = { } }) .then(() => { - return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout'); + return utils.execFile('openssl', ['x509', '-in', certificate_file, '-issuer', '-noout']); }) .then((result) => { @@ -690,7 +688,7 @@ const internalCertificate = { } }) .then(() => { - return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout'); + return utils.execFile('openssl', ['x509', '-in', certificate_file, '-dates', '-noout']); }) .then((result) => { // notBefore=Jul 14 04:04:29 2018 GMT @@ -763,11 +761,7 @@ const internalCertificate = { requestCertbot: (certificate) => { logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); - let cmd = `${certbotCommand} certonly --cert-name "npm-${certificate.id}" --domains "${certificate.domain_names.join(',')}" --server "${process.env.ACME_SERVER}" --authenticator webroot --webroot-path "/tmp/acme-challenge"`; - - logger.info('Command:', cmd); - - return utils.exec(cmd).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); return result; }); @@ -792,12 +786,8 @@ const internalCertificate = { fs.mkdirSync('/data/tls/certbot/credentials', { recursive: true }); fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 }); - let mainCmd = `${certbotCommand} 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}"`; - - logger.info('Command:', mainCmd); - try { - const result = await utils.exec(mainCmd); + 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]); logger.info(result); return result; } catch (err) { @@ -857,18 +847,10 @@ const internalCertificate = { renewCertbot: async (certificate) => { logger.info(`Renewing Certbot certificates for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`); - const cmdr = `${certbotCommand} revoke --cert-path "/data/tls/certbot/live/npm-${certificate.id}/fullchain.pem" --cert-path "/data/tls/certbot/live/npm-${certificate.id}/privkey.pem" --no-delete-after-revoke`; - - logger.info('Command:', cmdr); - - const revokeResult = await utils.exec(cmdr); + const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']); logger.info(revokeResult); - const cmd = `${certbotCommand} renew --force-renewal --cert-name "npm-${certificate.id}"`; - - logger.info('Command:', cmd); - - const renewResult = await utils.exec(cmd); + const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']); logger.info(renewResult); return renewResult; @@ -887,18 +869,10 @@ const internalCertificate = { logger.info(`Renewing Certbot certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`); - const cmdr = `${certbotCommand} revoke --cert-path "/data/tls/certbot/live/npm-${certificate.id}/fullchain.pem" --cert-path "/data/tls/certbot/live/npm-${certificate.id}/privkey.pem" --no-delete-after-revoke`; - - logger.info('Command:', cmdr); - - const revokeResult = await utils.exec(cmdr); + const revokeResult = await utils.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']); logger.info(revokeResult); - const cmd = `${certbotCommand} renew --force-renewal --cert-name "npm-${certificate.id}"`; - - logger.info('Command:', cmd); - - const renewResult = await utils.exec(cmd); + const renewResult = await utils.execFile(certbotCommand, [...certbotArgs, 'renew', '--force-renewal', '--cert-name', `npm-${certificate.id}`, '--no-random-sleep-on-renew']); logger.info(renewResult); return renewResult; @@ -912,10 +886,8 @@ const internalCertificate = { revokeCertbot: (certificate, throw_errors) => { logger.info('Revoking Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); - const mainCmd = `${certbotCommand} revoke --cert-path "/data/tls/certbot/live/npm-${certificate.id}/fullchain.pem" --cert-path "/data/tls/certbot/live/npm-${certificate.id}/privkey.pem" --no-delete-after-revoke`; - return utils - .exec(mainCmd) + .execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke']) .then(async (result) => { fs.rm('/data/tls/certbot/credentials/credentials-' + certificate.id, { force: true }, (err) => { if (err) { @@ -939,64 +911,6 @@ const internalCertificate = { }); }, - /** - * @param {Object} in_use_result - * @param {Number} in_use_result.total_count - * @param {Array} in_use_result.proxy_hosts - * @param {Array} in_use_result.redirection_hosts - * @param {Array} in_use_result.dead_hosts - */ - disableInUseHosts: (in_use_result) => { - if (in_use_result.total_count) { - const promises = []; - - if (in_use_result.proxy_hosts.length) { - promises.push(internalNginx.bulkDeleteConfigs('proxy_host', in_use_result.proxy_hosts)); - } - - if (in_use_result.redirection_hosts.length) { - promises.push(internalNginx.bulkDeleteConfigs('redirection_host', in_use_result.redirection_hosts)); - } - - if (in_use_result.dead_hosts.length) { - promises.push(internalNginx.bulkDeleteConfigs('dead_host', in_use_result.dead_hosts)); - } - - return Promise.all(promises); - } else { - return Promise.resolve(); - } - }, - - /** - * @param {Object} in_use_result - * @param {Number} in_use_result.total_count - * @param {Array} in_use_result.proxy_hosts - * @param {Array} in_use_result.redirection_hosts - * @param {Array} in_use_result.dead_hosts - */ - enableInUseHosts: (in_use_result) => { - if (in_use_result.total_count) { - const promises = []; - - if (in_use_result.proxy_hosts.length) { - promises.push(internalNginx.bulkGenerateConfigs('proxy_host', in_use_result.proxy_hosts)); - } - - if (in_use_result.redirection_hosts.length) { - promises.push(internalNginx.bulkGenerateConfigs('redirection_host', in_use_result.redirection_hosts)); - } - - if (in_use_result.dead_hosts.length) { - promises.push(internalNginx.bulkGenerateConfigs('dead_host', in_use_result.dead_hosts)); - } - - return Promise.all(promises); - } else { - return Promise.resolve(); - } - }, - testHttpsChallenge: async (access, domains) => { await access.can('certificates:list'); diff --git a/backend/internal/nginx.js b/backend/internal/nginx.js index 8974e39c6..6548afdbb 100644 --- a/backend/internal/nginx.js +++ b/backend/internal/nginx.js @@ -79,7 +79,7 @@ const internalNginx = { * @returns {Promise} */ test: () => { - return utils.exec('nginx -tq'); + return utils.execFile('nginx', ['-tq']); }, /** @@ -88,24 +88,20 @@ const internalNginx = { reload: () => { return internalNginx.test().then(() => { - try { - utils.exec('certbot-ocsp-fetcher.sh -c /data/tls/certbot -o /data/tls/certbot/live --no-reload-webserver --quiet || true'); - } catch { - // do nothing - } - if (fs.existsSync('/usr/local/nginx/logs/nginx.pid')) { - const ngxPID = fs.readFileSync('/usr/local/nginx/logs/nginx.pid', 'utf8').trim(); - if (ngxPID.length > 0) { - logger.info('Reloading Nginx'); - utils.exec('nginx -s reload'); - } else { - logger.info('Starting Nginx'); - utils.execfg('nginx -e stderr'); - } - } else { - logger.info('Starting Nginx'); - utils.execfg('nginx -e stderr'); - } + return utils + .execFile('certbot-ocsp-fetcher.sh', ['-c', '/data/tls/certbot', '-o', '/data/tls/certbot/live', '--no-reload-webserver', '--quiet']) + .then(() => { + if (fs.existsSync('/usr/local/nginx/logs/nginx.pid') && fs.readFileSync('/usr/local/nginx/logs/nginx.pid', 'utf8').trim().length > 0) { + logger.info('Reloading Nginx'); + return utils.execFile('nginx', ['-s', 'reload']); + } else { + logger.info('Starting Nginx'); + return utils.execfg('nginx', ['-e', 'stderr']); + } + }) + .catch(() => { + /* do nothing */ + }); }); }, @@ -166,7 +162,7 @@ const internalNginx = { */ generateConfig: (host_type, host_row) => { // Prevent modifying the original object: - let host = JSON.parse(JSON.stringify(host_row)); + let host = JSON.parse(JSON.stringify(host_row)); const nice_host_type = internalNginx.getFileFriendlyHostType(host_type); const renderEngine = utils.getRenderEngine(); @@ -287,20 +283,6 @@ const internalNginx = { return Promise.all(promises); }, - /** - * @param {String} host_type - * @param {Array} hosts - * @returns {Promise} - */ - bulkDeleteConfigs: (host_type, hosts) => { - const promises = []; - hosts.map(function (host) { - promises.push(internalNginx.deleteConfig(host_type, host)); - }); - - return Promise.all(promises); - }, - /** * @param {string} config * @returns {boolean} diff --git a/backend/lib/certbot.js b/backend/lib/certbot.js index 5105e3019..6a4e0f25d 100644 --- a/backend/lib/certbot.js +++ b/backend/lib/certbot.js @@ -59,9 +59,8 @@ const certbot = { const plugin = dnsPlugins[pluginKey]; logger.start(`Installing ${pluginKey}...`); - const cmd = 'pip install --upgrade --no-cache-dir ' + plugin.package_name; return utils - .exec(cmd) + .execFile('pip', ['install', '--upgrade', '--no-cache-dir', plugin.package_name]) .then((result) => { logger.complete(`Installed ${pluginKey}`); return result; diff --git a/backend/lib/utils.js b/backend/lib/utils.js index 9b3983254..082f03264 100644 --- a/backend/lib/utils.js +++ b/backend/lib/utils.js @@ -1,41 +1,17 @@ const _ = require('lodash'); -const exec = require('child_process').exec; const spawn = require('child_process').spawn; const execFile = require('child_process').execFile; const { Liquid } = require('liquidjs'); +const logger = require('../logger').global; const error = require('./error'); -// const logger = require('../logger').global; module.exports = { - /** - * @param {String} cmd - */ - exec: async function (cmd, options = {}) { - // logger.debug('CMD:', cmd); - - const { stdout, stderr } = await new Promise((resolve, reject) => { - const child = exec(cmd, options, (isError, stdout, stderr) => { - if (isError) { - reject(new error.CommandError(stderr, isError)); - } else { - resolve({ stdout, stderr }); - } - }); - - child.on('error', (e) => { - reject(new error.CommandError(stderr, 1, e)); - }); - }); - return stdout; - }, - /** * @param {String} cmd * @param {Array} args */ execFile: async function (cmd, args, options = {}) { - // logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : '')); - + logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : '')); const { stdout, stderr } = await new Promise((resolve, reject) => { const child = execFile(cmd, args, options, (isError, stdout, stderr) => { if (isError) { @@ -54,10 +30,11 @@ module.exports = { /** * @param {String} cmd + * @param {Array} args */ - execfg: function (cmd) { + execfg: function (cmd, args) { return new Promise((resolve, reject) => { - const childProcess = spawn(cmd, { + const childProcess = spawn(cmd, args, { shell: true, detached: true, stdio: 'inherit', diff --git a/backend/package.json b/backend/package.json index 9604104b0..f9997005f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -5,6 +5,7 @@ "main": "index.js", "dependencies": { "@apidevtools/json-schema-ref-parser": "11.7.2", + "apache-md5": "1.1.8", "ajv": "8.17.1", "archiver": "7.0.1", "batchflow": "0.4.0", diff --git a/backend/schema/paths/nginx/access-lists/listID/put.json b/backend/schema/paths/nginx/access-lists/listID/put.json index 3a69f8567..7f887dad6 100644 --- a/backend/schema/paths/nginx/access-lists/listID/put.json +++ b/backend/schema/paths/nginx/access-lists/listID/put.json @@ -49,8 +49,7 @@ "minLength": 1 }, "password": { - "type": "string", - "minLength": 1 + "type": "string" } } } diff --git a/backend/setup.js b/backend/setup.js index 60544408d..fbf7acc80 100644 --- a/backend/setup.js +++ b/backend/setup.js @@ -1,8 +1,8 @@ +const fs = require('fs'); const logger = require('./logger').setup; const certificateModel = require('./models/certificate'); const userModel = require('./models/user'); const userPermissionModel = require('./models/user_permission'); -const utils = require('./lib/utils'); const authModel = require('./models/auth'); const settingModel = require('./models/setting'); const certbot = require('./lib/certbot'); @@ -117,12 +117,9 @@ const setupCertbotPlugins = () => { plugins.push(certificate.meta.dns_provider); } - // Make sure credentials file exists - const credentials_loc = '/data/tls/certbot/credentials/credentials-' + certificate.id; - // Escape single quotes and backslashes - const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll("'", "\\'").replaceAll('\\', '\\\\'); - const credentials_cmd = "[ -f '" + credentials_loc + "' ] || { mkdir -p /data/tls/certbot/credentials 2> /dev/null; echo '" + escapedCredentials + "' > '" + credentials_loc + "' && chmod 600 '" + credentials_loc + "'; }"; - promises.push(utils.exec(credentials_cmd)); + const credentialsLocation = '/data/tls/certbot/credentials/credentials-' + certificate.id; + fs.mkdirSync('/data/tls/certbot/credentials', { recursive: true }); + fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 }); } }); diff --git a/backend/templates/_access.conf b/backend/templates/_access.conf index 1562e6edb..6b9082b65 100644 --- a/backend/templates/_access.conf +++ b/backend/templates/_access.conf @@ -1,25 +1,24 @@ -{% if access_list_id > 0 %} - {% if access_list.items.length > 0 %} +{%- if access_list_id > 0 %} + {%- if access_list.items.length > 0 %} # Authorization auth_basic "Authorization required"; auth_basic_user_file /data/etc/access/{{ access_list_id }}; - {% if access_list.pass_auth == 0 %} + {%- unless access_list.pass_auth %} proxy_set_header Authorization ""; - {% endif %} - - {% endif %} + {%- endunless %} + {%- endif %} # Access Rules: {{ access_list.clients | size }} total - {% for client in access_list.clients %} + {%- for client in access_list.clients %} {{client | nginxAccessRule}} - {% endfor %} + {%- endfor %} deny all; # Access checks must... - {% if access_list.satisfy_any == 1 %} + {%- if access_list.satisfy_any %} satisfy any; - {% else %} + {%- else %} satisfy all; - {% endif %} -{% endif %} + {%- endif %} +{%- endif %} diff --git a/backend/templates/_brotli.conf b/backend/templates/_brotli.conf index 39ef12863..c9e124e7e 100644 --- a/backend/templates/_brotli.conf +++ b/backend/templates/_brotli.conf @@ -1,4 +1,4 @@ -{% if http2_support == 1 or http2_support == true -%} +{%- if http2_support %} # Enable Brotli include conf.d/include/brotli.conf; -{% endif %} +{%- endif %} diff --git a/backend/templates/_certificates.conf b/backend/templates/_certificates.conf index aff3bde32..dee4f9a2a 100644 --- a/backend/templates/_certificates.conf +++ b/backend/templates/_certificates.conf @@ -1,14 +1,14 @@ -{% if certificate and certificate_id > 0 -%} -{% if certificate.provider == "letsencrypt" %} +{%- if certificate and certificate_id > 0 %} +{%- if certificate.provider == "letsencrypt" %} # Certbot TLS include conf.d/include/tls-ciphers.conf; ssl_certificate /data/tls/certbot/live/npm-{{ certificate_id }}/fullchain.pem; ssl_certificate_key /data/tls/certbot/live/npm-{{ certificate_id }}/privkey.pem; ssl_stapling_file /data/tls/certbot/live/npm-{{ certificate_id }}.der; -{% else %} +{%- else %} # Custom TLS - include conf.d/include/tls-ciphers.conf; + include conf.d/include/tls-ciphers-no-stapling.conf; ssl_certificate /data/tls/custom/npm-{{ certificate_id }}/fullchain.pem; ssl_certificate_key /data/tls/custom/npm-{{ certificate_id }}/privkey.pem; -{% endif %} -{% endif %} +{%- endif %} +{%- endif %} diff --git a/backend/templates/_forced_tls.conf b/backend/templates/_forced_tls.conf index 3b0226a2a..cfd7bb5c9 100644 --- a/backend/templates/_forced_tls.conf +++ b/backend/templates/_forced_tls.conf @@ -1,6 +1,6 @@ -{% if certificate and certificate_id > 0 -%} -{% if ssl_forced == 1 or ssl_forced == true %} +{%- if certificate and certificate_id > 0 %} +{%- if ssl_forced %} # Force TLS include conf.d/include/force-tls.conf; -{% endif %} -{% endif %} +{%- endif %} +{%- endif %} diff --git a/backend/templates/_hsts.conf b/backend/templates/_hsts.conf index c0a743ed2..8ecd16a6b 100644 --- a/backend/templates/_hsts.conf +++ b/backend/templates/_hsts.conf @@ -1,17 +1,17 @@ -{% if certificate and certificate_id > 0 -%} -{% if ssl_forced == 1 or ssl_forced == true %} -{% if hsts_enabled == 1 or hsts_enabled == true %} +{%- if certificate and certificate_id > 0 %} +{%- if ssl_forced %} +{%- if hsts_enabled %} more_clear_headers "Expect-CT"; include conf.d/include/hsts.conf; -{% endif %} -{% endif %} -{% endif %} +{%- endif %} +{%- endif %} +{%- endif %} -{% unless certificate and certificate_id > 0 -%} -{% unless ssl_forced == 1 or ssl_forced == true %} -{% unless hsts_enabled == 1 or hsts_enabled == true %} +{%- unless certificate and certificate_id > 0 %} +{%- unless ssl_forced %} +{%- unless hsts_enabled %} more_clear_headers "Expect-CT"; more_clear_headers "Strict-Transport-Security"; -{% endunless %} -{% endunless %} -{% endunless %} +{%- endunless %} +{%- endunless %} +{%- endunless %} diff --git a/backend/templates/_listen.conf b/backend/templates/_listen.conf index 8ad3be224..1b9972b8f 100644 --- a/backend/templates/_listen.conf +++ b/backend/templates/_listen.conf @@ -3,18 +3,18 @@ listen 80; listen [::]:80; -{% if certificate and certificate_id > 0 %} +{%- if certificate and certificate_id > 0 %} listen 443 ssl; listen [::]:443 ssl; listen 443 quic; listen [::]:443 quic; -{% if hsts_subdomains == 1 or hsts_subdomains == true %} +{%- if hsts_subdomains %} more_set_headers 'Alt-Svc: h3=":443"; ma=86400'; -{% else %} +{%- else %} more_clear_headers "Alt-Svc"; http3 off; -{% endif %} -{% endif %} +{%- endif %} +{%- endif %} server_name {{ domain_names | join: " " }}; diff --git a/backend/templates/_location.conf b/backend/templates/_location.conf index 193690956..8f021a61b 100644 --- a/backend/templates/_location.conf +++ b/backend/templates/_location.conf @@ -6,10 +6,10 @@ location {{ path }} { set $forward_host "{{ forward_host }}"; set $forward_port {{ forward_port }}; - {% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %} + {%- if allow_websocket_upgrade %} proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; - {% endif %} + {%- endif %} include conf.d/include/proxy-location.conf; proxy_set_header X-Forwarded-Host $host{{ path }}; diff --git a/backend/templates/dead_host.conf b/backend/templates/dead_host.conf index d17b45928..f7e593c6f 100644 --- a/backend/templates/dead_host.conf +++ b/backend/templates/dead_host.conf @@ -1,27 +1,27 @@ -{% include "_header_comment.conf" %} +{%- include "_header_comment.conf" %} -{% if enabled == 1 or enabled == true %} +{%- if enabled %} server { -{% include "_listen.conf" %} -{% include "_certificates.conf" %} -{% include "_hsts.conf" %} -{% include "_forced_tls.conf" %} -{% include "_brotli.conf" %} +{%- include "_listen.conf" %} +{%- include "_certificates.conf" %} +{%- include "_hsts.conf" %} +{%- include "_forced_tls.conf" %} +{%- include "_brotli.conf" %} include conf.d/include/always.conf; {{ advanced_config }} -{% if use_default_location == 1 or use_default_location == true %} +{%- if use_default_location %} location / { include conf.d/include/always.conf; root /html/dead; try_files $uri /index.html; } -{% endif %} +{%- endif %} # Custom - include /data/nginx/custom/server_dead.conf; + include /data/nginx_custom/server_dead.conf; } -{% endif %} +{%- endif %} diff --git a/backend/templates/ip_ranges.conf b/backend/templates/ip_ranges.conf index ee7db9359..a1fb5abf7 100644 --- a/backend/templates/ip_ranges.conf +++ b/backend/templates/ip_ranges.conf @@ -1,6 +1,6 @@ -{% for range in ip_ranges %} +{%- for range in ip_ranges %} set_real_ip_from {{ range }}; -{% endfor %} +{%- endfor %} map $http_cf_connecting_ip $real_ip { "" $http_x_real_ip; diff --git a/backend/templates/proxy_host.conf b/backend/templates/proxy_host.conf index a34aa9c0f..b2bb752d0 100644 --- a/backend/templates/proxy_host.conf +++ b/backend/templates/proxy_host.conf @@ -1,55 +1,55 @@ -{% include "_header_comment.conf" %} +{%- include "_header_comment.conf" %} -{% if enabled == 1 or enabled == true %} +{%- if enabled %} server { set $forward_scheme {{ forward_scheme }}; set $server "{{ forward_host }}"; set $port {{ forward_port }}; -{% include "_listen.conf" %} -{% include "_certificates.conf" %} -{% include "_hsts.conf" %} -{% include "_forced_tls.conf" %} -{% include "_brotli.conf" %} -{% include "_access.conf" %} +{%- include "_listen.conf" %} +{%- include "_certificates.conf" %} +{%- include "_hsts.conf" %} +{%- include "_forced_tls.conf" %} +{%- include "_brotli.conf" %} +{%- include "_access.conf" %} - {% if block_exploits == 1 or block_exploits == true %} + {%- if block_exploits %} modsecurity on; - {% if caching_enabled == 1 or caching_enabled == true -%} + {%- if caching_enabled %} modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity-crs.conf; - {% else %} + {%- else %} modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity.conf; - {% endif %} - {% endif %} + {%- endif %} + {%- endif %} include conf.d/include/always.conf; - {% if access_list_id > 0 %} - {% if access_list.items.length > 0 %} + {%- if access_list_id > 0 %} + {%- if access_list.items.length > 0 %} {{ access_list.passauth }} - {% endif %} - {% endif %} + {%- endif %} + {%- endif %} {{ advanced_config }} # custom locations {{ locations }} -{% if use_default_location == 1 or use_default_location == true %} +{%- if use_default_location %} location / { include conf.d/include/always.conf; - {% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %} + {%- if allow_websocket_upgrade %} proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; - {% endif %} + {%- endif %} # Proxy! include conf.d/include/proxy.conf; } -{% endif %} +{%- endif %} # Custom - include /data/nginx/custom/server_proxy.conf; + include /data/nginx_custom/server_proxy.conf; } -{% endif %} +{%- endif %} diff --git a/backend/templates/redirection_host.conf b/backend/templates/redirection_host.conf index 60030424b..913dfae1d 100644 --- a/backend/templates/redirection_host.conf +++ b/backend/templates/redirection_host.conf @@ -1,29 +1,29 @@ -{% include "_header_comment.conf" %} +{%- include "_header_comment.conf" %} -{% if enabled == 1 or enabled == true %} +{%- if enabled %} server { -{% include "_listen.conf" %} -{% include "_certificates.conf" %} -{% include "_hsts.conf" %} -{% include "_forced_tls.conf" %} -{% include "_brotli.conf" %} +{%- include "_listen.conf" %} +{%- include "_certificates.conf" %} +{%- include "_hsts.conf" %} +{%- include "_forced_tls.conf" %} +{%- include "_brotli.conf" %} include conf.d/include/always.conf; {{ advanced_config }} -{% if use_default_location == 1 or use_default_location == true %} +{%- if use_default_location %} location / { include conf.d/include/always.conf; - {% if preserve_path == 1 or preserve_path == true %} + {%- if preserve_path %} return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}$request_uri; - {% else %} + {%- else %} return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}; - {% endif %} + {%- endif %} } -{% endif %} +{%- endif %} # Custom - include /data/nginx/custom/server_redirect.conf; + include /data/nginx_custom/server_redirect.conf; } -{% endif %} +{%- endif %} diff --git a/backend/templates/stream.conf b/backend/templates/stream.conf index 1e258adb9..1d534694b 100644 --- a/backend/templates/stream.conf +++ b/backend/templates/stream.conf @@ -2,9 +2,9 @@ # {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }} # ------------------------------------------------------------ -{% if enabled == 1 or enabled == true %} +{%- if enabled %} -{% if tcp_forwarding == 1 or tcp_forwarding == true -%} +{%- if tcp_forwarding %} server { listen {{ incoming_port }}; listen [::]:{{ incoming_port }}; @@ -12,21 +12,21 @@ server { proxy_pass {{ forwarding_host }}:{{ forwarding_port }}; # Custom - include /data/nginx/custom/server_stream.conf; - include /data/nginx/custom/server_stream_tcp.conf; + include /data/nginx_custom/server_stream.conf; + include /data/nginx_custom/server_stream_tcp.conf; } -{% endif %} +{%- endif %} -{% if udp_forwarding == 1 or udp_forwarding == true %} +{%- if udp_forwarding %} server { listen {{ incoming_port }} udp; listen [::]:{{ incoming_port }} udp; proxy_pass {{ forwarding_host }}:{{ forwarding_port }}; # Custom - include /data/nginx/custom/server_stream.conf; - include /data/nginx/custom/server_stream_udp.conf; + include /data/nginx_custom/server_stream.conf; + include /data/nginx_custom/server_stream_udp.conf; } -{% endif %} +{%- endif %} -{% endif %} +{%- endif %} diff --git a/compose.yaml b/compose.yaml index 7fb4782ca..889a19b4f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -9,10 +9,14 @@ services: # - "/var/www:/var/www" # optional, if you want to use it as webserver for html/php # - "/opt/npm-letsencrypt:/etc/letsencrypt" # Only needed for first time migration from original nginx-proxy-manager to this fork environment: - - "TZ=Europe/Berlin" # set timezone, required + - "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_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_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 # - "PUID=1000" # set group id, default 0 (root) # - "PGID=1000" # set user id, default 0 (root), requires PUID -# - "NIBEP=48694" # internal port of the NOMplus API, always bound to 127.0.0.1, default 48693, you need to change it, if you want to run multiple npm instances in network mode host +# - "NIBEP=48694" # internal port of the NPMplus API, always bound to 127.0.0.1, default 48693, you need to change it, if you want to run multiple npm instances in network mode host # - "GOAIWSP=48684" # internal port of goaccess, always bound to 127.0.0.1, default 48683, you need to change it, if you want to run multiple npm with goaccess instances in network mode host # - "NPM_PORT=82" # Port the NPM UI should be bound to, default 81, you need to change it, if you want to run multiple npm instances in network mode host # - "NPM_PORT=92" # Port the goaccess should be bound to, default 91, you need to change it, if you want to run multiple npm with goaccess instances in network mode host diff --git a/rootfs/usr/local/bin/launch.sh b/rootfs/usr/local/bin/launch.sh index 3548bc78f..987e69c83 100755 --- a/rootfs/usr/local/bin/launch.sh +++ b/rootfs/usr/local/bin/launch.sh @@ -36,6 +36,41 @@ if [ "$PHP83" = "true" ]; then fi fi + +if [ "$(echo "$ACME_SERVER" | sed "s|^https\?://\([^/]\+\).*$|\1|g")" = "acme.zerossl.com" ] && [ -z "$ACME_EAB_KID" ] && [ -z "$ACME_EAB_HMAC_KEY" ]; then + if [ -z "$ACME_EMAIL" ]; then + echo "ACME_EMAIL is required to use zerossl. Either set it or use a different acme server like letsencrypt (ACME_SERVER: https://acme-v02.api.letsencrypt.org/directory)" + sleep inf + fi + + ZS_EAB="$(curl -s https://api.zerossl.com/acme/eab-credentials-email --data "email=$ACME_EMAIL")" + export ZS_EAB + ACME_EAB_KID="$(echo "$ZS_EAB" | jq -r .eab_kid)" + export ACME_EAB_KID + ACME_EAB_HMAC_KEY="$(echo "$ZS_EAB" | jq -r .eab_hmac_key)" + export ACME_EAB_HMAC_KEY +fi + +if [ ! -d /data/tls/certbot/accounts/"$(echo "$ACME_SERVER" | sed "s|^https\?://\([^/]\+\).*$|\1|g")" ]; then + if [ -z "$ACME_EMAIL" ]; then + if ! certbot --logs-dir /tmp/certbot-log --work-dir /tmp/certbot-work --config-dir /data/tls/certbot --config /etc/tls/certbot.ini --agree-tos --non-interactive --no-eff-email \ + register --server "$ACME_SERVER" --register-unsafely-without-email; then + sleep inf + fi + elif [ -n "$ACME_EMAIL" ] && [ -z "$ACME_EAB_KID" ] && [ -z "$ACME_EAB_HMAC_KEY" ]; then + if ! certbot --logs-dir /tmp/certbot-log --work-dir /tmp/certbot-work --config-dir /data/tls/certbot --config /etc/tls/certbot.ini --agree-tos --non-interactive --no-eff-email \ + register --server "$ACME_SERVER" --email "$ACME_EMAIL"; then + sleep inf + fi + elif [ -n "$ACME_EMAIL" ] && [ -n "$ACME_EAB_KID" ] && [ -n "$ACME_EAB_HMAC_KEY" ]; then + if ! certbot --logs-dir /tmp/certbot-log --work-dir /tmp/certbot-work --config-dir /data/tls/certbot --config /etc/tls/certbot.ini --agree-tos --non-interactive --no-eff-email \ + register --server "$ACME_SERVER" --eab-kid "$ACME_EAB_KID" --eab-hmac-key "$ACME_EAB_HMAC_KEY" --email "$ACME_EMAIL"; then + sleep inf + fi + fi +fi + + if [ "$PHP82" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FOR; fi & if [ "$PHP83" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/83/conf.d php-fpm83 -c /data/php/83 -y /data/php/83/php-fpm.conf -FOR; fi & if [ "$LOGROTATE" = "true" ]; then while true; do logrotate --verbose --state /data/etc/logrotate.status /etc/logrotate; sleep 25h; done; fi & diff --git a/rootfs/usr/local/bin/start.sh b/rootfs/usr/local/bin/start.sh index 029d3fd3b..22d86437d 100755 --- a/rootfs/usr/local/bin/start.sh +++ b/rootfs/usr/local/bin/start.sh @@ -40,13 +40,13 @@ if [ -n "$LE_STAGING" ]; then fi if [ -n "$PHP81" ]; then - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|fastcgi_pass php81;|fastcgi_pass php82;|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|fastcgi_pass php81;|fastcgi_pass php82;|g" {} \; echo "PHP81 was removed, please use PHP82 or PHP83" sleep inf fi if [ -n "$PHP81_APKS" ]; then - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|fastcgi_pass php81;|fastcgi_pass php82;|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|fastcgi_pass php81;|fastcgi_pass php82;|g" {} \; echo "PHP81_APKS was removed, please use PHP82_APKS or PHP83_APKS" sleep inf fi @@ -58,6 +58,22 @@ if [ -z "$TZ" ] || ! echo "$TZ" | grep -q "^[A-Za-z0-9_+-]\+/[A-Za-z0-9_+-]\+$"; fi +if ! echo "$ACME_SERVER" | grep -q "^https\?://.\+$"; then + echo "ACME_SERVER needs to start with http:// or https://" + sleep inf +fi + +if [ -n "$ACME_EMAIL" ] && ! echo "$ACME_EMAIL" | grep -q "^.*@.*$"; then + echo "ACME_EMAIL needs to contains @." + sleep inf +fi + +if { [ -n "$ACME_EAB_KID" ] || [ -n "$ACME_EAB_HMAC_KEY" ]; } && { [ -z "$ACME_EAB_KID" ] || [ -z "$ACME_EAB_HMAC_KEY" ] || [ -z "$ACME_EMAIL" ]; }; then + echo "You need to set ACME_EAB_KID, ACME_EAB_HMAC_KEY AND ACME_EMAIL (all are needed) or none of them or ONLY ACME_EMAIL." + sleep inf +fi + + if ! echo "$PUID" | grep -q "^[0-9]\+$"; then echo "PUID needs to be a number." sleep inf @@ -419,6 +435,10 @@ mkdir -p /tmp/acme-challenge \ /tmp/npmhome \ /tmp/goa +if [ -d /data/nginx/custom ]; then + mv -vn /data/nginx/custom /data/nginx_custom +fi + mkdir -vp /data/tls/certbot/credentials \ /data/tls/certbot/renewal \ /data/tls/custom \ @@ -432,7 +452,7 @@ mkdir -vp /data/tls/certbot/credentials \ /data/nginx/proxy_host \ /data/nginx/dead_host \ /data/nginx/stream \ - /data/nginx/custom + /data/nginx_custom if [ -s /data/database.sqlite ] && [ "$DB_SQLITE_FILE" != "/data/database.sqlite" ]; then mv -vn /data/database.sqlite "$DB_SQLITE_FILE" @@ -458,8 +478,8 @@ if [ -s /data/nginx/dummykey.pem ]; then mv -vn /data/nginx/dummykey.pem /data/tls/dummykey.pem fi -if [ -f /data/nginx/custom/root.conf ]; then - mv -vn /data/nginx/custom/root.conf /data/nginx/custom/root_top.conf +if [ -f /data/nginx_custom/root.conf ]; then + mv -vn /data/nginx_custom/root.conf /data/nginx_custom/root_top.conf fi if [ -n "$(ls -A /data/nginx/html 2> /dev/null)" ]; then @@ -548,60 +568,61 @@ fi touch /tmp/ip_ranges.conf \ /data/etc/html/index.html \ - /data/nginx/custom/events.conf \ - /data/nginx/custom/http.conf \ - /data/nginx/custom/http_top.conf \ - /data/nginx/custom/root_top.conf \ - /data/nginx/custom/server_dead.conf \ - /data/nginx/custom/server_proxy.conf \ - /data/nginx/custom/server_redirect.conf \ - /data/nginx/custom/stream.conf \ - /data/nginx/custom/stream_top.conf \ - /data/nginx/custom/server_stream.conf \ - /data/nginx/custom/server_stream_tcp.conf \ - /data/nginx/custom/server_stream_udp.conf \ + /data/nginx_custom/events.conf \ + /data/nginx_custom/http.conf \ + /data/nginx_custom/http_top.conf \ + /data/nginx_custom/root_top.conf \ + /data/nginx_custom/server_dead.conf \ + /data/nginx_custom/server_proxy.conf \ + /data/nginx_custom/server_redirect.conf \ + /data/nginx_custom/stream.conf \ + /data/nginx_custom/stream_top.conf \ + /data/nginx_custom/server_stream.conf \ + /data/nginx_custom/server_stream_tcp.conf \ + /data/nginx_custom/server_stream_udp.conf \ /data/etc/modsecurity/modsecurity-extra.conf -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s| http2||g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|\(listen .*\) http3|\1 quic|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|quic reuseport;|quic;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|security_headers on;|include conf.d/include/hsts.conf;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|more_set_headers \"Alt-Svc: h3=':443'; ma=86400\";|more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|nginx/custom|nginx_custom|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s| http2||g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|\(listen .*\) http3|\1 quic|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|quic reuseport;|quic;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|security_headers on;|include conf.d/include/hsts.conf;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|more_set_headers \"Alt-Svc: h3=':443'; ma=86400\";|more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/data/access|/data/nginx/access|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/data/nginx/access|/data/etc/access|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/data/nginx/html/|/data/etc/html/|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/access|/data/nginx/access|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/nginx/access|/data/etc/access|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/nginx/html/|/data/etc/html/|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/data/custom_ssl|/data/tls/custom|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/etc/letsencrypt|/data/tls/certbot|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/data/letsencrypt|/data/tls/certbot|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/custom_ssl|/data/tls/custom|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/tls/certbot|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/letsencrypt|/data/tls/certbot|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/data/ssl|/data/tls|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|ssl_certificate_key /data/nginx/dummykey.pem;|ssl_certificate_key /data/tls/dummykey.pem;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|ssl_certificate /data/nginx/dummycert.pem;|ssl_certificate /data/tls/dummycert.pem;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/ssl|/data/tls|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|ssl_certificate_key /data/nginx/dummykey.pem;|ssl_certificate_key /data/tls/dummykey.pem;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|ssl_certificate /data/nginx/dummycert.pem;|ssl_certificate /data/tls/dummycert.pem;|g" {} \; find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/data/ssl|/data/tls|g" {} \; find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/tls/certbot|g" {} \; find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/data/letsencrypt|/data/tls/certbot|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/block-exploits.conf/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|/html/404|/html/dead|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|include conf.d/include/acme-challenge.conf;|include conf.d/include/always.conf;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|include conf.d/include/letsencrypt-acme-challenge.conf;|include conf.d/include/always.conf;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/block-exploits.conf/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/html/404|/html/dead|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/acme-challenge.conf;|include conf.d/include/always.conf;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/letsencrypt-acme-challenge.conf;|include conf.d/include/always.conf;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|include conf.d/include/force-ssl.conf;|include conf.d/include/force-tls.conf;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|include conf.d/include/ssl-ciphers.conf;|include conf.d/include/tls-ciphers.conf;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/force-ssl.conf;|include conf.d/include/force-tls.conf;|g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/ssl-ciphers.conf;|include conf.d/include/tls-ciphers.conf;|g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/http3/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/Asset Caching/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/assets.conf/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/http3/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/Asset Caching/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/assets.conf/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/error_log/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/access_log/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/proxy_http_version/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/error_log/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/access_log/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/proxy_http_version/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/ssl_stapling/d" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/ssl_stapling_verify/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/ssl_stapling/d" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "/ssl_stapling_verify/d" {} \; if [ -s /data/nginx/default.conf ]; then sed -i "/ssl_stapling/d" /data/nginx/default.conf; fi if [ -s /data/nginx/default.conf ]; then sed -i "/ssl_stapling_verify/d" /data/nginx/default.conf; fi @@ -642,7 +663,7 @@ sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $IPV4_BINDING:\2/g" /app/templates/default.conf sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\({{ incoming_port }}\)/listen $IPV4_BINDING:\2/g" /app/templates/stream.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $IPV4_BINDING:\2/g" {} \; -find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9-]\+\)/listen $IPV4_BINDING:\2/g" {} \; +find /data/nginx -type f -name '*.conf' -exec sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9-]\+\)/listen $IPV4_BINDING:\2/g" {} \; if [ "$DISABLE_IPV6" = "true" ]; then sed -i "s|ipv6=on;|ipv6=off;|g" /usr/local/nginx/conf/nginx.conf @@ -650,14 +671,14 @@ if [ "$DISABLE_IPV6" = "true" ]; then sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /app/templates/default.conf sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\({{ incoming_port }}\)/#listen \[\1\]:\2/g" /app/templates/stream.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9-]\+\)/#listen \[\1\]:\2/g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9-]\+\)/#listen \[\1\]:\2/g" {} \; else sed -i "s|ipv6=off;|ipv6=on;|g" /usr/local/nginx/conf/nginx.conf sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $IPV6_BINDING:\2/g" /app/templates/_listen.conf sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $IPV6_BINDING:\2/g" /app/templates/default.conf sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\({{ incoming_port }}\)/listen $IPV6_BINDING:\2/g" /app/templates/stream.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $IPV6_BINDING:\2/g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9-]\+\)/listen $IPV6_BINDING:\2/g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9-]\+\)/listen $IPV6_BINDING:\2/g" {} \; fi sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $NPM_IPV4_BINDING:$NPM_PORT/g" /usr/local/nginx/conf/conf.d/npm.conf @@ -686,12 +707,17 @@ if [ "$DISABLE_HTTP" = "true" ]; then sed -i "s|#\?\(listen.*80\)|#\1|g" /app/templates/_listen.conf sed -i "s|#\?\(listen.*80\)|#\1|g" /app/templates/default.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|#\1|g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|#\?\(listen.*80\)|#\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|#\1|g" {} \; +elif [ "$DISABLE_IPV6" = "true" ]; then + sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" /app/templates/_listen.conf + sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" /app/templates/default.conf + find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" {} \; else sed -i "s|#\?\(listen.*80\)|\1|g" /app/templates/_listen.conf sed -i "s|#\?\(listen.*80\)|\1|g" /app/templates/default.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|\1|g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|#\?\(listen.*80\)|\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|\1|g" {} \; fi if [ "$DISABLE_H3_QUIC" = "true" ]; then @@ -701,8 +727,17 @@ if [ "$DISABLE_H3_QUIC" = "true" ]; then sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" /app/templates/default.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|#\1|g" {} \; find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|#\?\(listen.*quic\)|#\1|g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|#\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" {} \; +elif [ "$DISABLE_IPV6" = "true" ]; then + sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" /app/templates/_listen.conf + sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/_listen.conf + sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" /app/templates/default.conf + sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/default.conf + find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" {} \; + find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \; else sed -i "s|#\?\(listen.*quic\)|\1|g" /app/templates/_listen.conf sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/_listen.conf @@ -710,8 +745,8 @@ else sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/default.conf find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|\1|g" {} \; find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|#\?\(listen.*quic\)|\1|g" {} \; - find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|\1|g" {} \; + find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \; fi if [ "$NGINX_LOG_NOT_FOUND" = "true" ]; then @@ -948,11 +983,6 @@ if [ "$DISABLE_NGINX_BEAUTIFIER" = "false" ]; then nginxbeautifier -s 4 -r /data/nginx fi -#find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|add_header alt-svc 'h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400';|add_header Alt-Svc 'h3=\":443\"; ma=86400';|g" {} \; -#find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "s|add_header alt-svc 'h3=\":443\";|add_header Alt-Svc 'h3=\":443\"; ma=86400';|g" {} \; -#find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/ma=86400, h3-29=\":443\";/d" {} \; -#find /data/nginx -type f -name '*.conf' -not -path "/data/nginx/custom/*" -exec sed -i "/^[[:space:]]*ma=86400';[[:space:]]*$/d" {} \; - rm -vf /usr/local/nginx/logs/nginx.pid rm -vf /run/*.sock diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/brotli.conf b/rootfs/usr/local/nginx/conf/conf.d/include/brotli.conf index 4bc590c49..31645ca2b 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/brotli.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/brotli.conf @@ -1,4 +1,4 @@ brotli on; -brotli_types *; +brotli_types text/css text/javascript text/xml application/atom+xml application/rss+xml text/markdown text/mathml text/plain text/vnd.sun.j2me.app-descriptor text/vnd.wap.wml text/x-component application/json application/xhtml+xml application/xspf+xml font/woff font/woff2 image/avif image/bmp image/png image/svg+xml image/tiff image/vnd.wap.wbmp image/webp image/x-icon image/x-jng audio/midi audio/mpeg audio/ogg audio/x-m4a audio/x-realaudio; brotli_comp_level 0; brotli_static on; diff --git a/rootfs/usr/local/nginx/conf/nginx.conf b/rootfs/usr/local/nginx/conf/nginx.conf index 47d347955..f17ead2cc 100644 --- a/rootfs/usr/local/nginx/conf/nginx.conf +++ b/rootfs/usr/local/nginx/conf/nginx.conf @@ -6,11 +6,11 @@ worker_processes auto; worker_cpu_affinity auto; # Custom -include /data/nginx/custom/root_top.conf; +include /data/nginx_custom/root_top.conf; events { # Custom - include /data/nginx/custom/events.conf; + include /data/nginx_custom/events.conf; } http { @@ -40,7 +40,7 @@ http { gzip on; gzip_vary on; - gzip_types *; + gzip_types text/css text/javascript text/xml application/atom+xml application/rss+xml text/markdown text/mathml text/plain text/vnd.sun.j2me.app-descriptor text/vnd.wap.wml text/x-component application/json application/xhtml+xml application/xspf+xml font/woff font/woff2 image/avif image/bmp image/png image/svg+xml image/tiff image/vnd.wap.wbmp image/webp image/x-icon image/x-jng audio/midi audio/mpeg audio/ogg audio/x-m4a audio/x-realaudio; gzip_proxied any; gzip_comp_level 1; gzip_http_version 1.0; @@ -132,7 +132,7 @@ http { include conf.d/*.conf; # Custom - include /data/nginx/custom/http_top.conf; + include /data/nginx_custom/http_top.conf; # Files generated by NPM include /data/nginx/proxy_host/*.conf; @@ -140,7 +140,7 @@ http { include /data/nginx/dead_host/*.conf; # Custom - include /data/nginx/custom/http.conf; + include /data/nginx_custom/http.conf; } stream { @@ -149,11 +149,11 @@ stream { resolver local=on valid=10s ipv6=on; # Custom - include /data/nginx/custom/stream_top.conf; + include /data/nginx_custom/stream_top.conf; # Files generated by NPM include /data/nginx/stream/*.conf; # Custom - include /data/nginx/custom/stream.conf; + include /data/nginx_custom/stream.conf; } diff --git a/test/cypress/e2e/api/Settings.cy.js b/test/cypress/e2e/api/Settings.cy.js deleted file mode 100644 index 6942760c7..000000000 --- a/test/cypress/e2e/api/Settings.cy.js +++ /dev/null @@ -1,124 +0,0 @@ -/// - -describe('Settings endpoints', () => { - let token; - - before(() => { - cy.getToken().then((tok) => { - token = tok; - }); - }); - - it('Get all settings', function() { - cy.task('backendApiGet', { - token: token, - path: '/api/settings', - }).then((data) => { - cy.validateSwaggerSchema('get', 200, '/settings', data); - expect(data.length).to.be.greaterThan(0); - }); - }); - - it('Get default-site setting', function() { - cy.task('backendApiGet', { - token: token, - path: '/api/settings/default-site', - }).then((data) => { - cy.validateSwaggerSchema('get', 200, '/settings/{settingID}', data); - expect(data).to.have.property('id'); - expect(data.id).to.be.equal('default-site'); - }); - }); - - it('Default Site congratulations', function() { - cy.task('backendApiPut', { - token: token, - path: '/api/settings/default-site', - data: { - value: 'congratulations', - }, - }).then((data) => { - cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); - expect(data).to.have.property('id'); - expect(data.id).to.be.equal('default-site'); - expect(data).to.have.property('value'); - expect(data.value).to.be.equal('congratulations'); - }); - }); - - it('Default Site 404', function() { - cy.task('backendApiPut', { - token: token, - path: '/api/settings/default-site', - data: { - value: '404', - }, - }).then((data) => { - cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); - expect(data).to.have.property('id'); - expect(data.id).to.be.equal('default-site'); - expect(data).to.have.property('value'); - expect(data.value).to.be.equal('404'); - }); - }); - - it('Default Site 444', function() { - cy.task('backendApiPut', { - token: token, - path: '/api/settings/default-site', - data: { - value: '444', - }, - }).then((data) => { - cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); - expect(data).to.have.property('id'); - expect(data.id).to.be.equal('default-site'); - expect(data).to.have.property('value'); - expect(data.value).to.be.equal('444'); - }); - }); - - it('Default Site redirect', function() { - cy.task('backendApiPut', { - token: token, - path: '/api/settings/default-site', - data: { - value: 'redirect', - meta: { - redirect: 'https://www.google.com', - }, - }, - }).then((data) => { - cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); - expect(data).to.have.property('id'); - expect(data.id).to.be.equal('default-site'); - expect(data).to.have.property('value'); - expect(data.value).to.be.equal('redirect'); - expect(data).to.have.property('meta'); - expect(data.meta).to.have.property('redirect'); - expect(data.meta.redirect).to.be.equal('https://www.google.com'); - }); - }); - - it('Default Site html', function() { - cy.task('backendApiPut', { - token: token, - path: '/api/settings/default-site', - data: { - value: 'html', - meta: { - html: '

hello world

' - }, - }, - }).then((data) => { - cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data); - expect(data).to.have.property('id'); - expect(data.id).to.be.equal('default-site'); - expect(data).to.have.property('value'); - expect(data.value).to.be.equal('html'); - expect(data).to.have.property('meta'); - expect(data.meta).to.have.property('html'); - expect(data.meta.html).to.be.equal('

hello world

'); - }); - }); -});