rebrand to NPMplus/improve security headers/upsteam changes/dockerlint

Signed-off-by: Zoey <zoey@z0ey.de>
This commit is contained in:
Zoey
2023-10-09 18:38:58 +02:00
parent e2214b5f69
commit fb0bb721f7
31 changed files with 202 additions and 110 deletions

View File

@@ -14,6 +14,9 @@ jobs:
- name: Convert Username
id: un
run: echo "un=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Convert repository name
id: rn
run: echo "rn=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
@@ -22,9 +25,14 @@ jobs:
password: ${{ github.token }}
- name: Push develop to latest
run: |
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/nginx-proxy-manager:caddy ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/nginx-proxy-manager:caddy ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.run_number }} ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.run_number }} ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
- name: Show Caddy version
run: |
docker run --rm --entrypoint caddy ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy version
docker run --rm --entrypoint caddy ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy version
docker run --rm --entrypoint caddy ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy version
docker run --rm --entrypoint caddy ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy version

View File

@@ -31,6 +31,9 @@ jobs:
- name: Convert Username
id: un
run: echo "un=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Convert repository name
id: rn
run: echo "rn=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
@@ -46,5 +49,5 @@ jobs:
platforms: linux/amd64,linux/arm64 #,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4 #,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy-${{ github.ref_name }}
ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:caddy-${{ github.ref_name }}
${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}
ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:caddy-${{ github.ref_name }}

View File

@@ -14,6 +14,9 @@ jobs:
- name: Convert Username
id: un
run: echo "un=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Convert repository name
id: rn
run: echo "rn=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
@@ -22,11 +25,14 @@ jobs:
password: ${{ github.token }}
- name: Push develop to latest
run: |
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:latest ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.run_number }} ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:latest ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.run_number }} ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/nginx-proxy-manager:latest ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/nginx-proxy-manager:latest ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:latest ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
docker buildx imagetools create --tag ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.run_number }} ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:latest ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
docker buildx imagetools create --tag ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.run_number }} ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
- name: Show Nginx version
run: |
docker run --rm --entrypoint nginx ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:latest -V
docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:latest -V
docker run --rm --entrypoint nginx ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:latest -V
docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:latest -V

View File

@@ -42,6 +42,9 @@ jobs:
- name: Convert Username
id: un
run: echo "un=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Convert repository name
id: rn
run: echo "rn=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
@@ -63,15 +66,15 @@ jobs:
platforms: linux/amd64,linux/arm64 #,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4 #,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }}
ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }}
${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
build-args: |
"BUILD=${{ github.event.repository.name }}"
"BUILD=${{ steps.rn.outputs.rn }}"
- name: show version
if: ${{ github.event_name != 'pull_request' }}
run: |
docker run --rm --entrypoint nginx ${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }} -V
docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ github.ref_name }} -V
docker run --rm --entrypoint nginx ${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }} -V
docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }} -V
- name: Set PR-Number (PR)
if: ${{ github.event_name == 'pull_request' }}
id: pr
@@ -84,15 +87,15 @@ jobs:
file: ./Dockerfile
platforms: linux/amd64,linux/arm64 #,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4 #,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
push: ${{ github.event_name == 'pull_request' }}
tags: ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ steps.pr.outputs.pr }}
tags: ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }}
build-args: |
"BUILD=${{ github.event.repository.name }}"
"BUILD=${{ steps.rn.outputs.rn }}"
- name: show version (PR)
if: ${{ github.event_name == 'pull_request' }}
run: docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ steps.pr.outputs.pr }} -V
run: docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }} -V
- name: add comment (PR)
uses: mshick/add-pr-comment@v2
if: ${{ github.event_name == 'pull_request' }}
with:
message: "The Docker Image can now be found here: `ghcr.io/${{ steps.un.outputs.un }}/${{ github.event.repository.name }}:${{ steps.pr.outputs.pr }}`"
repo-token: ${{ github.token }}
message: "The Docker Image can now be found here: `ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }}`"
repo-token: ${{ github.token }}

