diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 8afab8f4..ef993f75 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,9 +30,9 @@ jobs: run: | sudo npm install --global cross-env sudo pip install certbot - sudo mkdir -p /usr/local/nginx/conf/conf.d/include /tmp/letsencrypt-acme-challenge + sudo mkdir -p /usr/local/nginx/conf/conf.d/include /data/ssl/certbot /tmp/acme-challenge sudo touch /usr/local/nginx/conf/conf.d/include/ip_ranges.conf - sudo cp rootfs/usr/local/nginx/conf/letsencrypt.ini /usr/local/nginx/conf/letsencrypt.ini + sudo cp rootfs/etc/ssl/certbot.ini /data/ssl/certbot/config.ini mv global backend cd backend npm install --force diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 3e0a9f50..09c9dd86 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -30,6 +30,8 @@ jobs: sed -i "s/0.0.0/$(cat ../global/.version)/g" package.json yarn --no-lockfile install yarn --no-lockfile build + mkdir dist/.well-known + cp ../security.txt dist/.well-known - name: Cache frontend uses: actions/cache/save@v3 diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml index 5aa332d1..7b73c95a 100644 --- a/.github/workflows/pull-request.yaml +++ b/.github/workflows/pull-request.yaml @@ -25,9 +25,9 @@ jobs: run: | sudo npm install --global cross-env sudo pip install certbot - sudo mkdir -p /usr/local/nginx/conf/conf.d/include /tmp/letsencrypt-acme-challenge + sudo mkdir -p /usr/local/nginx/conf/conf.d/include /data/ssl/certbot /tmp/acme-challenge sudo touch /usr/local/nginx/conf/conf.d/include/ip_ranges.conf - sudo cp rootfs/usr/local/nginx/conf/letsencrypt.ini /usr/local/nginx/conf/letsencrypt.ini + sudo cp rootfs/etc/ssl/certbot.ini /data/ssl/certbot/config.ini mv global backend cd backend npm install --force @@ -57,6 +57,8 @@ jobs: sed -i "s/0.0.0/$(cat ../global/.version)/g" package.json yarn --no-lockfile install yarn --no-lockfile build + mkdir dist/.well-known + cp ../security.txt dist/.well-known - name: Set up QEMU uses: docker/setup-qemu-action@v2 diff --git a/Dockerfile b/Dockerfile index bffe7b27..9bbfde39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM zoeyvid/nginx-quic:29 +FROM zoeyvid/nginx-quic:30 COPY rootfs / COPY backend /app COPY global /app/global @@ -21,8 +21,8 @@ RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/testing | tee -a /etc/apk/re wget https://bootstrap.pypa.io/get-pip.py -O - | python3 && \ # Change permission - chmod +x /usr/local/bin/start && \ - chmod +x /usr/local/bin/check-health && \ + chmod +x /bin/start.sh && \ + chmod +x /bin/check-health.sh && \ # Build Backend sed -i "s/0.0.0/$(cat global/.version)/g" package.json && \ @@ -33,5 +33,5 @@ RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/testing | tee -a /etc/apk/re ENV NODE_ENV=production \ DB_SQLITE_FILE=/data/database.sqlite -ENTRYPOINT ["bash", "start"] -HEALTHCHECK CMD check-health +ENTRYPOINT ["start.sh"] +HEALTHCHECK CMD check-health.sh diff --git a/README.md b/README.md index e7ea06b6..a3428744 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ so that the barrier for entry here is low. - Fix Proxy Hosts, if origin only accepts TLSv1.3 - Only use TLSv1.2 and TLSv1.3 - Uses OCSP Stapling - - Needs manual migration if you use custom certificates, just upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/custom_ssl/npm-[certificate-id]` folder + - Needs manual migration if you use custom certificates, just upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/ssl/custom/npm-[certificate-id]` folder - Smaller then the original - Runs the admin interface on port 81 with ssl (https) - Default page runs also with ssl (https) @@ -53,7 +53,9 @@ so that the barrier for entry here is low. - Easy security headers, see [here](https://github.com/GetPageSpeed/ngx_security_headers), enabled by default if you enable hsts - Access Log disabled - Error Log written to console -- PHP included, you can add php extensions, see aviable packages here: https://pkgs.alpinelinux.org/packages?name=php* +- PHP included, you can add php extensions, see aviable packages here: https://pkgs.alpinelinux.org/packages?branch=edge&name=php*&arch=x86_64 +- allows different acme servers +- up to 64 domains per cert allowed ## Soon - more @@ -66,13 +68,17 @@ so that the barrier for entry here is low. 3. Maybe set an Access List 4. Make your SSL Settings 5. -a) Custom Nginx Configuration (advanced tab), which looks the following for plain html, the slash at the end of the file path is important: +a) Custom Nginx Configuration (advanced tab), which looks the following for file server: +- Note: the slash at the end of the file path is important ``` location / { alias /var/www//; } ``` -b) Custom Nginx Configuration (advanced tab), which looks the following for plain html & php, the slash at the end of the file path is important: +b) Custom Nginx Configuration (advanced tab), which looks the following for file server and **php**: +- Note: the slash at the end of the file path is important +- Note: you can replace `fastcgi_pass php82;` with `fastcgi_pass` `php7`/`php8`/`php81`/`php82` `;` +- Note: to add more php extension use the packes from [here](https://pkgs.alpinelinux.org/packages?branch=edge&name=php\*&arch=x86_64) and add them using the `PHP_APKS` env (see compose file) ``` location / { alias /var/www//; @@ -84,6 +90,12 @@ if (!-f $document_root$fastcgi_script_name) {return 404;} }} ``` +# 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 + # Quick Setup 1. Install Docker and Docker Compose (or portainer) @@ -109,7 +121,7 @@ services: - "TZ=Europe/Berlin" # - "NGINX_LOG_NOT_FOUND=true" # Allow logging of 404 errors # - "NPM_LISTEN_LOCALHOST=true" # Bind the NPM Dashboard on Port 81 only to localhost -# - "PHP_APKS=php7-curl php8-curl php81-curl php-82-curl" # Add php extensions, see aviable packages here: https://pkgs.alpinelinux.org/packages?name=php* +# - "PHP_APKS=php7-curl php8-curl php81-curl php-82-curl" # Add php extensions, see aviable packages here: https://pkgs.alpinelinux.org/packages?branch=edge&name=php\*&arch=x86_64 ``` 3. Bring up your stack by running (or deploy your portainer stack) diff --git a/backend/config/.gitignore b/backend/config/.gitignore deleted file mode 100644 index d6b7ef32..00000000 --- a/backend/config/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/backend/config/.gitkeep b/backend/config/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/backend/config/.gitkeep @@ -0,0 +1 @@ + diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index 083bfa62..13fc9e33 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -467,7 +467,7 @@ const internalAccessList = { * @returns {String} */ getFilename: (list) => { - return '/data/access/' + list.id; + return '/data/nginx/access/' + list.id; }, /** diff --git a/backend/internal/certificate.js b/backend/internal/certificate.js index dde4a77a..0c736063 100644 --- a/backend/internal/certificate.js +++ b/backend/internal/certificate.js @@ -11,12 +11,11 @@ const dnsPlugins = require('../global/certbot-dns-plugins'); const internalAuditLog = require('./audit-log'); const internalNginx = require('./nginx'); const internalHost = require('./host'); -const letsencryptStaging = process.env.NODE_ENV !== 'production'; -const letsencryptConfig = '/usr/local/nginx/conf/letsencrypt.ini'; -const certbotCommand = 'certbot --config-dir /data/letsencrypt'; const archiver = require('archiver'); const path = require('path'); const { isArray } = require('lodash'); +const certbotConfig = '/data/ssl/certbot/config.ini'; +const certbotCommand = 'certbot --config-dir /data/ssl/certbot'; function omissions() { return ['is_deleted']; @@ -45,10 +44,9 @@ const internalCertificate = { logger.info('Renewing SSL certs close to expiry...'); const cmd = certbotCommand + ' renew --non-interactive --quiet ' + - '--config "' + letsencryptConfig + '" ' + + '--config "' + certbotConfig + '" ' + '--preferred-challenges "dns,http" ' + - '--disable-hook-validation ' + - (letsencryptStaging ? '--staging' : ''); + '--disable-hook-validation'; return utils.exec(cmd) .then((result) => { @@ -63,7 +61,7 @@ const internalCertificate = { }); }) .then(() => { - // Now go and fetch all the letsencrypt certs from the db and query the files and update expiry times + // Now go and fetch all the certbot certs from the db and query the files and update expiry times return certificateModel .query() .where('is_deleted', 0) @@ -74,7 +72,7 @@ const internalCertificate = { certificates.map(function (certificate) { promises.push( - internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem') + internalCertificate.getCertificateInfoFromFile('/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem') .then((cert_info) => { return certificateModel .query() @@ -202,9 +200,9 @@ const internalCertificate = { } }) .then(() => { - // At this point, the letsencrypt cert should exist on disk. + // At this point, the certbot cert should exist on disk. // Lets get the expiry date from the file and update the row silently - return internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem') + return internalCertificate.getCertificateInfoFromFile('/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem') .then((cert_info) => { return certificateModel .query() @@ -354,7 +352,7 @@ const internalCertificate = { }) .then((certificate) => { if (certificate.provider === 'letsencrypt') { - const zipDirectory = '/data/letsencrypt/live/npm-' + data.id; + const zipDirectory = '/data/ssl/certbot/live/npm-' + data.id; if (!fs.existsSync(zipDirectory)) { throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists'); @@ -523,7 +521,7 @@ const internalCertificate = { return new Promise((resolve, reject) => { if (certificate.provider === 'letsencrypt') { - reject(new Error('Refusing to write letsencrypt certs here')); + reject(new Error('Refusing to write certbot certs here')); return; } @@ -844,14 +842,12 @@ const internalCertificate = { logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const cmd = certbotCommand + ' certonly ' + - '--config "' + letsencryptConfig + '" ' + + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + - '--agree-tos ' + '--authenticator webroot ' + '--email "' + certificate.meta.letsencrypt_email + '" ' + '--preferred-challenges "dns,http" ' + - '--domains "' + certificate.domain_names.join(',') + '" ' + - (letsencryptStaging ? '--staging' : ''); + '--domains "' + certificate.domain_names.join(',') + '"'; logger.info('Command:', cmd); @@ -878,24 +874,18 @@ const internalCertificate = { logger.info(`Requesting Let's Encrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`); - const credentialsLocation = '/data/letsencrypt/credentials/credentials-' + certificate.id; + const credentialsLocation = '/data/ssl/certbot/credentials/credentials-' + certificate.id; // Escape single quotes and backslashes const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\'); - const credentialsCmd = 'mkdir -p /data/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\''; + const credentialsCmd = 'mkdir -p /data/ssl/certbot/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\''; let prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies; - // Special case for cloudflare - if (dns_plugin.package_name === 'certbot-dns-cloudflare') { - prepareCmd = 'pip install certbot-dns-cloudflare --index-url https://www.piwheels.org/simple --prefer-binary'; - } - // Whether the plugin has a ---credentials argument const hasConfigArg = certificate.meta.dns_provider !== 'route53'; let mainCmd = certbotCommand + ' certonly ' + - '--config "' + letsencryptConfig + '" ' + + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + - '--agree-tos ' + '--email "' + certificate.meta.letsencrypt_email + '" ' + '--domains "' + certificate.domain_names.join(',') + '" ' + '--authenticator ' + dns_plugin.full_plugin_name + ' ' + @@ -908,8 +898,7 @@ const internalCertificate = { certificate.meta.propagation_seconds !== undefined ? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds : '' - ) + - (letsencryptStaging ? ' --staging' : ''); + ); // Prepend the path to the credentials file as an environment variable if (certificate.meta.dns_provider === 'route53') { @@ -954,7 +943,7 @@ const internalCertificate = { return renewMethod(certificate) .then(() => { - return internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem'); + return internalCertificate.getCertificateInfoFromFile('/data/ssl/certbot/live/npm-' + certificate.id + '/fullchain.pem'); }) .then((cert_info) => { return certificateModel @@ -989,12 +978,11 @@ const internalCertificate = { logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const cmd = certbotCommand + ' renew --force-renewal ' + - '--config "' + letsencryptConfig + '" ' + + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew ' + - '--disable-hook-validation ' + - (letsencryptStaging ? '--staging' : ''); + '--disable-hook-validation '; logger.info('Command:', cmd); @@ -1019,15 +1007,14 @@ const internalCertificate = { logger.info(`Renewing Let's Encrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`); let mainCmd = certbotCommand + ' renew ' + - '--config "' + letsencryptConfig + '" ' + + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--disable-hook-validation ' + - '--no-random-sleep-on-renew ' + - (letsencryptStaging ? ' --staging' : ''); + '--no-random-sleep-on-renew'; // Prepend the path to the credentials file as an environment variable if (certificate.meta.dns_provider === 'route53') { - const credentialsLocation = '/data/letsencrypt/credentials/credentials-' + certificate.id; + const credentialsLocation = '/data/ssl/certbot/credentials/credentials-' + certificate.id; mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd; } @@ -1049,13 +1036,12 @@ const internalCertificate = { logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', ')); const mainCmd = certbotCommand + ' revoke ' + - '--config "' + letsencryptConfig + '" ' + - '--cert-path "/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' + - '--delete-after-revoke ' + - (letsencryptStaging ? '--staging' : ''); + '--config "' + certbotConfig + '" ' + + '--cert-path "/data/ssl/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/letsencrypt/credentials/credentials-${certificate.id}' || true`; + const delete_credentialsCmd = `rm -f '/data/ssl/certbot/credentials/credentials-${certificate.id}' || true`; logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd); @@ -1079,7 +1065,7 @@ const internalCertificate = { * @returns {Boolean} */ hasLetsEncryptSslCerts: (certificate) => { - const letsencryptPath = '/data/letsencrypt/live/npm-' + certificate.id; + const letsencryptPath = '/data/ssl/certbot/live/npm-' + certificate.id; return fs.existsSync(letsencryptPath + '/fullchain.pem') && fs.existsSync(letsencryptPath + '/privkey.pem'); }, @@ -1155,7 +1141,7 @@ const internalCertificate = { } // Create a test challenge file - const testChallengeDir = '/tmp/letsencrypt-acme-challenge/.well-known/acme-challenge'; + const testChallengeDir = '/tmp/acme-challenge/.well-known/acme-challenge'; const testChallengeFile = testChallengeDir + '/test-challenge'; fs.mkdirSync(testChallengeDir, {recursive: true}); fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'}); diff --git a/backend/internal/nginx.js b/backend/internal/nginx.js index 88d1e87c..b62eb526 100644 --- a/backend/internal/nginx.js +++ b/backend/internal/nginx.js @@ -270,7 +270,7 @@ const internalNginx = { /** * This generates a temporary nginx config listening on port 80 for the domain names listed - * in the certificate setup. It allows the letsencrypt acme challenge to be requested by letsencrypt + * in the certificate setup. It allows the certbot acme challenge to be requested by certbot * when requesting a certificate without having a hostname set up already. * * @param {Object} certificate @@ -278,7 +278,7 @@ const internalNginx = { */ generateLetsEncryptRequestConfig: (certificate) => { if (debug_mode) { - logger.info('Generating LetsEncrypt Request Config:', certificate); + logger.info('Generating certbot Request Config:', certificate); } let renderEngine = new Liquid({ @@ -287,10 +287,10 @@ const internalNginx = { return new Promise((resolve, reject) => { let template = null; - let filename = '/usr/local/nginx/conf/conf.d/letsencrypt_' + certificate.id + '.conf'; + let filename = '/usr/local/nginx/conf/conf.d/certbot_' + certificate.id + '.conf'; try { - template = fs.readFileSync(__dirname + '/../templates/letsencrypt-request.conf', {encoding: 'utf8'}); + template = fs.readFileSync(__dirname + '/../templates/certbot-request.conf', {encoding: 'utf8'}); } catch (err) { reject(new error.ConfigurationError(err.message)); return; diff --git a/backend/schema/definitions.json b/backend/schema/definitions.json index 4b4f3405..8e5f62bd 100644 --- a/backend/schema/definitions.json +++ b/backend/schema/definitions.json @@ -172,7 +172,7 @@ "description": "Domain Names separated by a comma", "example": "*.jc21.com,blog.jc21.com", "type": "array", - "maxItems": 15, + "maxItems": 64, "uniqueItems": true, "items": { "type": "string", diff --git a/backend/setup.js b/backend/setup.js index d117ca46..09874703 100644 --- a/backend/setup.js +++ b/backend/setup.js @@ -169,26 +169,21 @@ const setupCertbotPlugins = () => { .andWhere('provider', 'letsencrypt') .then((certificates) => { if (certificates && certificates.length) { - let plugins = []; - let promises = []; - let install_cloudflare_plugin = false; + let plugins = []; + let promises = []; certificates.map(function (certificate) { if (certificate.meta && certificate.meta.dns_challenge === true) { - const dns_plugin = dns_plugins[certificate.meta.dns_provider]; + const dns_plugin = dns_plugins[certificate.meta.dns_provider]; + const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`; - if (dns_plugin.package_name === 'certbot-dns-cloudflare') { - install_cloudflare_plugin = true; - } else { - const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`; - if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install); - } + if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install); // Make sure credentials file exists - const credentials_loc = '/data/letsencrypt/credentials/credentials-' + certificate.id; + const credentials_loc = '/data/ssl/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/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }'; + const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /data/ssl/certbot/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }'; promises.push(utils.exec(credentials_cmd)); } }); @@ -198,10 +193,6 @@ const setupCertbotPlugins = () => { promises.push(utils.exec(install_cmd)); } - if (install_cloudflare_plugin) { - promises.push(utils.exec('pip install certbot-dns-cloudflare --index-url https://www.piwheels.org/simple --prefer-binary')); - } - if (promises.length) { return Promise.all(promises) .then(() => { diff --git a/backend/templates/_certificates.conf b/backend/templates/_certificates.conf index d42707fb..01c21bda 100644 --- a/backend/templates/_certificates.conf +++ b/backend/templates/_certificates.conf @@ -2,17 +2,17 @@ {% if certificate.provider == "letsencrypt" %} # Let's Encrypt SSL include conf.d/include/ssl-ciphers.conf; - ssl_certificate /data/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem; - ssl_certificate_key /data/letsencrypt/live/npm-{{ certificate_id }}/privkey.pem; - ssl_trusted_certificate /data/letsencrypt/live/npm-{{ certificate_id }}/chain.pem; + ssl_certificate /data/ssl/certbot/live/npm-{{ certificate_id }}/fullchain.pem; + ssl_certificate_key /data/ssl/certbot/live/npm-{{ certificate_id }}/privkey.pem; + ssl_trusted_certificate /data/ssl/certbot/live/npm-{{ certificate_id }}/chain.pem; ssl_stapling on; ssl_stapling_verify on; {% else %} # Custom SSL include conf.d/include/ssl-ciphers.conf; - ssl_certificate /data/custom_ssl/npm-{{ certificate_id }}/fullchain.pem; - ssl_certificate_key /data/custom_ssl/npm-{{ certificate_id }}/privkey.pem; - ssl_trusted_certificate /data/custom_ssl/npm-{{ certificate_id }}/chain.pem; + ssl_certificate /data/ssl/custom/npm-{{ certificate_id }}/fullchain.pem; + ssl_certificate_key /data/ssl/custom/npm-{{ certificate_id }}/privkey.pem; + ssl_trusted_certificate /data/ssl/custom/npm-{{ certificate_id }}/chain.pem; ssl_stapling on; ssl_stapling_verify on; {% endif %} diff --git a/backend/templates/letsencrypt-request.conf b/backend/templates/certbot-request.conf similarity index 64% rename from backend/templates/letsencrypt-request.conf rename to backend/templates/certbot-request.conf index 4e0f34a4..10c4cd0b 100644 --- a/backend/templates/letsencrypt-request.conf +++ b/backend/templates/certbot-request.conf @@ -6,11 +6,11 @@ server { server_name {{ domain_names | join: " " }}; - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; include conf.d/include/block-exploits.conf; location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; return 404; } } diff --git a/backend/templates/dead_host.conf b/backend/templates/dead_host.conf index 16baa985..df8d6e6f 100644 --- a/backend/templates/dead_host.conf +++ b/backend/templates/dead_host.conf @@ -8,13 +8,17 @@ server { {% include "_forced_ssl.conf" %} {{ advanced_config }} - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; include conf.d/include/block-exploits.conf; {% if use_default_location %} location / { alias /html/404/; + include conf.d/include/acme-challenge.conf; } {% endif %} + # Custom + include /data/nginx/custom/server_dead.conf; + } {% endif %} diff --git a/backend/templates/default.conf b/backend/templates/default.conf index 65e0ceaf..fe17275b 100644 --- a/backend/templates/default.conf +++ b/backend/templates/default.conf @@ -15,7 +15,7 @@ server { include conf.d/include/force-ssl.conf; include conf.d/include/ssl-ciphers.conf; - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; include conf.d/include/block-exploits.conf; add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400'; @@ -30,21 +30,21 @@ server { {%- if value == "redirect" %} location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; return 307 {{ meta.redirect }}; } {%- endif %} {%- if value == "congratulations" %} location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; alias /html/default/; } {%- endif %} {%- if value == "html" %} location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; alias /data/nginx/html/; } {%- endif %} diff --git a/backend/templates/proxy_host.conf b/backend/templates/proxy_host.conf index 720a6b37..ed14841d 100644 --- a/backend/templates/proxy_host.conf +++ b/backend/templates/proxy_host.conf @@ -11,14 +11,14 @@ server { {% include "_hsts.conf" %} {% include "_forced_ssl.conf" %} - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; include conf.d/include/block-exploits.conf; {{ advanced_config }} {% if use_default_location %} location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; {% if access_list_id > 0 %} {% if access_list.items.length > 0 %} @@ -40,7 +40,7 @@ server { {% if access_list.items.length > 0 %} # Authorization auth_basic "Authorization required"; - auth_basic_user_file /data/access/{{ access_list_id }}; + auth_basic_user_file /data/nginx/access/{{ access_list_id }}; {{ access_list.passauth }} {% endif %} diff --git a/backend/templates/redirection_host.conf b/backend/templates/redirection_host.conf index 53a5101d..d8c20d81 100644 --- a/backend/templates/redirection_host.conf +++ b/backend/templates/redirection_host.conf @@ -8,11 +8,11 @@ server { {% include "_forced_ssl.conf" %} {{ advanced_config }} - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; include conf.d/include/block-exploits.conf; {% if use_default_location %} location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; {% if preserve_path == 1 or preserve_path == true %} return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}$request_uri; {% else %} diff --git a/compose.yaml b/compose.yaml index da3e6da0..d8aeb415 100644 --- a/compose.yaml +++ b/compose.yaml @@ -13,4 +13,4 @@ services: - "TZ=Europe/Berlin" # - "NGINX_LOG_NOT_FOUND=true" # Allow logging of 404 errors # - "NPM_LISTEN_LOCALHOST=true" # Bind the NPM Dashboard on Port 81 only to localhost -# - "PHP_APKS=php7-curl php8-curl php81-curl php-82-curl" # Add php extensions, see aviable packages here: https://pkgs.alpinelinux.org/packages?name=php* +# - "PHP_APKS=php7-curl php8-curl php81-curl php-82-curl" # Add php extensions, see aviable packages here: https://pkgs.alpinelinux.org/packages?branch=edge&name=php\*&arch=x86_64 diff --git a/frontend/js/app/nginx/certificates/form.js b/frontend/js/app/nginx/certificates/form.js index 097e6549..1139e0c3 100644 --- a/frontend/js/app/nginx/certificates/form.js +++ b/frontend/js/app/nginx/certificates/form.js @@ -268,7 +268,7 @@ module.exports = Mn.View.extend({ this.ui.domain_names.selectize({ delimiter: ',', persist: false, - maxOptions: 15, + maxOptions: 64, create: function (input) { return { value: input, diff --git a/frontend/js/app/nginx/dead/form.js b/frontend/js/app/nginx/dead/form.js index 8f6774f6..336a3f4e 100644 --- a/frontend/js/app/nginx/dead/form.js +++ b/frontend/js/app/nginx/dead/form.js @@ -233,7 +233,7 @@ module.exports = Mn.View.extend({ this.ui.domain_names.selectize({ delimiter: ',', persist: false, - maxOptions: 15, + maxOptions: 64, create: function (input) { return { value: input, diff --git a/frontend/js/app/nginx/proxy/form.js b/frontend/js/app/nginx/proxy/form.js index 1dfb5c18..506debe0 100644 --- a/frontend/js/app/nginx/proxy/form.js +++ b/frontend/js/app/nginx/proxy/form.js @@ -271,7 +271,7 @@ module.exports = Mn.View.extend({ this.ui.domain_names.selectize({ delimiter: ',', persist: false, - maxOptions: 15, + maxOptions: 64, create: function (input) { return { value: input, diff --git a/frontend/js/app/nginx/redirection/form.js b/frontend/js/app/nginx/redirection/form.js index 1f81feeb..0067e622 100644 --- a/frontend/js/app/nginx/redirection/form.js +++ b/frontend/js/app/nginx/redirection/form.js @@ -235,7 +235,7 @@ module.exports = Mn.View.extend({ this.ui.domain_names.selectize({ delimiter: ',', persist: false, - maxOptions: 15, + maxOptions: 64, create: function (input) { return { value: input, diff --git a/frontend/js/i18n/messages.json b/frontend/js/i18n/messages.json index b76f71d3..1c4908da 100644 --- a/frontend/js/i18n/messages.json +++ b/frontend/js/i18n/messages.json @@ -79,7 +79,7 @@ "ssl-certificate": "SSL Certificate", "none": "None", "new-cert": "Request a new SSL Certificate", - "with-le": "with Let's Encrypt", + "with-le": "with Certbot", "no-ssl": "This host will not use HTTPS", "advanced": "Advanced", "advanced-warning": "Enter your custom Nginx configuration here at your own risk!", @@ -97,14 +97,14 @@ "delete": "Delete" }, "ssl": { - "letsencrypt": "Let's Encrypt", + "letsencrypt": "Certbot", "other": "Custom", "none": "HTTP only", - "letsencrypt-email": "Email Address for Let's Encrypt", - "letsencrypt-agree": "I Agree to the Let's Encrypt Terms of Service", + "letsencrypt-email": "Email Address for Certbot", + "letsencrypt-agree": "I Agree to the Let's Encrypt Terms of Service / ToS of custom set CA", "delete-ssl": "The SSL certificates attached will NOT be removed, they will need to be removed manually.", "hosts-warning": "These domains must be already configured to point to this installation", - "no-wildcard-without-dns": "Cannot request Let's Encrypt Certificate for wildcard domains when not using DNS challenge", + "no-wildcard-without-dns": "Cannot request Certificate for wildcard domains when not using DNS challenge", "dns-challenge": "Use a DNS Challenge", "certbot-warning": "This section requires some knowledge about Certbot and its DNS plugins. Please consult the respective plugins documentation.", "dns-provider": "DNS Provider", @@ -185,11 +185,11 @@ "title": "SSL Certificates", "empty": "There are no SSL Certificates", "add": "Add SSL Certificate", - "form-title": "Add {provider, select, letsencrypt{Let's Encrypt} other{Custom}} Certificate", + "form-title": "Add {provider, select, letsencrypt{Certbot} other{Custom}} Certificate", "delete": "Delete SSL Certificate", "delete-confirm": "Are you sure you want to delete this SSL Certificate? Any hosts using it will need to be updated later.", "help-title": "SSL Certificates", - "help-content": "SSL certificates (correctly known as TLS Certificates) are a form of encryption key which allows your site to be encrypted for the end user.\nNPM uses a service called Let's Encrypt to issue SSL certificates for free.\nIf you have any sort of personal information, passwords, or sensitive data behind NPM, it's probably a good idea to use a certificate.\nNPM also supports DNS authentication for if you're not running your site facing the internet, or if you just want a wildcard certificate.", + "help-content": "SSL certificates (correctly known as TLS Certificates) are a form of encryption key which allows your site to be encrypted for the end user.\nNPM uses by default a service called Let's Encrypt to issue SSL certificates for free.\nIf you have any sort of personal information, passwords, or sensitive data behind NPM, it's probably a good idea to use a certificate.\nNPM also supports DNS authentication for if you're not running your site facing the internet, or if you just want a wildcard certificate.", "other-certificate": "Certificate", "other-certificate-key": "Certificate Key", "other-intermediate-certificate": "Intermediate Certificate", @@ -205,7 +205,7 @@ "reachability-wrong-data": "There is a server found at this domain but it returned an unexpected data. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.", "reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.", "download": "Download", - "renew-title": "Renew Let's Encrypt Certificate", + "renew-title": "Renew Certificate", "search": "Search Certificate…" }, "access-lists": { diff --git a/global/certbot-dns-plugins.js b/global/certbot-dns-plugins.js index 9e88ee9a..3e1fd704 100644 --- a/global/certbot-dns-plugins.js +++ b/global/certbot-dns-plugins.js @@ -511,7 +511,7 @@ aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`, version_requirement: '~=0.4.3', dependencies: '', credentials: `dns_transip_username = my_username -dns_transip_key_file = /data/letsencrypt/transip-rsa.key`, +dns_transip_key_file = /data/ssl/certbot/transip-rsa.key`, full_plugin_name: 'dns-transip', }, //####################################################// diff --git a/rootfs/bin/check-health.sh b/rootfs/bin/check-health.sh new file mode 100644 index 00000000..17593328 --- /dev/null +++ b/rootfs/bin/check-health.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if (cgi-fcgi -bind -connect /dev/php7.sock &> /dev/null && cgi-fcgi -bind -connect /dev/php8.sock &> /dev/null && cgi-fcgi -bind -connect /dev/php81.sock &> /dev/null && cgi-fcgi -bind -connect /dev/php82.sock &> /dev/null && [ "$(wget -q --no-check-certificate https://127.0.0.1:81/api -O - | jq --raw-output '.status')" == "OK" ]); then + echo "OK" + exit 0 +else + echo "NOT OK" + exit 1 +fi diff --git a/rootfs/usr/local/bin/start b/rootfs/bin/start.sh similarity index 73% rename from rootfs/usr/local/bin/start rename to rootfs/bin/start.sh index dd4181b7..07c25f8e 100644 --- a/rootfs/usr/local/bin/start +++ b/rootfs/bin/start.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # From https://github.com/nextcloud/all-in-one/pull/1377/files if [ -n "$PHP_APKS" ]; then @@ -21,23 +21,23 @@ if [ -n "$PHP_APKS" ]; then fi echo "Installing $apk via apk..." - if ! apk add --no-cache "$apk" >/dev/null; then + if ! apk add --no-cache "$apk" &> /dev/null; then echo "The packet $apk was not installed!" fi done fi -mkdir -p /tmp/letsencrypt-acme-challenge \ - /data/letsencrypt \ - /data/custom_ssl \ - /data/access \ +mkdir -p /tmp/acme-challenge \ + /data/ssl/certbot \ + /data/ssl/custom \ /data/php \ /data/nginx/redirection_host \ /data/nginx/proxy_host \ /data/nginx/dead_host \ /data/nginx/stream \ /data/nginx/custom \ + /data/nginx/access \ /data/nginx/html || exit 1 if [ -f /data/nginx/default_host/site.conf ]; then @@ -48,21 +48,46 @@ if [ -f /data/nginx/default_www/index.html ]; then mv /data/nginx/default_www/index.html /data/nginx/html/index.html || exit 1 fi +if [ -e /data/access ]; then +mv /data/access/* /data/nginx/access || exit 1 +fi + +if [ -e /etc/letsencrypt/live ]; then +mv /etc/letsencrypt/* /data/ssl/certbot || exit 1 +fi + +if [ -e /data/letsencrypt/live ]; then +mv /data/letsencrypt/* /data/ssl/certbot || exit 1 +fi + +if [ -e /data/custom_ssl/npm-* ]; then +mv /data/custom_ssl/* /data/ssl/custom || exit 1 +fi + rm -rf /data/letsencrypt-acme-challenge \ /data/nginx/default_host \ /data/nginx/default_www \ /data/nginx/streams \ /data/nginx/temp \ + /data/index.html \ + /data/letsencrypt \ + /data/custom_ssl \ + /data/certbot \ + /data/access \ /data/logs \ /data/error.log \ /data/nginx/error.log || exit 1 -if [ -e /etc/letsencrypt/live ]; then -mv /etc/letsencrypt/* /data/letsencrypt || exit 1 -fi +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/access|/data/nginx/access|g" {} \; || exit 1 -find /data/nginx -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/letsencrypt|g" {} \; || exit 1 -find /data/letsencrypt -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/letsencrypt|g" {} \; || exit 1 +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/custom_ssl|/data/ssl/custom|g" {} \; || exit 1 +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/ssl/certbot|g" {} \; || exit 1 +find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/letsencrypt|/data/ssl/certbot|g" {} \; || exit 1 + +find /data/ssl/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/ssl/certbot|g" {} \; || exit 1 +find /data/ssl/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/data/letsencrypt|/data/ssl/certbot|g" {} \; || exit 1 + +find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/letsencrypt-acme-challenge.conf;|include conf.d/include/acme-challenge.conf;|g" {} \; || exit 1 find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/assets.conf;||g" {} \; || exit 1 find /data/nginx -type f -name '*.conf' -exec sed -i "s/# Asset Caching//g" {} \; || exit 1 @@ -78,12 +103,17 @@ if [ ! -f /data/nginx/default.conf ]; then cp /usr/local/nginx/conf/conf.d/include/default.conf /data/nginx/default.conf || exit 1 fi +if [ ! -f /data/ssl/certbot/config.ini ]; then +cp /etc/ssl/certbot.ini /data/ssl/certbot/config.ini || exit 1 +fi + touch /data/nginx/default.conf \ /data/nginx/html/index.html \ /data/nginx/custom/root.conf \ /data/nginx/custom/events.conf \ /data/nginx/custom/http.conf \ /data/nginx/custom/http_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 \ @@ -107,32 +137,32 @@ if [ "$NGINX_LOG_NOT_FOUND" == "true" ]; then sed -i "s/log_not_found off;/log_not_found on;/g" /usr/local/nginx/conf/nginx.conf || exit 1 fi -if ! nginx -t 2> /dev/null; then +if ! nginx -t &> /dev/null; then nginx -T || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -while (nginx -t 2> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt 2> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt 2> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt 2> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt 2> /dev/null); do +while (nginx -t &> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt &> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt &> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt &> /dev/null && cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt &> /dev/null); do nginx || exit 1 & cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FOR || exit 1 & cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FOR || exit 1 & @@ -142,27 +172,27 @@ node --abort_on_uncaught_exception --max_old_space_size=250 index.js || exit 1 & wait done -if ! nginx -t 2> /dev/null; then +if ! nginx -t &> /dev/null; then nginx -T || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/7/conf.d php-fpm7 -c /data/php/7 -y /data/php/7/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/8/conf.d php-fpm8 -c /data/php/8 -y /data/php/8/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi -if ! cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt 2> /dev/null; then +if ! cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt &> /dev/null; then cross-env PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FORt || exit 1 sleep inf || exit 1 fi diff --git a/rootfs/etc/ssl/certbot.ini b/rootfs/etc/ssl/certbot.ini new file mode 100644 index 00000000..e50f5b5d --- /dev/null +++ b/rootfs/etc/ssl/certbot.ini @@ -0,0 +1,13 @@ +text = true +agree-tos = true +non-interactive = true +key-type = ecdsa +must-staple = true +rsa-key-size = 4096 +elliptic-curve = secp384r1 +webroot-path = /tmp/acme-challenge + +# 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 diff --git a/rootfs/etc/ssl/dhparam.txt b/rootfs/etc/ssl/dhparam.txt deleted file mode 100644 index ded74236..00000000 --- a/rootfs/etc/ssl/dhparam.txt +++ /dev/null @@ -1,96 +0,0 @@ - DH Parameters: (8192 bit) - prime: - 00:ea:c9:82:7f:46:79:c5:05:5f:8e:70:c6:a7:2b: - b2:66:57:1b:99:cd:9a:50:f2:96:57:c2:fb:fd:c7: - 40:e4:7c:43:52:bc:ec:4c:88:0f:1a:80:d9:b6:be: - 9c:30:e0:f2:15:f0:37:66:b8:29:70:fa:58:b4:06: - 2b:eb:c5:a5:04:b4:a3:55:de:da:74:68:68:29:fe: - a0:69:c0:f6:c3:61:79:f5:64:59:c3:5a:77:7c:b8: - 83:c1:db:96:d7:fb:59:20:84:0e:49:ad:40:f0:bd: - b7:21:1f:a9:bf:6e:38:88:24:27:83:cb:42:f2:1f: - 2e:37:d3:15:a9:b4:01:ab:19:1d:fe:a0:0b:36:80: - 40:49:c2:7b:06:de:fb:5e:48:c0:92:74:8b:cf:a1: - 0a:ff:f5:d9:f5:c6:57:2e:37:cc:8f:e2:45:f7:ec: - f2:e1:52:ef:c6:fb:75:33:ae:3b:b8:aa:20:84:80: - b5:10:ff:ae:db:ca:31:85:e4:ab:60:da:53:50:0b: - 7e:5d:66:83:b8:e8:e2:98:3c:b2:4a:bf:05:52:e9: - d3:9b:a0:4b:b7:da:52:70:2e:92:38:97:65:0d:78: - 58:77:93:e3:c2:f6:ea:da:86:cc:df:4a:19:14:db: - 8f:8d:48:cf:5b:29:fa:b8:51:66:9d:6f:83:65:8f: - 59:70:fb:aa:c8:8d:98:6b:d8:9f:5b:ee:48:b5:f1: - ef:c3:a4:85:cc:c8:15:fe:ed:4c:aa:bf:49:66:70: - 5a:21:6a:b8:af:cb:ad:6c:3d:59:33:10:18:a8:04: - 6b:f0:6b:39:1d:ec:46:34:1b:eb:24:2a:84:2b:06: - 7d:73:90:22:ef:06:1a:c2:10:bd:99:11:4b:67:a3: - 7b:86:6a:05:3a:cc:64:00:e6:6a:f5:b1:24:b6:79: - 0f:d4:ba:36:1b:80:eb:f4:23:a8:1d:8e:93:87:eb: - d5:f4:43:e2:aa:ce:ad:7c:53:c6:e7:8e:92:9d:11: - fe:18:53:c3:dc:24:77:77:8d:04:01:d8:14:5b:1c: - aa:de:46:cb:5e:cd:b5:bd:41:6d:59:fa:9e:5a:8a: - b8:25:76:63:ac:97:21:75:e8:ed:3c:d5:e2:bf:d1: - 79:b9:52:b5:fd:56:bd:91:8a:ea:61:69:f9:e2:80: - ca:cd:4a:04:c0:e0:5d:26:96:49:73:67:90:5d:14: - b2:c3:c8:80:68:7f:95:38:f8:da:fe:50:cc:ea:ef: - c8:eb:a6:ae:51:92:50:73:c3:c2:44:09:f7:d5:a1: - 6a:da:03:33:ef:b5:ed:ac:89:a7:02:a1:f8:a4:37: - eb:db:e9:6a:2a:39:5e:48:23:23:12:3c:80:60:f9: - 36:1a:c3:20:ff:e3:e5:67:ca:54:16:d7:44:c4:f3: - 75:f3:9b:37:19:4e:a5:07:a5:49:53:d3:17:6d:4a: - b2:e5:34:88:e2:f4:b0:36:5a:4b:05:70:ef:de:c5: - a0:a0:83:3d:72:a4:e0:13:27:0b:fe:29:95:5b:42: - 56:84:c1:3c:d7:09:80:ea:f8:33:2d:f1:42:20:b6: - ca:8b:68:71:af:2c:24:e9:c6:b9:e0:f4:ca:8f:78: - c1:ff:7c:d4:62:d1:e3:b3:65:aa:41:68:7f:18:9f: - c1:90:a8:e4:8c:82:07:a8:72:81:f6:98:12:ea:bd: - 29:9e:54:94:fa:9e:f0:2f:e2:d5:47:88:4d:47:ee: - ec:b9:16:ba:29:47:11:d9:c5:3c:0f:4c:87:93:2c: - e4:93:df:70:71:17:df:01:7b:e2:84:d0:26:56:47: - 7e:03:a3:18:89:66:d6:a5:65:2c:ea:64:ff:6a:b9: - 8f:c4:18:2d:b3:68:2a:0e:74:b5:f5:9a:0b:cc:4e: - 20:ee:46:69:06:2e:a9:58:a0:48:b9:0c:71:2e:b7: - 3a:84:11:d0:6e:e0:1d:a7:56:4e:35:7c:da:88:72: - 4a:8e:7f:af:fd:4b:68:0b:08:dd:90:b0:a1:9c:e1: - 0a:7a:b9:38:1a:08:46:07:f7:83:70:ad:95:58:77: - fa:bb:83:37:c3:81:90:2f:59:2a:9c:eb:f4:bf:dd: - 15:1b:b2:f0:b7:03:c8:aa:d9:6f:ee:e4:0b:42:c1: - e5:bc:01:af:e5:c7:6c:07:a1:e0:47:ca:ad:b7:f6: - 2b:7c:4f:09:08:7c:d9:34:21:64:93:f6:a4:c3:6d: - c4:de:11:5b:a5:85:af:f9:f7:13:1a:ab:1e:93:6a: - 99:20:23:63:d3:b4:52:1d:4a:a8:bc:cd:4c:27:42: - e3:84:fb:42:69:00:65:ae:a1:ee:16:6e:e4:39:b2: - c8:3f:34:de:ec:dc:46:56:8e:b2:e8:40:97:b5:56: - f0:d7:d9:ae:1f:3b:ec:ca:56:80:c4:d1:18:21:19: - 8b:a6:13:08:8e:48:56:ad:63:42:89:43:41:f0:63: - c8:cf:f2:6e:d1:6b:f6:1b:a5:bc:23:00:2e:2d:37: - 71:51:99:3b:1c:fe:1b:bb:2e:d2:c7:e3:2b:70:cc: - aa:8b:8f:98:51:23:dc:3c:3f:32:47:99:41:c0:98: - 0a:3b:b5:44:23:f6:b7:ec:2d:b5:81:20:f2:e5:4a: - 3c:6e:f5:5d:da:dd:d2:7d:47:18:1d:43:d9:50:c5: - 6e:da:4e:73:5d:ba:17:c2:33:92:0d:8f:1a:8d:0a: - 3c:4b:9b:0f:0f:82:a6:d8:c7:fa:38:2b:89:95:df: - 05:16:d1:9e:e7 - generator: 5 (0x5) ------BEGIN DH PARAMETERS----- -MIIECAKCBAEA6smCf0Z5xQVfjnDGpyuyZlcbmc2aUPKWV8L7/cdA5HxDUrzsTIgP -GoDZtr6cMODyFfA3ZrgpcPpYtAYr68WlBLSjVd7adGhoKf6gacD2w2F59WRZw1p3 -fLiDwduW1/tZIIQOSa1A8L23IR+pv244iCQng8tC8h8uN9MVqbQBqxkd/qALNoBA -ScJ7Bt77XkjAknSLz6EK//XZ9cZXLjfMj+JF9+zy4VLvxvt1M647uKoghIC1EP+u -28oxheSrYNpTUAt+XWaDuOjimDyySr8FUunTm6BLt9pScC6SOJdlDXhYd5Pjwvbq -2obM30oZFNuPjUjPWyn6uFFmnW+DZY9ZcPuqyI2Ya9ifW+5ItfHvw6SFzMgV/u1M -qr9JZnBaIWq4r8utbD1ZMxAYqARr8Gs5HexGNBvrJCqEKwZ9c5Ai7wYawhC9mRFL -Z6N7hmoFOsxkAOZq9bEktnkP1Lo2G4Dr9COoHY6Th+vV9EPiqs6tfFPG546SnRH+ -GFPD3CR3d40EAdgUWxyq3kbLXs21vUFtWfqeWoq4JXZjrJchdejtPNXiv9F5uVK1 -/Va9kYrqYWn54oDKzUoEwOBdJpZJc2eQXRSyw8iAaH+VOPja/lDM6u/I66auUZJQ -c8PCRAn31aFq2gMz77XtrImnAqH4pDfr2+lqKjleSCMjEjyAYPk2GsMg/+PlZ8pU -FtdExPN185s3GU6lB6VJU9MXbUqy5TSI4vSwNlpLBXDv3sWgoIM9cqTgEycL/imV -W0JWhME81wmA6vgzLfFCILbKi2hxrywk6ca54PTKj3jB/3zUYtHjs2WqQWh/GJ/B -kKjkjIIHqHKB9pgS6r0pnlSU+p7wL+LVR4hNR+7suRa6KUcR2cU8D0yHkyzkk99w -cRffAXvihNAmVkd+A6MYiWbWpWUs6mT/armPxBgts2gqDnS19ZoLzE4g7kZpBi6p -WKBIuQxxLrc6hBHQbuAdp1ZONXzaiHJKjn+v/UtoCwjdkLChnOEKerk4GghGB/eD -cK2VWHf6u4M3w4GQL1kqnOv0v90VG7LwtwPIqtlv7uQLQsHlvAGv5cdsB6HgR8qt -t/YrfE8JCHzZNCFkk/akw23E3hFbpYWv+fcTGqsek2qZICNj07RSHUqovM1MJ0Lj -hPtCaQBlrqHuFm7kObLIPzTe7NxGVo6y6ECXtVbw19muHzvsylaAxNEYIRmLphMI -jkhWrWNCiUNB8GPIz/Ju0Wv2G6W8IwAuLTdxUZk7HP4buy7Sx+MrcMyqi4+YUSPc -PD8yR5lBwJgKO7VEI/a37C21gSDy5Uo8bvVd2t3SfUcYHUPZUMVu2k5zXboXwjOS -DY8ajQo8S5sPD4Km2Mf6OCuJld8FFtGe5wIBBQ== ------END DH PARAMETERS----- diff --git a/rootfs/usr/local/bin/check-health b/rootfs/usr/local/bin/check-health deleted file mode 100644 index e0a7b55c..00000000 --- a/rootfs/usr/local/bin/check-health +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -if (cgi-fcgi -bind -connect /dev/php7.sock > /dev/null && cgi-fcgi -bind -connect /dev/php8.sock > /dev/null && cgi-fcgi -bind -connect /dev/php81.sock > /dev/null && cgi-fcgi -bind -connect /dev/php82.sock > /dev/null && [ "$(wget -q --no-check-certificate https://127.0.0.1:81/api -O - | jq --raw-output '.status')" == "OK" ]); then - echo "OK" - exit 0 -else - echo "NOT OK" - exit 1 -fi diff --git a/rootfs/usr/local/nginx/conf/conf.d/include/letsencrypt-acme-challenge.conf b/rootfs/usr/local/nginx/conf/conf.d/include/acme-challenge.conf similarity index 85% rename from rootfs/usr/local/nginx/conf/conf.d/include/letsencrypt-acme-challenge.conf rename to rootfs/usr/local/nginx/conf/conf.d/include/acme-challenge.conf index a53f177a..3c1b4c68 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/letsencrypt-acme-challenge.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/acme-challenge.conf @@ -2,7 +2,7 @@ location ^~ /.well-known/acme-challenge/ { auth_basic off; auth_request off; allow all; - root /tmp/letsencrypt-acme-challenge; + root /tmp/acme-challenge; } location = /.well-known/acme-challenge/ { 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 2039015f..1e0806a9 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/include/default.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/include/default.conf @@ -15,7 +15,7 @@ server { include conf.d/include/force-ssl.conf; include conf.d/include/ssl-ciphers.conf; - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; include conf.d/include/block-exploits.conf; add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400'; @@ -23,7 +23,7 @@ server { ssl_certificate_key /data/nginx/dummykey.pem; location / { - include conf.d/include/letsencrypt-acme-challenge.conf; + include conf.d/include/acme-challenge.conf; alias /html/default/; } } 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 be6ca2d7..813796d4 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 @@ -19,7 +19,6 @@ server { include conf.d/include/force-ssl.conf; include conf.d/include/ssl-ciphers.conf; - include conf.d/include/letsencrypt-acme-challenge.conf; include conf.d/include/block-exploits.conf; add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400'; diff --git a/rootfs/usr/local/nginx/conf/conf.d/npm.conf b/rootfs/usr/local/nginx/conf/conf.d/npm.conf index 336bc806..5e8b0ad3 100644 --- a/rootfs/usr/local/nginx/conf/conf.d/npm.conf +++ b/rootfs/usr/local/nginx/conf/conf.d/npm.conf @@ -10,7 +10,6 @@ server { ssl_certificate_key /data/nginx/dummykey.pem; include conf.d/include/ssl-ciphers.conf; include conf.d/include/block-exploits.conf; - include conf.d/include/letsencrypt-acme-challenge.conf; add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400'; location /api { diff --git a/rootfs/usr/local/nginx/conf/letsencrypt.ini b/rootfs/usr/local/nginx/conf/letsencrypt.ini deleted file mode 100644 index 40494283..00000000 --- a/rootfs/usr/local/nginx/conf/letsencrypt.ini +++ /dev/null @@ -1,7 +0,0 @@ -text = True -non-interactive = True -webroot-path = /tmp/letsencrypt-acme-challenge -rsa-key-size = 4096 -key-type = ecdsa -elliptic-curve = secp384r1 -preferred-chain = ISRG Root X1 diff --git a/security.txt b/security.txt new file mode 100644 index 00000000..2b5476c0 --- /dev/null +++ b/security.txt @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +Contact: mailto:zoeyvid@zvcdn.de +Expires: 2023-12-31T22:59:00.000Z +Encryption: https://zvcdn.de/publickey.asc +Preferred-Languages: de, en +Canonical: https://npm.zvcdn.de/.well-known/security.txt +Canonical: https://raw.githubusercontent.com/ZoeyVid/nginx-proxy-manager/develop/rootfs/app/frontend/.well-known/security.txt +-----BEGIN PGP SIGNATURE----- + +iHUEARYKAB0WIQQZsl0LheH0mUz2hsVuOQn3bP/+fAUCY7CHHAAKCRBuOQn3bP/+ +fHysAP9ZfBWAtWp+dE1Oow886oGvRGuhikWy31JhFuGa9OjWZgD/UDNXnaTe3m06 +D56Zc3GiQIW1QEboXMVmVwX4IEQN7Qk= +=uSIG +-----END PGP SIGNATURE-----