diff --git a/.github/workflows/dependency-updates.yml b/.github/workflows/dependency-updates.yml index 29c690252..d9a770932 100644 --- a/.github/workflows/dependency-updates.yml +++ b/.github/workflows/dependency-updates.yml @@ -25,7 +25,7 @@ jobs: sed -i "s|ARG CSNB_VER=.*|ARG CSNB_VER=$CSNB_VER|" Dockerfile echo "version=$CSNB_VER" >> $GITHUB_OUTPUT - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: signoff: true delete-branch: true @@ -51,7 +51,7 @@ jobs: sed -i "s|ARG CRS_VER=.*|ARG CRS_VER=$CRS_VER|" Dockerfile echo "version=$CRS_VER" >> $GITHUB_OUTPUT - name: Create Pull Request - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: signoff: true delete-branch: true diff --git a/.github/workflows/update-and-lint.yml b/.github/workflows/update-and-lint.yml index f6af7af9e..912da2eac 100644 --- a/.github/workflows/update-and-lint.yml +++ b/.github/workflows/update-and-lint.yml @@ -24,9 +24,7 @@ jobs: - name: nginxbeautifier run: | yarn global add nginxbeautifier - mv -v rootfs/usr/local/nginx/conf/exploits.conf exploits.conf nginxbeautifier -s 4 -r rootfs/usr/local/nginx/conf - mv -v exploits.conf rootfs/usr/local/nginx/conf/exploits.conf - name: push changes run: | git add -A diff --git a/Caddy.Dockerfile b/Caddy.Dockerfile index aa15630de..b7ef9b767 100644 --- a/Caddy.Dockerfile +++ b/Caddy.Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.20.2 +FROM alpine:3.20.3 RUN apk add --no-cache ca-certificates tzdata COPY --from=caddy:2.8.4 /usr/bin/caddy /usr/bin/caddy COPY Caddyfile /etc/caddy/Caddyfile diff --git a/Dockerfile b/Dockerfile index 2b8f24f8c..8b0550c96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:labs -FROM --platform="$BUILDPLATFORM" alpine:3.20.2 AS frontend +FROM --platform="$BUILDPLATFORM" alpine:3.20.3 AS frontend COPY frontend /app COPY global/certbot-dns-plugins.json /app/certbot-dns-plugins.json ARG NODE_ENV=production \ @@ -18,7 +18,7 @@ COPY darkmode.css /app/dist/css/darkmode.css COPY security.txt /app/dist/.well-known/security.txt -FROM --platform="$BUILDPLATFORM" alpine:3.20.2 AS build-backend +FROM --platform="$BUILDPLATFORM" alpine:3.20.3 AS build-backend SHELL ["/bin/ash", "-eo", "pipefail", "-c"] COPY backend /app COPY global/certbot-dns-plugins.json /app/certbot-dns-plugins.json @@ -37,7 +37,7 @@ RUN apk upgrade --no-cache -a && \ fi && \ yarn cache clean --all && \ clean-modules --yes -FROM alpine:3.20.2 AS strip-backend +FROM alpine:3.20.3 AS strip-backend COPY --from=build-backend /app /app RUN apk upgrade --no-cache -a && \ apk add --no-cache ca-certificates binutils file && \ @@ -45,7 +45,7 @@ RUN apk upgrade --no-cache -a && \ find /app/node_modules -name "*.node" -type f -exec file {} \; -FROM --platform="$BUILDPLATFORM" alpine:3.20.2 AS crowdsec +FROM --platform="$BUILDPLATFORM" alpine:3.20.3 AS crowdsec SHELL ["/bin/ash", "-eo", "pipefail", "-c"] ARG CSNB_VER=v1.0.8 WORKDIR /src @@ -67,22 +67,24 @@ RUN apk upgrade --no-cache -a && \ sed -i "s|BOUNCING_ON_TYPE=all|BOUNCING_ON_TYPE=ban|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf -FROM zoeyvid/nginx-quic:306-python +FROM zoeyvid/nginx-quic:337-python SHELL ["/bin/ash", "-eo", "pipefail", "-c"] COPY rootfs / -COPY --from=zoeyvid/certbot-docker:46 /usr/local /usr/local -COPY --from=zoeyvid/curl-quic:408 /usr/local/bin/curl /usr/local/bin/curl +COPY --from=zoeyvid/certbot-docker:49 /usr/local /usr/local +COPY --from=zoeyvid/curl-quic:416 /usr/local/bin/curl /usr/local/bin/curl -ARG CRS_VER=v4.5.0 +ARG CRS_VER=v4.7.0 RUN apk upgrade --no-cache -a && \ apk add --no-cache ca-certificates tzdata tini \ nodejs \ bash nano \ - openssl apache2-utils \ + logrotate apache2-utils \ 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 && \ curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online --home /usr/local/acme.sh --nocron && \ + curl https://raw.githubusercontent.com/tomwassenberg/certbot-ocsp-fetcher/refs/heads/main/certbot-ocsp-fetcher -o /usr/local/bin/certbot-ocsp-fetcher.sh && \ + chmod +x /usr/local/bin/certbot-ocsp-fetcher.sh && \ git clone https://github.com/coreruleset/coreruleset --branch "$CRS_VER" /tmp/coreruleset && \ mkdir -v /usr/local/nginx/conf/conf.d/include/coreruleset && \ mv -v /tmp/coreruleset/crs-setup.conf.example /usr/local/nginx/conf/conf.d/include/coreruleset/crs-setup.conf.example && \ diff --git a/README.md b/README.md index 0094c8194..4e4f02cd0 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ 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 @@ -61,7 +62,6 @@ so that the barrier for entry here is low. - Only enables TLSv1.2 and TLSv1.3 protocols - Faster creation of TLS certificates can be achieved by eliminating unnecessary Nginx reloads and configuration creations. - Uses OCSP Stapling for enhanced security - - If using custom certificates, upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/tls/custom/npm-[certificate-id]` folder (manual migration may be needed) - Resolved dnspod plugin issue - To migrate manually, delete all dnspod certs and recreate them OR change the credentials file as per the template given [here](https://github.com/ZoeyVid/NPMplus/blob/develop/global/certbot-dns-plugins.js) - Smaller docker image with alpine-based distribution @@ -91,11 +91,11 @@ so that the barrier for entry here is low. ## migration - **NOTE: migrating back to the original is not possible**, so make first a **backup** before migration, so you can use the backup to switch back -- if you use custom certificates, you need to upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/tls/custom/npm-[certificate-id]` folder -- some buttons have changed, check if they are still correct +- since many buttons changed, please edit every host you have and click save. (Please also resave it, if all buttons/values are fine, to update the host config to fully fit the NPMplus template) - please delete all dnspod certs and recreate them OR you manually change the credentialsfile (see [here](https://github.com/ZoeyVid/npmplus/blob/develop/global/certbot-dns-plugins.js) for the template) - since this fork has dependency on `network_mode: host`, please don't forget to open port 80/tcp, 443/tcp and 443/udp (and maybe 81/tcp) in your firewall - 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 # Crowdsec 1. Install crowdsec using this compose file: https://github.com/ZoeyVid/NPMplus/blob/develop/compose.crowdsec.yaml and enable LOGROTATE @@ -198,7 +198,7 @@ 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.com +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. diff --git a/backend/doc/api.swagger.json b/backend/doc/api.swagger.json index 4d97d5e06..c48084994 100644 --- a/backend/doc/api.swagger.json +++ b/backend/doc/api.swagger.json @@ -102,7 +102,7 @@ "modified_on": "2023-03-30T01:11:50.000Z", "is_deleted": 0, "is_disabled": 0, - "email": "admin@example.com", + "email": "admin@example.org", "name": "Administrator", "nickname": "Admin", "avatar": "", @@ -144,7 +144,7 @@ "modified_on": "2023-03-30T01:11:50.000Z", "is_deleted": 0, "is_disabled": 0, - "email": "admin@example.com", + "email": "admin@example.org", "name": "Administrator", "nickname": "Admin", "avatar": "", @@ -223,7 +223,7 @@ "modified_on": "2023-03-30T01:11:50.000Z", "is_deleted": 0, "is_disabled": 0, - "email": "admin@example.com", + "email": "admin@example.org", "name": "Administrator", "nickname": "Admin", "avatar": "", diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index 298f06e9c..daf04a16c 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -480,14 +480,6 @@ const internalCertificate = { resolve(); } }); - - fs.writeFile(dir + '/chain.pem', certificate.meta.intermediate_certificate, function (err) { - if (err) { - reject(err); - } else { - resolve(); - } - }); }).then(() => { return new Promise((resolve, reject) => { fs.writeFile(dir + '/privkey.pem', certificate.meta.certificate_key, function (err) { @@ -777,7 +769,7 @@ const internalCertificate = { requestLetsEncryptSsl: (certificate) => { logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); - let cmd = certbotCommand + ' certonly ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--authenticator webroot ' + '--preferred-challenges "dns,http" ' + '--domains "' + certificate.domain_names.join(',') + '"'; + let cmd = certbotCommand + ' certonly ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--authenticator webroot ' + '--preferred-challenges "http,dns" ' + '--domains "' + certificate.domain_names.join(',') + '"'; if (certificate.meta.letsencrypt_email === '') { cmd = cmd + ' --register-unsafely-without-email '; @@ -881,7 +873,15 @@ const internalCertificate = { renewLetsEncryptSsl: (certificate) => { logger.info('Renewing Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); - const cmd = certbotCommand + ' renew --force-renewal ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew'; + const cmdr = certbotCommand + ' revoke ' + '--config "' + certbotConfig + '" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/privkey.pem" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem"'; + + logger.info('Command:', cmdr); + + utils.exec(cmdr).then((result) => { + logger.info(result); + }); + + const cmd = certbotCommand + ' renew --force-renewal ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--preferred-challenges "http,dns" ' + '--no-random-sleep-on-renew'; logger.info('Command:', cmd); @@ -904,6 +904,14 @@ const internalCertificate = { logger.info(`Renewing Certbot certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`); + const mainCmdr = certbotCommand + ' revoke ' + '--config "' + certbotConfig + '" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/privkey.pem" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem"'; + + logger.info('Command:', mainCmdr); + + utils.exec(mainCmdr).then(async (result) => { + logger.info(result); + }); + const mainCmd = certbotCommand + ' renew --force-renewal ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew'; logger.info('Command:', mainCmd); @@ -924,15 +932,10 @@ const internalCertificate = { const mainCmd = certbotCommand + ' revoke ' + '--config "' + certbotConfig + '" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/privkey.pem" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem" ' + '--delete-after-revoke'; - // Don't fail command if file does not exist - const delete_credentialsCmd = `rm -f '/data/tls/certbot/credentials/credentials-${certificate.id}' || true`; - - logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd); - return utils .exec(mainCmd) .then(async (result) => { - await utils.exec(delete_credentialsCmd); + await fs.rm('/data/tls/certbot/credentials/credentials-' + certificate.id, { force: true }); logger.info(result); return result; }) diff --git a/backend/internal/ip_ranges.js b/backend/internal/ip_ranges.js index 4518db872..d21beb40f 100644 --- a/backend/internal/ip_ranges.js +++ b/backend/internal/ip_ranges.js @@ -102,7 +102,7 @@ const internalIpRanges = { const renderEngine = utils.getRenderEngine(); return new Promise((resolve, reject) => { let template = null; - const filename = '/data/nginx/ip_ranges.conf'; + const filename = '/tmp/ip_ranges.conf'; try { template = fs.readFileSync(__dirname + '/../templates/ip_ranges.conf', { encoding: 'utf8' }); } catch (err) { diff --git a/backend/internal/nginx.js b/backend/internal/nginx.js index 5483f2d8f..d843687ec 100644 --- a/backend/internal/nginx.js +++ b/backend/internal/nginx.js @@ -32,7 +32,7 @@ const internalNginx = { // We're deleting this config regardless. // Don't throw errors, as the file may not exist at all // Delete the .err file too - return internalNginx.deleteConfig(host_type, host, false, true); + return internalNginx.deleteConfig(host_type, host); }) .then(() => { return internalNginx.generateConfig(host_type, host); @@ -52,27 +52,11 @@ const internalNginx = { meta: combined_meta, }); }) - .catch((err) => { - // Remove the error_log line because it's a docker-ism false positive that doesn't need to be reported. - // It will always look like this: - // nginx: [alert] could not open error log file: open() "/dev/null" failed (6: No such device or address) - - const valid_lines = []; - const err_lines = err.message.split('\n'); - err_lines.map(function (line) { - if (line.indexOf('/dev/null') === -1) { - valid_lines.push(line); - } - }); - - if (config.debug()) { - logger.error('Nginx test failed:', valid_lines.join('\n')); - } - - // config is bad, update meta and delete config + .catch(() => { + utils.exec('nginx -t'); combined_meta = _.assign({}, host.meta, { nginx_online: false, - nginx_err: valid_lines.join('\n'), + nginx_err: 'see dockert logs', }); return model @@ -83,9 +67,6 @@ const internalNginx = { }) .then(() => { internalNginx.renameConfigAsError(host_type, host); - }) - .then(() => { - return internalNginx.deleteConfig(host_type, host, true); }); }); }) @@ -114,17 +95,23 @@ const internalNginx = { reload: () => { return internalNginx.test().then(() => { + try { + utils.exec('certbot-ocsp-fetcher.sh -c /data/tls/certbot -o /data/tls/certbot/live --quiet --no-reload-webserver'); + } catch { + // do nothing + } if (fs.existsSync(NgxPidFilePath)) { const ngxPID = fs.readFileSync(NgxPidFilePath, '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'); utils.execfg('nginx -e stderr'); } } else { logger.info('Starting Nginx'); + utils.exec('certbot-ocsp-fetcher.sh -c /data/tls/certbot -o /data/tls/certbot/live --quiet --no-reload-webserver'); utils.execfg('nginx -e stderr'); } }); @@ -262,20 +249,6 @@ const internalNginx = { }); }, - /** - * A simple wrapper around unlinkSync that writes to the logger - * - * @param {String} filename - */ - deleteFile: (filename) => { - logger.debug('Deleting file: ' + filename); - try { - fs.unlinkSync(filename); - } catch (err) { - logger.debug('Could not delete file:', JSON.stringify(err, null, 2)); - } - }, - /** * * @param {String} host_type @@ -291,15 +264,11 @@ const internalNginx = { * @param {Boolean} [delete_err_file] * @returns {Promise} */ - deleteConfig: (host_type, host, delete_err_file) => { + deleteConfig: (host_type, host) => { const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id); - const config_file_err = config_file + '.err'; return new Promise((resolve /*, reject */) => { - internalNginx.deleteFile(config_file); - if (delete_err_file) { - internalNginx.deleteFile(config_file_err); - } + fs.rm(config_file, { force: true }); resolve(); }); }, @@ -312,16 +281,11 @@ const internalNginx = { renameConfigAsError: (host_type, host) => { const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id); const config_file_err = config_file + '.err'; - - return new Promise((resolve /*, reject */) => { - fs.unlink(config_file, () => { - // ignore result, continue - fs.rename(config_file, config_file_err, () => { - // also ignore result, as this is a debugging informative file anyway - resolve(); - }); - }); - }); + try { + fs.rename(config_file, config_file_err); + } catch { + // do nothing + } }, /** @@ -346,7 +310,7 @@ const internalNginx = { bulkDeleteConfigs: (host_type, hosts) => { const promises = []; hosts.map(function (host) { - promises.push(internalNginx.deleteConfig(host_type, host, true)); + promises.push(internalNginx.deleteConfig(host_type, host)); }); return Promise.all(promises); diff --git a/backend/knexfile.js b/backend/knexfile.js index 81de3ed25..3c33162e9 100644 --- a/backend/knexfile.js +++ b/backend/knexfile.js @@ -1,6 +1,6 @@ module.exports = { development: { - client: 'mysql', + client: 'mysql2', migrations: { tableName: 'migrations', stub: 'lib/migrate_template.js', @@ -9,7 +9,7 @@ module.exports = { }, production: { - client: 'mysql', + client: 'mysql2', migrations: { tableName: 'migrations', stub: 'lib/migrate_template.js', diff --git a/backend/lib/config.js b/backend/lib/config.js index 4ea383f50..e034cb482 100644 --- a/backend/lib/config.js +++ b/backend/lib/config.js @@ -36,7 +36,7 @@ const configure = () => { logger.info('Using MySQL configuration'); instance = { database: { - engine: 'mysql', + engine: 'mysql2', host: envMysqlHost, port: process.env.DB_MYSQL_PORT || 3306, user: envMysqlUser, diff --git a/backend/migrations/20240921100301_regenerate_default_host.js b/backend/migrations/20240921100301_regenerate_default_host.js new file mode 100644 index 000000000..82e6c403e --- /dev/null +++ b/backend/migrations/20240921100301_regenerate_default_host.js @@ -0,0 +1,51 @@ +const migrate_name = 'stream_domain'; +const logger = require('../logger').migrate; +const internalNginx = require('../internal/nginx'); + +async function regenerateDefaultHost(knex) { + const row = await knex('setting').select('*').where('id', 'default-site').first(); + + if (!row) { + return Promise.resolve(); + } + + return internalNginx + .deleteConfig('default') + .then(() => { + return internalNginx.generateConfig('default', row); + }) + .then(() => { + return internalNginx.test(); + }) + .then(() => { + return internalNginx.reload(); + }); +} + +/** + * Migrate + * + * @see http://knexjs.org/#Schema + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.up = function (knex) { + logger.info('[' + migrate_name + '] Migrating Up...'); + + return regenerateDefaultHost(knex); +}; + +/** + * Undo Migrate + * + * @param {Object} knex + * @param {Promise} Promise + * @returns {Promise} + */ +exports.down = function (knex) { + logger.info('[' + migrate_name + '] Migrating Down...'); + + return regenerateDefaultHost(knex); +}; diff --git a/backend/package.json b/backend/package.json index 4dc0c572b..616bddf5b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,28 +9,28 @@ "archiver": "7.0.1", "batchflow": "0.4.0", "bcrypt": "5.1.1", - "better-sqlite3": "11.1.2", - "body-parser": "1.20.2", + "better-sqlite3": "11.3.0", + "body-parser": "2.0.1", "compression": "1.7.4", - "express": "4.19.2", + "express": "4.21.0", "express-fileupload": "1.5.1", "gravatar": "1.8.2", "jsonwebtoken": "9.0.2", "knex": "3.1.0", - "liquidjs": "10.16.1", + "liquidjs": "10.17.0", "lodash": "4.17.21", "moment": "2.30.1", - "mysql": "2.18.1", + "mysql2": "3.11.3", "node-rsa": "1.1.1", - "objection": "3.1.4", + "objection": "3.1.5", "path": "0.12.7", "signale": "1.4.0" }, "author": "Jamie Curnow and ZoeyVid ", "license": "MIT", "devDependencies": { - "@eslint/js": "9.9.0", - "eslint": "9.9.0", + "@eslint/js": "9.11.1", + "eslint": "9.11.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-prettier": "5.2.1", "globals": "15.9.0", diff --git a/backend/setup.js b/backend/setup.js index a41baf984..c5b89bb64 100644 --- a/backend/setup.js +++ b/backend/setup.js @@ -22,7 +22,7 @@ const setupDefaultUser = () => { .then((row) => { if (!row.count) { // Create a new user and set password - let email = process.env.INITIAL_ADMIN_EMAIL || 'admin@example.com'; + let email = process.env.INITIAL_ADMIN_EMAIL || 'admin@example.org'; let password = process.env.INITIAL_ADMIN_PASSWORD || 'iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi'; logger.info('Creating a new user: ' + email + ' with password: ' + password); diff --git a/backend/templates/_certificates.conf b/backend/templates/_certificates.conf index fff752d56..aff3bde32 100644 --- a/backend/templates/_certificates.conf +++ b/backend/templates/_certificates.conf @@ -4,12 +4,11 @@ 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_trusted_certificate /data/tls/certbot/live/npm-{{ certificate_id }}/chain.pem; + ssl_stapling_file /data/tls/certbot/live/npm-{{ certificate_id }}.der; {% else %} - # Custom SSL + # Custom TLS include conf.d/include/tls-ciphers.conf; ssl_certificate /data/tls/custom/npm-{{ certificate_id }}/fullchain.pem; ssl_certificate_key /data/tls/custom/npm-{{ certificate_id }}/privkey.pem; - ssl_trusted_certificate /data/tls/custom/npm-{{ certificate_id }}/chain.pem; {% endif %} {% endif %} diff --git a/backend/templates/default.conf b/backend/templates/default.conf index 8513ccc8d..3f42e2cce 100644 --- a/backend/templates/default.conf +++ b/backend/templates/default.conf @@ -19,9 +19,11 @@ server { include conf.d/include/tls-ciphers.conf; include conf.d/include/always.conf; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; {%- if value == "404" %} location / { diff --git a/frontend/js/app/main.js b/frontend/js/app/main.js index e85b4f620..c825664b5 100644 --- a/frontend/js/app/main.js +++ b/frontend/js/app/main.js @@ -48,7 +48,7 @@ const App = Mn.Application.extend({ Backbone.history.start({pushState: true}); // Ask the admin use to change their details - if (Cache.User.get('email') === 'admin@example.com') { + if (Cache.User.get('email') === 'admin@example.com' || Cache.User.get('email') === 'admin@example.org') { Controller.showUserForm(Cache.User); } }); diff --git a/frontend/js/app/nginx/certificates/form.ejs b/frontend/js/app/nginx/certificates/form.ejs index 899fd9701..24989561e 100644 --- a/frontend/js/app/nginx/certificates/form.ejs +++ b/frontend/js/app/nginx/certificates/form.ejs @@ -165,9 +165,9 @@
-
<%- i18n('certificates', 'other-intermediate-certificate') %>*
+
<%- i18n('certificates', 'other-intermediate-certificate') %>
- +
diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js index f743f2186..410e149c6 100644 --- a/frontend/js/app/nginx/certificates/form.js +++ b/frontend/js/app/nginx/certificates/form.js @@ -149,10 +149,7 @@ module.exports = Mn.View.extend({ ssl_files.push({name: 'certificate_key', file: this.ui.other_certificate_key[0].files[0]}); } - if (!this.ui.other_intermediate_certificate[0].files.length || !this.ui.other_intermediate_certificate[0].files[0].size) { - alert('Intermediate Certificate file is not attached'); - return; - } else { + if (this.ui.other_intermediate_certificate[0].files.length && this.ui.other_intermediate_certificate[0].files[0].size) { if (this.ui.other_intermediate_certificate[0].files[0].size > this.max_file_size) { alert('Intermediate Certificate file is too large (> 100kb)'); return; diff --git a/frontend/js/app/user/form.js b/frontend/js/app/user/form.js index ef92ec3e9..74fea4035 100644 --- a/frontend/js/app/user/form.js +++ b/frontend/js/app/user/form.js @@ -25,10 +25,10 @@ module.exports = Mn.View.extend({ let view = this; let data = this.ui.form.serializeJSON(); - let show_password = this.model.get('email') === 'admin@example.com'; + let show_password = (this.model.get('email') === 'admin@example.com' || this.model.get('email') === 'admin@example.org'); - // admin@example.com is not allowed - if (data.email === 'admin@example.com') { + // admin@example.com and admin@example.org is not allowed + if (data.email === 'admin@example.com' || data.email === 'admin@example.org') { this.ui.error.text(App.i18n('users', 'default_error')).show(); this.ui.buttons.prop('disabled', false).removeClass('btn-disabled'); return; diff --git a/frontend/package.json b/frontend/package.json index 218498905..ead54dc77 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,7 @@ "dependencies": { "@babel/core": "7.25.2", "babel-core": "6.26.3", - "babel-loader": "8.3.0", + "babel-loader": "8.4.1", "babel-preset-env": "1.7.0", "backbone": "1.6.0", "backbone.marionette": "4.1.3", @@ -28,7 +28,7 @@ "mini-css-extract-plugin": "1.6.2", "moment": "2.30.1", "node-sass": "9.0.0", - "nodemon": "3.1.4", + "nodemon": "3.1.7", "numeral": "2.0.6", "sass-loader": "10.5.2", "style-loader": "4.0.0", diff --git a/rootfs/etc/tls/certbot.ini b/rootfs/etc/tls/certbot.ini index 300c83438..3202cf058 100644 --- a/rootfs/etc/tls/certbot.ini +++ b/rootfs/etc/tls/certbot.ini @@ -4,12 +4,17 @@ webroot-path = /tmp/acme-challenge new-key= true key-type = ecdsa -must-staple = false +must-staple = true no-reuse-key = true rsa-key-size = 4096 elliptic-curve = secp384r1 -# An example of using an alternate ACME server that uses EAB credentials -# server = https://dv.acme-v02.api.pki.goog/directory -# eab-kid = somestringofstuffwithoutquotes -# eab-hmac-key = yaddayaddahexhexnotquoted +#server = https://acme-v02.api.letsencrypt.org/directory + +#server = https://acme.zerossl.com/v2/DV90 +#eab-kid = somestringofstuffwithoutquotes +#eab-hmac-key = yaddayaddahexhexnotquoted + +#server = https://dv.acme-v02.api.pki.goog/directory +#eab-kid = somestringofstuffwithoutquotes +#eab-hmac-key = yaddayaddahexhexnotquoted diff --git a/rootfs/usr/local/bin/aio.sh b/rootfs/usr/local/bin/aio.sh index a4e2554a2..d75870baf 100755 --- a/rootfs/usr/local/bin/aio.sh +++ b/rootfs/usr/local/bin/aio.sh @@ -2,7 +2,7 @@ if [ "$NC_AIO" = "true" ] && [ ! -f /data/etc/aio.lock ]; then while [ "$(healthcheck.sh)" != "OK" ]; do sleep 10s; done - curl -POST http://127.0.0.1:48693/nginx/proxy-hosts -sH 'Content-Type: application/json' -d '{"domain_names":["'"$NC_DOMAIN"'"],"forward_scheme":"http","forward_host":"127.0.0.1","forward_port":11000,"allow_websocket_upgrade":true,"access_list_id":"0","certificate_id":"new","ssl_forced":true,"http2_support":true,"hsts_enabled":true,"hsts_subdomains":true,"meta":{"letsencrypt_email":"","letsencrypt_agree":true,"dns_challenge":false},"advanced_config":"","locations":[],"block_exploits":false,"caching_enabled":false}' -H "Authorization: Bearer $(curl -POST http://127.0.0.1:48693/tokens -sH 'Content-Type: application/json' -d '{"identity":"admin@example.com","secret":"iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi"}' | jq -r .token)" + curl -POST http://127.0.0.1:48693/nginx/proxy-hosts -sH 'Content-Type: application/json' -d '{"domain_names":["'"$NC_DOMAIN"'"],"forward_scheme":"http","forward_host":"127.0.0.1","forward_port":11000,"allow_websocket_upgrade":true,"access_list_id":"0","certificate_id":"new","ssl_forced":true,"http2_support":true,"hsts_enabled":true,"hsts_subdomains":true,"meta":{"letsencrypt_email":"","letsencrypt_agree":true,"dns_challenge":false},"advanced_config":"","locations":[],"block_exploits":false,"caching_enabled":false}' -H "Authorization: Bearer $(curl -POST http://127.0.0.1:48693/tokens -sH 'Content-Type: application/json' -d '{"identity":"admin@example.org","secret":"iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi"}' | jq -r .token)" touch /data/etc/aio.lock echo "The default config for AIO should now be created. Please check the log for any errors and try to resolve them, then delete the aio.lock file and retry." fi diff --git a/rootfs/usr/local/bin/start.sh b/rootfs/usr/local/bin/start.sh index b06c8b754..7f316d85a 100755 --- a/rootfs/usr/local/bin/start.sh +++ b/rootfs/usr/local/bin/start.sh @@ -387,7 +387,6 @@ fi if [ "$LOGROTATE" = "true" ]; then - apk add --no-cache logrotate sed -i "s|rotate [0-9]\+|rotate $LOGROTATIONS|g" /etc/logrotate touch /data/nginx/access.log \ /data/nginx/stream.log @@ -433,7 +432,7 @@ if [ -s /data/nginx/default_host/site.conf ]; then fi if [ -s /data/nginx/default_www/index.html ]; then - mv -vn /data/nginx/default_www/index.html /data/nginx/html/index.html + mv -vn /data/nginx/default_www/index.html /data/etc/html/index.html fi if [ -s /data/nginx/dummycert.pem ]; then @@ -461,7 +460,7 @@ if [ -n "$(ls -A /data/nginx/access 2> /dev/null)" ]; then fi if [ -n "$(ls -A /etc/letsencrypt 2> /dev/null)" ]; then - mv -vn /etc/letsencrypt/* /data/tls/certbot + cp -van /etc/letsencrypt/* /data/tls/certbot fi if [ -n "$(ls -A /data/letsencrypt 2> /dev/null)" ]; then @@ -504,7 +503,9 @@ if [ "$CLEAN" = "true" ]; then /data/ssl \ /data/logs \ /data/error.log \ - /data/nginx/error.log + /data/nginx/error.log \ + /data/nginx/ip_ranges.conf + find /data/nginx -name "*.err" -delete rm -vf /data/tls/certbot/crs/*.pem rm -vf /data/tls/certbot/keys/*.pem @@ -531,12 +532,8 @@ if [ "$FULLCLEAN" = "true" ]; then fi fi -if [ "$SKIP_IP_RANGES" = "true" ]; then - rm -vf /data/nginx/ip_ranges.conf -fi - -touch /data/etc/html/index.html \ - /data/nginx/ip_ranges.conf \ +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 \ @@ -618,124 +615,6 @@ cp -a /usr/local/nginx/conf/conf.d/include/coreruleset/rules/RESPONSE-999-EXCLUS cp -va /usr/local/nginx/conf/conf.d/include/coreruleset/plugins/* /data/etc/modsecurity/crs-plugins -if [ "$DEFAULT_CERT_ID" = "0" ]; then - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "no DEFAULT_CERT_ID set, using dummycerts." -else - if [ -d "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID" ]; then - if [ ! -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/fullchain.pem ]; then - echo "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID/fullchain.pem does not exist" - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "using dummycerts." - else - export DEFAULT_CERT=/data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/fullchain.pem - echo "DEFAULT_CERT set to /data/tls/certbot/live/npm-$DEFAULT_CERT_ID/fullchain.pem" - - if [ ! -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/privkey.pem ]; then - echo "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID/privkey.pem does not exist" - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "using dummycerts." - else - export DEFAULT_KEY=/data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/privkey.pem - echo "DEFAULT_KEY set to /data/tls/certbot/live/npm-$DEFAULT_CERT_ID/privkey.pem" - - if [ ! -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/chain.pem ]; then - echo "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID/chain.pem does not exist, running without it" - else - export DEFAULT_CHAIN=/data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/chain.pem - echo "DEFAULT_CHAIN set to /data/tls/certbot/live/npm-$DEFAULT_CERT_ID/chain.pem" - fi - fi - fi - - elif [ -d "/data/tls/custom/npm-$DEFAULT_CERT_ID" ]; then - if [ ! -s /data/tls/custom/npm-"$DEFAULT_CERT_ID"/fullchain.pem ]; then - echo "/data/tls/custom/npm-$DEFAULT_CERT_ID/fullchain.pem does not exist" - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "using dummycerts." - else - export DEFAULT_CERT=/data/tls/custom/npm-"$DEFAULT_CERT_ID"/fullchain.pem - echo "DEFAULT_CERT set to /data/tls/custom/npm-$DEFAULT_CERT_ID/fullchain.pem" - - if [ ! -s /data/tls/custom/npm-"$DEFAULT_CERT_ID"/privkey.pem ]; then - echo "/data/tls/custom/npm-$DEFAULT_CERT_ID/privkey.pem does not exist" - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "using dummycerts." - else - export DEFAULT_KEY=/data/tls/custom/npm-"$DEFAULT_CERT_ID"/privkey.pem - echo "DEFAULT_KEY set to /data/tls/custom/npm-$DEFAULT_CERT_ID/privkey.pem" - - if [ ! -s /data/tls/custom/npm-"$DEFAULT_CERT_ID"/chain.pem ]; then - echo "/data/tls/custom/npm-$DEFAULT_CERT_ID/chain.pem does not exist, running without it" - else - export DEFAULT_CHAIN=/data/tls/custom/npm-"$DEFAULT_CERT_ID"/chain.pem - echo "DEFAULT_CHAIN set to /data/tls/custom/npm-$DEFAULT_CERT_ID/chain.pem" - fi - fi - fi - - else - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "cert with ID $DEFAULT_CERT_ID does not exist, using dummycerts." - fi -fi - -if [ "$DEFAULT_CERT" = "/data/tls/dummycert.pem" ] && [ "$DEFAULT_KEY" != "/data/tls/dummykey.pem" ]; then - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "something went wrong, using dummycerts." -fi -if [ "$DEFAULT_CERT" != "/data/tls/dummycert.pem" ] && [ "$DEFAULT_KEY" = "/data/tls/dummykey.pem" ]; then - export DEFAULT_CERT=/data/tls/dummycert.pem - export DEFAULT_KEY=/data/tls/dummykey.pem - echo "something went wrong, using dummycerts." -fi - -if [ "$DEFAULT_CERT" = "/data/tls/dummycert.pem" ] || [ "$DEFAULT_KEY" = "/data/tls/dummykey.pem" ]; then - if [ ! -s /data/tls/dummycert.pem ] || [ ! -s /data/tls/dummykey.pem ]; then - rm -vrf /data/tls/dummycert.pem \ - /data/tls/dummykey.pem - openssl req -new -newkey rsa:4096 -days 365000 -nodes -x509 -subj '/CN=*' -sha256 -keyout /data/tls/dummykey.pem -out /data/tls/dummycert.pem - fi -else - rm -vrf /data/tls/dummycert.pem \ - /data/tls/dummykey.pem -fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /app/templates/default.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /app/templates/default.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /app/templates/default.conf; fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/include/default.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/include/default.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /usr/local/nginx/conf/conf.d/include/default.conf; fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf; fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/npm.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/npm.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /usr/local/nginx/conf/conf.d/npm.conf; fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf; fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf; fi - -sed -i "s|#\?ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf -sed -i "s|#\?ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|#\?ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf; fi - sed -i "s|48693|$NIBEP|g" /app/index.js sed -i "s|48693|$NIBEP|g" /usr/local/nginx/conf/conf.d/npm.conf @@ -878,14 +757,185 @@ else rm -vf /usr/local/nginx/conf/conf.d/crowdsec.conf fi + +if [ "$DEFAULT_CERT_ID" = "0" ]; then + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "no DEFAULT_CERT_ID set, using dummycerts." +else + if [ -d "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID" ]; then + if [ ! -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/fullchain.pem ]; then + echo "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID/fullchain.pem does not exist" + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "using dummycerts." + else + export DEFAULT_CERT=/data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/fullchain.pem + echo "DEFAULT_CERT set to /data/tls/certbot/live/npm-$DEFAULT_CERT_ID/fullchain.pem" + + if [ ! -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/privkey.pem ]; then + echo "/data/tls/certbot/live/npm-$DEFAULT_CERT_ID/privkey.pem does not exist" + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "using dummycerts." + else + export DEFAULT_KEY=/data/tls/certbot/live/npm-"$DEFAULT_CERT_ID"/privkey.pem + echo "DEFAULT_KEY set to /data/tls/certbot/live/npm-$DEFAULT_CERT_ID/privkey.pem" + + if [ -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID".der ]; then + export DEFAULT_STAPLING_FILE=/data/tls/certbot/live/npm-"$DEFAULT_CERT_ID".der + echo "DEFAULT_STAPLING_FILE set to /data/tls/certbot/live/npm-$DEFAULT_CERT_ID.der" + fi + fi + fi + + elif [ -d "/data/tls/custom/npm-$DEFAULT_CERT_ID" ]; then + if [ ! -s /data/tls/custom/npm-"$DEFAULT_CERT_ID"/fullchain.pem ]; then + echo "/data/tls/custom/npm-$DEFAULT_CERT_ID/fullchain.pem does not exist" + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "using dummycerts." + else + export DEFAULT_CERT=/data/tls/custom/npm-"$DEFAULT_CERT_ID"/fullchain.pem + echo "DEFAULT_CERT set to /data/tls/custom/npm-$DEFAULT_CERT_ID/fullchain.pem" + + if [ ! -s /data/tls/custom/npm-"$DEFAULT_CERT_ID"/privkey.pem ]; then + echo "/data/tls/custom/npm-$DEFAULT_CERT_ID/privkey.pem does not exist" + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "using dummycerts." + else + export DEFAULT_KEY=/data/tls/custom/npm-"$DEFAULT_CERT_ID"/privkey.pem + echo "DEFAULT_KEY set to /data/tls/custom/npm-$DEFAULT_CERT_ID/privkey.pem" + fi + fi + + else + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "cert with ID $DEFAULT_CERT_ID does not exist, using dummycerts." + fi +fi + +if [ "$DEFAULT_CERT" = "/data/tls/dummycert.pem" ] && [ "$DEFAULT_KEY" != "/data/tls/dummykey.pem" ]; then + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "something went wrong, using dummycerts." +fi +if [ "$DEFAULT_CERT" != "/data/tls/dummycert.pem" ] && [ "$DEFAULT_KEY" = "/data/tls/dummykey.pem" ]; then + export DEFAULT_CERT=/data/tls/dummycert.pem + export DEFAULT_KEY=/data/tls/dummykey.pem + echo "something went wrong, using dummycerts." +fi + +if [ "$DEFAULT_CERT" = "/data/tls/dummycert.pem" ] || [ "$DEFAULT_KEY" = "/data/tls/dummykey.pem" ]; then + if [ ! -s /data/tls/dummycert.pem ] || [ ! -s /data/tls/dummykey.pem ]; then + rm -vrf /data/tls/dummycert.pem /data/tls/dummykey.pem + openssl req -new -newkey rsa:4096 -days 365000 -nodes -x509 -subj '/CN=*' -sha256 -keyout /data/tls/dummykey.pem -out /data/tls/dummycert.pem + fi +else + rm -vrf /data/tls/dummycert.pem /data/tls/dummykey.pem +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /app/templates/default.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /app/templates/default.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /app/templates/default.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /app/templates/default.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /app/templates/default.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /app/templates/default.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /app/templates/default.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /app/templates/default.conf +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/include/default.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/include/default.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /usr/local/nginx/conf/conf.d/include/default.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /usr/local/nginx/conf/conf.d/include/default.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /usr/local/nginx/conf/conf.d/include/default.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /usr/local/nginx/conf/conf.d/include/default.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /usr/local/nginx/conf/conf.d/include/default.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /usr/local/nginx/conf/conf.d/include/default.conf +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /usr/local/nginx/conf/conf.d/no-server-name.conf +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/npm.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/npm.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /usr/local/nginx/conf/conf.d/npm.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /usr/local/nginx/conf/conf.d/npm.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /usr/local/nginx/conf/conf.d/npm.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /usr/local/nginx/conf/conf.d/npm.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /usr/local/nginx/conf/conf.d/npm.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /usr/local/nginx/conf/conf.d/npm.conf +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf +fi + +sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf +sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf +fi + sed -i "s|ssl_certificate .*|ssl_certificate $DEFAULT_CERT;|g" /data/nginx/default.conf sed -i "s|ssl_certificate_key .*|ssl_certificate_key $DEFAULT_KEY;|g" /data/nginx/default.conf -if [ -n "$DEFAULT_CHAIN" ]; then sed -i "s|ssl_trusted_certificate .*|ssl_trusted_certificate $DEFAULT_CHAIN;|g" /data/nginx/default.conf; fi +if [ -n "$DEFAULT_STAPLING_FILE" ]; then + sed -i "s|ssl_stapling off;|ssl_stapling on;|g" /data/nginx/default.conf + sed -i "s|ssl_stapling_verify off;|ssl_stapling_verify on;|g" /data/nginx/default.conf + sed -i "s|#\?ssl_stapling_file .*|ssl_stapling_file $DEFAULT_STAPLING_FILE;|g" /data/nginx/default.conf +else + sed -i "s|ssl_stapling on;|ssl_stapling off;|g" /data/nginx/default.conf + sed -i "s|ssl_stapling_verify on;|ssl_stapling_verify off;|g" /data/nginx/default.conf + sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /data/nginx/default.conf +fi if [ "$GOA" = "true" ]; then apk add --no-cache goaccess - mkdir -vp /data/etc/goaccess/data \ - /data/etc/goaccess/geoip + mkdir -vp /data/etc/goaccess/data /data/etc/goaccess/geoip cp -van /usr/local/nginx/conf/conf.d/include/goaccess.conf /usr/local/nginx/conf/conf.d/goaccess.conf cp -van /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf /usr/local/nginx/conf/conf.d/goaccess-no-server-name.conf elif [ "$FULLCLEAN" = "true" ]; then diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/always.conf b/rootfs/usr/local/nginx/conf/conf.d/include/always.conf index 2c971bb95..f8cd08a9a 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/always.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/always.conf @@ -22,16 +22,3 @@ location /fancyindex/ { location ~ /\.ht { deny all; } - -location ~ /\.git { - deny all; -} - - -if ($blocked_user_agent) { - return 403; -} - -if ($blocked_query_string) { - return 403; -} diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/default.conf b/rootfs/usr/local/nginx/conf/conf.d/include/default.conf index 02e31a80c..687ff32a2 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/default.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/default.conf @@ -19,9 +19,11 @@ server { include conf.d/include/tls-ciphers.conf; include conf.d/include/always.conf; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; location / { include conf.d/include/always.conf; diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/force-tls.conf b/rootfs/usr/local/nginx/conf/conf.d/include/force-tls.conf index 5fd4810f8..1f766afaf 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/force-tls.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/force-tls.conf @@ -1,3 +1,10 @@ +# Check if the original scheme is HTTP if ($scheme = "http") { return 301 https://$host$request_uri; } + +# Check if the request was forwarded with HTTP protocol +# This is necessary when behind a proxy like Cloudflare +if ($http_x_forwarded_proto = "http") { + return 301 https://$host$request_uri; +} diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf b/rootfs/usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf index ddeb65696..95cb90f22 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf @@ -11,7 +11,9 @@ server { include conf.d/include/tls-ciphers.conf; include conf.d/include/always.conf; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; } diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/goaccess.conf b/rootfs/usr/local/nginx/conf/conf.d/include/goaccess.conf index 9a834c215..fb4fc623c 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/goaccess.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/goaccess.conf @@ -12,9 +12,11 @@ server { modsecurity on; modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity.conf; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; location / { include conf.d/include/always.conf; diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/tls-ciphers.conf b/rootfs/usr/local/nginx/conf/conf.d/include/tls-ciphers.conf index 698e2cce7..c67393450 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/tls-ciphers.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/tls-ciphers.conf @@ -4,11 +4,13 @@ ssl_stapling on; ssl_stapling_verify on; ssl_session_timeout 1d; -ssl_session_cache shared:MozSSL:10m; # about 40000 sessions -ssl_session_tickets off; -ssl_dhparam /etc/tls/dhparam; +ssl_session_cache shared:SSL:10m; -# intermediate configuration. tweak to your needs. +ssl_dhparam /etc/tls/dhparam; ssl_protocols TLSv1.2 TLSv1.3; -ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305; + +ssl_ecdh_curve p384_mlkem768:x25519_mlkem768:p384_kyber768:x25519_kyber768:secp384r1:x25519:prime256v1; + ssl_prefer_server_ciphers on; +ssl_conf_command Options PrioritizeChaCha; +ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305; diff --git a/rootfs/usr/local/nginx/conf/conf.d/no-server-name.conf b/rootfs/usr/local/nginx/conf/conf.d/no-server-name.conf index 588ab93fd..dad0dce0f 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/no-server-name.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/no-server-name.conf @@ -18,7 +18,9 @@ server { add_header Alt-Svc 'h3=":443"; ma=86400'; http3 on; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; } diff --git a/rootfs/usr/local/nginx/conf/conf.d/npm-no-server-name.conf b/rootfs/usr/local/nginx/conf/conf.d/npm-no-server-name.conf index 457a238f2..095a9cee6 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/npm-no-server-name.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/npm-no-server-name.conf @@ -11,7 +11,9 @@ server { include conf.d/include/tls-ciphers.conf; include conf.d/include/always.conf; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; } diff --git a/rootfs/usr/local/nginx/conf/conf.d/npm.conf b/rootfs/usr/local/nginx/conf/conf.d/npm.conf index 2fb87fc43..f6ce24f3e 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/npm.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/npm.conf @@ -12,9 +12,11 @@ server { modsecurity on; modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity.conf; - #ssl_certificate ; - #ssl_certificate_key ; - #ssl_trusted_certificate ; + ssl_certificate ; + ssl_certificate_key ; + #ssl_stapling_file ; + ssl_stapling off; + ssl_stapling_verify off; location /api { proxy_set_header Upgrade $http_upgrade; diff --git a/rootfs/usr/local/nginx/conf/exploits.conf b/rootfs/usr/local/nginx/conf/exploits.conf deleted file mode 100644 index bddb4e1b8..000000000 --- a/rootfs/usr/local/nginx/conf/exploits.conf +++ /dev/null @@ -1,22 +0,0 @@ -map $query_string $blocked_query_string { - default 0; - "~*union.*select.*\(" 1; - "~*union.*all.*select.*" 1; - "~*concat.*\(" 1; - "~*[a-zA-Z0-9_]=(\.\.//?)+" 1; - "~*[a-zA-Z0-9_]=/([a-z0-9_.]//?)+" 1; - "~*(<|%3C).*script.*(>|%3E)" 1; - "~*GLOBALS(=|\[|\%[0-9A-Z]{0,2})" 1; - "~*_REQUEST(=|\[|\%[0-9A-Z]{0,2})" 1; - "~*proc/self/environ" 1; - "~*mosConfig_[a-zA-Z_]{1,21}(=|\%3D)" 1; - "~*base64_(en|de)code\(.*\)" 1; -} - -map $http_user_agent $blocked_user_agent { - default 0; - "~*Google-Extended" 1; - "~*GPTBot" 1; - "~*ChatGPT-User" 1; - "~*CCBot" 1; -} \ No newline at end of file diff --git a/rootfs/usr/local/nginx/conf/nginx.conf b/rootfs/usr/local/nginx/conf/nginx.conf index 0b7b3aa85..28ae14d5b 100644 --- a/rootfs/usr/local/nginx/conf/nginx.conf +++ b/rootfs/usr/local/nginx/conf/nginx.conf @@ -28,6 +28,8 @@ http { more_clear_headers "X-Page-Speed"; more_clear_headers "X-Varnish"; + server_names_hash_bucket_size 64; + aio threads; sendfile on; tcp_nopush on; @@ -86,8 +88,6 @@ http { websocket "socket"; } - include exploits.conf; - upstream php82 { server unix:/run/php82.sock; } @@ -107,7 +107,7 @@ http { fancyindex_default_sort name; fancyindex_hide_parent_dir off; fancyindex_directories_first on; - fancyindex_time_format "%d-%m-%Y %T"; + fancyindex_time_format "%Y-%m-%d %T"; fancyindex_ignore "fancyindex"; fancyindex_header "/fancyindex/header.html"; fancyindex_footer "/fancyindex/footer.html"; @@ -123,7 +123,7 @@ http { include fastcgi.conf; - include /data/nginx/ip_ranges.conf; + include /tmp/ip_ranges.conf; include /data/nginx/default.conf; include conf.d/*.conf;