27
.github/workflows/dockerlint.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Dockerlint
on:
push:
pull_request:
workflow_dispatch:
jobs:
docker-lint:
runs-on: ubuntu-latest
name: docker-lint
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install hadolint
run: |
sudo wget https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64 -O /usr/bin/hadolint
sudo chmod +x /usr/bin/hadolint
- name: run lint
run: |
DOCKERFILES="$(find . -name "*Dockerfile*")"
for file in $(echo "$DOCKERFILES" | tr " " "\n"); do
# DL3018 warning: Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
# DL3013 warning: Pin versions in pip. Instead of `pip install <package>` use `pip install <package>==<version>` or `pip install --requirement <requirements file>`
hadolint "$file" --ignore DL3013 --ignore DL3018 | tee -a hadolint.log
done
if grep -q "DL[0-9]\+\|SC[0-9]\+" hadolint.log; then
exit 1
fi

View File

@@ -1,10 +1,10 @@
FROM --platform="$BUILDPLATFORM" alpine:3.18.3 as frontend
FROM --platform="$BUILDPLATFORM" alpine:3.18.4 as frontend
COPY frontend /build/frontend
COPY global/certbot-dns-plugins.js /build/frontend/certbot-dns-plugins.js
ARG NODE_ENV=production \
NODE_OPTIONS=--openssl-legacy-provider
WORKDIR /build/frontend
RUN apk add --no-cache ca-certificates nodejs yarn git python3 build-base && \
cd /build/frontend && \
yarn --no-lockfile install && \
yarn --no-lockfile build && \
yarn cache clean --all
@@ -12,14 +12,15 @@ COPY darkmode.css /build/frontend/dist/css/darkmode.css
COPY security.txt /build/frontend/dist/.well-known/security.txt
FROM --platform="$BUILDPLATFORM" alpine:3.18.3 as backend
FROM --platform="$BUILDPLATFORM" alpine:3.18.4 as backend
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
COPY backend /build/backend
COPY global/certbot-dns-plugins.js /build/backend/certbot-dns-plugins.js
ARG NODE_ENV=production \
TARGETARCH
WORKDIR /build/backend
RUN apk add --no-cache ca-certificates nodejs-current yarn && \
wget https://gobinaries.com/tj/node-prune -O - | sh && \
cd /build/backend && \
wget -q https://gobinaries.com/tj/node-prune -O - | sh && \
if [ "$TARGETARCH" = "amd64" ]; then \
npm_config_target_platform=linux npm_config_target_arch=x64 yarn install --no-lockfile; \
elif [ "$TARGETARCH" = "arm64" ]; then \
@@ -29,31 +30,31 @@ RUN apk add --no-cache ca-certificates nodejs-current yarn && \
yarn cache clean --all
FROM python:3.11.5-alpine3.18 as certbot
FROM python:3.12.0-alpine3.18 as certbot
ENV PATH="/usr/local/certbot/bin:$PATH"
RUN apk add --no-cache ca-certificates build-base libffi-dev && \
python3 -m venv /usr/local/certbot && \
. /usr/local/certbot/bin/activate && \
pip install --no-cache-dir certbot
FROM --platform="$BUILDPLATFORM" alpine:3.18.3 as crowdsec
FROM --platform="$BUILDPLATFORM" alpine:3.18.4 as crowdsec
WORKDIR /src
RUN apk add --no-cache ca-certificates git build-base && \
git clone --recursive https://github.com/crowdsecurity/cs-nginx-bouncer /src && \
cd /src && \
make && \
tar xzf crowdsec-nginx-bouncer.tgz && \
mv crowdsec-nginx-bouncer-* crowdsec-nginx-bouncer && \
cd /src/crowdsec-nginx-bouncer && \
sed -i "/lua_package_path/d" nginx/crowdsec_nginx.conf && \
sed -i "s|/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf|/data/etc/crowdsec/crowdsec.conf|g" nginx/crowdsec_nginx.conf && \
sed -i "s|API_KEY=.*|API_KEY=|g" lua-mod/config_example.conf && \
sed -i "s|ENABLED=.*|ENABLED=false|g" lua-mod/config_example.conf && \
sed -i "s|API_URL=.*|API_URL=http://127.0.0.1:8080|g" lua-mod/config_example.conf && \
sed -i "s|BAN_TEMPLATE_PATH=.*|BAN_TEMPLATE_PATH=/data/etc/crowdsec/ban.html|g" lua-mod/config_example.conf && \
sed -i "s|CAPTCHA_TEMPLATE_PATH=.*|CAPTCHA_TEMPLATE_PATH=/data/etc/crowdsec/captcha.html|g" lua-mod/config_example.conf
sed -i "/lua_package_path/d" /src/crowdsec-nginx-bouncer/nginx/crowdsec_nginx.conf && \
sed -i "s|/etc/crowdsec/bouncers/crowdsec-nginx-bouncer.conf|/data/etc/crowdsec/crowdsec.conf|g" /src/crowdsec-nginx-bouncer/nginx/crowdsec_nginx.conf && \
sed -i "s|API_KEY=.*|API_KEY=|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \
sed -i "s|ENABLED=.*|ENABLED=false|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \
sed -i "s|API_URL=.*|API_URL=http://127.0.0.1:8080|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \
sed -i "s|BAN_TEMPLATE_PATH=.*|BAN_TEMPLATE_PATH=/data/etc/crowdsec/ban.html|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \
sed -i "s|CAPTCHA_TEMPLATE_PATH=.*|CAPTCHA_TEMPLATE_PATH=/data/etc/crowdsec/captcha.html|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf
FROM zoeyvid/nginx-quic:197
FROM zoeyvid/nginx-quic:205
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
COPY rootfs /
RUN apk add --no-cache ca-certificates tzdata tini \
lua5.1-lzlib \
@@ -61,8 +62,8 @@ RUN apk add --no-cache ca-certificates tzdata tini \
openssl apache2-utils \
coreutils grep jq curl shadow sudo \
luarocks5.1 wget lua5.1-dev build-base git yarn && \
wget https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended -O /usr/local/nginx/conf/conf.d/include/modsecurity.conf && \
wget https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/unicode.mapping -O /usr/local/nginx/conf/conf.d/include/unicode.mapping && \
wget -q https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/modsecurity.conf-recommended -O /usr/local/nginx/conf/conf.d/include/modsecurity.conf && \
wget -q https://raw.githubusercontent.com/SpiderLabs/ModSecurity/v3/master/unicode.mapping -O /usr/local/nginx/conf/conf.d/include/unicode.mapping && \
sed -i "s|SecRuleEngine .*|SecRuleEngine On|g" /usr/local/nginx/conf/conf.d/include/modsecurity.conf && \
echo "Include /data/etc/modsecurity/modsecurity.conf" | tee -a /usr/local/nginx/conf/conf.d/include/modsecurity.conf && \
cp /usr/local/nginx/conf/conf.d/include/modsecurity.conf /usr/local/nginx/conf/conf.d/include/modsecurity-crs.conf && \

