Compare commits

...

1 Commits

Author SHA1 Message Date
Zoey
d79a7de134 WIP (summary later)
Signed-off-by: Zoey <zoey@z0ey.de>
2025-01-03 22:51:04 +01:00
73 changed files with 821 additions and 1977 deletions

View File

@@ -72,9 +72,9 @@ RUN apk upgrade --no-cache -a && \
sed -i "s|APPSEC_PROCESS_TIMEOUT=.*|APPSEC_PROCESS_TIMEOUT=10000|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf
FROM zoeyvid/nginx-quic:368-python
FROM zoeyvid/nginx-quic:371-python
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
ARG CRS_VER=v4.9.0
ARG CRS_VER=v4.10.0
COPY rootfs /
COPY --from=strip-backend /app /app
@@ -113,20 +113,20 @@ COPY --from=crowdsec /src/crowdsec-nginx-bouncer/lua-mod/templa
COPY --from=crowdsec /src/crowdsec-nginx-bouncer/lua-mod/lib/crowdsec.lua /usr/local/nginx/lib/lua/crowdsec.lua
COPY --from=crowdsec /src/crowdsec-nginx-bouncer/lua-mod/lib/plugins /usr/local/nginx/lib/lua/plugins
COPY --from=frontend /app/dist /html/frontend
COPY --from=zoeyvid/certbot-docker:69 /usr/local /usr/local
LABEL com.centurylinklabs.watchtower.monitor-only="true"
ENV NODE_ENV=production \
NODE_CONFIG_DIR=/data/etc/npm \
DB_SQLITE_FILE=/data/etc/npm/database.sqlite
ENV ACME_SERVER="https://acme-v02.api.letsencrypt.org/directory" \
ACME_MUST_STAPLE=true \
ENV NODE_ENV=production \
TV=1 \
ACME_SERVER="https://acme-v02.api.letsencrypt.org/directory" \
ACME_MUST_STAPLE=false \
ACME_OCSP_STAPLING=false \
ACME_KEY_TYPE=rsa \
ACME_SERVER_TLS_VERIFY=true \
PUID=0 \
PGID=0 \
NIBEP=48693 \
GOAIWSP=48683 \
NIBEP=48683 \
GOAIWSP=48693 \
NPM_PORT=81 \
GOA_PORT=91 \
IPV4_BINDING=0.0.0.0 \
@@ -136,16 +136,19 @@ ENV ACME_SERVER="https://acme-v02.api.letsencrypt.org/directory" \
NPM_IPV6_BINDING=[::] \
GOA_IPV6_BINDING=[::] \
DISABLE_IPV6=false \
NPM_DISABLE_IPV6=false \
GOA_DISABLE_IPV6=false \
NPM_LISTEN_LOCALHOST=false \
GOA_LISTEN_LOCALHOST=false \
DEFAULT_CERT_ID=0 \
HTTP_PORT=80 \
HTTPS_PORT=443 \
DISABLE_HTTP=false \
DISABLE_H3_QUIC=false \
NGINX_QUIC_BPF=false \
NGINX_ACCESS_LOG=false \
NGINX_LOG_NOT_FOUND=false \
NGINX_404_REDIRECT=false \
NGINX_HSTS_SUBDMAINS=true \
X_FRAME_OPTIONS=deny \
NGINX_DISABLE_PROXY_BUFFERING=false \
DISABLE_NGINX_BEAUTIFIER=false \
CLEAN=true \
@@ -158,7 +161,8 @@ ENV ACME_SERVER="https://acme-v02.api.letsencrypt.org/directory" \
GOA=false \
GOACLA="--agent-list --real-os --double-decode --anonymize-ip --anonymize-level=1 --keep-last=30 --with-output-resolver --no-query-string" \
PHP82=false \
PHP83=false
PHP83=false \
PHP84=false
WORKDIR /app
ENTRYPOINT ["tini", "--", "entrypoint.sh"]

View File