View File

@@ -1,17 +1,5 @@
<p align="center" class="items-center">
<img src="https://nginxproxymanager.com/github.png">
<!---
<br><br>
<img src="https://img.shields.io/badge/version-2.10.4-green.svg?style=for-the-badge">
<a href="https://hub.docker.com/r/zoeyvid/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/zoeyvid/nginx-proxy-manager.svg?style=for-the-badge">
</a>
<a href="https://hub.docker.com/r/zoeyvid/nginx-proxy-manager">
<img src="https://img.shields.io/docker/pulls/zoeyvid/nginx-proxy-manager.svg?style=for-the-badge">
</a>
--->
</p>
# NPMplus
This project comes as a pre-built docker image that enables you to easily forward to your websites
running at home or otherwise, including free TLS, without having to know too much about Nginx or Letsencrypt.
@@ -20,7 +8,7 @@ running at home or otherwise, including free TLS, without having to know too muc
- [Screenshots](https://nginxproxymanager.com/screenshots)
**Note: To fix [this issue](https://github.com/SpiderLabs/ModSecurity/issues/2848), instead of running `nginx -s reload`, this fork stops nginx and starts it again. This can result in a 502 error when you update your hosts. See https://github.com/ZoeyVid/nginx-proxy-manager/issues/296 and https://github.com/ZoeyVid/nginx-proxy-manager/issues/283.** <br>
**Note: To fix [this issue](https://github.com/SpiderLabs/ModSecurity/issues/2848), instead of running `nginx -s reload`, this fork stops nginx and starts it again. This can result in a 502 error when you update your hosts. See https://github.com/ZoeyVid/NPMplus/issues/296 and https://github.com/ZoeyVid/NPMplus/issues/283.** <br>
**Note: NO armv7 support.** <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: If you don't use network mode host, which I don't recommend, don't forget to expose port 443 on tcp AND udp (http3/quic needs udp).** <br>
@@ -54,12 +42,12 @@ so that the barrier for entry here is low.
# List of new features
- Supports HTTP/3 (QUIC) protocol.
- Supports CrowdSec IPS. Please see [here](https://github.com/ZoeyVid/nginx-proxy-manager#crowdsec) to enable it.
- Supports CrowdSec IPS. Please see [here](https://github.com/ZoeyVid/NPMplus#crowdsec) to enable it.
- Supports ModSecurity, with coreruleset as an option. You can configure ModSecurity/coreruleset by editing the files in the `/opt/npm/etc/modsecurity` folder.
- If the core ruleset blocks valid requests, please check the `/data/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).
- Note: To fix [this issue](https://github.com/SpiderLabs/ModSecurity/issues/2848), instead of running `nginx -s reload`, this fork stops nginx and starts it again. This will result in a 502 error when you update your hosts. See https://github.com/ZoeyVid/nginx-proxy-manager/issues/296 and https://github.com/ZoeyVid/nginx-proxy-manager/issues/283.
- Note: To fix [this issue](https://github.com/SpiderLabs/ModSecurity/issues/2848), instead of running `nginx -s reload`, this fork stops nginx and starts it again. This will result in a 502 error when you update your hosts. See https://github.com/ZoeyVid/NPMplus/issues/296 and https://github.com/ZoeyVid/NPMplus/issues/283.
- 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
@@ -67,13 +55,13 @@ so that the barrier for entry here is low.
- Uses OCSP Stapling for enhanced security
- If using custom certificates, upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/tls/custom/npm-[certificate-id]` folder (manual migration may be needed)
- Resolved dnspod plugin issue
- To migrate manually, delete all dnspod certs and recreate them OR change the credentials file as per the template given [here](https://github.com/ZoeyVid/nginx-proxy-manager/blob/develop/global/certbot-dns-plugins.js)
- 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
- Admin backend interface runs with https
- Default page also runs with https
- Uses [fancyindex](https://gitHub.com/Naereen/Nginx-Fancyindex-Theme) if used as webserver
- Exposes INTERNAL backend api only to localhost
- Easy application of security headers using [ngx_security_headers](https://github.com/GetPageSpeed/ngx_security_headers)
- Basic security headers are added if you enable HSTS (HSTS has always subdomains and preload enabled)
- Access Log disabled
- Error Log written to console
- `Server` response header hidden
@@ -85,7 +73,7 @@ so that the barrier for entry here is low.
- Allows infinite upload size
- Automatic database vacuum (only sqlite)
- Automatic cleaning of old certbot certs (set FULLCLEAN to true)
- Password reset (only sqlite) using `docker exec -it nginx-proxy-manager password-reset.js USER_EMAIL PASSWORD`
- 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 `/data/etc/npm/ca.crt` and `DB_MYSQL_CA` set to `/data/etc/npm/ca.crt` (not tested)
- Supports PUID/PGID in network mode host; add `net.ipv4.ip_unprivileged_port_start=0` at the end of `/etc/sysctl.conf`
- Option to set IP bindings for multiple instances in network mode host
@@ -101,7 +89,7 @@ so that the barrier for entry here is low.
- **NOTE: migrating back to the original is not possible**, so make first a **backup** before migration, so you can use the backup to switch back
- if you use custom certificates, you need to upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/tls/custom/npm-[certificate-id]` folder
- some buttons have changed, check if they are still correct
- please delete all dnspod certs and recreate them OR you manually change the credentialsfile (see [here](https://github.com/ZoeyVid/nginx-proxy-manager/blob/develop/global/certbot-dns-plugins.js) for the template)
- please delete all dnspod certs and recreate them OR you manually change the credentialsfile (see [here](https://github.com/ZoeyVid/npmplus/blob/develop/global/certbot-dns-plugins.js) for the template)
- since this fork has dependency on `network_mode: host`, please don't forget to open port 80 and 443 (and maybe 81) in your firewall
# Crowdsec
@@ -168,9 +156,9 @@ location / {
```yml
version: "3"
services:
nginx-proxy-manager:
container_name: nginx-proxy-manager
image: zoeyvid/nginx-proxy-manager
npmplus:
container_name: npmplus
image: zoeyvid/npmplus
restart: always
network_mode: host
volumes:
@@ -234,8 +222,8 @@ If you want to sponsor them, please see [here](https://github.com/NginxProxyMana
## Getting Support
1. [Found a bug?](https://github.com/ZoeyVid/nginx-proxy-manager/issues)
2. [Discussions](https://github.com/ZoeyVid/nginx-proxy-manager/discussions)
1. [Found a bug?](https://github.com/ZoeyVid/NPMplus/issues)
2. [Discussions](https://github.com/ZoeyVid/NPMplus/discussions)
<!---
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community)
4. [Reddit](https://reddit.com/r/nginxproxymanager)

View File

@@ -1,7 +1,7 @@
const config = require('./lib/config');
if (!config.has('database')) {
throw new Error('Database config does not exist! Please read the instructions: https://nginxproxymanager.com/setup');
throw new Error('Database config does not exist! Please read the instructions: https://github.com/ZoeyVid/NPMplus');
}
function generateDbConfig() {

View File

@@ -1,7 +1,7 @@
{
"openapi": "3.0.0",
"info": {
"title": "Nginx Proxy Manager API",
"title": "NPMplus API",
"version": "2.x.x"
},
"servers": [

View File

@@ -788,14 +788,19 @@ const internalCertificate = {
requestLetsEncryptSsl: (certificate) => {
logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const cmd = certbotCommand + ' certonly ' +
let cmd = certbotCommand + ' certonly ' +
'--config "' + certbotConfig + '" ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--authenticator webroot ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--preferred-challenges "dns,http" ' +
'--domains "' + certificate.domain_names.join(',') + '"';
if (certificate.meta.letsencrypt_email === '') {
cmd = cmd + ' --register-unsafely-without-email ';
} else {
cmd = cmd + ' --email "' + certificate.meta.letsencrypt_email + '" ';
}
logger.info('Command:', cmd);
return utils.exec(cmd)
@@ -833,7 +838,6 @@ const internalCertificate = {
let mainCmd = certbotCommand + ' certonly ' +
'--config "' + certbotConfig + '" ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
'--authenticator ' + dns_plugin.full_plugin_name + ' ' +
(
@@ -852,6 +856,16 @@ const internalCertificate = {
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
}
if (certificate.meta.dns_provider === 'duckdns') {
mainCmd = mainCmd + ' --dns-duckdns-no-txt-restore';
}
if (certificate.meta.letsencrypt_email === '') {
mainCmd = mainCmd + ' --register-unsafely-without-email ';
} else {
mainCmd = mainCmd + ' --email "' + certificate.meta.letsencrypt_email + '" ';
}
logger.info('Command:', `${credentialsCmd} && ${prepareCmd} && ${mainCmd}`);
return utils.exec(credentialsCmd)
@@ -1103,7 +1117,7 @@ const internalCertificate = {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(formBody),
'Connection': 'keep-alive',
'User-Agent': 'Nginx Proxy Manager',
'User-Agent': 'NPMplus',
'Accept': '*/*'
}
};

View File

@@ -1,8 +1,8 @@
{
"name": "nginx-proxy-manager",
"name": "npmplus",
"version": "0.0.0",
"description": "A beautiful interface for creating Nginx endpoints",
"main": "js/index.js",
"main": "index.js",
"dependencies": {
"@apidevtools/json-schema-ref-parser": "11.1.0",
"ajv": "6.12.6",
@@ -15,21 +15,21 @@
"express-fileupload": "1.4.1",
"gravatar": "1.8.2",
"jsonwebtoken": "9.0.2",
"knex": "2.5.1",
"knex": "3.0.1",
"liquidjs": "10.9.2",
"lodash": "4.17.21",
"moment": "2.29.4",
"mysql": "2.18.1",
"node-rsa": "1.1.1",
"objection": "3.1.1",
"objection": "3.1.2",
"path": "0.12.7",
"signale": "1.4.0",
"sqlite3": "5.1.6"
},
"author": "Jamie Curnow <jc@jc21.com>",
"author": "Jamie Curnow <jc@jc21.com> and ZoeyVid <zoeyvid@zvcdn.de>",
"license": "MIT",
"devDependencies": {
"eslint": "8.50.0",
"eslint": "8.51.0",
"eslint-plugin-align-assignments": "1.1.2"
}
}

View File

@@ -9,7 +9,7 @@ const sqlite3 = require('sqlite3');
function usage() {
console.log(`usage: node ${process.argv[1]} USER_EMAIL PASSWORD
Reset password of a Nginx Proxy Manager user.
Reset password of a NPMplus user.
Arguments:
USER_EMAIL Email address of the user to reset the password.
@@ -56,4 +56,4 @@ if (fs.existsSync(process.env.DB_SQLITE_FILE)) {
}
);
});
}
}

View File

@@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "root",
"title": "Nginx Proxy Manager REST API",
"description": "This is the Nginx Proxy Manager REST API",
"title": "NPMplus REST API",
"description": "This is the NPMplus REST API",
"version": "2.0.0",
"links": [
{

View File

@@ -1,7 +1,17 @@
{% if certificate and certificate_id > 0 -%}
{% if ssl_forced == 1 or ssl_forced == true %}
{% if hsts_enabled == 1 or hsts_enabled == true %}
security_headers on;
add_header X-XSS-Protection "0" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src https: 'unsafe-inline' 'unsafe-eval'; upgrade-insecure-requests" always;
add_header Expect-CT "enforce; max-age=86400" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Cross-Origin-Embedder-Policy-Report-Only "require-corp; report-to='default'" always;
add_header Cross-Origin-Opener-Policy-Report-Only "same-origin-allow-popups; report-to='default'" always;
{% endif %}
{% endif %}
{% endif %}

View File

@@ -1,8 +1,8 @@
version: "3"
services:
caddy:
container_name: nginx-proxy-manager-caddy
image: zoeyvid/nginx-proxy-manager:caddy
npmplus-caddy:
container_name: npmplus-caddy
image: zoeyvid/npmplus:caddy
restart: always
network_mode: bridge
ports:
@@ -10,6 +10,6 @@ services:
environment:
- "TZ=Europe/Berlin"
nginx-proxy-manager:
npmplus:
environment:
- "DISABLE_HTTP=true" # disables nginx to listen on port 80, default false

View File

@@ -1,8 +1,8 @@
version: "3"
services:
nginx-proxy-manager:
container_name: nginx-proxy-manager
image: zoeyvid/nginx-proxy-manager
npmplus:
container_name: npmplus
image: zoeyvid/npmplus
restart: always
network_mode: host
volumes:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,4 +1,4 @@
<% var title = 'Nginx Proxy Manager' %>
<% var title = 'NPMplus' %>
<%- include partials/header.ejs %>
<div id="app" class="page">

View File

@@ -1,4 +1,4 @@
<% var title = 'Login &ndash; Nginx Proxy Manager' %>
<% var title = 'Login &ndash; NPMplus' %>
<%- include partials/header.ejs %>
<div class="page" id="login" data-version="<%= version %>">

View File

@@ -60,7 +60,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://github.com/GetPageSpeed/ngx_security_headers" target="_blank"><i class="fe fe-help-circle"></i></a></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://github.com/ZoeyVid/NPMplus/blob/develop/backend/templates/_hsts.conf" target="_blank"><i class="fe fe-help-circle"></i></a></span>
</label>
</div>
</div>

View File

@@ -128,7 +128,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://github.com/GetPageSpeed/ngx_security_headers" target="_blank"><i class="fe fe-help-circle"></i></a></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://github.com/ZoeyVid/NPMplus/blob/develop/backend/templates/_hsts.conf" target="_blank"><i class="fe fe-help-circle"></i></a></span>
</label>
</div>
</div>

View File

@@ -109,7 +109,7 @@
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://github.com/GetPageSpeed/ngx_security_headers" target="_blank"><i class="fe fe-help-circle"></i></a></span>
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://github.com/ZoeyVid/NPMplus/blob/develop/backend/templates/_hsts.conf" target="_blank"><i class="fe fe-help-circle"></i></a></span>
</label>
</div>
</div>

View File

@@ -4,7 +4,7 @@
<div class="col-auto">
<ul class="list-inline list-inline-dots mb-0">
<li class="list-inline-item"><a href="#" onclick="toggleDarkMode()">Toggle Dark Mode</a></li>
<li class="list-inline-item"><a href="https://github.com/ZoeyVid/nginx-proxy-manager" target="_blank"><%- i18n('footer', 'fork-me') %></a></li>
<li class="list-inline-item"><a href="https://github.com/ZoeyVid/NPMplus" target="_blank"><%- i18n('footer', 'fork-me') %></a></li>
</ul>
</div>
</div>

View File

@@ -41,9 +41,9 @@
"title": "Login to your account"
},
"main": {
"app": "Nginx Proxy Manager",
"app": "NPMplus",
"version": "0.0.0",
"welcome": "Welcome to Nginx Proxy Manager",
"welcome": "Welcome to NPMplus",
"logged-in": "You are logged in as {name}",
"unknown-error": "Error loading stuff. Please reload the app.",
"unknown-user": "Unknown User",
@@ -60,8 +60,8 @@
},
"footer": {
"fork-me": "Repository on GitHub",
"copy": "&copy; 2023 <a href=\"{url}\" target=\"_blank\">jc21.com</a>",
"copyzv": "and 2023 <a href=\"{url}\" target=\"_blank\">ZoeyVid</a> MIT-License.",
"copy": "&copy; 2023 <a href=\"{url}\" target=\"_blank\">jc21.com</a> NPM",
"copyzv": "and &copy; 2023 <a href=\"{url}\" target=\"_blank\">ZoeyVid</a> NPMplus - MIT-License - ",
"theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler v0.0.31</a>"
},
"dashboard": {
@@ -87,7 +87,7 @@
"advanced-config": "Custom Nginx Configuration",
"advanced-config-var-headline": "These proxy details are available as nginx variables:",
"advanced-config-header-info": "Please note, adding a location '/' will overwrite the proxy configuration",
"hsts-enabled": "Enable security headers",
"hsts-enabled": "Enable HSTS and security headers",
"hsts-subdomains": "Enable HTTP/3-Quic",
"locations": "Custom locations"
},
@@ -129,7 +129,7 @@
"delete": "Delete Proxy Host",
"delete-confirm": "Are you sure you want to delete the Proxy host for: <strong>{domains}</strong>?",
"help-title": "What is a Proxy Host?",
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional TLS termination for your service that might not have TLS support built in.\nProxy Hosts are the most common use for the Nginx Proxy Manager.",
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional TLS termination for your service that might not have TLS support built in.\nProxy Hosts are the most common use for the NPMplus.",
"access-list": "Access List",
"allow-websocket-upgrade": "Websockets Support",
"ignore-invalid-upstream-ssl": "Ignore Invalid TLS",
@@ -201,7 +201,7 @@
"reachability-failed-to-reach-api": "Communication with the API failed, is NPM running correctly?",
"reachability-failed-to-check": "Failed to check the reachability due to a communication error with site24x7.com.",
"reachability-ok": "Your server is reachable and creating certificates should be possible.",
"reachability-404": "There is a server found at this domain but it does not seem to be Nginx Proxy Manager. Please make sure your domain points to the IP where your NPM instance is running.",
"reachability-404": "There is a server found at this domain but it does not seem to be NPMplus. Please make sure your domain points to the IP where your NPM instance is running.",
"reachability-not-resolved": "There is no server available at this domain. Please make sure your domain exists and points to the IP where your NPM instance is running and if necessary port 80 is forwarded in your router.",
"reachability-wrong-data": "There is a server found at this domain but it returned an unexpected data. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.",
"reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.",

View File

@@ -1,5 +1,5 @@
{
"name": "nginx-proxy-manager",
"name": "npmplus",
"version": "0.0.0",
"description": "A beautiful interface for creating Nginx endpoints",
"main": "js/index.js",
@@ -41,6 +41,6 @@
"scripts": {
"build": "webpack --mode production"
},
"author": "Jamie Curnow <jc@jc21.com>",
"author": "Jamie Curnow <jc@jc21.com> and ZoeyVid <zoeyvid@zvcdn.de>",
"license": "MIT"
}

View File

@@ -447,9 +447,20 @@ aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
dependencies: '',
credentials: `dns_strato_username = user
dns_strato_password = pass
# uncomment if you're using two factor authentication:
# dns_strato_totp_devicename = 2fa_device
# dns_strato_totp_secret = 2fa_secret
#
# uncomment if domain name contains special characters
# insert domain display name as seen on your account page here
# dns_strato_domain_display_name = my-punicode-url.de`,
# dns_strato_domain_display_name = my-punicode-url.de
#
# if you're not using strato.de or another special endpoint you can customise it below
# you will probably only need to adjust the host, but you can also change the complete endpoint url
# dns_strato_custom_api_scheme = https
# dns_strato_custom_api_host = www.strato.de
# dns_strato_custom_api_port = 443
# dns_strato_custom_api_path = "/apps/CustomerService"`,
full_plugin_name: 'dns-strato',
},
//####################################################//

8
rootfs/bin/aio.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
if [ "$NC_AIO" = "true" ] && [ ! -f /data/etc/aio.lock ]; then
while [ "$(healthcheck.sh)" != "OK" ]; do sleep 10s; done
curl -POST http://127.0.0.1:48693/nginx/proxy-hosts -sH 'Content-Type: application/json' -d '{"domain_names":["'"$NC_DOMAIN"'"],"forward_scheme":"http","forward_host":"127.0.0.1","forward_port":11000,"allow_websocket_upgrade":true,"access_list_id":"0","certificate_id":"new","ssl_forced":true,"http2_support":true,"hsts_enabled":true,"hsts_subdomains":true,"meta":{"letsencrypt_email":"","letsencrypt_agree":true,"dns_challenge":false},"advanced_config":"","locations":[],"block_exploits":false,"caching_enabled":false}' -H "Authorization: Bearer $(curl -POST http://127.0.0.1:48693/tokens -sH 'Content-Type: application/json' -d '{"identity":"admin@example.com","secret":"iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi"}' | jq -r .token)"
touch /data/etc/aio.lock
echo "The default config for AIO should now be created. Please check the log for any errors and try to resolve them, then delete the aio.lock file and retry."
fi

View File

@@ -38,4 +38,5 @@ fi
if [ "$PHP81" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/81/conf.d php-fpm81 -c /data/php/81 -y /data/php/81/php-fpm.conf -FOR; fi &
if [ "$PHP82" = "true" ]; then PHP_INI_SCAN_DIR=/data/php/82/conf.d php-fpm82 -c /data/php/82 -y /data/php/82/php-fpm.conf -FOR; fi &
aio.sh &
index.js

View File

@@ -121,11 +121,23 @@ if [ -n "$PHP82_APKS" ] && ! echo "$PHP82_APKS" | grep -q "^[a-z0-9 _-]\+$"; the
fi
if [ -n "$NC_AIO" ] && ! echo "$NC_AIO" | grep -q "^true$\|^false$"; then
echo "NC_AIO needs to be true or false."
sleep inf
fi
if [ -n "$NC_AIO" ] && ! echo "$NC_DOMAIN" | grep -q "^[a-z0-9.]\+$"; then
echo "NC_DOMAIN can consist of lower letters a-z, numbers 0-9 and dots and is required in AIO mode."
sleep inf
fi
if [ "$PGID" != "0" ] && [ "$PUID" = "0" ]; then
echo "You've set PGID but not PUID. Running resetting PGID to 0."
export PGID="0"
fi
if [ "$NPM_LISTEN_LOCALHOST" = "true" ]; then
export NPM_IPV4_BINDING="127.0.0.1"
export NPM_IPV6_BINDING="[::1]"

View File

@@ -18,7 +18,7 @@
<h1 class="text-center">404 Not Found</h1>
</div>
<p class="text-center">
<small>Powered by <a href="https://github.com/ZoeyVid/nginx-proxy-manager" target="_blank">Nginx Proxy Manager</a>
<small>Powered by <a href="https://github.com/ZoeyVid/NPMplus" target="_blank">NPMplus</a>
</small>
</p>
</div>

View File

@@ -16,12 +16,12 @@
<div class="container">
<div class="jumbotron">
<h1 class="text-center">Congratulations!</h1>
<p>You've successfully started the Nginx Proxy Manager.</p>
<p>You've successfully started NPMplus.</p>
<p>If you're seeing this site then you're trying to access a host that isn't set up yet.</p>
<p>Log in to the Admin panel to get started.</p>
</div>
<p class="text-center">
<small>Powered by <a href="https://github.com/ZoeyVid/nginx-proxy-manager" target="_blank">Nginx Proxy Manager</a>
<small>Powered by <a href="https://github.com/ZoeyVid/NPMplus" target="_blank">NPMplus</a>
</small>
</p>
</div>