@@ -5,16 +5,10 @@ running at home or otherwise, including free TLS, without having to know too muc
- [Quick Setup](#quick-setup)
**Note: NO armv7, route53 and aws cloudfront ip ranges support.** <br>
**Note: Other Databases like MariaDB may work, but are unsupported.** <br>
**Note: watchtower does NOT update NPMplus, you need to do it yourself (it will only pull the image, but not update the container itself).** <br>
**Note: access.log/stream.log, logrotate and goaccess are NOT enabled by default bceuase of GDPR, you can enable them in the compose.yaml.** <br>
**Note: add `net.ipv4.ip_unprivileged_port_start=0` at the end of `/etc/sysctl.conf` to support PUID/PGID in network mode host.** <br>
**Note: Don't forget to open Port 80 (tcp) and 443 (tcp AND udp, http3/quic needs udp) in your firewall (because of network mode host, you also need to open this ports in ufw, if you use ufw).** <br>
**Note: If you don't use network mode host, which I don't recommend, don't forget to also expose port 443/udp (http3/quic needs udp) and to enable IPv6 in Docker see step 1 and 2 [here](https://github.com/nextcloud/all-in-one/blob/main/docker-ipv6-support.md).** <br>
**MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING: please see/read/use the ACME_MUST_STAPLE env option of the compose.yaml** <br>
**Note: no armv7, route53 and aws cloudfront ip ranges support.** <br>
**Note: other Databases like MariaDB/MySQL or PostgreSQL may work, but are unsupported and have no advantage over SQLite.** <br>
**Note: watchtower does not update NPMplus, you need to do it yourself (it will only pull the image, but will not redeploy the container itself).** <br>
**Note: remember to add your domain to the hsts preload list if you use security headers: https://hstspreload.org** <br>
## Project Goal
I created this project to fill a personal need to provide users with an easy way to accomplish reverse
@@ -37,17 +31,18 @@ so that the barrier for entry here is low.
- Supports HTTP/3 (QUIC) protocol.
- Supports CrowdSec IPS. Please see [here](https://github.com/ZoeyVid/NPMplus#crowdsec) to enable it.
- goaccess included, see compose.yaml to enable, runs by default on https://<ip>:91 (nginx config from [here](https://github.com/xavier-hernandez/goaccess-for-nginxproxymanager/blob/main/resources/nginx/nginx.conf))
- Supports ModSecurity, with coreruleset as an option. You can configure ModSecurity/coreruleset by editing the files in the `/opt/npm/etc/modsecurity` folder (no support from me, you need to write the rules yourself - for CRS I can try to help you).
- Supports ModSecurity, with coreruleset as an option. You can configure ModSecurity/coreruleset by editing the files in the `/opt/npm/etc/modsecurity` folder (no support from me, you need to write the rules yourself - for CoreRuleSet I can try to help you).
- By default NPMplus UI does not work when you proxy NPMplus through NPMplus and you have CoreRuleSet enabled, see below
- ModSecurity by default blocks uploads of big files, you need to edit its config to fix this, but it can use a lot of resources to scan big files by ModSecurity
- ModSecurity overblocking (403 Error) with CRS? Please see [here](https://coreruleset.org/docs/concepts/false_positives_tuning) and edit the `/opt/npm/etc/modsecurity/crs-setup.conf` file.
- Try to whitelist the Content-Type you are sending (for example, `application/activity+json` for Mastodon and `application/dns-message` for DoH).
- Try to whitelist the HTTP request method you are using (for example, `PUT` is blocked by default, which also affects NPM).
- CRS plugins are supported, you can find a guide in this readme
- ModSecurity overblocking (403 Error) when using CoreRuleSet? Please see [here](https://coreruleset.org/docs/concepts/false_positives_tuning) and edit the `/opt/npm/etc/modsecurity/crs-setup.conf` file.
- Try to whitelist the Content-Type you are sending (for example, `application/activity+json` for Mastodon and `application/dns-message` for DoH).
- Try to whitelist the HTTP request method you are using (for example, `PUT` is blocked by default, which also blocks NPMplus UI).
- CoreRuleSet plugins are supported, you can find a guide in this readme
- Darkmode button in the footer for comfortable viewing (CSS done by [@theraw](https://github.com/theraw))
- Fixes proxy to https origin when the origin only accepts TLSv1.3
- Only enables TLSv1.2 and TLSv1.3 protocols, also ML-KEM support
- Faster creation of TLS certificates is achieved by eliminating unnecessary nginx reloads and configuration creations.
- Uses OCSP Stapling for enhanced security (manual certs not supported)
- Supports OCSP Stapling/Must-Staple for enhanced security (manual certs not supported, see compose.yaml for details)
- 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
@@ -60,7 +55,7 @@ so that the barrier for entry here is low.
- access.log is disabled by default, unified and moved to `/opt/npm/nginx/access.log`
- Error Log written to console
- `Server` response header hidden
- PHP 8.2/8.3 optional, with option to add extensions; available packages can added using envs in the compose file
- PHP optional, with option to add extensions; available packages can added using envs in the compose file
- Allows different acme servers using env
- Supports up to 99 domains per cert
- Brotli compression can be enabled
@@ -69,7 +64,6 @@ so that the barrier for entry here is low.
- Automatic database vacuum (only sqlite)
- Automatic cleaning of old invalid certbot certs (set CLEAN to true)
- Password reset (only sqlite) using `docker exec -it npmplus password-reset.js USER_EMAIL PASSWORD`
- Supports TLS for MariaDB/MySQL; set `DB_MYSQL_TLS` env to true. Self-signed certificates can be uploaded to `/opt/npm/etc/npm/ca.crt` and `DB_MYSQL_CA` set to `/data/etc/npm/ca.crt` (not tested, unsupported)
- multi lang support, if you want to add an language, see this commit as an example: https://github.com/ZoeyVid/NPMplus/commit/a026b42329f66b89fe1fbe5e6034df5d3fc2e11f (implementation based on [@lateautumn233](https://github.com/lateautumn233) fork)
- See the compose file for all available options
- many env options optimized for network_mode host (ports/ip bindings)
@@ -79,17 +73,16 @@ 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
- please delete all dnspod certs and recreate them after migration OR you manually change the credentialsfile (see [here](https://github.com/ZoeyVid/npmplus/blob/develop/global/certbot-dns-plugins.json) for the template)
- stop nginx-proxy-manager download the latest compose.yaml, adjust your paths (of /etc/letsencrypt and /data) to the ones you used with nginx-proxy-manager and adjust the env of the compose file how you like it and then deploy it
- you can now remove the /etc/letsencrypt mount, since it was moved to /data while migration and redeploy the compose file
- since this fork uses `network_mode: host` by default (and all guides are written for this mode), please don't forget to open port 80/tcp, 443/tcp and 443/udp (and maybe 81/tcp) in your firewall
- 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 certs using dnspod as dns provider and recreate them after migration, since the certbot plugin used was replaced
- stop nginx-proxy-manager download the latest compose.yaml, adjust your paths (of /etc/letsencrypt and /data) to the ones you used with nginx-proxy-manager and adjust the envs of the compose file how you like it and then deploy it
- you can now remove the /etc/letsencrypt mount, since it was moved to /data while migration, and redeploy the compose file
- since many buttons changed, please check if they are still correct for every host you have.
- maybe setup crowdsec (see below)
- please report all (migration) issues you may have
# Quick Setup
1. Install Docker and Docker Compose (or portainer)
- [Docker Install documentation](https://docs.docker.com/engine)
1. Install Docker and Docker Compose (podman or docker rootless may also work)
- [Docker Install documentation](https://docs.docker.com/engine/install)
- [Docker Compose Install documentation](https://docs.docker.com/compose/install/linux)
2. Download this [compose.yaml](https://raw.githubusercontent.com/ZoeyVid/NPMplus/refs/heads/develop/compose.yaml) (or use its content as a portainer stack)
3. adjust TZ and ACME_EMAIL to your values and maybe adjust other env options to your needs.
@@ -170,8 +163,8 @@ location / {
```
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: first enable `PHP82` and/or `PHP83` inside your compose file
- Note: you can replace `fastcgi_pass php82;` with `fastcgi_pass php83;`
- Note: first enable `PHP82`, `PHP83` and/or `PHP84` inside your compose file
- Note: you can replace `fastcgi_pass php82;` with `fastcgi_pass php83;`/`fastcgi_pass php84;`
- Note: to add more php extension using envs you can set in the compose file
```
location / {
@@ -191,11 +184,11 @@ location / {
### prerun scripts (EXPERT option) - if you don't know what this is, ignore it
run order: entrypoint.sh (prerun scripts) => start.sh => launch.sh <br>
if you need to run scripts before NPMplus launches put them under: `/opt/npm/etc/prerun/*.sh` (please add `#!/bin/sh` / `#!/bin/bash` to the top of the script) <br>
if you need to run scripts before NPMplus launches put them under: `/opt/npm/etc/prerun/*.sh` (please add `#!/usr/bin/env sh` / `#!/usr/bin/env bash` to the top of the script) <br>
you need to create this folder yourself - **NOTE:** I won't help you creating those patches/scripts if you need them you also need to know how to create them
## Contributing
All are welcome to create pull requests for this project.
All are welcome to create pull requests for this project, but this does not mean it will be merged.
# Please report Bugs first to this fork before reporting them to the upstream Repository
## Getting Help

View File

@@ -21,8 +21,8 @@ async function appStart() {
internalCertificate.initTimer();
internalIpRanges.initTimer();
const server = app.listen(48693, '127.0.0.1', () => {
logger.info('Backend PID ' + process.pid + ' listening on port 48693 ...');
const server = app.listen(Number(process.env.NIBEP), '127.0.0.1', () => {
logger.info('Backend PID ' + process.pid + ' listening on port ' + process.env.NIBEP);
process.on('SIGTERM', () => {
logger.info('PID ' + process.pid + ' received SIGTERM');

View File

@@ -783,7 +783,6 @@ const internalCertificate = {
logger.info(`Requesting Certbot certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
const credentialsLocation = '/data/tls/certbot/credentials/credentials-' + certificate.id;
fs.mkdirSync('/data/tls/certbot/credentials', { recursive: true });
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 });
try {
@@ -889,16 +888,6 @@ const internalCertificate = {
return utils
.execFile(certbotCommand, [...certbotArgs, 'revoke', '--cert-name', `npm-${certificate.id}`, '--no-delete-after-revoke'])
.then(async (result) => {
fs.rm('/data/tls/certbot/credentials/credentials-' + certificate.id, { force: true }, (err) => {
if (err) {
logger.error('Error deleting credentials:', err.message);
if (throw_errors) {
throw err;
}
} else {
logger.info('Credentials file deleted successfully');
}
});
logger.info(result);
return result;
})

View File

@@ -104,7 +104,7 @@ const internalIpRanges = {
let template = null;
const filename = '/tmp/ip_ranges.conf';
try {
template = fs.readFileSync(__dirname + '/../templates/ip_ranges.conf', { encoding: 'utf8' });
template = fs.readFileSync('/app/templates/ip_ranges.conf', { encoding: 'utf8' });
} catch (err) {
reject(new error.ConfigurationError(err.message));
return;

View File

@@ -7,7 +7,6 @@ const error = require('../lib/error');
const internalNginx = {
/**
* This will:
* - test the nginx config first to make sure it's OK
* - create / recreate the config for the host
* - test again
* - IF OK: update the meta with online status
@@ -23,15 +22,7 @@ const internalNginx = {
let combined_meta = {};
return internalNginx
.test()
.then(() => {
// Nginx is OK
// We're deleting this config regardless.
return internalNginx.deleteConfig(host_type, host);
})
.then(() => {
return internalNginx.generateConfig(host_type, host);
})
.generateConfig(host_type, host)
.then(() => {
// Test nginx again and update meta with result
return internalNginx
@@ -79,14 +70,7 @@ const internalNginx = {
* @returns {Promise}
*/
test: () => {
return utils
.execFile('certbot-ocsp-fetcher.sh', ['-c', '/data/tls/certbot', '-o', '/data/tls/certbot/live', '--no-reload-webserver', '--quiet'])
.then(() => {
return utils.execFile('nginx', ['-tq']);
})
.catch(() => {
return utils.execFile('nginx', ['-tq']);
});
return utils.execFile('nginx', ['-tq']);
},
/**
@@ -94,7 +78,17 @@ const internalNginx = {
*/
reload: () => {
return internalNginx.test().then(() => {
if (process.env.ACME_OCSP_STAPLING === 'true') {
return utils.execFile('certbot-ocsp-fetcher.sh', ['-c', '/data/tls/certbot', '-o', '/data/tls/certbot/live', '--no-reload-webserver', '--quiet']).finally(() => {
if (fs.existsSync('/usr/local/nginx/logs/nginx.pid') && fs.readFileSync('/usr/local/nginx/logs/nginx.pid', 'utf8').trim().length > 0) {
logger.info('Reloading Nginx');
return utils.execFile('nginx', ['-s', 'reload']);
} else {
logger.info('Starting Nginx');
utils.execfg('nginx', ['-e', 'stderr']);
}
});
} else {
if (fs.existsSync('/usr/local/nginx/logs/nginx.pid') && fs.readFileSync('/usr/local/nginx/logs/nginx.pid', 'utf8').trim().length > 0) {
logger.info('Reloading Nginx');
return utils.execFile('nginx', ['-s', 'reload']);
@@ -102,7 +96,7 @@ const internalNginx = {
logger.info('Starting Nginx');
utils.execfg('nginx', ['-e', 'stderr']);
}
});
}
},
/**
@@ -127,7 +121,7 @@ const internalNginx = {
let template;
try {
template = fs.readFileSync(__dirname + '/../templates/_location.conf', { encoding: 'utf8' });
template = fs.readFileSync('/app/templates/_location.conf', { encoding: 'utf8' });
} catch (err) {
reject(new error.ConfigurationError(err.message));
return;
@@ -146,6 +140,7 @@ const internalNginx = {
locationCopy.forward_host = split.shift();
locationCopy.forward_path = `/${split.join('/')}`;
}
locationCopy.env = process.env;
renderedLocations += await renderEngine.parseAndRender(template, locationCopy);
}
@@ -172,7 +167,7 @@ const internalNginx = {
const filename = internalNginx.getConfigName(nice_host_type, host.id);
try {
template = fs.readFileSync(__dirname + '/../templates/' + nice_host_type + '.conf', { encoding: 'utf8' });
template = fs.readFileSync('/app/templates/' + nice_host_type + '.conf', { encoding: 'utf8' });
} catch (err) {
reject(new error.ConfigurationError(err.message));
return;
@@ -206,6 +201,8 @@ const internalNginx = {
locationsPromise = Promise.resolve();
}
host.env = process.env;
locationsPromise.then(() => {
renderEngine
.parseAndRender(template, host)

View File

@@ -49,15 +49,14 @@ const configure = () => {
return;
}
const envSqliteFile = process.env.DB_SQLITE_FILE || '/data/etc/npm/database.sqlite';
logger.info(`Using Sqlite: ${envSqliteFile}`);
logger.info('Using Sqlite: /data/etc/npm/database.sqlite');
instance = {
database: {
engine: 'knex-native',
knex: {
client: 'better-sqlite3',
connection: {
filename: envSqliteFile,
filename: '/data/etc/npm/database.sqlite',
},
useNullAsDefault: true,
},

View File

@@ -1,4 +1,6 @@
const _ = require('lodash');
const fs = require('fs');
const crypto = require('crypto');
const spawn = require('child_process').spawn;
const execFile = require('child_process').execFile;
const { Liquid } = require('liquidjs');
@@ -6,6 +8,21 @@ const logger = require('../logger').global;
const error = require('./error');
module.exports = {
writeHash: function () {
const envVars = fs.readdirSync('/app/templates').flatMap((file) => {
const content = fs.readFileSync('/app/templates/' + file, 'utf8');
const matches = content.match(/env\.[A-Z0-9_]+/g) || [];
return matches.map((match) => match.replace('env.', ''));
});
const uniqueEnvVars =
[...new Set(envVars)]
.sort()
.map((varName) => process.env[varName])
.join('') + process.env.TV;
const hash = crypto.createHash('sha512').update(uniqueEnvVars).digest('hex');
fs.writeFileSync('/data/etc/npm/env.sha512sum', hash);
},
/**
* @param {String} cmd
* @param {Array} args
@@ -94,7 +111,7 @@ module.exports = {
*/
getRenderEngine: function () {
const renderEngine = new Liquid({
root: __dirname + '/../templates/',
root: '/app/templates/',
});
/**

View File

@@ -0,0 +1,42 @@
const migrate_name = 'change_forwarding_port_to_string';
const logger = require('../logger').migrate;
/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.up = function (knex /*, Promise */) {
logger.info('[' + migrate_name + '] Migrating Up...');
return knex.schema
.alterTable('stream', (table) => {
table.string('forwarding_port', 12).notNull().alter();
})
.then(function () {
logger.info('[' + migrate_name + '] stream Table altered');
});
};
/**
* Undo Migrate
*
* @param {Object} knex
* @param {Promise} Promise
* @returns {Promise}
*/
exports.down = function (knex /*, Promise */) {
logger.info('[' + migrate_name + '] Migrating Down...');
return knex.schema
.alterTable('stream', (table) => {
table.integer('forwarding_port').notNull().unsigned().alter();
})
.then(function () {
logger.info('[' + migrate_name + '] stream Table altered');
});
};

View File

@@ -18,10 +18,10 @@
"gravatar": "1.8.2",
"jsonwebtoken": "9.0.2",
"knex": "3.1.0",
"liquidjs": "10.19.0",
"liquidjs": "10.20.0",
"lodash": "4.17.21",
"moment": "2.30.1",
"mysql2": "3.11.5",
"mysql2": "3.12.0",
"node-rsa": "1.1.1",
"objection": "3.1.5",
"path": "0.12.7",
@@ -35,7 +35,7 @@
"eslint": "9.17.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "5.2.1",
"globals": "15.13.0",
"globals": "15.14.0",
"prettier": "3.4.2"
},
"scripts": {

View File

@@ -1,5 +1,4 @@
const express = require('express');
const pjson = require('../package.json');
const error = require('../lib/error');
let router = express.Router({
@@ -13,15 +12,8 @@ let router = express.Router({
* GET /api
*/
router.get('/', (req, res /*, next*/) => {
let version = pjson.version.split('-').shift().split('.');
res.status(200).send({
status: 'OK',
version: {
major: parseInt(version.shift(), 10),
minor: parseInt(version.shift(), 10),
revision: parseInt(version.shift(), 10),
},
});
});

View File

@@ -76,7 +76,7 @@
"uniqueItems": true,
"items": {
"type": "string",
"pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$"
"pattern": "^(([^.]+\\.)+[^.]+)|(\\[[0-9a-f:]+\\])$"
}
},
"enabled": {

View File

@@ -30,7 +30,7 @@
"uniqueItems": true,
"items": {
"type": "string",
"pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$"
"pattern": "^(([^.]+\\.)+[^.]+)|(\\[[0-9a-f:]+\\])$"
}
},
"expires_on": {

View File

@@ -2,37 +2,12 @@
"type": "object",
"description": "Health object",
"additionalProperties": false,
"required": ["status", "version"],
"required": ["status"],
"properties": {
"status": {
"type": "string",
"description": "Healthy",
"example": "OK"
},
"version": {
"type": "object",
"description": "The version object",
"example": {
"major": 2,
"minor": 0,
"revision": 0
},
"additionalProperties": false,
"required": ["major", "minor", "revision"],
"properties": {
"major": {
"type": "integer",
"minimum": 0
},
"minor": {
"type": "integer",
"minimum": 0
},
"revision": {
"type": "integer",
"minimum": 0
}
}
}
}
}

View File

@@ -44,8 +44,7 @@
},
"forward_host": {
"type": "string",
"minLength": 1,
"maxLength": 255
"pattern": "^(([^.]+\\.)+[^.]+)|(\\[[0-9a-f:]+\\])$"
},
"forward_port": {
"type": "integer",
@@ -101,6 +100,7 @@
},
"path": {
"type": "string",
"pattern": "^/.+$",
"minLength": 1
},
"forward_scheme": {
@@ -113,7 +113,8 @@
"$ref": "#/properties/forward_port"
},
"forward_path": {
"type": "string"
"type": "string",
"pattern": "^($|/.+$)"
},
"advanced_config": {
"type": "string"

View File

@@ -34,7 +34,7 @@
"description": "Domain Name",
"example": "jc21.com",
"type": "string",
"pattern": "^(?:[^.*]+\\.?)+[^.]$"
"pattern": "^(([^.]+\\.)+[^.]+)|(\\[[0-9a-f:]+\\])($|/.*$)"
},
"preserve_path": {
"description": "Should the path be preserved",

View File

@@ -18,31 +18,17 @@
},
"incoming_port": {
"type": "string",
"pattern": "^(?!80$|443$)([0-9]+|[0-9]+-[0-9]+)$",
"pattern": "^([0-9]+{1,5}$|[0-9]+{1,5}-[0-9]+{1,5}$)",
"maxLength": 11
},
"forwarding_host": {
"anyOf": [
{
"description": "Domain Name",
"example": "jc21.com",
"type": "string",
"pattern": "^(?:[^.*]+\\.?)+[^.]$"
},
{
"type": "string",
"format": "ipv4"
},
{
"type": "string",
"format": "ipv6"
}
]
"type": "string",
"pattern": "^(([^.]+\\.)+[^.]+)|(\\[[0-9a-f:]+\\])$"
},
"forwarding_port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
"type": "string",
"pattern": "^([0-9]+{1,5}|\\$server_port)$",
"maxLength": 12
},
"tcp_forwarding": {
"type": "boolean"

View File

@@ -29,6 +29,7 @@
"type": "string",
"description": "Email",
"minLength": 3,
"pattern": "@",
"example": "jc@jc21.com"
},
"name": {

View File

@@ -1,240 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "definitions",
"definitions": {
"id": {
"description": "Unique identifier",
"example": 123456,
"readOnly": true,
"type": "integer",
"minimum": 1
},
"setting_id": {
"description": "Unique identifier for a Setting",
"example": "default-site",
"readOnly": true,
"type": "string",
"minLength": 2
},
"token": {
"type": "string",
"minLength": 10
},
"expand": {
"anyOf": [
{
"type": "null"
},
{
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
]
},
"sort": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"required": [
"field",
"dir"
],
"additionalProperties": false,
"properties": {
"field": {
"type": "string"
},
"dir": {
"type": "string",
"pattern": "^(asc|desc)$"
}
}
}
},
"query": {
"anyOf": [
{
"type": "null"
},
{
"type": "string",
"minLength": 1,
"maxLength": 255
}
]
},
"criteria": {
"anyOf": [
{
"type": "null"
},
{
"type": "object"
}
]
},
"fields": {
"anyOf": [
{
"type": "null"
},
{
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
]
},
"omit": {
"anyOf": [
{
"type": "null"
},
{
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
]
},
"created_on": {
"description": "Date and time of creation",
"format": "date-time",
"readOnly": true,
"type": "string"
},
"modified_on": {
"description": "Date and time of last update",
"format": "date-time",
"readOnly": true,
"type": "string"
},
"user_id": {
"description": "User ID",
"example": 1234,
"type": "integer",
"minimum": 1
},
"certificate_id": {
"description": "Certificate ID",
"example": 1234,
"anyOf": [
{
"type": "integer",
"minimum": 0
},
{
"type": "string",
"pattern": "^new$"
}
]
},
"access_list_id": {
"description": "Access List ID",
"example": 1234,
"type": "integer",
"minimum": 0
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"email": {
"description": "Email Address",
"example": "john@example.com",
"format": "email",
"type": "string",
"minLength": 6,
"maxLength": 100
},
"password": {
"description": "Password",
"type": "string",
"minLength": 8,
"maxLength": 255
},
"domain_name": {
"description": "Domain Name",
"example": "jc21.com",
"type": "string",
"pattern": "^(?:[^.*]+\\.?)+[^.]$"
},
"domain_names": {
"description": "Domain Names separated by a comma",
"example": "*.jc21.com,blog.jc21.com",
"type": "array",
"maxItems": 99,
"uniqueItems": true,
"items": {
"type": "string",
"pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$"
}
},
"http_code": {
"description": "Redirect HTTP Status Code",
"example": 302,
"type": "integer",
"minimum": 300,
"maximum": 308
},
"scheme": {
"description": "RFC Protocol",
"example": "HTTPS or $scheme",
"type": "string",
"minLength": 4
},
"enabled": {
"description": "Is Enabled",
"example": true,
"type": "boolean"
},
"ssl_enabled": {
"description": "Is SSL Enabled",
"example": true,
"type": "boolean"
},
"ssl_forced": {
"description": "Is SSL Forced",
"example": false,
"type": "boolean"
},
"hsts_enabled": {
"description": "Is HSTS Enabled",
"example": false,
"type": "boolean"
},
"hsts_subdomains": {
"description": "Is HSTS applicable to all subdomains",
"example": false,
"type": "boolean"
},
"ssl_provider": {
"type": "string",
"pattern": "^(letsencrypt|other)$"
},
"http2_support": {
"description": "HTTP2 Protocol Support",
"example": false,
"type": "boolean"
},
"block_exploits": {
"description": "Should we block common exploits",
"example": true,
"type": "boolean"
},
"caching_enabled": {
"description": "Should we cache assets",
"example": true,
"type": "boolean"
}
}
}

View File

@@ -1,173 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "endpoints/certificates",
"title": "Certificates",
"description": "Endpoints relating to Certificates",
"stability": "stable",
"type": "object",
"definitions": {
"id": {
"$ref": "../definitions.json#/definitions/id"
},
"created_on": {
"$ref": "../definitions.json#/definitions/created_on"
},
"modified_on": {
"$ref": "../definitions.json#/definitions/modified_on"
},
"provider": {
"$ref": "../definitions.json#/definitions/ssl_provider"
},
"nice_name": {
"type": "string",
"description": "Nice Name for the custom certificate"
},
"domain_names": {
"$ref": "../definitions.json#/definitions/domain_names"
},
"expires_on": {
"description": "Date and time of expiration",
"format": "date-time",
"readOnly": true,
"type": "string"
},
"meta": {
"type": "object",
"additionalProperties": false,
"properties": {
"letsencrypt_email": {
"type": "string",
"format": "email"
},
"letsencrypt_agree": {
"type": "boolean"
},
"dns_challenge": {
"type": "boolean"
},
"dns_provider": {
"type": "string"
},
"dns_provider_credentials": {
"type": "string"
},
"propagation_seconds": {
"anyOf": [
{
"type": "integer",
"minimum": 0
}
]
}
}
}
},
"properties": {
"id": {
"$ref": "#/definitions/id"
},
"created_on": {
"$ref": "#/definitions/created_on"
},
"modified_on": {
"$ref": "#/definitions/modified_on"
},
"provider": {
"$ref": "#/definitions/provider"
},
"nice_name": {
"$ref": "#/definitions/nice_name"
},
"domain_names": {
"$ref": "#/definitions/domain_names"
},
"expires_on": {
"$ref": "#/definitions/expires_on"
},
"meta": {
"$ref": "#/definitions/meta"
}
},
"links": [
{
"title": "List",
"description": "Returns a list of Certificates",
"href": "/nginx/certificates",
"access": "private",
"method": "GET",
"rel": "self",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "array",
"items": {
"$ref": "#/properties"
}
}
},
{
"title": "Create",
"description": "Creates a new Certificate",
"href": "/nginx/certificates",
"access": "private",
"method": "POST",
"rel": "create",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"provider"
],
"properties": {
"provider": {
"$ref": "#/definitions/provider"
},
"nice_name": {
"$ref": "#/definitions/nice_name"
},
"domain_names": {
"$ref": "#/definitions/domain_names"
},
"meta": {
"$ref": "#/definitions/meta"
}
}
},
"targetSchema": {
"properties": {
"$ref": "#/properties"
}
}
},
{
"title": "Delete",
"description": "Deletes a existing Certificate",
"href": "/nginx/certificates/{definitions.identity.example}",
"access": "private",
"method": "DELETE",
"rel": "delete",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "boolean"
}
},
{
"title": "Test HTTP Challenge",
"description": "Tests whether the HTTP challenge should work",
"href": "/nginx/certificates/{definitions.identity.example}/test-http",
"access": "private",
"method": "GET",
"rel": "info",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
}
}
]
}

View File

@@ -1,234 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "endpoints/streams",
"title": "Streams",
"description": "Endpoints relating to Streams",
"stability": "stable",
"type": "object",
"definitions": {
"id": {
"$ref": "../definitions.json#/definitions/id"
},
"created_on": {
"$ref": "../definitions.json#/definitions/created_on"
},
"modified_on": {
"$ref": "../definitions.json#/definitions/modified_on"
},
"incoming_port": {
"type": "string",
"pattern": "^([0-9]+|[0-9]+-[0-9]+)$",
"maxLength": 11
},
"forwarding_host": {
"anyOf": [
{
"$ref": "../definitions.json#/definitions/domain_name"
},
{
"type": "string",
"format": "ipv4"
},
{
"type": "string",
"format": "ipv6"
}
]
},
"forwarding_port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"tcp_forwarding": {
"type": "boolean"
},
"udp_forwarding": {
"type": "boolean"
},
"enabled": {
"$ref": "../definitions.json#/definitions/enabled"
},
"meta": {
"type": "object"
}
},
"properties": {
"id": {
"$ref": "#/definitions/id"
},
"created_on": {
"$ref": "#/definitions/created_on"
},
"modified_on": {
"$ref": "#/definitions/modified_on"
},
"incoming_port": {
"$ref": "#/definitions/incoming_port"
},
"forwarding_host": {
"$ref": "#/definitions/forwarding_host"
},
"forwarding_port": {
"$ref": "#/definitions/forwarding_port"
},
"tcp_forwarding": {
"$ref": "#/definitions/tcp_forwarding"
},
"udp_forwarding": {
"$ref": "#/definitions/udp_forwarding"
},
"enabled": {
"$ref": "#/definitions/enabled"
},
"meta": {
"$ref": "#/definitions/meta"
}
},
"links": [
{
"title": "List",
"description": "Returns a list of Streams",
"href": "/nginx/streams",
"access": "private",
"method": "GET",
"rel": "self",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "array",
"items": {
"$ref": "#/properties"
}
}
},
{
"title": "Create",
"description": "Creates a new Stream",
"href": "/nginx/streams",
"access": "private",
"method": "POST",
"rel": "create",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"incoming_port",
"forwarding_host",
"forwarding_port"
],
"properties": {
"incoming_port": {
"$ref": "#/definitions/incoming_port"
},
"forwarding_host": {
"$ref": "#/definitions/forwarding_host"
},
"forwarding_port": {
"$ref": "#/definitions/forwarding_port"
},
"tcp_forwarding": {
"$ref": "#/definitions/tcp_forwarding"
},
"udp_forwarding": {
"$ref": "#/definitions/udp_forwarding"
},
"meta": {
"$ref": "#/definitions/meta"
}
}
},
"targetSchema": {
"properties": {
"$ref": "#/properties"
}
}
},
{
"title": "Update",
"description": "Updates a existing Stream",
"href": "/nginx/streams/{definitions.identity.example}",
"access": "private",
"method": "PUT",
"rel": "update",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {
"incoming_port": {
"$ref": "#/definitions/incoming_port"
},
"forwarding_host": {
"$ref": "#/definitions/forwarding_host"
},
"forwarding_port": {
"$ref": "#/definitions/forwarding_port"
},
"tcp_forwarding": {
"$ref": "#/definitions/tcp_forwarding"
},
"udp_forwarding": {
"$ref": "#/definitions/udp_forwarding"
},
"meta": {
"$ref": "#/definitions/meta"
}
}
},
"targetSchema": {
"properties": {
"$ref": "#/properties"
}
}
},
{
"title": "Delete",
"description": "Deletes a existing Stream",
"href": "/nginx/streams/{definitions.identity.example}",
"access": "private",
"method": "DELETE",
"rel": "delete",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "boolean"
}
},
{
"title": "Enable",
"description": "Enables a existing Stream",
"href": "/nginx/streams/{definitions.identity.example}/enable",
"access": "private",
"method": "POST",
"rel": "update",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "boolean"
}
},
{
"title": "Disable",
"description": "Disables a existing Stream",
"href": "/nginx/streams/{definitions.identity.example}/disable",
"access": "private",
"method": "POST",
"rel": "update",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "boolean"
}
}
]
}

View File

@@ -1,287 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "endpoints/users",
"title": "Users",
"description": "Endpoints relating to Users",
"stability": "stable",
"type": "object",
"definitions": {
"id": {
"$ref": "../definitions.json#/definitions/id"
},
"created_on": {
"$ref": "../definitions.json#/definitions/created_on"
},
"modified_on": {
"$ref": "../definitions.json#/definitions/modified_on"
},
"name": {
"description": "Name",
"example": "Jamie Curnow",
"type": "string",
"minLength": 2,
"maxLength": 100
},
"nickname": {
"description": "Nickname",
"example": "Jamie",
"type": "string",
"minLength": 2,
"maxLength": 50
},
"email": {
"$ref": "../definitions.json#/definitions/email"
},
"avatar": {
"description": "Avatar",
"example": "http://somewhere.jpg",
"type": "string",
"minLength": 2,
"maxLength": 150,
"readOnly": true
},
"roles": {
"description": "Roles",
"example": [
"admin"
],
"type": "array"
},
"is_disabled": {
"description": "Is Disabled",
"example": false,
"type": "boolean"
}
},
"links": [
{
"title": "List",
"description": "Returns a list of Users",
"href": "/users",
"access": "private",
"method": "GET",
"rel": "self",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "array",
"items": {
"$ref": "#/properties"
}
}
},
{
"title": "Create",
"description": "Creates a new User",
"href": "/users",
"access": "private",
"method": "POST",
"rel": "create",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"required": [
"name",
"nickname",
"email"
],
"properties": {
"name": {
"$ref": "#/definitions/name"
},
"nickname": {
"$ref": "#/definitions/nickname"
},
"email": {
"$ref": "#/definitions/email"
},
"roles": {
"$ref": "#/definitions/roles"
},
"is_disabled": {
"$ref": "#/definitions/is_disabled"
},
"auth": {
"type": "object",
"description": "Auth Credentials",
"example": {
"type": "password",
"secret": "bigredhorsebanana"
}
}
}
},
"targetSchema": {
"properties": {
"$ref": "#/properties"
}
}
},
{
"title": "Update",
"description": "Updates a existing User",
"href": "/users/{definitions.identity.example}",
"access": "private",
"method": "PUT",
"rel": "update",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"properties": {
"name": {
"$ref": "#/definitions/name"
},
"nickname": {
"$ref": "#/definitions/nickname"
},
"email": {
"$ref": "#/definitions/email"
},
"roles": {
"$ref": "#/definitions/roles"
},
"is_disabled": {
"$ref": "#/definitions/is_disabled"
}
}
},
"targetSchema": {
"properties": {
"$ref": "#/properties"
}
}
},
{
"title": "Delete",
"description": "Deletes a existing User",
"href": "/users/{definitions.identity.example}",
"access": "private",
"method": "DELETE",
"rel": "delete",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"targetSchema": {
"type": "boolean"
}
},
{
"title": "Set Password",
"description": "Sets a password for an existing User",
"href": "/users/{definitions.identity.example}/auth",
"access": "private",
"method": "PUT",
"rel": "update",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"required": [
"type",
"secret"
],
"properties": {
"type": {
"type": "string",
"pattern": "^password$"
},
"current": {
"type": "string",
"minLength": 1,
"maxLength": 99
},
"secret": {
"type": "string",
"minLength": 8,
"maxLength": 99
}
}
},
"targetSchema": {
"type": "boolean"
}
},
{
"title": "Set Permissions",
"description": "Sets Permissions for a User",
"href": "/users/{definitions.identity.example}/permissions",
"access": "private",
"method": "PUT",
"rel": "update",
"http_header": {
"$ref": "../examples.json#/definitions/auth_header"
},
"schema": {
"type": "object",
"properties": {
"visibility": {
"type": "string",
"pattern": "^(all|user)$"
},
"access_lists": {
"type": "string",
"pattern": "^(hidden|view|manage)$"
},
"dead_hosts": {
"type": "string",
"pattern": "^(hidden|view|manage)$"
},
"proxy_hosts": {
"type": "string",
"pattern": "^(hidden|view|manage)$"
},
"redirection_hosts": {
"type": "string",
"pattern": "^(hidden|view|manage)$"
},
"streams": {
"type": "string",
"pattern": "^(hidden|view|manage)$"
},
"certificates": {
"type": "string",
"pattern": "^(hidden|view|manage)$"
}
}
},
"targetSchema": {
"type": "boolean"
}
}
],
"properties": {
"id": {
"$ref": "#/definitions/id"
},
"created_on": {
"$ref": "#/definitions/created_on"
},
"modified_on": {
"$ref": "#/definitions/modified_on"
},
"name": {
"$ref": "#/definitions/name"
},
"nickname": {
"$ref": "#/definitions/nickname"
},
"email": {
"$ref": "#/definitions/email"
},
"avatar": {
"$ref": "#/definitions/avatar"
},
"roles": {
"$ref": "#/definitions/roles"
},
"is_disabled": {
"$ref": "#/definitions/is_disabled"
}
}
}

View File

@@ -1,42 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "root",
"title": "NPMplus REST API",
"description": "This is the NPMplus REST API",
"version": "2.0.0",
"links": [
{
"href": "http://npm.example.com/api",
"rel": "self"
}
],
"properties": {
"tokens": {
"$ref": "endpoints/tokens.json"
},
"users": {
"$ref": "endpoints/users.json"
},
"proxy-hosts": {
"$ref": "endpoints/proxy-hosts.json"
},
"redirection-hosts": {
"$ref": "endpoints/redirection-hosts.json"
},
"dead-hosts": {
"$ref": "endpoints/dead-hosts.json"
},
"streams": {
"$ref": "endpoints/streams.json"
},
"certificates": {
"$ref": "endpoints/certificates.json"
},
"access-lists": {
"$ref": "endpoints/access-lists.json"
},
"settings": {
"$ref": "endpoints/settings.json"
}
}
}

View File

@@ -7,6 +7,13 @@ const authModel = require('./models/auth');
const settingModel = require('./models/setting');
const certbot = require('./lib/certbot');
const proxyModel = require('./models/proxy_host');
const redirectModel = require('./models/redirection_host');
const deadModel = require('./models/dead_host');
const streamModel = require('./models/stream');
const internalNginx = require('./internal/nginx');
const utils = require('./lib/utils');
/**
* Creates a default admin users if one doesn't already exist in the database
*
@@ -73,6 +80,7 @@ const setupDefaultUser = () => {
* @returns {Promise}
*/
const setupDefaultSettings = () => {
let defaultp = process.env.INITIAL_DEFAULT_PAGE || 'congratulations';
return settingModel
.query()
.select(settingModel.raw('COUNT(`id`) as `count`'))
@@ -86,7 +94,7 @@ const setupDefaultSettings = () => {
id: 'default-site',
name: 'Default Site',
description: 'What to show when Nginx is hit with an unknown Host',
value: 'congratulations',
value: defaultp,
meta: {},
})
.then(() => {
@@ -116,10 +124,7 @@ const setupCertbotPlugins = () => {
if (plugins.indexOf(certificate.meta.dns_provider) === -1) {
plugins.push(certificate.meta.dns_provider);
}
const credentialsLocation = '/data/tls/certbot/credentials/credentials-' + certificate.id;
fs.mkdirSync('/data/tls/certbot/credentials', { recursive: true });
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, { mode: 0o600 });
fs.writeFileSync('/tmp/certbot-credentials/credentials-' + certificate.id, certificate.meta.dns_provider_credentials, { mode: 0o600 });
}
});
@@ -134,6 +139,82 @@ const setupCertbotPlugins = () => {
});
};
module.exports = function () {
return setupDefaultUser().then(setupDefaultSettings).then(setupCertbotPlugins);
/**
* regenerate all hosts if needed
*
* @returns {Promise}
*/
const regenerateAllHosts = () => {
if (process.env.REGENERATE_ALL === 'true') {
const promises = [];
promises.push(
proxyModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.then((rows) => {
if (rows && rows.length) {
internalNginx.bulkGenerateConfigs('proxy_host', rows);
}
}),
);
promises.push(
redirectModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.then((rows) => {
if (rows && rows.length) {
internalNginx.bulkGenerateConfigs('redirection_host', rows);
}
}),
);
promises.push(
deadModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.then((rows) => {
if (rows && rows.length) {
internalNginx.bulkGenerateConfigs('dead_host', rows);
}
}),
);
promises.push(
streamModel
.query()
.where('is_deleted', 0)
.andWhere('enabled', 1)
.then((rows) => {
if (rows && rows.length) {
internalNginx.bulkGenerateConfigs('stream', rows);
}
}),
);
promises.push(
settingModel
.query()
.where('id', 'default-site')
.first()
.then((row) => {
internalNginx.generateConfig('default', row);
}),
);
// Execute all promises and then write the hash
return Promise.all(promises).then(() => {
utils.writeHash();
});
}
return Promise.resolve(); // Return resolved promise if REGENERATE_ALL is not true
};
module.exports = function () {
return setupDefaultUser().then(setupDefaultSettings).then(setupCertbotPlugins).then(regenerateAllHosts);
};

View File

@@ -1,24 +1,24 @@
{%- if access_list_id > 0 %}
{%- if access_list.items.length > 0 %}
{% if access_list_id > 0 %}
{% if access_list.items.length > 0 %}
# Authorization
auth_basic "Authorization required";
auth_basic_user_file /data/etc/access/{{ access_list_id }};
{%- unless access_list.pass_auth %}
{% unless access_list.pass_auth %}
proxy_set_header Authorization "";
{%- endunless %}
{%- endif %}
{% endunless %}
{% endif %}
# Access Rules: {{ access_list.clients | size }} total
{%- for client in access_list.clients %}
{% for client in access_list.clients %}
{{client | nginxAccessRule}}
{%- endfor %}
{% endfor %}
deny all;
# Access checks must...
{%- if access_list.satisfy_any %}
{% if access_list.satisfy_any %}
satisfy any;
{%- else %}
{% else %}
satisfy all;
{%- endif %}
{%- endif %}
{% endif %}
{% endif %}

View File

@@ -1,4 +1,4 @@
{%- if http2_support %}
{% if http2_support %}
# Enable Brotli
include conf.d/include/brotli.conf;
{%- endif %}
{% endif %}

View File

@@ -1,14 +1,18 @@
{%- if certificate and certificate_id > 0 %}
{%- if certificate.provider == "letsencrypt" %}
{% if certificate and certificate_id > 0 %}
{% if certificate.provider == "letsencrypt" %}
# Certbot TLS
include conf.d/include/tls-ciphers.conf;
ssl_certificate /data/tls/certbot/live/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/tls/certbot/live/npm-{{ certificate_id }}/privkey.pem;
{% if env.ACME_OCSP_STAPLING == "true" %}
ssl_stapling_file /data/tls/certbot/live/npm-{{ certificate_id }}.der;
{%- else %}
include conf.d/include/tls-ciphers.conf;
{% else %}
include conf.d/include/tls-ciphers-no-stapling.conf;
{% endif %}
{% else %}
# Custom TLS
include conf.d/include/tls-ciphers-no-stapling.conf;
ssl_certificate /data/tls/custom/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/tls/custom/npm-{{ certificate_id }}/privkey.pem;
{%- endif %}
{%- endif %}
{% endif %}
{% endif %}

View File

@@ -1,6 +1,6 @@
{%- if certificate and certificate_id > 0 %}
{%- if ssl_forced %}
{% if certificate and certificate_id > 0 %}
{% if ssl_forced %}
# Force TLS
include conf.d/include/force-tls.conf;
{%- endif %}
{%- endif %}
{% endif %}
{% endif %}

View File

@@ -1,17 +1,7 @@
{%- if certificate and certificate_id > 0 %}
{%- if ssl_forced %}
{%- if hsts_enabled %}
more_clear_headers "Expect-CT";
{% if certificate and certificate_id > 0 %}
{% if ssl_forced %}
{% if hsts_enabled %}
include conf.d/include/hsts.conf;
{%- endif %}
{%- endif %}
{%- endif %}
{%- unless certificate and certificate_id > 0 %}
{%- unless ssl_forced %}
{%- unless hsts_enabled %}
more_clear_headers "Expect-CT";
more_clear_headers "Strict-Transport-Security";
{%- endunless %}
{%- endunless %}
{%- endunless %}
{% endif %}
{% endif %}
{% endif %}

View File

@@ -1,21 +1,24 @@
{% if env.DISABLE_HTTP == "false" %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTP_PORT }};
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTP_PORT }};{% endif %}
{% else %}
listen unix:/run/nginx-{{ id }}.sock;
{% endif %}
listen 80;
listen [::]:80;
{% if certificate and certificate_id > 0 %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTPS_PORT }} ssl;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTPS_PORT }} ssl;{% endif %}
{%- if certificate and certificate_id > 0 %}
listen 443 ssl;
listen [::]:443 ssl;
{% if env.DISABLE_H3_QUIC == "false" %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTPS_PORT }} quic;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTPS_PORT }} quic;{% endif %}
listen 443 quic;
listen [::]:443 quic;
{%- if hsts_subdomains %}
more_set_headers 'Alt-Svc: h3=":443"; ma=86400';
{%- else %}
{% if hsts_subdomains %}
more_set_headers 'Alt-Svc: h3=":{{ env.HTTPS_PORT }}"; ma=86400';
{% else %}
more_clear_headers "Alt-Svc";
http3 off;
{%- endif %}
{%- endif %}
{% endif %}
{% endif %}
{% endif %}
server_name {{ domain_names | join: " " }};

View File

@@ -3,12 +3,12 @@ location {{ path }} {
set $forward_path "{{ forward_path }}";
{%- if allow_websocket_upgrade %}
{% if allow_websocket_upgrade %}
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{%- endif %}
{% endif %}
include conf.d/include/proxy-location.conf;
include conf.d/include/proxy.conf;
proxy_set_header X-Forwarded-Host $host{{ path }};
if ($forward_path = "") {
rewrite ^{{ path }}(/.*)$ $1 break;

View File

@@ -1,28 +1,27 @@
{%- include "_header_comment.conf" %}
{% include "_header_comment.conf" %}
{%- if enabled %}
{% if enabled %}
server {
{%- include "_listen.conf" %}
{%- include "_certificates.conf" %}
{%- include "_hsts.conf" %}
{%- include "_forced_tls.conf" %}
{%- include "_brotli.conf" %}
{% include "_listen.conf" %}
{% include "_certificates.conf" %}
{% include "_hsts.conf" %}
{% include "_forced_tls.conf" %}
{% include "_brotli.conf" %}
include conf.d/include/always.conf;
{{ advanced_config }}
{%- if use_default_location %}
{% if use_default_location %}
location / {
include conf.d/include/always.conf;
root /html/404deadpage;
error_page 404 /404deadpage.html;
try_files $uri =404;
}
{%- endif %}
{% endif %}
# Custom
include /data/nginx_custom/server_dead.conf;
include /data/custom_nginx/server_dead.conf;
}
{%- endif %}
{% endif %}

View File

@@ -2,60 +2,97 @@
# Default Site
# ------------------------------------------------------------
server {
listen 80 default_server;
listen [::]:80 default_server;
{% if env.DISABLE_HTTP == "false" %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTP_PORT }};
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTP_PORT }};{% endif %}
{% endif %}
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
listen {{ env.IPV4_BINDING }}:{{ env.HTTPS_PORT }} ssl;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTPS_PORT }} ssl;{% endif %}
listen 443 quic reuseport default_server;
listen [::]:443 quic reuseport default_server;
more_set_headers 'Alt-Svc: h3=":443"; ma=86400';
server_name _;
{% if env.DISABLE_H3_QUIC == "false" %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTPS_PORT }} quic reuseport;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTPS_PORT }} quic reuseport;{% endif %}
more_set_headers 'Alt-Svc: h3=":{{ env.HTTPS_PORT }}"; ma=86400';
{% else %}
more_clear_headers "Alt-Svc";
http3 off;
{% endif %}
server_name "";
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
include conf.d/include/tls-ciphers-no-stapling.conf;
{%- if value == "404" %}
return 444;
}
server {
{% if env.DISABLE_HTTP == "false" %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTP_PORT }} default_server;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTP_PORT }} default_server;{% endif %}
{% endif %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTPS_PORT }} ssl default_server;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTPS_PORT }} ssl default_server;{% endif %}
{% if env.DISABLE_H3_QUIC == "false" %}
listen {{ env.IPV4_BINDING }}:{{ env.HTTPS_PORT }} quic default_server;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ env.HTTPS_PORT }} quic default_server;{% endif %}
more_set_headers 'Alt-Svc: h3=":{{ env.HTTPS_PORT }}"; ma=86400';
{% else %}
more_clear_headers "Alt-Svc";
http3 off;
{% endif %}
server_name _;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/always.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
include conf.d/include/tls-ciphers-no-stapling.conf;
{% if value == "404" %}
location / {
include conf.d/include/always.conf;
root /html/404deadpage;
error_page 404 /404deadpage.html;
try_files $uri =404;
}
{%- endif %}
{% endif %}
{%- if value == "444" %}
{% if value == "444" %}
return 444;
{%- endif %}
{% endif %}
{%- if value == "redirect" %}
{% if value == "redirect" %}
location / {
include conf.d/include/always.conf;
return 307 {{ meta.redirect }};
}
{%- endif %}
{% endif %}
{%- if value == "congratulations" %}
{% if value == "congratulations" %}
location / {
include conf.d/include/always.conf;
root /html/default;
try_files $uri /index.html;
}
{%- endif %}
{% endif %}
{%- if value == "html" %}
{% if value == "html" %}
location / {
include conf.d/include/always.conf;
root /data/etc/html;
try_files $uri /index.html;
}
{%- endif %}
{% endif %}
}

View File

@@ -1,6 +1,6 @@
{%- for range in ip_ranges %}
{% for range in ip_ranges %}
set_real_ip_from {{ range }};
{%- endfor %}
{% endfor %}
map $http_cf_connecting_ip $real_ip {
"" $http_x_real_ip;

View File

@@ -1,55 +1,56 @@
{%- include "_header_comment.conf" %}
{% include "_header_comment.conf" %}
{%- if enabled %}
{% if enabled %}
server {
set $forward_scheme {{ forward_scheme }};
set $server "{{ forward_host }}";
set $port {{ forward_port }};
{%- include "_listen.conf" %}
{%- include "_certificates.conf" %}
{%- include "_hsts.conf" %}
{%- include "_forced_tls.conf" %}
{%- include "_brotli.conf" %}
{%- include "_access.conf" %}
{% include "_listen.conf" %}
{% include "_certificates.conf" %}
{% include "_hsts.conf" %}
{% include "_forced_tls.conf" %}
{% include "_brotli.conf" %}
{% include "_access.conf" %}
{%- if block_exploits %}
{% if block_exploits %}
modsecurity on;
{%- if caching_enabled %}
{% if caching_enabled %}
modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity-crs.conf;
{%- else %}
{% else %}
modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity.conf;
{%- endif %}
{%- endif %}
{% endif %}
{% endif %}
include conf.d/include/always.conf;
{%- if access_list_id > 0 %}
{%- if access_list.items.length > 0 %}
{% if access_list_id > 0 %}
{% if access_list.items.length > 0 %}
{{ access_list.passauth }}
{%- endif %}
{%- endif %}
{% endif %}
{% endif %}
{{ advanced_config }}
# custom locations
{{ locations }}
{%- if use_default_location %}
{% if use_default_location %}
location / {
include conf.d/include/always.conf;
{%- if allow_websocket_upgrade %}
{% if allow_websocket_upgrade %}
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{%- endif %}
{% endif %}
# Proxy!
include conf.d/include/proxy.conf;
proxy_pass $forward_scheme://$server:$port$request_uri;
}
{%- endif %}
{% endif %}
# Custom
include /data/nginx_custom/server_proxy.conf;
include /data/custom_nginx/server_proxy.conf;
}
{%- endif %}
{% endif %}

View File

@@ -1,29 +1,29 @@
{%- include "_header_comment.conf" %}
{% include "_header_comment.conf" %}
{%- if enabled %}
{% if enabled %}
server {
{%- include "_listen.conf" %}
{%- include "_certificates.conf" %}
{%- include "_hsts.conf" %}
{%- include "_forced_tls.conf" %}
{%- include "_brotli.conf" %}
{% include "_listen.conf" %}
{% include "_certificates.conf" %}
{% include "_hsts.conf" %}
{% include "_forced_tls.conf" %}
{% include "_brotli.conf" %}
include conf.d/include/always.conf;
{{ advanced_config }}
{%- if use_default_location %}
{% if use_default_location %}
location / {
include conf.d/include/always.conf;
{%- if preserve_path %}
{% if preserve_path %}
return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}$request_uri;
{%- else %}
{% else %}
return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }};
{%- endif %}
{% endif %}
}
{%- endif %}
{% endif %}
# Custom
include /data/nginx_custom/server_redirect.conf;
include /data/custom_nginx/server_redirect.conf;
}
{%- endif %}
{% endif %}

View File

@@ -2,31 +2,31 @@
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
# ------------------------------------------------------------
{%- if enabled %}
{% if enabled %}
{%- if tcp_forwarding %}
{% if tcp_forwarding %}
server {
listen {{ incoming_port }};
listen [::]:{{ incoming_port }};
listen {{ env.IPV4_BINDING }}:{{ incoming_port }};
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ incoming_port }};{% endif %}
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
# Custom
include /data/nginx_custom/server_stream.conf;
include /data/nginx_custom/server_stream_tcp.conf;
include /data/custom_nginx/server_stream.conf;
include /data/custom_nginx/server_stream_tcp.conf;
}
{%- endif %}
{% endif %}
{%- if udp_forwarding %}
{% if udp_forwarding %}
server {
listen {{ incoming_port }} udp;
listen [::]:{{ incoming_port }} udp;
listen {{ env.IPV4_BINDING }}:{{ incoming_port }} udp;
{% if env.DISABLE_IPV6 == "false" %}listen {{ env.IPV6_BINDING }}:{{ incoming_port }} udp;{% endif %}
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
# Custom
include /data/nginx_custom/server_stream.conf;
include /data/nginx_custom/server_stream_udp.conf;
include /data/custom_nginx/server_stream.conf;
include /data/custom_nginx/server_stream_udp.conf;
}
{%- endif %}
{% endif %}
{%- endif %}
{% endif %}

View File

@@ -4,22 +4,25 @@ services:
image: zoeyvid/npmplus
restart: always
network_mode: host
# privileged: true # required if you set NGINX_QUIC_BPF to true
volumes:
- "/opt/npm:/data"
# - "/var/www:/var/www" # optional, if you want to use it as webserver for html/php
# - "/opt/npm-letsencrypt:/etc/letsencrypt" # Only needed for first time migration from original nginx-proxy-manager to this fork
environment:
- "TZ=your-timezone" # set timezone, required, set it to one of the values from the "TZ identifier" https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
- "ACME_EMAIL=your-email" # email address which should be used for acme, currently optional, may be required in the future, so I recommend you to enter your email here
# - "ACME_SERVER=https://dv.acme-v02.api.pki.goog/directory" # acme server to used when requesting/renewing certs using certbot, default is (currently, may change later) set to: https://acme-v02.api.letsencrypt.org/directory (letsencrypt)
# - "ACME_EAB_KID=123456789abcdef" # Key Identifier for External Account Binding for the acme server
# - "ACME_EAB_HMAC_KEY=123456789abcdef" # HMAC key for External Account Binding for the acme server
# - "ACME_MUST_STAPLE=false" # enables must-staple, default true (will change soon, see https://github.com/ZoeyVid/NPMplus/discussions/1285), I recommend you to enable this if your CA supports it
- "ACME_EMAIL=your-email" # email address which should be used for acme, currently optional, may be required in the future, so I recommend you to enter your email here, optional for letsencrypt, but required for zerossl and google public ca
# - "ACME_SERVER=https://dv.acme-v02.api.pki.goog/directory (google public ca) / https://acme.zerossl.com/v2/DV90 (zerossl)" # acme server used when requesting/renewing certs using certbot, default is set to: https://acme-v02.api.letsencrypt.org/directory (letsencrypt)
# - "ACME_EAB_KID=123456789abcdef" # Key Identifier for External Account Binding for the acme server, not supported by letsencrypt, optional for zerossl (Login on theier site => Developer), but required for google public ca: https://cloud.google.com/certificate-manager/docs/public-ca-tutorial?hl=de#request-key-hmac
# - "ACME_EAB_HMAC_KEY=123456789abcdef" # HMAC key for External Account Binding for the acme server, not supported by letsencrypt, optional for zerossl (Login on theier site => Developer), but required for google public ca: https://cloud.google.com/certificate-manager/docs/public-ca-tutorial?hl=de#request-key-hmac
# - "ACME_MUST_STAPLE=true" # enables must-staple, default false, I recommend you to enable this if your CA supports it, supported by zerossl, google public ca ignores this, unsupported by letsencrypt (will fail)
# not released # - "ACME_OCSP_STAPLING=true" # enables ocsp stapling, default false, I recommend you to enable this if your CA supports it, supported by zerossl and google public ca, unsupported by letsencrypt (will create warning in your log)
# not released # - "ACME_KEY_TYPE=rsa" # which key type to use ecdsa or rsa, default and recommended: ecdsa
# - "ACME_SERVER_TLS_VERIFY=false" # enables checking if ACME_SERVER has a valid TLS cert, default true
# - "PUID=1000" # set group id, default 0 (root)
# - "PGID=1000" # set user id, default 0 (root), requires PUID
# - "NIBEP=48694" # internal port of the NPMplus API, always bound to 127.0.0.1, default 48693, you need to change it, if you want to run multiple npm instances in network mode host
# - "GOAIWSP=48684" # internal port of goaccess, always bound to 127.0.0.1, default 48683, you need to change it, if you want to run multiple npm with goaccess instances in network mode host
# - "NIBEP=48684" # internal port of the NPMplus API, always bound to 127.0.0.1, default 48683, you need to change it, if you want to run multiple npm instances in network mode host
# - "GOAIWSP=48694" # internal port of goaccess, always bound to 127.0.0.1, default 48693, you need to change it, if you want to run multiple npm with goaccess instances in network mode host
# - "NPM_PORT=82" # Port the NPM UI should be bound to, default 81, you need to change it, if you want to run multiple npm instances in network mode host
# - "GOA_PORT=92" # Port the goaccess should be bound to, default 91, you need to change it, if you want to run multiple npm with goaccess instances in network mode host
# - "IPV4_BINDING=127.0.0.1" # IPv4 address to bind, defaults to all
@@ -28,16 +31,19 @@ services:
# - "IPV6_BINDING=[::1]" # IPv6 address to bind, defaults to all
# - "NPM_IPV6_BINDING=[::1]" # IPv6 address to bind for the NPM UI, defaults to all
# - "GOA_IPV6_BINDING=[::1]" # IPv6 address to bind for goaccess, defaults to all
# - "DISABLE_IPV6=true" # disable IPv6 and IPv6 resolver of nginx, overrides with IPV6_BINDING, default false
# - "NPM_DISABLE_IPV6=true" # disable IPv6 for the NPM UI, overrides NPM_IPV6_BINDING, default false
# - "GOA_DISABLE_IPV6=true" # disable IPv6 for goaccess, overrides GOA_IPV6_BINDING, default false
# - "DISABLE_IPV6=true" # fully disables listing on IPv6 and the IPv6 resolver of nginx, overrides IPV6_BINDING/NPM_IPV6_BINDING/GOA_IPV6_BINDING, default false
# - "NPM_LISTEN_LOCALHOST=true" # Binds the NPM UI only to localhost, overrides NPM_IPV4_BINDING/NPM_IPV6_BINDING, default false
# - "GOA_LISTEN_LOCALHOST=true" # Binds goaccess only to localhost, overrides NPM_IPV4_BINDING/NPM_IPV6_BINDING, default false
# - "DEFAULT_CERT_ID=1" # ID of cert, which should be used instead of dummycerts, default 0/unset/dummycerts
# not released # - "HTTP_PORT=8080" # tcp port to use for http traffic, default 80
# not released # - "HTTPS_PORT=8443" # udp and tcp port to use for https traffic, this also needs to be changed if you don't use network_mode host to keep http3/quic working, default 443
# - "DISABLE_HTTP=true" # disables nginx to listen on port 80, default false
# - "DISABLE_H3_QUIC=true" # disables nginx to listen on port 443 udp for default and your hosts, this will disable HTTP/3 and QUIC, default false
# - "DISABLE_H3_QUIC=true" # disables nginx to listen on port 443 udp for default and your hosts, this will fully disable HTTP/3 and QUIC, even if you enable it inside the UI, not recommended, default false
# not released # - "NGINX_QUIC_BPF=true" # enables nginxs quic_bpf (https://nginx.org/en/docs/http/ngx_http_v3_module.html#quic_bpf), you also need to to give the NPMplus container privileged permissions to use this, default false
# - "NGINX_LOG_NOT_FOUND=true" # Allow logging of 404 errors, default false
# - "NGINX_404_REDIRECT=true" # Redirect to / instead of showing a 404 error page, default false
# not released # - "NGINX_HSTS_SUBDMAINS=false" # when enabling security headers, also enable hsts for subdomains, default true
# not released # - "X_FRAME_OPTIONS=sameorigin" # value to use for the X-Frame-Options header when enabling security headers, valid is deny, sameorigin and none (means unset), default deny, since this applies to all hosts I recommend you to instead keep the default and only change it for hosts which need it using the advanced config and more_set_headers
# - "NGINX_DISABLE_PROXY_BUFFERING=true" # Disables the proxy_buffering/proxy_request_buffering options of nginx, default false, may not work if you use crowdsec/appsec
# - "DISABLE_NGINX_BEAUTIFIER=true" # disables nginxbeautifier, useful when it fails parsing non-standard configs, default false
# - "CLEAN=false" # Clean folders, default true
@@ -50,12 +56,15 @@ services:
# - "GOA=true" # Enables goaccess, requires LOGROTATE, default false --- if you download the GeoLite2-Country.mmdb, GeoLite2-City.mmdb AND GeoLite2-ASN.mmdb file from MaxMind and place them in /opt/npm/etc/goaccess/geoip it will automatically enable GeoIP in goaccess after restarting NPMplus (no need to change GOACLA below), you may also deploy the compose.geoip.yaml (please change the timezone)
# - "GOACLA=--agent-list --real-os --double-decode --anonymize-ip --anonymize-level=2 --keep-last=7 --with-output-resolver --no-query-string" # Arguments that should be passed to goaccess, default: https://github.com/ZoeyVid/NPMplus/blob/develop/rootfs/usr/local/bin/launch.sh#L50 and: --agent-list --real-os --double-decode --anonymize-ip --anonymize-level=1 --keep-last=30 --with-output-resolver --no-query-string
# - "PHP82=true" # Activate PHP82, default false
# - "PHP82_APKS=php82-curl php82-openssl" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.20&repo=community&arch=x86_64&name=php82-*, default none, requires PHP82
# - "PHP82_APKS=php82-curl php82-openssl" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.21&repo=community&arch=x86_64&name=php82-*, default none, requires PHP82
# - "PHP83=true" # Activate PHP83, default false
# - "PHP83_APKS=php83-curl php83-openssl" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.20&repo=community&arch=x86_64&name=php83-*, default none, requires PHP83
# - "PHP_APKS=php-pecl-apcu php-pecl-redis" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.20&repo=community&arch=x86_64&name=php-*, default none, requires PHP82 and/or PHP83, not recommended, please use PHP82_APKS or PHP83_APKS
# - "PHP83_APKS=php83-curl php83-openssl" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.21&repo=community&arch=x86_64&name=php83-*, default none, requires PHP83
# not released # - "PHP84=true" # Activate PHP84, default false
# not released # - "PHP84_APKS=php84-curl php84-openssl" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.21&repo=community&arch=x86_64&name=php84-*, default none, requires PHP84
# - "PHP_APKS=php-pecl-apcu php-pecl-redis" # Add php extensions, see available packages here: https://pkgs.alpinelinux.org/packages?branch=v3.21&repo=community&arch=x86_64&name=php-*, default none, requires PHP82, PHP83 and/or PHP84, not recommended, please use PHP82_APKS, PHP83_APKS or PHP84_APKS
# - "INITIAL_ADMIN_EMAIL=initial-email" # email to use instead of admin@example.org on first start of NPMplus for the initial user
# - "INITIAL_ADMIN_PASSWORD=initial-password" # password to use instead of the one in the README.md on first start of NPMplus for the initial user
# - "INITIAL_ADMIN_PASSWORD=initial-password" # password to use instead of iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi on first start of NPMplus for the initial user
# - "INITIAL_DEFAULT_PAGE=444" # default page to set on first start of NPMplus for the initial user, default congratulations, can be one of: 404, 444, redirect, congratulations or html
# This can be used with DISABLE_HTTP=true, to force HTTPS redirects for every host
# npmplus-caddy:

View File

@@ -198,10 +198,6 @@ function DownloadFile(verb, path, filename) {
}
module.exports = {
status: function () {
return fetch('get', '');
},
Tokens: {
/**

View File

@@ -2,8 +2,7 @@ const UserModel = require('../models/user');
let cache = {
User: new UserModel.Model(),
locale: navigator.languages[0].toLowerCase(),
version: null
locale: navigator.languages[0].toLowerCase()
};
module.exports = cache;

View File

@@ -50,7 +50,8 @@ module.exports = Mn.View.extend({
onRender: function () {
let view = this;
Api.Reports.getHostStats()
if (typeof view.stats.hosts === 'undefined') {
Api.Reports.getHostStats()
.then(response => {
if (!view.isDestroyed()) {
view.stats.hosts = response;
@@ -60,6 +61,7 @@ module.exports = Mn.View.extend({
.catch(err => {
console.log(err);
});
}
},
/**

View File

@@ -31,11 +31,7 @@ const App = Mn.Application.extend({
}
// Check if we are still logged in by refreshing the token
Api.status()
.then(result => {
Cache.version = [result.version.major, result.version.minor, result.version.revision].join('.');
})
.then(Api.Tokens.refresh)
Api.Tokens.refresh()
.then(this.bootstrap)
.then(() => {
console.info(i18n('main', 'logged-in', Cache.User.attributes));
@@ -106,14 +102,7 @@ const App = Mn.Application.extend({
*/
bootstrapTimer: function () {
setTimeout(() => {
Api.status()
.then(result => {
let version = [result.version.major, result.version.minor, result.version.revision].join('.');
if (version !== Cache.version) {
document.location.reload();
}
})
.then(this.bootstrap)
this.bootstrap()
.then(() => {
this.bootstrapTimer();
})

View File

@@ -132,7 +132,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required<%- getLetsencryptAgree() ? ' checked' : '' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository'}) %> <span class="form-required">*</span></span>
</label>
</div>
</div>

View File

@@ -272,7 +272,7 @@ module.exports = Mn.View.extend({
text: input
};
},
createFilter: /^(?:\*\.)?(?:[^.*]+\.?)+[^.]$/
createFilter: /^([^.]+\.)+[^.]+$/
});
this.ui.dns_challenge_content.hide();
this.ui.credentials_file_content.hide();

View File

@@ -180,7 +180,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required disabled>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository'}) %> <span class="form-required">*</span></span>
</label>
</div>
</div>

View File

@@ -45,7 +45,6 @@ module.exports = Mn.View.extend({
this.ui.letsencrypt.hide().find('input').prop('disabled', true);
}
let enabled = id === 'new' || parseInt(id, 10) > 0;
let inputs = this.ui.ssl_forced.add(this.ui.hsts_subdomains);
@@ -71,8 +70,6 @@ module.exports = Mn.View.extend({
if (!checked) {
this.ui.hsts_enabled.prop('checked', false);
}
this.ui.hsts_enabled.trigger('change');
},
'change @ui.dns_challenge_switch': function () {
@@ -228,7 +225,7 @@ module.exports = Mn.View.extend({
text: input
};
},
createFilter: /^(?:\*\.)?(?:[^.*]+\.?)+[^.]$/
createFilter: /^(([^.]+\.)+[^.]+)|(\[[0-9a-f:]+\])$/
});
// Certificates

View File

@@ -75,7 +75,7 @@
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="caching_enabled" value="1"<%- caching_enabled ? ' checked' : '' %>>
<input type="checkbox" class="custom-switch-input" name="caching_enabled" value="1"<%- caching_enabled ? ' checked' : '' %><%- block_exploits ? '' : ' disabled' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'enable-crs') %></span>
</label>
@@ -248,7 +248,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required disabled>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository'}) %> <span class="form-required">*</span></span>
</label>
</div>
</div>
@@ -269,7 +269,7 @@
<label class="form-label"><%- i18n('all-hosts', 'advanced-config') %></label>
<textarea name="advanced_config" rows="8" class="form-control text-monospace" placeholder="# <%- i18n('all-hosts', 'advanced-warning') %>"><%- advanced_config %></textarea>
</div>
<p class="small text-gray"><i class="fe fe-alert-triangle"></i> <%- i18n('all-hosts', 'advanced-config-header-info') %></p>
<p class="small text-gray"><i class="fe fe-alert-triangle"></i> <%- i18n('all-hosts', 'advanced-config-header-info', {url: 'https://github.com/openresty/headers-more-nginx-module?tab=readme-ov-file#more_set_headers'}) %></p>
</div>
</div>
</div>

View File

@@ -24,6 +24,8 @@ module.exports = Mn.View.extend({
form: 'form',
domain_names: 'input[name="domain_names"]',
forward_host: 'input[name="forward_host"]',
block_exploits: 'input[name="block_exploits"]',
caching_enabled: 'input[name="caching_enabled"]',
buttons: '.modal-footer button',
cancel: 'button.cancel',
save: 'button.save',
@@ -51,6 +53,18 @@ module.exports = Mn.View.extend({
},
events: {
'change @ui.block_exploits': function () {
let checked = this.ui.block_exploits.prop('checked');
this.ui.caching_enabled
.prop('disabled', !checked)
.parents('.form-group')
.css('opacity', checked ? 1 : 0.5);
if (!checked) {
this.ui.caching_enabled.prop('checked', false);
}
},
'change @ui.certificate_select': function () {
let id = this.ui.certificate_select.val();
if (id === 'new') {
@@ -85,8 +99,6 @@ module.exports = Mn.View.extend({
if (!checked) {
this.ui.hsts_enabled.prop('checked', false);
}
this.ui.hsts_enabled.trigger('change');
},
'change @ui.dns_challenge_switch': function () {
@@ -252,8 +264,7 @@ module.exports = Mn.View.extend({
onRender: function () {
let view = this;
this.ui.ssl_forced.trigger('change');
this.ui.hsts_enabled.trigger('change');
this.ui.block_exploits.trigger('change');
// Domain names
this.ui.domain_names.selectize({
@@ -266,7 +277,7 @@ module.exports = Mn.View.extend({
text: input
};
},
createFilter: /^(?:\*\.)?(?:[^.*]+\.?)+[^.]$/
createFilter: /^(([^.]+\.)+[^.]+)|(\[[0-9a-f:]+\])$/
});
// Access Lists

View File

@@ -229,7 +229,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required disabled>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
<span class="custom-switch-description"><%= i18n('tls', 'certbot-agree', {url: 'https://letsencrypt.org/repository'}) %> <span class="form-required">*</span></span>
</label>
</div>
</div>

View File

@@ -71,8 +71,6 @@ module.exports = Mn.View.extend({
if (!checked) {
this.ui.hsts_enabled.prop('checked', false);
}
this.ui.hsts_enabled.trigger('change');
},
'change @ui.dns_challenge_switch': function () {
@@ -230,7 +228,7 @@ module.exports = Mn.View.extend({
text: input
};
},
createFilter: /^(?:\*\.)?(?:[^.*]+\.?)+[^.]$/
createFilter: /^(([^.]+\.)+[^.]+)|(\[[0-9a-f:]+\])$/
});
// Certificates

View File

@@ -21,7 +21,7 @@
<div class="col-sm-4 col-md-4">
<div class="form-group">
<label class="form-label"><%- i18n('streams', 'forwarding-port') %> <span class="form-required">*</span></label>
<input name="forwarding_port" type="number" class="form-control text-monospace" placeholder="eg: 80" min="1" max="65535" value="<%- forwarding_port %>" required>
<input name="forwarding_port" type="text" class="form-control text-monospace" placeholder="eg: 80 or $server_port" value="<%- forwarding_port %>" autocomplete="off" maxlength="12" required>
</div>
</div>
<div class="col-sm-6 col-md-6">

View File

@@ -4,11 +4,5 @@ const Cache = require('../../cache');
module.exports = Mn.View.extend({
className: 'container',
template: template,
templateContext: {
getVersion: function () {
return Cache.version || '0.0.0';
}
}
template: template
});

View File

@@ -27,7 +27,7 @@
"all-hosts": {
"advanced": "Erweitert",
"advanced-config": "Individuelle Nginx-Konfiguration",
"advanced-config-header-info": "Bitte beachten Sie, dass das Hinzufügen eines Pfads '/' die Proxy-Konfiguration überschreibt",
"advanced-config-header-info": "Bitte beachten Sie, dass das Hinzufügen eines Pfads '/' die Proxy-Konfiguration überschreibt. Wenn Header gesetzt werden sollen, wird empfohlen <a href=\"{url}\" target=\"_blank\">more_set_headers</a> zu nutzen.",
"advanced-config-var-headline": "Diese Proxy-Details sind als nginx-Variablen verfügbar:",
"advanced-warning": "Geben Sie hier Ihre eigene Nginx-Konfiguration ein - auf eigenes Risiko!",
"cert-provider": "Zertifikat-Anbieter",
@@ -35,7 +35,7 @@
"domain-names": "Domain-Namen",
"empty-subtitle": "{manage, select, true{Warum erstellen Sie keinen?} other{Und Sie haben nicht die Erlaubnis, einen zu erstellen.}}",
"enable-brotli": "Brotli einschalten",
"enable-crs": "CoreRuleSet aktivieren (Erfordert ModSecurity)",
"enable-crs": "CoreRuleSet aktivieren",
"enable-hsts": "Aktivieren Sie HSTS und Sicherheits-Header",
"enable-http3": "Aktiviere HTTP/3-Quic",
"enable-modsec": "ModSecurity einschalten",

View File

@@ -27,7 +27,7 @@
"all-hosts": {
"advanced": "Advanced",
"advanced-config": "Custom Nginx Configuration",
"advanced-config-header-info": "Please note, adding a location '/' will overwrite the proxy configuration",
"advanced-config-header-info": "Please note, adding a location '/' will overwrite the proxy configuration. If you want to set headers I recommend you to use <a href=\"{url}\" target=\"_blank\">more_set_headers</a>",
"advanced-config-var-headline": "These proxy details are available as nginx variables:",
"advanced-warning": "Enter your custom Nginx configuration here at your own risk!",
"cert-provider": "Certificate Provider",
@@ -35,7 +35,7 @@
"domain-names": "Domain Names",
"empty-subtitle": "{manage, select, true{Why don't you create one?} other{And you don't have permission to create one.}}",
"enable-brotli": "Enable Brotli",
"enable-crs": "Enable CoreRuleSet (Requires ModSecurity)",
"enable-crs": "Enable CoreRuleSet",
"enable-hsts": "Enable HSTS and security headers",
"enable-http3": "Enable HTTP/3-Quic",
"enable-modsec": "Enable ModSecurity",

View File

@@ -34,9 +34,6 @@ module.exports = Mn.View.extend({
},
templateContext: {
i18n: i18n,
getVersion: function () {
return $('#login').data('version');
}
i18n: i18n
}
});

View File

@@ -1,83 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Dead Host</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<style>
@media (prefers-color-scheme: dark) {
body {
background-color: rgb(17 24 39);
color: white;
}
#box {
background-color: rgb(31 41 55);
}
}
@media (prefers-color-scheme: light) {
body {
background-color: white;
color: black;
}
#box {
background-color: rgb(229 231 235);
}
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
text-align: center;
}
#box {
border-radius: 2rem;
position: absolute;
padding: 1rem;
padding-right: 5rem;
padding-left: 5rem;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
h1 {
font-size: 64px;
}
p {
font-size: 24px;
}
#notice {
font-size: 12px;
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
}
@media (max-width: 600px) {
h1 {
font-size: 32px;
}
p {
font-size: 16px;
}
#box {
padding-right: 2rem;
padding-left: 2rem;
}
}
</style>
<div id="box">
<h1>Dead Host</h1>
</div>
</body>
</html>

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env sh
if [ "$NC_AIO" = "true" ] && [ ! -f /data/etc/aio.lock ]; then
while [ "$(healthcheck.sh)" != "OK" ]; do sleep 10s; done

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env sh
if [ -n "$(ls -A /data/etc/prerun 2> /dev/null)" ]; then
for script in /data/etc/prerun/*.sh; do

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env sh
export HCNPM_IP="$NPM_IPV4_BINDING"
export HCGOA_IP="$GOA_IPV4_BINDING"

View File

@@ -1,15 +1,7 @@
#!/bin/sh
#!/usr/bin/env sh
echo "
-------------------------------------
_ _ ___ __ __ _
| \ || . \| \ \ ___ | | _ _ ___
| || _/| || . \| || | |[_-[
|_\_||_| |_|_|_|| _/|_| \__|/__/
|_|
-------------------------------------
Version: $(jq -r .version /app/package.json)
Date: $(date)
User: $(whoami)
PUID: $PUID
User ID: $(id -u)
@@ -36,6 +28,13 @@ if [ "$PHP83" = "true" ]; then
fi
fi
if [ "$PHP84" = "true" ]; then
if ! PHP_INI_SCAN_DIR=/data/php/84/conf.d php-fpm84 -c /data/php/84 -y /data/php/84/php-fpm.conf -FORt > /dev/null 2>&1; then
PHP_INI_SCAN_DIR=/data/php/84/conf.d php-fpm84 -c /data/php/84 -y /data/php/84/php-fpm.conf -FORt
sleep inf
fi
fi
if [ "$(echo "$ACME_SERVER" | sed "s|^https\?://\([^/]\+\).*$|\1|g")" = "acme.zerossl.com" ] && [ -z "$ACME_EAB_KID" ] && [ -z "$ACME_EAB_HMAC_KEY" ]; then
if [ -z "$ACME_EMAIL" ]; then
@@ -70,10 +69,18 @@ if [ ! -d /data/tls/certbot/accounts/"$(echo "$ACME_SERVER" | sed "s|^https\?://
fi
fi
if [ "$ACME_OCSP_STAPLING" = "true" ]; then
rm -vf /data/tls/certbot/live/npm-*.der
certbot-ocsp-fetcher.sh -c /data/tls/certbot -o /data/tls/certbot/live --no-reload-webserver || true
else
rm -vf /data/tls/certbot/live/npm-*.der
fi
touch /data/etc/logrotate.lock
echo "Starting services..."
if [ "$PHP82" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FOR; fi &
if [ "$PHP83" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/83/conf.d php-fpm83 -c /data/php/83 -y /data/php/83/php-fpm.conf -FOR; fi &
if [ "$PHP84" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/84/conf.d php-fpm84 -c /data/php/84 -y /data/php/84/php-fpm.conf -FOR; fi &
if [ "$LOGROTATE" = "true" ]; then while true; do touch /data/etc/logrotate.lock; logrotate --verbose --state /data/etc/logrotate.state /etc/logrotate; rm /data/etc/logrotate.lock; sleep 25h; done; fi &
# shellcheck disable=SC2086
if [ "$GOA" = "true" ]; then while true; do if [ -f /data/nginx/access.log ] && [ ! -f /data/etc/logrotate.lock ]; then goaccess --no-global-config --num-tests=0 --tz="$TZ" --date-format="%d/%b/%Y" --time-format="%H:%M:%S" --log-format='[%d:%t %^] %v %h %T "%r" %s %b %b %R %u' --no-ip-validation \

View File

@@ -1,16 +1,29 @@
#!/bin/sh
#!/usr/bin/env sh
echo "
-------------------------------------
_ _ ___ __ __ _
| \ || . \| \ \ ___ | | _ _ ___
| || _/| || . \| || | |[_-[
|_\_||_| |_|_|_|| _/|_| \__|/__/
|_|
-------------------------------------
Version: $(jq -r .version /app/package.json)
Date: $(date)
-------------------------------------
"
if [ "$(whoami)" != "root" ] || [ "$(id -u)" != "0" ] || [ "$(id -g)" != "0" ]; then
echo '--------------------------------------'
echo "-----------------------------------------------------------------"
echo "This docker container must be run as root, do not specify a user."
echo '--------------------------------------'
echo "-----------------------------------------------------------------"
sleep inf
fi
if [ ! -d /data ]; then
echo '--------------------------------------'
echo "/data is not mounted! Check your docker configuration."
echo '--------------------------------------'
echo "----------------------------------------------"
echo "/data is not mounted! Check your compose.yaml."
echo "----------------------------------------------"
sleep inf
fi
@@ -18,9 +31,23 @@ fi
touch /data/.env
. /data/.env
if [ -s /tmp/env.sha512sum ] && [ "$(cat /tmp/env.sha512sum)" != "$(sha512sum < /data/.env)" ]; then
echo "You need to recreate the NPMplus container after changing the .env file, restart is not supported"
sleep inf
fi
if [ -n "$NPM_CERT_ID" ]; then
echo "NPM_CERT_ID env is replaced by DEFAULT_CERT_ID, please change it to DEFAULT_CERT_ID"
sha512sum < /data/.env > /tmp/env.sha512sum
#tmp
if [ -n "$NPM_DISABLE_IPV6" ]; then
echo "NPM_DISABLE_IPV6 env is not supported. DISABLE_IPV6 will also disable IPv6 for the NPMplus web UI."
sleep inf
fi
#tmp
if [ -n "$GOA_DISABLE_IPV6" ]; then
echo "GOA_DISABLE_IPV6 env is not supported. DISABLE_IPV6 will also disable IPv6 for goaccess."
sleep inf
fi
@@ -29,30 +56,13 @@ if [ -n "$LE_SERVER" ]; then
sleep inf
fi
if [ -n "$DEBUG" ]; then
echo "DEBUG env is unsopported."
sleep inf
fi
if [ -n "$X_FRAME_OPTIONS" ]; then
echo "X_FRAME_OPTIONS env is unsopported."
sleep inf
fi
if [ -n "$LE_STAGING" ]; then
echo "LE_STAGING env is unsopported, please use ACME_SERVER."
echo "LE_STAGING env is not supported, please use ACME_SERVER."
sleep inf
fi
if [ -n "$PHP81" ]; then
find /data/nginx -type f -name '*.conf' -exec sed -i "s|fastcgi_pass php81;|fastcgi_pass php82;|g" {} \;
echo "PHP81 was removed, please use PHP82 or PHP83"
sleep inf
fi
if [ -n "$PHP81_APKS" ]; then
find /data/nginx -type f -name '*.conf' -exec sed -i "s|fastcgi_pass php81;|fastcgi_pass php82;|g" {} \;
echo "PHP81_APKS was removed, please use PHP82_APKS or PHP83_APKS"
if [ -n "$DEBUG" ]; then
echo "DEBUG env is not supported."
sleep inf
fi
@@ -83,6 +93,16 @@ if ! echo "$ACME_MUST_STAPLE" | grep -q "^true$\|^false$"; then
sleep inf
fi
if ! echo "$ACME_OCSP_STAPLING" | grep -q "^true$\|^false$"; then
echo "ACME_OCSP_STAPLING needs to be true or false."
sleep inf
fi
if ! echo "$ACME_KEY_TYPE" | grep -q "^ecdsa$\|^rsa$"; then
echo "ACME_KEY_TYPE needs to be ecdsa or rsa."
sleep inf
fi
if ! echo "$ACME_SERVER_TLS_VERIFY" | grep -q "^true$\|^false$"; then
echo "ACME_SERVER_TLS_VERIFY needs to be true or false."
sleep inf
@@ -90,12 +110,22 @@ fi
if ! echo "$PUID" | grep -q "^[0-9]\+$"; then
echo "PUID needs to be a number."
echo "PUID needs to be a number greater or equal to 1000, or equal to 0."
sleep inf
fi
if [ "$PUID" -lt "1000" ] && [ "$PUID" != "0" ]; then
echo "PUID needs to be a number greater or equal to 1000, or equal to 0."
sleep inf
fi
if ! echo "$PGID" | grep -q "^[0-9]\+$"; then
echo "PGID needs to be a number."
echo "PGID needs to be a number greater or equal to 1000, or equal to 0."
sleep inf
fi
if [ "$PGID" -lt "1000" ] && [ "$PGID" != "0" ]; then
echo "PGID needs to be a number greater or equal to 1000, or equal to 0."
sleep inf
fi
@@ -104,6 +134,10 @@ if [ "$PGID" != "0" ] && [ "$PUID" = "0" ]; then
sleep inf
fi
if [ "$PGID" = "0" ] && [ "$PUID" != "0" ]; then
echo "You've set PUID but not PGID. Are you sure that this is what you wanted?"
fi
if ! echo "$NIBEP" | grep -q "^[0-9]\+$"; then
echo "NIBEP needs to be a number."
@@ -149,17 +183,33 @@ if [ "$GOA_LISTEN_LOCALHOST" = "true" ]; then
fi
if ! echo "$IPV4_BINDING" | grep -q "^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$"; then
if ! echo "$HTTP_PORT" | grep -q "^[0-9]\+$"; then
echo "HTTP_PORT needs to be a number."
sleep inf
fi
if ! echo "$HTTPS_PORT" | grep -q "^[0-9]\+$"; then
echo "HTTPS_PORT needs to be a number."
sleep inf
fi
if [ "$HTTP_PORT" = "$HTTPS_PORT" ] && [ "$DISABLE_HTTP" = "false" ]; then
echo "HTTP_PORT and HTTPS_PORT need to be different."
sleep inf
fi
if ! echo "$IPV4_BINDING" | grep -q "^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$"; then
echo "IPV4_BINDING needs to be a IPv4-Address: four blocks of numbers separated by dots."
sleep inf
fi
if ! echo "$NPM_IPV4_BINDING" | grep -q "^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$"; then
if ! echo "$NPM_IPV4_BINDING" | grep -q "^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$"; then
echo "NPM_IPV4_BINDING needs to be a IPv4-Address: four blocks of numbers separated by dots."
sleep inf
fi
if ! echo "$GOA_IPV4_BINDING" | grep -q "^[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+$"; then
if ! echo "$GOA_IPV4_BINDING" | grep -q "^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$"; then
echo "GOA_IPV4_BINDING needs to be a IPv4-Address: four blocks of numbers separated by dots."
sleep inf
fi
@@ -185,16 +235,6 @@ if ! echo "$DISABLE_IPV6" | grep -q "^true$\|^false$"; then
sleep inf
fi
if ! echo "$NPM_DISABLE_IPV6" | grep -q "^true$\|^false$"; then
echo "NPM_DISABLE_IPV6 needs to be true or false."
sleep inf
fi
if ! echo "$GOA_DISABLE_IPV6" | grep -q "^true$\|^false$"; then
echo "GOA_DISABLE_IPV6 needs to be true or false."
sleep inf
fi
if ! echo "$DEFAULT_CERT_ID" | grep -q "^[0-9]\+$"; then
echo "DEFAULT_CERT_ID needs to be a number."
@@ -211,6 +251,11 @@ if ! echo "$DISABLE_H3_QUIC" | grep -q "^true$\|^false$"; then
sleep inf
fi
if ! echo "$NGINX_QUIC_BPF" | grep -q "^true$\|^false$"; then
echo "NGINX_QUIC_BPF needs to be true or false."
sleep inf
fi
if ! echo "$NGINX_LOG_NOT_FOUND" | grep -q "^true$\|^false$"; then
echo "NGINX_LOG_NOT_FOUND needs to be true or false."
sleep inf
@@ -221,6 +266,16 @@ if ! echo "$NGINX_404_REDIRECT" | grep -q "^true$\|^false$"; then
sleep inf
fi
if ! echo "$NGINX_HSTS_SUBDMAINS" | grep -q "^true$\|^false$"; then
echo "NGINX_HSTS_SUBDMAINS needs to be true or false."
sleep inf
fi
if ! echo "$X_FRAME_OPTIONS" | grep -q "^none$\|^sameorigin$\|^deny$"; then
echo "X_FRAME_OPTIONS needs to be none, sameorigin or deny."
sleep inf
fi
if ! echo "$NGINX_DISABLE_PROXY_BUFFERING" | grep -q "^true$\|^false$"; then
echo "NGINX_DISABLE_PROXY_BUFFERING needs to be true or false."
sleep inf
@@ -295,8 +350,8 @@ if [ -n "$GOACLA" ] && ! echo "$GOACLA" | grep -q "^-[a-zA-Z0-9 =/_.-]\+$"; then
fi
if [ -n "$PHP_APKS" ] && [ "$PHP82" = "false" ] && [ "$PHP83" = "false" ]; then
echo "PHP_APKS is set, but PHP82 and PHP83 is disabled."
if [ -n "$PHP_APKS" ] && [ "$PHP82" = "false" ] && [ "$PHP83" = "false" ] && [ "$PHP84" = "false" ]; then
echo "PHP_APKS is set, but PHP82, PHP83 and PHP84 is disabled."
sleep inf
fi
@@ -333,8 +388,29 @@ if [ -n "$PHP83_APKS" ] && ! echo "$PHP83_APKS" | grep -q "^[a-z0-9 _-]\+$"; the
fi
if [ -n "$INITIAL_ADMIN_EMAIL" ] && ! echo "$INITIAL_ADMIN_EMAIL" | grep -q "^.*@.*$"; then
echo "INITIAL_ADMIN_EMAIL needs to contains @."
if ! echo "$PHP84" | grep -q "^true$\|^false$"; then
echo "PHP84 needs to be true or false."
sleep inf
fi
if [ -n "$PHP84_APKS" ] && [ "$PHP84" = "false" ]; then
echo "PHP84_APKS is set, but PHP84 is disabled."
sleep inf
fi
if [ -n "$PHP84_APKS" ] && ! echo "$PHP84_APKS" | grep -q "^[a-z0-9 _-]\+$"; then
echo "PHP84_APKS can consist of lower letters a-z, numbers 0-9, spaces, underscores and hyphens."
sleep inf
fi
if [ -n "$INITIAL_ADMIN_EMAIL" ] && ! echo "$INITIAL_ADMIN_EMAIL" | grep -q "@.*\."; then
echo "INITIAL_ADMIN_EMAIL needs to contains a @ and one dot."
sleep inf
fi
if [ -n "$INITIAL_DEFAULT_PAGE" ] && ! echo "$INITIAL_DEFAULT_PAGE" | grep -q "^\(404\|444\|redirect\|congratulations\|html\)$"; then
echo "INITIAL_DEFAULT_PAGE needs to be 404, 444, redirect, congratulations or html."
sleep inf
fi
@@ -344,91 +420,108 @@ if [ -n "$NC_AIO" ] && ! echo "$NC_AIO" | grep -q "^true$\|^false$"; then
sleep inf
fi
if [ "$NC_AIO" = "true" ] && ([ -z "$NC_DOMAIN" ] || ! echo "$NC_DOMAIN" | grep -q "^[a-z0-9.]\+$"); then
echo "NC_DOMAIN must consist of lower letters a-z, numbers 0-9 and dots and is required in AIO mode."
sleep inf
fi
if [ "$NC_AIO" = "true" ]; then
export DISABLE_HTTP="true"
if [ -z "$NC_DOMAIN" ]; then
echo "NC_DOMAIN is required in AIO mode."
sleep inf
fi
fi
if [ ! -s /data/etc/npm/env.sha512sum ] || [ "$(cat /data/etc/npm/env.sha512sum)" != "$( (grep "env\.[A-Z0-9_]\+" -roh /app/templates | sed "s|env.||g" | sort | uniq | xargs printenv; echo "$TV") | tr -d "\n" | sha512sum | cut -d" " -f1)" ]; then
echo "At least one ENV changed, all hosts will be regenerated."
export REGENERATE_ALL="true"
fi
if [ "$ACME_MUST_STAPLE" = "true" ]; then
sed -i "s|must-staple = .*|must-staple = true|g" /etc/certbot.ini
else
sed -i "s|must-staple = .*|must-staple = false|g" /etc/certbot.ini
if [ "$ACME_MUST_STAPLE" = "false" ]; then
sed -i "s|must-staple = true|must-staple = false|g" /etc/certbot.ini
fi
if [ "$ACME_KEY_TYPE" = "rsa" ]; then
sed -i "s|key-type = ecdsa|key-type = rsa|g" /etc/certbot.ini
fi
if [ "$PHP82" = "true" ]; then
apk add --no-cache php82-fpm
# From https://github.com/nextcloud/all-in-one/pull/1377/files
if [ -n "$PHP82_APKS" ]; then
for apk in $(echo "$PHP82_APKS" | tr " " "\n"); do
if ! echo "$apk" | grep -q "^php82-.*$"; then
echo "$apk is a non allowed value."
echo "It needs to start with \"php82-\"."
echo "It is set to \"$apk\"."
sleep inf
fi
echo "Installing $apk via apk..."
if ! apk add --no-cache "$apk" > /dev/null 2>&1; then
echo "The apk \"$apk\" was not installed!"
fi
done
fi
mkdir -vp /data/php
cp -varnT /etc/php82 /data/php/82
sed -i "s|listen =.*|listen = /run/php82.sock|" /data/php/82/php-fpm.d/www.conf
sed -i "s|#\?listen =.*|listen = /run/php82.sock|" /data/php/82/php-fpm.d/www.conf
sed -i "s|;error_log =.*|error_log = /proc/self/fd/2|g" /data/php/82/php-fpm.conf
sed -i "s|include=.*|include=/data/php/82/php-fpm.d/*.conf|g" /data/php/82/php-fpm.conf
elif [ "$FULLCLEAN" = "true" ]; then
rm -vrf /data/php/82
fi
if [ "$PHP83" = "true" ]; then
apk add --no-cache php83-fpm
# From https://github.com/nextcloud/all-in-one/pull/1377/files
if [ -n "$PHP83_APKS" ]; then
for apk in $(echo "$PHP83_APKS" | tr " " "\n"); do
if ! echo "$apk" | grep -q "^php83-.*$"; then
echo "$apk is a non allowed value."
echo "It needs to start with \"php83-\"."
echo "It is set to \"$apk\"."
sleep inf
fi
echo "Installing $apk via apk..."
if ! apk add --no-cache "$apk" > /dev/null 2>&1; then
echo "The apk \"$apk\" was not installed!"
fi
done
fi
mkdir -vp /data/php
cp -varnT /etc/php83 /data/php/83
sed -i "s|listen =.*|listen = /run/php83.sock|" /data/php/83/php-fpm.d/www.conf
sed -i "s|#\?listen =.*|listen = /run/php83.sock|" /data/php/83/php-fpm.d/www.conf
sed -i "s|;error_log =.*|error_log = /proc/self/fd/2|g" /data/php/83/php-fpm.conf
sed -i "s|include=.*|include=/data/php/83/php-fpm.d/*.conf|g" /data/php/83/php-fpm.conf
elif [ "$FULLCLEAN" = "true" ]; then
rm -vrf /data/php/83
fi
if { [ "$PHP82" = "true" ] || [ "$PHP83" = "true" ]; } && [ -n "$PHP_APKS" ]; then
if [ "$PHP84" = "true" ]; then
apk add --no-cache php84-fpm
# From https://github.com/nextcloud/all-in-one/pull/1377/files
if [ -n "$PHP84_APKS" ]; then
for apk in $(echo "$PHP84_APKS" | tr " " "\n"); do
if ! echo "$apk" | grep -q "^php84-.*$"; then
echo "$apk is a non allowed value."
echo "It needs to start with \"php84-\"."
echo "It is set to \"$apk\"."
sleep inf
fi
echo "Installing $apk via apk..."
if ! apk add --no-cache "$apk" > /dev/null 2>&1; then
echo "The apk \"$apk\" was not installed!"
fi
done
fi
mkdir -vp /data/php
cp -varnT /etc/php84 /data/php/84
sed -i "s|#\?listen =.*|listen = /run/php84.sock|" /data/php/84/php-fpm.d/www.conf
sed -i "s|;error_log =.*|error_log = /proc/self/fd/2|g" /data/php/84/php-fpm.conf
sed -i "s|include=.*|include=/data/php/84/php-fpm.d/*.conf|g" /data/php/84/php-fpm.conf
elif [ "$FULLCLEAN" = "true" ]; then
rm -vrf /data/php/84
fi
if { [ "$PHP82" = "true" ] || [ "$PHP83" = "true" ] || [ "$PHP84" = "true" ]; } && [ -n "$PHP_APKS" ]; then
# From https://github.com/nextcloud/all-in-one/pull/1377/files
for apk in $(echo "$PHP_APKS" | tr " " "\n"); do
if ! echo "$apk" | grep -q "^php-.*$"; then
@@ -444,6 +537,9 @@ if { [ "$PHP82" = "true" ] || [ "$PHP83" = "true" ]; } && [ -n "$PHP_APKS" ]; th
done
fi
if [ "$FULLCLEAN" = "true" ] && [ "$PHP82" = "false" ] && [ "$PHP83" = "false" ] && [ "$PHP84" = "false" ]; then
rm -vrf /data/php
fi
if [ "$LOGROTATE" = "true" ]; then
sed -i "s|rotate [0-9]\+|rotate $LOGROTATIONS|g" /etc/logrotate
@@ -458,17 +554,12 @@ elif [ "$FULLCLEAN" = "true" ]; then
fi
mkdir -p /tmp/acme-challenge \
/tmp/certbot-work \
/tmp/certbot-log \
/tmp/npmhome \
/tmp/goa
if [ -d /data/nginx/custom ]; then
mv -vn /data/nginx/custom /data/nginx_custom
fi
mkdir -vp /data/tls/certbot/credentials \
/data/tls/certbot/renewal \
/tmp/goa \
/tmp/certbot-log \
/tmp/certbot-work \
/tmp/certbot-credentials
mkdir -vp /data/tls/certbot/renewal \
/data/tls/custom \
/data/etc/npm \
/data/etc/html \
@@ -480,40 +571,38 @@ mkdir -vp /data/tls/certbot/credentials \
/data/nginx/proxy_host \
/data/nginx/dead_host \
/data/nginx/stream \
/data/nginx_custom
/data/custom_nginx
touch /tmp/ip_ranges.conf \
/data/nginx/default.conf \
/data/etc/html/index.html \
/data/custom_nginx/events.conf \
/data/custom_nginx/http.conf \
/data/custom_nginx/http_top.conf \
/data/custom_nginx/root_top.conf \
/data/custom_nginx/root.conf \
/data/custom_nginx/server_dead.conf \
/data/custom_nginx/server_proxy.conf \
/data/custom_nginx/server_redirect.conf \
/data/custom_nginx/stream.conf \
/data/custom_nginx/stream_top.conf \
/data/custom_nginx/server_stream.conf \
/data/custom_nginx/server_stream_tcp.conf \
/data/custom_nginx/server_stream_udp.conf \
/data/etc/modsecurity/modsecurity-extra.conf
if [ -s /data/database.sqlite ] && [ "$DB_SQLITE_FILE" != "/data/database.sqlite" ]; then
mv -vn /data/database.sqlite "$DB_SQLITE_FILE"
if [ -s /data/database.sqlite ]; then
mv -vn /data/database.sqlite /data/etc/npm/database.sqlite
fi
if [ -s /data/etc/logrotate.status ]; then
mv -vn /data/etc/logrotate.status /data/etc/logrotate.state
if [ -s "$DB_SQLITE_FILE" ] && [ "$DB_SQLITE_FILE" != "/data/etc/npm/database.sqlite" ]; then
mv -vn "$DB_SQLITE_FILE" /data/etc/npm/database.sqlite
echo "DB_SQLITE_FILE is not supported."
fi
if [ -s /data/keys.json ]; then
mv -vn /data/keys.json /data/etc/npm/keys.json
fi
if [ -s /data/nginx/default_host/site.conf ]; then
mv -vn /data/nginx/default_host/site.conf /data/nginx/default.conf
fi
if [ -s /data/nginx/default_www/index.html ]; then
mv -vn /data/nginx/default_www/index.html /data/etc/html/index.html
fi
if [ -s /data/nginx/dummycert.pem ]; then
mv -vn /data/nginx/dummycert.pem /data/tls/dummycert.pem
fi
if [ -s /data/nginx/dummykey.pem ]; then
mv -vn /data/nginx/dummykey.pem /data/tls/dummykey.pem
fi
if [ -f /data/nginx_custom/root.conf ]; then
mv -vn /data/nginx_custom/root.conf /data/nginx_custom/root_top.conf
fi
if [ -n "$(ls -A /data/nginx/html 2> /dev/null)" ]; then
mv -vn /data/nginx/html/* /data/etc/html
fi
@@ -522,36 +611,27 @@ if [ -n "$(ls -A /data/access 2> /dev/null)" ]; then
mv -vn /data/access/* /data/etc/access
fi
if [ -n "$(ls -A /data/nginx/access 2> /dev/null)" ]; then
mv -vn /data/nginx/access/* /data/etc/access
fi
if [ -n "$(ls -A /etc/letsencrypt 2> /dev/null)" ]; then
cp -van /etc/letsencrypt/* /data/tls/certbot
find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/tls/certbot|g" {} \;
rm -r /etc/letsencrypt/*
fi
if [ -n "$(ls -A /data/letsencrypt 2> /dev/null)" ]; then
mv -vn /data/letsencrypt/* /data/tls/certbot
fi
find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/data/tls/certbot/credentials|/tmp/certbot-credentials|g" {} \;
if [ -n "$(ls -A /data/custom_ssl 2> /dev/null)" ]; then
mv -vn /data/custom_ssl/* /data/tls/custom
fi
if [ -n "$(ls -A /data/ssl 2> /dev/null)" ]; then
mv -vn /data/ssl/* /data/tls
if [ -d /data/nginx/custom ]; then
mv -vn /data/nginx/custom /data/nginx_custom
fi
if [ -d /data/tls/certbot/live ] && [ -d /data/tls/certbot/archive ]; then
find /data/tls/certbot/live ! -name "$(printf "*\n*")" -type f -name "*.pem" > tmp
while IFS= read -r cert
do
rm -vf "$cert"
ln -s "$(find /data/tls/certbot/archive/"$(echo "$cert" | sed "s|/data/tls/certbot/live/\(npm-[0-9]\+/.*\).pem|\1|g")"*.pem | sort -r | head -n1 | sed "s|/data/tls/certbot/|../../|g")" "$cert"
done < tmp
rm tmp
#tmp
if [ -d /data/nginx_custom ]; then
mv -vn /data/nginx_custom /data/custom_nginx
fi
if [ "$CLEAN" = "true" ]; then
rm -vrf /data/letsencrypt-acme-challenge \
/data/nginx/dummycert.pem \
@@ -567,16 +647,18 @@ if [ "$CLEAN" = "true" ]; then
/data/custom_ssl \
/data/certbot \
/data/access \
/data/php/8 \
/data/php/7 \
/data/ssl \
/data/logs \
/data/error.log \
/data/nginx/error.log \
/data/nginx/ip_ranges.conf
if [ -s /data/etc/npm/database.sqlite ]; then
sqlite-vaccum.js
fi
rm -vf /data/tls/certbot/crs/*.pem
rm -vf /data/tls/certbot/keys/*.pem
if [ -d /data/tls/certbot/live ] && [ -d /data/tls/certbot/archive ]; then
certs_in_use="$(find /data/tls/certbot/live -type l -name "*.pem" -exec readlink -f {} \;)"
export certs_in_use
@@ -592,76 +674,6 @@ if [ "$CLEAN" = "true" ]; then
fi
fi
if [ -s "$DB_SQLITE_FILE" ]; then
sqlite-vaccum.js
fi
if [ "$FULLCLEAN" = "true" ]; then
if [ "$PHP82" != "true" ] && [ "$PHP83" != "true" ]; then
rm -vrf /data/php
fi
fi
touch /tmp/ip_ranges.conf \
/data/etc/html/index.html \
/data/nginx_custom/events.conf \
/data/nginx_custom/http.conf \
/data/nginx_custom/http_top.conf \
/data/nginx_custom/root_top.conf \
/data/nginx_custom/server_dead.conf \
/data/nginx_custom/server_proxy.conf \
/data/nginx_custom/server_redirect.conf \
/data/nginx_custom/stream.conf \
/data/nginx_custom/stream_top.conf \
/data/nginx_custom/server_stream.conf \
/data/nginx_custom/server_stream_tcp.conf \
/data/nginx_custom/server_stream_udp.conf \
/data/etc/modsecurity/modsecurity-extra.conf
find /data/nginx -type f -name '*.conf' -exec sed -i "s|nginx/custom|nginx_custom|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s| http2||g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|\(listen .*\) http3|\1 quic|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|quic reuseport;|quic;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|security_headers on;|include conf.d/include/hsts.conf;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|more_set_headers \"Alt-Svc: h3=':443'; ma=86400\";|more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/access|/data/nginx/access|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/nginx/access|/data/etc/access|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/nginx/html/|/data/etc/html/|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/custom_ssl|/data/tls/custom|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/tls/certbot|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/letsencrypt|/data/tls/certbot|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/data/ssl|/data/tls|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|ssl_certificate_key /data/nginx/dummykey.pem;|ssl_certificate_key /data/tls/dummykey.pem;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|ssl_certificate /data/nginx/dummycert.pem;|ssl_certificate /data/tls/dummycert.pem;|g" {} \;
find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/data/ssl|/data/tls|g" {} \;
find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/etc/letsencrypt|/data/tls/certbot|g" {} \;
find /data/tls/certbot/renewal -type f -name '*.conf' -exec sed -i "s|/data/letsencrypt|/data/tls/certbot|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/block-exploits.conf/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|/html/404|/html/dead|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/acme-challenge.conf;|include conf.d/include/always.conf;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/letsencrypt-acme-challenge.conf;|include conf.d/include/always.conf;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/force-ssl.conf;|include conf.d/include/force-tls.conf;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|include conf.d/include/ssl-ciphers.conf;|include conf.d/include/tls-ciphers.conf;|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/http3/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/Asset Caching/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/assets.conf/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/error_log/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/access_log/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/proxy_http_version/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/ssl_stapling/d" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "/ssl_stapling_verify/d" {} \;
if [ -s /data/nginx/default.conf ]; then sed -i "/ssl_stapling/d" /data/nginx/default.conf; fi
if [ -s /data/nginx/default.conf ]; then sed -i "/ssl_stapling_verify/d" /data/nginx/default.conf; fi
if [ ! -s /data/etc/modsecurity/modsecurity-default.conf ]; then
cp -van /usr/local/nginx/conf/conf.d/include/modsecurity.conf.example /data/etc/modsecurity/modsecurity-default.conf
@@ -687,136 +699,9 @@ if [ ! -s /data/etc/modsecurity/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.exam
fi
cp -a /usr/local/nginx/conf/conf.d/include/coreruleset/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example /data/etc/modsecurity/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
cp -va /usr/local/nginx/conf/conf.d/include/coreruleset/plugins/* /data/etc/modsecurity/crs-plugins
cp -a /usr/local/nginx/conf/conf.d/include/coreruleset/plugins/* /data/etc/modsecurity/crs-plugins
sed -i "s|48693|$NIBEP|g" /app/index.js
sed -i "s|48693|$NIBEP|g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s|48683|$GOAIWSP|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $IPV4_BINDING:\2/g" /app/templates/_listen.conf
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $IPV4_BINDING:\2/g" /app/templates/default.conf
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\({{ incoming_port }}\)/listen $IPV4_BINDING:\2/g" /app/templates/stream.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $IPV4_BINDING:\2/g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9-]\+\)/listen $IPV4_BINDING:\2/g" {} \;
if [ "$DISABLE_IPV6" = "true" ]; then
sed -i "s|ipv6=on;|ipv6=off;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /app/templates/_listen.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /app/templates/default.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\({{ incoming_port }}\)/#listen \[\1\]:\2/g" /app/templates/stream.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9-]\+\)/#listen \[\1\]:\2/g" {} \;
else
sed -i "s|ipv6=off;|ipv6=on;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $IPV6_BINDING:\2/g" /app/templates/_listen.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $IPV6_BINDING:\2/g" /app/templates/default.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\({{ incoming_port }}\)/listen $IPV6_BINDING:\2/g" /app/templates/stream.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $IPV6_BINDING:\2/g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9-]\+\)/listen $IPV6_BINDING:\2/g" {} \;
fi
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $NPM_IPV4_BINDING:$NPM_PORT/g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $NPM_IPV4_BINDING:$NPM_PORT/g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf
if [ "$NPM_DISABLE_IPV6" = "true" ]; then
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf
else
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $NPM_IPV6_BINDING:$NPM_PORT/g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $NPM_IPV6_BINDING:$NPM_PORT/g" /usr/local/nginx/conf/conf.d/npm-no-server-name.conf
fi
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $GOA_IPV4_BINDING:$GOA_PORT/g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
sed -i "s/#\?listen \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:\)\?\([0-9]\+\)/listen $GOA_IPV4_BINDING:$GOA_PORT/g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf
if [ "$GOA_DISABLE_IPV6" = "true" ]; then
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/#listen \[\1\]:\2/g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf
else
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $GOA_IPV6_BINDING:$GOA_PORT/g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
sed -i "s/#\?listen \[\([0-9a-f:]\+\)\]:\([0-9]\+\)/listen $GOA_IPV6_BINDING:$GOA_PORT/g" /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf
fi
if [ "$DISABLE_HTTP" = "true" ]; then
sed -i "s|#\?\(listen.*80\)|#\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(listen.*80\)|#\1|g" /app/templates/default.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|#\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|#\1|g" {} \;
elif [ "$DISABLE_IPV6" = "true" ]; then
sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" /app/templates/default.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+:80\)|\1|g" {} \;
else
sed -i "s|#\?\(listen.*80\)|\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(listen.*80\)|\1|g" /app/templates/default.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*80\)|\1|g" {} \;
fi
if [ "$DISABLE_H3_QUIC" = "true" ]; then
sed -i "s|#\?\(listen.*quic\)|#\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(listen.*quic\)|#\1|g" /app/templates/default.conf
sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" /app/templates/default.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|#\1|g" {} \;
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|#\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|#\1|g" {} \;
elif [ "$DISABLE_IPV6" = "true" ]; then
sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" /app/templates/default.conf
sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/default.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" {} \;
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+.*quic\)|\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \;
else
sed -i "s|#\?\(listen.*quic\)|\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/_listen.conf
sed -i "s|#\?\(listen.*quic\)|\1|g" /app/templates/default.conf
sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" /app/templates/default.conf
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|\1|g" {} \;
find /usr/local/nginx/conf/conf.d -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(listen.*quic\)|\1|g" {} \;
find /data/nginx -type f -name '*.conf' -exec sed -i "s|#\?\(more_set_headers 'Alt-Svc: h3=\":443\"; ma=86400';\)|\1|g" {} \;
fi
if [ "$NGINX_LOG_NOT_FOUND" = "true" ]; then
sed -i "s|log_not_found.*|log_not_found on;|g" /usr/local/nginx/conf/nginx.conf
else
sed -i "s|log_not_found.*|log_not_found off;|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$NGINX_404_REDIRECT" = "true" ]; then
sed -i "s|#error_page 404|error_page 404|g" /usr/local/nginx/conf/nginx.conf
else
sed -i "s|error_page 404|#error_page 404|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$NGINX_DISABLE_PROXY_BUFFERING" = "true" ]; then
sed -i "s|proxy_buffering.*|proxy_buffering off;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|proxy_request_buffering.*|proxy_request_buffering off;|g" /usr/local/nginx/conf/nginx.conf
else
sed -i "s|proxy_buffering.*|proxy_buffering on;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|proxy_request_buffering.*|proxy_request_buffering on;|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$LOGROTATE" = "true" ]; then
sed -i "s|access_log off; # http|access_log /data/nginx/access.log log;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|access_log off; # stream|access_log /data/nginx/stream.log proxy;|g" /usr/local/nginx/conf/nginx.conf
else
sed -i "s|access_log /data/nginx/access.log log;|access_log off; # http|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|access_log /data/nginx/stream.log proxy;|access_log off; # stream|g" /usr/local/nginx/conf/nginx.conf
fi
if [ -s /data/tls/certbot/config.ini ]; then
echo "tls/certbot/config.ini is now unsupported, to remove this warning, just delete the file - some options are replaced by env."
fi
if [ ! -s /data/etc/crowdsec/ban.html ]; then
cp -van /usr/local/nginx/conf/conf.d/include/ban.html /data/etc/crowdsec/ban.html
fi
@@ -866,7 +751,7 @@ 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
if [ -s /data/tls/certbot/live/npm-"$DEFAULT_CERT_ID".der ] && [ "$ACME_OCSP_STAPLING" = "true" ]; 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
@@ -901,12 +786,7 @@ else
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
if { [ "$DEFAULT_CERT" = "/data/tls/dummycert.pem" ] && [ "$DEFAULT_KEY" != "/data/tls/dummykey.pem" ]; } || { [ "$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."
@@ -915,118 +795,96 @@ 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
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -days 365000 -nodes -x509 -subj '/CN=*' -sha512 -keyout /data/tls/dummykey.pem -out /data/tls/dummycert.pem
fi
unset DEFAULT_STAPLING_FILE
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
if [ -n "$DEFAULT_STAPLING_FILE" ] && [ "$ACME_OCSP_STAPLING" = "true" ]; then
sed -i "s|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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
if [ -n "$DEFAULT_STAPLING_FILE" ] && [ "$ACME_OCSP_STAPLING" = "true" ]; then
sed -i "s|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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
if [ -n "$DEFAULT_STAPLING_FILE" ] && [ "$ACME_OCSP_STAPLING" = "true" ]; then
sed -i "s|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|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|48683|$NIBEP|g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s|48693|$GOAIWSP|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
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_STAPLING_FILE" ]; then
sed -i "s|tls-ciphers-no-stapling.conf;|tls-ciphers.conf;|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|tls-ciphers.conf;|tls-ciphers-no-stapling.conf;|g" /data/nginx/default.conf
sed -i "s|#\?ssl_stapling_file .*|#ssl_stapling_file ;|g" /data/nginx/default.conf
fi
sed -i "s|#\?listen 0.0.0.0:81|listen $NPM_IPV4_BINDING:$NPM_PORT|g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s|#\?listen 0.0.0.0:91|listen $GOA_IPV4_BINDING:$GOA_PORT|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
if [ ! -s /data/nginx/default.conf ]; then
cp -van /usr/local/nginx/conf/conf.d/include/default.conf /data/nginx/default.conf
if [ "$DISABLE_IPV6" = "true" ]; then
sed -i "s|ipv6=on;|ipv6=off;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|#\?listen \[::\]:81|#listen $NPM_IPV6_BINDING:$NPM_PORT|g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s|#\?listen \[::\]:91|#listen $GOA_IPV6_BINDING:$GOA_PORT|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
else
sed -i "s|#\?listen \[::\]:81|listen $NPM_IPV6_BINDING:$NPM_PORT|g" /usr/local/nginx/conf/conf.d/npm.conf
sed -i "s|#\?listen \[::\]:91|listen $GOA_IPV6_BINDING:$GOA_PORT|g" /usr/local/nginx/conf/conf.d/include/goaccess.conf
fi
sed -i "s|quic default_server|quic reuseport default_server|g" /data/nginx/default.conf
if [ "$GOA" = "true" ]; then
mkdir -vp /data/etc/goaccess/data /data/etc/goaccess/geoip
cp -va /usr/local/nginx/conf/conf.d/include/goaccess.conf /usr/local/nginx/conf/conf.d/goaccess.conf
cp -va /usr/local/nginx/conf/conf.d/include/goaccess-no-server-name.conf /usr/local/nginx/conf/conf.d/goaccess-no-server-name.conf
cp -van /usr/local/nginx/conf/conf.d/include/goaccess.conf /usr/local/nginx/conf/conf.d/goaccess.conf
elif [ "$FULLCLEAN" = "true" ]; then
rm -vrf /data/etc/goaccess
fi
if [ "$NGINX_QUIC_BPF" = "true" ]; then
sed -i "s|quic_bpf.*|quic_bpf on;|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$NGINX_LOG_NOT_FOUND" = "true" ]; then
sed -i "s|log_not_found.*|log_not_found on;|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$NGINX_404_REDIRECT" = "true" ]; then
sed -i "s|#error_page 404|error_page 404|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$NGINX_DISABLE_PROXY_BUFFERING" = "true" ]; then
sed -i "s|proxy_buffering.*|proxy_buffering off;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|proxy_request_buffering.*|proxy_request_buffering off;|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$NGINX_HSTS_SUBDMAINS" = "false" ]; then
sed -i "s|includeSubDomains; ||g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$X_FRAME_OPTIONS" = "sameorigin" ]; then
sed -i "s|DENY|SAMEORIGIN|g" /usr/local/nginx/conf/conf.d/include/hsts.conf
fi
if [ "$X_FRAME_OPTIONS" = "none" ]; then
sed -i "s|#\?\(.*DENY\)|#\1|g" /usr/local/nginx/conf/conf.d/include/hsts.conf
fi
if [ "$LOGROTATE" = "true" ]; then
sed -i "s|access_log off; # http|access_log /data/nginx/access.log log;|g" /usr/local/nginx/conf/nginx.conf
sed -i "s|access_log off; # stream|access_log /data/nginx/stream.log proxy;|g" /usr/local/nginx/conf/nginx.conf
fi
if [ "$DISABLE_NGINX_BEAUTIFIER" = "false" ]; then
nginxbeautifier -s 4 -r /data/nginx
fi
rm -vf /usr/local/nginx/logs/nginx.pid
rm -vf /run/*.sock
find /data/tls \
/data/etc/npm \
/data/etc/access \
-not -perm 770 \
-exec chmod 770 {} \;
rm -vf /usr/local/nginx/logs/nginx.pid
rm -vf /run/*.sock
if [ "$PUID" != "0" ]; then
if id -u npm > /dev/null 2>&1; then
usermod -u "$PUID" npm
@@ -1056,12 +914,16 @@ if [ "$PUID" != "0" ]; then
-not \( -uid "$PUID" -and -gid "$PGID" \) \
-exec chown "$PUID:$PGID" {} \;
if [ "$PHP82" = "true" ]; then
sed -i "s|user =.*|;user = root|" /data/php/82/php-fpm.d/www.conf
sed -i "s|group =.*|;group = root|" /data/php/82/php-fpm.d/www.conf
sed -i "s|;\?user =.*|;user = root|" /data/php/82/php-fpm.d/www.conf
sed -i "s|;\?group =.*|;group = root|" /data/php/82/php-fpm.d/www.conf
fi
if [ "$PHP83" = "true" ]; then
sed -i "s|user =.*|;user = root|" /data/php/83/php-fpm.d/www.conf
sed -i "s|group =.*|;group = root|" /data/php/83/php-fpm.d/www.conf
sed -i "s|;\?user =.*|;user = root|" /data/php/83/php-fpm.d/www.conf
sed -i "s|;\?group =.*|;group = root|" /data/php/83/php-fpm.d/www.conf
fi
if [ "$PHP84" = "true" ]; then
sed -i "s|;\?user =.*|;user = root|" /data/php/84/php-fpm.d/www.conf
sed -i "s|;\?group =.*|;group = root|" /data/php/84/php-fpm.d/www.conf
fi
sed -i "s|#\?user root;|#user root;|g" /usr/local/nginx/conf/nginx.conf
exec su-exec "$PUID:$PGID" launch.sh
@@ -1081,6 +943,10 @@ else
sed -i "s|;user =.*|user = root|" /data/php/83/php-fpm.d/www.conf
sed -i "s|;group =.*|group = root|" /data/php/83/php-fpm.d/www.conf
fi
if [ "$PHP84" = "true" ]; then
sed -i "s|;user =.*|user = root|" /data/php/84/php-fpm.d/www.conf
sed -i "s|;group =.*|group = root|" /data/php/84/php-fpm.d/www.conf
fi
sed -i "s|#user root;|user root;|g" /usr/local/nginx/conf/nginx.conf
exec launch.sh
fi

View File

@@ -1,31 +0,0 @@
# ------------------------------------------------------------
# Default Site
# ------------------------------------------------------------
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
listen 443 quic reuseport default_server;
listen [::]:443 quic reuseport default_server;
more_set_headers 'Alt-Svc: h3=":443"; ma=86400';
server_name _;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
location / {
include conf.d/include/always.conf;
root /html/default;
try_files $uri /index.html;
}
}

View File

@@ -1,17 +0,0 @@
server {
http3 off;
listen 82 ssl;
listen [::]:82 ssl;
server_name "";
return 444;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
}

View File

@@ -1,16 +1,29 @@
server {
http3 off;
listen 91 ssl default_server;
listen 0.0.0.0:91 ssl;
listen [::]:91 ssl;
server_name "";
include conf.d/include/always.conf;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers-no-stapling.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
return 444;
}
server {
listen 0.0.0.0:91 ssl default_server;
listen [::]:91 ssl default_server;
server_name _;
include conf.d/include/always.conf;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
modsecurity on;
modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity.conf;
include conf.d/include/tls-ciphers-no-stapling.conf;
ssl_certificate ;
ssl_certificate_key ;
@@ -23,7 +36,7 @@ server {
include conf.d/include/proxy-location.conf;
if ($goaccess = "socket") {
proxy_pass http://127.0.0.1:48683$request_uri;
proxy_pass http://127.0.0.1:48693$request_uri;
}
root /tmp/goa;

View File

@@ -1,7 +1,6 @@
more_set_headers "X-XSS-Protection: 0";
more_set_headers "X-Frame-Options: SAMEORIGIN";
more_set_headers "X-Frame-Options: DENY"; # or what ever you set using env
more_set_headers "X-Content-Type-Options: nosniff";
more_set_headers "Referrer-Policy: strict-origin-when-cross-origin";
more_set_headers "Content-Security-Policy: $content_security_policy";
more_set_headers "Content-Security-Policy: $content_security_policy"; # if not set by upstream: upgrade-insecure-requests, else upstreams value is used
more_set_headers "Strict-Transport-Security: $hsts_header";
more_set_headers "Strict-Transport-Security: $hsts_header"; # means: max-age=63072000; includeSubDomains; preload (includeSubDomains not when disabled via env)

View File

@@ -1,13 +0,0 @@
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header Accept-Encoding "";
proxy_set_header Host $host;
proxy_set_header Early-Data $ssl_early_data;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
proxy_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:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
proxy_http_version 1.1;

View File

@@ -6,9 +6,5 @@ proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header Accept-Encoding "";
proxy_set_header Host $host;
proxy_set_header Early-Data $ssl_early_data;
proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
proxy_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:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA;
proxy_http_version 1.1;
proxy_pass $forward_scheme://$server:$port$request_uri;
proxy_set_header Early-Data $ssl_early_data;

View File

@@ -9,7 +9,7 @@ ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/dhparam;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519MLKEM768:x25519_kyber768:x25519:x448:secp521r1:secp384r1:secp256r1;
ssl_ecdh_curve X25519MLKEM768:x25519:x448:secp521r1:secp384r1:secp256r1;
ssl_prefer_server_ciphers on;
ssl_conf_command Options PrioritizeChaCha;

View File

@@ -9,7 +9,7 @@ ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/dhparam;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519MLKEM768:x25519_kyber768:x25519:x448:secp521r1:secp384r1:secp256r1;
ssl_ecdh_curve X25519MLKEM768:x25519:x448:secp521r1:secp384r1:secp256r1;
ssl_prefer_server_ciphers on;
ssl_conf_command Options PrioritizeChaCha;

View File

@@ -1,24 +0,0 @@
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic;
listen [::]:443 quic;
server_name "";
return 444;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
add_header Alt-Svc 'h3=":443"; ma=86400';
http3 on;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
}

View File

@@ -1,17 +0,0 @@
server {
http3 off;
listen 81 ssl;
listen [::]:81 ssl;
server_name "";
return 444;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
}

View File

@@ -1,16 +1,29 @@
server {
http3 off;
listen 81 ssl default_server;
listen 0.0.0.0:81 ssl;
listen [::]:81 ssl;
server_name "";
include conf.d/include/always.conf;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers-no-stapling.conf;
ssl_certificate ;
ssl_certificate_key ;
#ssl_stapling_file ;
return 444;
}
server {
listen 0.0.0.0:81 ssl default_server;
listen [::]:81 ssl default_server;
server_name _;
include conf.d/include/always.conf;
include conf.d/include/brotli.conf;
include conf.d/include/force-tls.conf;
include conf.d/include/tls-ciphers.conf;
include conf.d/include/always.conf;
modsecurity on;
modsecurity_rules_file /usr/local/nginx/conf/conf.d/include/modsecurity.conf;
include conf.d/include/tls-ciphers-no-stapling.conf;
ssl_certificate ;
ssl_certificate_key ;
@@ -20,10 +33,10 @@ server {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
include conf.d/include/proxy-location.conf;
include conf.d/include/proxy.conf;
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://127.0.0.1:48693;
proxy_pass http://127.0.0.1:48683;
}
location / {

View File

@@ -5,12 +5,15 @@ error_log stderr warn;
worker_processes auto;
worker_cpu_affinity auto;
quic_bpf off;
# Custom
include /data/nginx_custom/root_top.conf;
include /data/custom_nginx/root.conf;
include /data/custom_nginx/root_top.conf;
events {
# Custom
include /data/nginx_custom/events.conf;
include /data/custom_nginx/events.conf;
}
http {
@@ -36,6 +39,7 @@ http {
tcp_nodelay on;
client_max_body_size 0;
client_body_buffer_size 512k;
http3_stream_buffer_size 512k;
reset_timedout_connection on;
gzip on;
@@ -99,6 +103,10 @@ http {
server unix:/run/php83.sock;
}
upstream php84 {
server unix:/run/php84.sock;
}
# Fancy Index
fancyindex off;
fancyindex_localtime on;
@@ -132,7 +140,7 @@ http {
include conf.d/*.conf;
# Custom
include /data/nginx_custom/http_top.conf;
include /data/custom_nginx/http_top.conf;
# Files generated by NPM
include /data/nginx/proxy_host/*.conf;
@@ -140,7 +148,7 @@ http {
include /data/nginx/dead_host/*.conf;
# Custom
include /data/nginx_custom/http.conf;
include /data/custom_nginx/http.conf;
}
stream {
@@ -149,11 +157,11 @@ stream {
resolver local=on valid=10s ipv6=on;
# Custom
include /data/nginx_custom/stream_top.conf;
include /data/custom_nginx/stream_top.conf;
# Files generated by NPM
include /data/nginx/stream/*.conf;
# Custom
include /data/nginx_custom/stream.conf;
include /data/custom_nginx/stream.conf;
}