5
.github/delete-merged-branch-config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
exclude:
|
||||||
|
- main
|
||||||
|
- stable
|
||||||
|
- develop
|
||||||
|
delete_closed_pr: true
|
37
.github/workflows/docker-latest.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
name: Docker push develop to latest
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Push develop to latest
|
||||||
|
run: |
|
||||||
|
curl -L https://github.com/regclient/regclient/releases/latest/download/regctl-linux-amd64 -o ./regctl
|
||||||
|
chmod +x ./regctl
|
||||||
|
./regctl image copy ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ github.ref_name }} ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:latest
|
||||||
|
./regctl image copy ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ github.ref_name }} ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:latest
|
||||||
|
|
||||||
|
- name: Show Nginx version
|
||||||
|
run: |
|
||||||
|
docker run --rm --entrypoint nginx ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:latest -V
|
||||||
|
docker run --rm --entrypoint nginx ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:latest -V
|
132
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
name: Build Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
paths:
|
||||||
|
- .github/workflows/docker.yml
|
||||||
|
- Dockerfile
|
||||||
|
- frontend/**
|
||||||
|
- backend/**
|
||||||
|
- global/**
|
||||||
|
- rootfs/**
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- .github/workflows/docker.yml
|
||||||
|
- Dockerfile
|
||||||
|
- frontend/**
|
||||||
|
- backend/**
|
||||||
|
- global/**
|
||||||
|
- rootfs/**
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
with:
|
||||||
|
platforms: arm64 #all
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
driver-opts: env.BUILDKIT_STEP_LOG_MAX_SIZE=-1
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ github.token }}
|
||||||
|
|
||||||
|
- name: Read .version file
|
||||||
|
id: version
|
||||||
|
run: echo "version=$(cat .version)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set versions
|
||||||
|
run: |
|
||||||
|
sed -i 's/"0.0.0"/"${{ steps.version.outputs.version }}"/g' frontend/package.json
|
||||||
|
cat frontend/package.json | grep "${{ steps.version.outputs.version }}"
|
||||||
|
sed -i 's/"0.0.0"/"${{ steps.version.outputs.version }}"/g' backend/package.json
|
||||||
|
cat backend/package.json | grep "${{ steps.version.outputs.version }}"
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
|
||||||
|
- name: Prepair frontend
|
||||||
|
run: |
|
||||||
|
export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
|
npm install --global yarn
|
||||||
|
cd frontend
|
||||||
|
yarn install
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
- name: Test Backend
|
||||||
|
run: |
|
||||||
|
export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
|
export DB_SQLITE_FILE=/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/backend-test/dev.sqlite
|
||||||
|
export NODE_ENV=dev
|
||||||
|
mv global backend
|
||||||
|
cp -r backend backend-test
|
||||||
|
cd backend-test
|
||||||
|
npm install --force
|
||||||
|
timeout 10 node --abort_on_uncaught_exception --max_old_space_size=250 index.js || if [ "$?" == "124" ]; then exit 0; else exit 1; fi
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
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.ref == 'refs/heads/develop' }}
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ github.ref_name }}
|
||||||
|
${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ github.ref_name }}
|
||||||
|
|
||||||
|
- name: show version
|
||||||
|
if: ${{ github.ref == 'refs/heads/develop' }}
|
||||||
|
run: |
|
||||||
|
docker run --rm --entrypoint nginx ${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ github.ref_name }} -V
|
||||||
|
docker run --rm --entrypoint nginx ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ github.ref_name }} -V
|
||||||
|
|
||||||
|
- name: Set PR-Number (PR)
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
id: pr
|
||||||
|
run: echo "pr=$(echo pr-${{ github.ref_name }} | sed "s/refs\/pull\/://g" | sed "s/\/merge//g")" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Build (PR)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
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/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ steps.pr.outputs.pr }}
|
||||||
|
|
||||||
|
- name: show version (PR)
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
run: docker run --rm --entrypoint nginx ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ 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/${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }}:${{ steps.pr.outputs.pr }}`"
|
||||||
|
repo-token: ${{ github.token }}
|
16
.github/workflows/json.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
name: JSON check
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-json:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: json-syntax-check
|
||||||
|
uses: limitusus/json-syntax-check@v2
|
||||||
|
with:
|
||||||
|
pattern: "\\.json$*"
|
785
.gitignore
vendored
@@ -1,5 +1,784 @@
|
|||||||
.DS_Store
|
# User-specific stuff
|
||||||
.idea
|
.idea
|
||||||
|
desktop.files.json
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
desktop.ini
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
composer.phar
|
||||||
|
/vendor/
|
||||||
|
|
||||||
|
!/jobs
|
||||||
|
!/.gitignore
|
||||||
|
!/*.xml
|
||||||
|
|
||||||
|
#ignore all files in jobs subdirectories except for folders
|
||||||
|
#note: git doesn't track folders, only file content
|
||||||
|
jobs/**
|
||||||
|
!jobs/**/
|
||||||
|
|
||||||
|
#uncomment the following line to save next build numbers with config
|
||||||
|
#!jobs/**/nextBuildNumber
|
||||||
|
|
||||||
|
#exclude only config.xml files in repository subdirectories
|
||||||
|
!config.xml
|
||||||
|
|
||||||
|
#don't track workspaces (when users build on the master)
|
||||||
|
jobs/**/*workspace
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
# .nfs files are created when an open file is removed but is still being accessed
|
||||||
|
.nfs*
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
._*
|
._*
|
||||||
.vscode
|
|
||||||
certbot-help.txt
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
.gradle
|
||||||
|
/build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
target/
|
||||||
|
pom.xml.tag
|
||||||
|
pom.xml.releaseBackup
|
||||||
|
pom.xml.versionsBackup
|
||||||
|
pom.xml.next
|
||||||
|
release.properties
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
buildNumber.properties
|
||||||
|
.mvn/timing.properties
|
||||||
|
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
|
||||||
|
.mvn/wrapper/maven-wrapper.jar
|
||||||
|
.flattened-pom.xml
|
||||||
|
|
||||||
|
# Common working directory
|
||||||
|
run
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
.env.test
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and *not* Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
/vendor/
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# Laravel 4 specific
|
||||||
|
bootstrap/compiled.php
|
||||||
|
app/storage/
|
||||||
|
|
||||||
|
# Laravel 5 & Lumen specific
|
||||||
|
public/storage
|
||||||
|
public/hot
|
||||||
|
|
||||||
|
# Laravel 5 & Lumen specific with changed public path
|
||||||
|
public_html/storage
|
||||||
|
public_html/hot
|
||||||
|
|
||||||
|
storage/*.key
|
||||||
|
.env
|
||||||
|
Homestead.yaml
|
||||||
|
Homestead.json
|
||||||
|
/.vagrant
|
||||||
|
.phpunit.result.cache
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# ignore everything in the root except the "wp-content" directory.
|
||||||
|
!wp-content/
|
||||||
|
|
||||||
|
# ignore everything in the "wp-content" directory, except:
|
||||||
|
# "mu-plugins", "plugins", "themes" directory
|
||||||
|
wp-content/*
|
||||||
|
!wp-content/mu-plugins/
|
||||||
|
!wp-content/plugins/
|
||||||
|
!wp-content/themes/
|
||||||
|
|
||||||
|
# ignore these plugins
|
||||||
|
wp-content/plugins/hello.php
|
||||||
|
|
||||||
|
# ignore specific themes
|
||||||
|
wp-content/themes/twenty*/
|
||||||
|
|
||||||
|
# ignore node dependency directories
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# ignore log files and databases
|
||||||
|
*.log
|
||||||
|
*.sql
|
||||||
|
*.sqlite
|
6
.imgbotconfig
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"schedule": "daily",
|
||||||
|
"aggressiveCompression": "true",
|
||||||
|
"compressWiki": "true",
|
||||||
|
"minKBReduced": 0
|
||||||
|
}
|
13
.whitesource
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"scanSettings": {
|
||||||
|
"baseBranches": []
|
||||||
|
},
|
||||||
|
"checkRunSettings": {
|
||||||
|
"vulnerableCheckRunConclusionLevel": "failure",
|
||||||
|
"displayMode": "diff"
|
||||||
|
},
|
||||||
|
"issueSettings": {
|
||||||
|
"minSeverityLevel": "LOW",
|
||||||
|
"issueType": "DEPENDENCY"
|
||||||
|
}
|
||||||
|
}
|
30
Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
FROM zoeyvid/nginx-quic:20
|
||||||
|
COPY rootfs /
|
||||||
|
COPY backend /app
|
||||||
|
COPY frontend/dist /app/frontend
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN apk upgrade --no-cache && \
|
||||||
|
apk add --no-cache ca-certificates wget tzdata \
|
||||||
|
python3 \
|
||||||
|
nodejs-current npm \
|
||||||
|
openssl apache2-utils jq \
|
||||||
|
gcc g++ libffi-dev python3-dev && \
|
||||||
|
|
||||||
|
# Install pip
|
||||||
|
wget https://bootstrap.pypa.io/get-pip.py -O - | python3 && \
|
||||||
|
|
||||||
|
# Change permission
|
||||||
|
chmod +x /usr/local/bin/start && \
|
||||||
|
chmod +x /usr/local/bin/check-health && \
|
||||||
|
|
||||||
|
# Build Backend
|
||||||
|
npm install --force && \
|
||||||
|
pip install --no-cache-dir certbot && \
|
||||||
|
apk del --no-cache gcc g++ libffi-dev python3-dev npm
|
||||||
|
|
||||||
|
ENV NODE_ENV=production \
|
||||||
|
DB_SQLITE_FILE=/data/database.sqlite
|
||||||
|
|
||||||
|
ENTRYPOINT ["start"]
|
||||||
|
HEALTHCHECK CMD check-health
|
253
Jenkinsfile
vendored
@@ -1,253 +0,0 @@
|
|||||||
pipeline {
|
|
||||||
agent {
|
|
||||||
label 'docker-multiarch'
|
|
||||||
}
|
|
||||||
options {
|
|
||||||
buildDiscarder(logRotator(numToKeepStr: '5'))
|
|
||||||
disableConcurrentBuilds()
|
|
||||||
ansiColor('xterm')
|
|
||||||
}
|
|
||||||
environment {
|
|
||||||
IMAGE = "nginx-proxy-manager"
|
|
||||||
BUILD_VERSION = getVersion()
|
|
||||||
MAJOR_VERSION = "2"
|
|
||||||
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('/', '-')}"
|
|
||||||
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
|
|
||||||
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
|
|
||||||
COMPOSE_INTERACTIVE_NO_CLI = 1
|
|
||||||
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
|
|
||||||
}
|
|
||||||
stages {
|
|
||||||
stage('Environment') {
|
|
||||||
parallel {
|
|
||||||
stage('Master') {
|
|
||||||
when {
|
|
||||||
branch 'master'
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
script {
|
|
||||||
env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Other') {
|
|
||||||
when {
|
|
||||||
not {
|
|
||||||
branch 'master'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
script {
|
|
||||||
// Defaults to the Branch name, which is applies to all branches AND pr's
|
|
||||||
env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Versions') {
|
|
||||||
steps {
|
|
||||||
sh 'cat frontend/package.json | jq --arg BUILD_VERSION "${BUILD_VERSION}" \'.version = $BUILD_VERSION\' | sponge frontend/package.json'
|
|
||||||
sh 'echo -e "\\E[1;36mFrontend Version is:\\E[1;33m $(cat frontend/package.json | jq -r .version)\\E[0m"'
|
|
||||||
sh 'cat backend/package.json | jq --arg BUILD_VERSION "${BUILD_VERSION}" \'.version = $BUILD_VERSION\' | sponge backend/package.json'
|
|
||||||
sh 'echo -e "\\E[1;36mBackend Version is:\\E[1;33m $(cat backend/package.json | jq -r .version)\\E[0m"'
|
|
||||||
sh 'sed -i -E "s/(version-)[0-9]+\\.[0-9]+\\.[0-9]+(-green)/\\1${BUILD_VERSION}\\2/" README.md'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Frontend') {
|
|
||||||
steps {
|
|
||||||
sh './scripts/frontend-build'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Backend') {
|
|
||||||
steps {
|
|
||||||
echo 'Checking Syntax ...'
|
|
||||||
sh 'docker pull nginxproxymanager/nginx-full:certbot-node'
|
|
||||||
// See: https://github.com/yarnpkg/yarn/issues/3254
|
|
||||||
sh '''docker run --rm \\
|
|
||||||
-v "$(pwd)/backend:/app" \\
|
|
||||||
-v "$(pwd)/global:/app/global" \\
|
|
||||||
-w /app \\
|
|
||||||
nginxproxymanager/nginx-full:certbot-node \\
|
|
||||||
sh -c "yarn install && yarn eslint . && rm -rf node_modules"
|
|
||||||
'''
|
|
||||||
|
|
||||||
echo 'Docker Build ...'
|
|
||||||
sh '''docker build --pull --no-cache --squash --compress \\
|
|
||||||
-t "${IMAGE}:ci-${BUILD_NUMBER}" \\
|
|
||||||
-f docker/Dockerfile \\
|
|
||||||
--build-arg TARGETPLATFORM=linux/amd64 \\
|
|
||||||
--build-arg BUILDPLATFORM=linux/amd64 \\
|
|
||||||
--build-arg BUILD_VERSION="${BUILD_VERSION}" \\
|
|
||||||
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\
|
|
||||||
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\
|
|
||||||
.
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Integration Tests Sqlite') {
|
|
||||||
steps {
|
|
||||||
// Bring up a stack
|
|
||||||
sh 'docker-compose up -d fullstack-sqlite'
|
|
||||||
sh './scripts/wait-healthy $(docker-compose ps -q fullstack-sqlite) 120'
|
|
||||||
|
|
||||||
// Run tests
|
|
||||||
sh 'rm -rf test/results'
|
|
||||||
sh 'docker-compose up cypress-sqlite'
|
|
||||||
// Get results
|
|
||||||
sh 'docker cp -L "$(docker-compose ps -q cypress-sqlite):/test/results" test/'
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
// Dumps to analyze later
|
|
||||||
sh 'mkdir -p debug'
|
|
||||||
sh 'docker-compose logs fullstack-sqlite | gzip > debug/docker_fullstack_sqlite.log.gz'
|
|
||||||
sh 'docker-compose logs db | gzip > debug/docker_db.log.gz'
|
|
||||||
// Cypress videos and screenshot artifacts
|
|
||||||
dir(path: 'test/results') {
|
|
||||||
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
|
||||||
}
|
|
||||||
junit 'test/results/junit/*'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Integration Tests Mysql') {
|
|
||||||
steps {
|
|
||||||
// Bring up a stack
|
|
||||||
sh 'docker-compose up -d fullstack-mysql'
|
|
||||||
sh './scripts/wait-healthy $(docker-compose ps -q fullstack-mysql) 120'
|
|
||||||
|
|
||||||
// Run tests
|
|
||||||
sh 'rm -rf test/results'
|
|
||||||
sh 'docker-compose up cypress-mysql'
|
|
||||||
// Get results
|
|
||||||
sh 'docker cp -L "$(docker-compose ps -q cypress-mysql):/test/results" test/'
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
// Dumps to analyze later
|
|
||||||
sh 'mkdir -p debug'
|
|
||||||
sh 'docker-compose logs fullstack-mysql | gzip > debug/docker_fullstack_mysql.log.gz'
|
|
||||||
sh 'docker-compose logs db | gzip > debug/docker_db.log.gz'
|
|
||||||
// Cypress videos and screenshot artifacts
|
|
||||||
dir(path: 'test/results') {
|
|
||||||
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
|
||||||
}
|
|
||||||
junit 'test/results/junit/*'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Docs') {
|
|
||||||
when {
|
|
||||||
not {
|
|
||||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
dir(path: 'docs') {
|
|
||||||
sh 'yarn install'
|
|
||||||
sh 'yarn build'
|
|
||||||
}
|
|
||||||
|
|
||||||
dir(path: 'docs/.vuepress/dist') {
|
|
||||||
sh 'tar -czf ../../docs.tgz *'
|
|
||||||
}
|
|
||||||
|
|
||||||
archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('MultiArch Build') {
|
|
||||||
when {
|
|
||||||
not {
|
|
||||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
|
||||||
// Docker Login
|
|
||||||
sh "docker login -u '${duser}' -p '${dpass}'"
|
|
||||||
// Buildx with push from cache
|
|
||||||
sh "./scripts/buildx --push ${BUILDX_PUSH_TAGS}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('Docs Deploy') {
|
|
||||||
when {
|
|
||||||
allOf {
|
|
||||||
branch 'master'
|
|
||||||
not {
|
|
||||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'npm-s3-docs', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
|
||||||
sh """docker run --rm \\
|
|
||||||
--name \${COMPOSE_PROJECT_NAME}-docs-upload \\
|
|
||||||
-e S3_BUCKET=jc21-npm-site \\
|
|
||||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
|
|
||||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
|
|
||||||
-v \$(pwd):/app \\
|
|
||||||
-w /app \\
|
|
||||||
jc21/ci-tools \\
|
|
||||||
scripts/docs-upload /app/docs/.vuepress/dist/
|
|
||||||
"""
|
|
||||||
|
|
||||||
sh """docker run --rm \\
|
|
||||||
--name \${COMPOSE_PROJECT_NAME}-docs-invalidate \\
|
|
||||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
|
|
||||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
|
|
||||||
jc21/ci-tools \\
|
|
||||||
aws cloudfront create-invalidation --distribution-id EN1G6DEWZUTDT --paths '/*'
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stage('PR Comment') {
|
|
||||||
when {
|
|
||||||
allOf {
|
|
||||||
changeRequest()
|
|
||||||
not {
|
|
||||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
steps {
|
|
||||||
script {
|
|
||||||
def comment = pullRequest.comment("This is an automated message from CI:\n\nDocker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
sh 'docker-compose down --remove-orphans --volumes -t 30'
|
|
||||||
sh 'echo Reverting ownership'
|
|
||||||
sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
|
|
||||||
}
|
|
||||||
success {
|
|
||||||
juxtapose event: 'success'
|
|
||||||
sh 'figlet "SUCCESS"'
|
|
||||||
}
|
|
||||||
failure {
|
|
||||||
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
|
|
||||||
juxtapose event: 'failure'
|
|
||||||
sh 'figlet "FAILURE"'
|
|
||||||
}
|
|
||||||
unstable {
|
|
||||||
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
|
|
||||||
juxtapose event: 'unstable'
|
|
||||||
sh 'figlet "UNSTABLE"'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def getVersion() {
|
|
||||||
ver = sh(script: 'cat .version', returnStdout: true)
|
|
||||||
return ver.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
def getCommit() {
|
|
||||||
ver = sh(script: 'git log -n 1 --format=%h', returnStdout: true)
|
|
||||||
return ver.trim()
|
|
||||||
}
|
|
85
README.md
@@ -1,21 +1,22 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://nginxproxymanager.com/github.png">
|
<img src="https://nginxproxymanager.com/github.png">
|
||||||
<br><br>
|
<br><br>
|
||||||
<img src="https://img.shields.io/badge/version-2.9.19-green.svg?style=for-the-badge">
|
<img src="https://img.shields.io/badge/version-2.9.19+-green.svg?style=for-the-badge">
|
||||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
<a href="https://hub.docker.com/r/zoeyvid/nginx-proxy-manager">
|
||||||
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
<img src="https://img.shields.io/docker/stars/zoeyvid/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
<a href="https://hub.docker.com/r/zoeyvid/nginx-proxy-manager">
|
||||||
<img src="https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
<img src="https://img.shields.io/docker/pulls/zoeyvid/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
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 SSL, without having to know too much about Nginx or Letsencrypt.
|
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
||||||
|
|
||||||
- [Quick Setup](#quick-setup)
|
- [Quick Setup](#quick-setup)
|
||||||
- [Full Setup](https://nginxproxymanager.com/setup/)
|
- [Screenshots](https://nginxproxymanager.com/screenshots)
|
||||||
- [Screenshots](https://nginxproxymanager.com/screenshots/)
|
|
||||||
|
|
||||||
## Project Goal
|
## Project Goal
|
||||||
|
|
||||||
@@ -37,6 +38,26 @@ so that the barrier for entry here is low.
|
|||||||
- User management, permissions and audit log
|
- User management, permissions and audit log
|
||||||
|
|
||||||
|
|
||||||
|
# New Features
|
||||||
|
|
||||||
|
- HTTP/3 (QUIC) Support if you enable HTTP/2 (can not be enabled separate)
|
||||||
|
- Fix Proxy Hosts, if origin only accepts TLSv1.3
|
||||||
|
- Only use TLSv1.2 and TLSv1.3
|
||||||
|
- Uses OCSP Stapling
|
||||||
|
- Needs manual migration if you use custom certificates, just upload the CA/Intermediate Certificate (file name: `chain.pem`) in the `/opt/npm/custom_ssl/npm-[certificate-id]` folder
|
||||||
|
- Smaller then the original
|
||||||
|
- Runs the admin interface on port 81 with ssl (https)
|
||||||
|
- Default page runs also with ssl (https)
|
||||||
|
- Uses [fancyindex](https://gitHub.com/Naereen/Nginx-Fancyindex-Theme) if you use the npm directly as webserver
|
||||||
|
- Expose INTERNAL backend api only to localhost
|
||||||
|
- Easy security headers, see [here](https://github.com/GetPageSpeed/ngx_security_headers), enabled by default if you enable hsts
|
||||||
|
- Access Log disabled
|
||||||
|
- Error Log written to console
|
||||||
|
|
||||||
|
## Soon
|
||||||
|
- more
|
||||||
|
- I will try to create a pr to contribute to the original project
|
||||||
|
|
||||||
## Hosting your home network
|
## Hosting your home network
|
||||||
|
|
||||||
I won't go in to too much detail here but here are the basics for someone new to this self-hosted world.
|
I won't go in to too much detail here but here are the basics for someone new to this self-hosted world.
|
||||||
@@ -48,36 +69,34 @@ I won't go in to too much detail here but here are the basics for someone new to
|
|||||||
|
|
||||||
## Quick Setup
|
## Quick Setup
|
||||||
|
|
||||||
1. Install Docker and Docker-Compose
|
1. Install Docker and Docker Compose
|
||||||
|
|
||||||
- [Docker Install documentation](https://docs.docker.com/install/)
|
- [Docker Install documentation](https://docs.docker.com/engine)
|
||||||
- [Docker-Compose Install documentation](https://docs.docker.com/compose/install/)
|
- [Docker Compose Install documentation](https://docs.docker.com/compose/install/linux)
|
||||||
|
|
||||||
2. Create a docker-compose.yml file similar to this:
|
2. Create a compose.yaml file similar to this:
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
version: '3'
|
version: "3"
|
||||||
services:
|
services:
|
||||||
app:
|
nginx-proxy-manager:
|
||||||
image: 'jc21/nginx-proxy-manager:latest'
|
container_name: nginx-proxy-manager
|
||||||
restart: unless-stopped
|
image: zoeyvid/nginx-proxy-manager
|
||||||
ports:
|
restart: always
|
||||||
- '80:80'
|
network_mode: host
|
||||||
- '81:81'
|
volumes:
|
||||||
- '443:443'
|
- "/opt/npm:/data"
|
||||||
volumes:
|
- "/opt/npm-letsencrypt:/etc/letsencrypt" # Only needed for first time migration from original nginx-proxy-manager to this fork
|
||||||
- ./data:/data
|
- "/var/www:/var/www" # optional, if you want to use it as webserver for html
|
||||||
- ./letsencrypt:/etc/letsencrypt
|
environment:
|
||||||
|
- "TZ=Europe/Berlin"
|
||||||
|
# - "NGINX_LOG_NOT_FOUND=true" # Allow logging of 404 errors
|
||||||
|
# - "NPM_LISTEN_LOCALHOST=true" # Bind the NPM Dashboard on Port 81 only to localhost
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Bring up your stack by running
|
3. Bring up your stack by running
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# If using docker-compose-plugin
|
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Log in to the Admin UI
|
4. Log in to the Admin UI
|
||||||
@@ -85,12 +104,12 @@ docker compose up -d
|
|||||||
When your docker container is running, connect to it on port `81` for the admin interface.
|
When your docker container is running, connect to it on port `81` for the admin interface.
|
||||||
Sometimes this can take a little bit because of the entropy of keys.
|
Sometimes this can take a little bit because of the entropy of keys.
|
||||||
|
|
||||||
[http://127.0.0.1:81](http://127.0.0.1:81)
|
[https://127.0.0.1:81](https://127.0.0.1:81)
|
||||||
|
|
||||||
Default Admin User:
|
Default Admin User:
|
||||||
```
|
```
|
||||||
Email: admin@example.com
|
Email: admin@example.com
|
||||||
Password: changeme
|
Password: 9KcvfmAvcVonB7YOMqdjJGsTG2JL058Rx6xFNMintAeaGETsRBRlSbfXdi1inoCa
|
||||||
```
|
```
|
||||||
|
|
||||||
Immediately after logging in with this default user you will be asked to modify your details and change your password.
|
Immediately after logging in with this default user you will be asked to modify your details and change your password.
|
||||||
@@ -101,9 +120,13 @@ Immediately after logging in with this default user you will be asked to modify
|
|||||||
Special thanks to [all of our contributors](https://github.com/NginxProxyManager/nginx-proxy-manager/graphs/contributors).
|
Special thanks to [all of our contributors](https://github.com/NginxProxyManager/nginx-proxy-manager/graphs/contributors).
|
||||||
|
|
||||||
|
|
||||||
|
# Please report Bugs first to this fork before reporting them to the original Repository
|
||||||
|
|
||||||
## Getting Support
|
## Getting Support
|
||||||
|
|
||||||
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
|
1. [Found a bug?](https://github.com/ZoeyVid/nginx-proxy-manager/issues)
|
||||||
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
|
2. [Discussions](https://github.com/ZoeyVid/nginx-proxy-manager/discussions)
|
||||||
|
<!---
|
||||||
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community)
|
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community)
|
||||||
4. [Reddit](https://reddit.com/r/nginxproxymanager)
|
4. [Reddit](https://reddit.com/r/nginxproxymanager)
|
||||||
|
--->
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
const config = require('config');
|
const config = require('config');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
if (!config.has('database')) {
|
if (!config.has('database')) {
|
||||||
throw new Error('Database config does not exist! Please read the instructions: https://github.com/jc21/nginx-proxy-manager/blob/master/doc/INSTALL.md');
|
throw new Error('Database config does not exist! Please read the instructions: https://github.com/jc21/nginx-proxy-manager/blob/master/doc/INSTALL.md');
|
||||||
@@ -7,8 +8,8 @@ if (!config.has('database')) {
|
|||||||
function generateDbConfig() {
|
function generateDbConfig() {
|
||||||
if (config.database.engine === 'knex-native') {
|
if (config.database.engine === 'knex-native') {
|
||||||
return config.database.knex;
|
return config.database.knex;
|
||||||
} else
|
} else {
|
||||||
return {
|
let newConfig = {
|
||||||
client: config.database.engine,
|
client: config.database.engine,
|
||||||
connection: {
|
connection: {
|
||||||
host: config.database.host,
|
host: config.database.host,
|
||||||
@@ -21,6 +22,16 @@ function generateDbConfig() {
|
|||||||
tableName: 'migrations'
|
tableName: 'migrations'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (process.env.DB_MYSQL_CA) {
|
||||||
|
newConfig.connection.ssl = {
|
||||||
|
ca: fs.readFileSync(process.env.DB_MYSQL_CA),
|
||||||
|
rejectUnauthorized: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return newConfig;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -30,4 +41,4 @@ if (typeof config.database.version !== 'undefined') {
|
|||||||
data.version = config.database.version;
|
data.version = config.database.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = require('knex')(data);
|
module.exports = require('knex')(data);
|
@@ -1151,7 +1151,7 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"maxLength": 64,
|
"maxLength": 64,
|
||||||
"example": "changeme"
|
"example": "9KcvfmAvcVonB7YOMqdjJGsTG2JL058Rx6xFNMintAeaGETsRBRlSbfXdi1inoCa"
|
||||||
},
|
},
|
||||||
"secret": {
|
"secret": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@@ -24,8 +24,8 @@ async function appStart () {
|
|||||||
internalCertificate.initTimer();
|
internalCertificate.initTimer();
|
||||||
internalIpRanges.initTimer();
|
internalIpRanges.initTimer();
|
||||||
|
|
||||||
const server = app.listen(3000, () => {
|
const server = app.listen(48693, '127.0.0.1', () => {
|
||||||
logger.info('Backend PID ' + process.pid + ' listening on port 3000 ...');
|
logger.info('Backend PID ' + process.pid + ' listening on port 48693 ...');
|
||||||
|
|
||||||
process.on('SIGTERM', () => {
|
process.on('SIGTERM', () => {
|
||||||
logger.info('PID ' + process.pid + ' received SIGTERM');
|
logger.info('PID ' + process.pid + ' received SIGTERM');
|
||||||
@@ -132,4 +132,3 @@ try {
|
|||||||
logger.error(err.message, err);
|
logger.error(err.message, err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,8 +12,8 @@ const internalAuditLog = require('./audit-log');
|
|||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const internalHost = require('./host');
|
const internalHost = require('./host');
|
||||||
const letsencryptStaging = process.env.NODE_ENV !== 'production';
|
const letsencryptStaging = process.env.NODE_ENV !== 'production';
|
||||||
const letsencryptConfig = '/etc/letsencrypt.ini';
|
const letsencryptConfig = '/usr/local/nginx/conf/letsencrypt.ini';
|
||||||
const certbotCommand = 'certbot';
|
const certbotCommand = 'certbot --config-dir /data/letsencrypt';
|
||||||
const archiver = require('archiver');
|
const archiver = require('archiver');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { isArray } = require('lodash');
|
const { isArray } = require('lodash');
|
||||||
@@ -74,7 +74,7 @@ const internalCertificate = {
|
|||||||
|
|
||||||
certificates.map(function (certificate) {
|
certificates.map(function (certificate) {
|
||||||
promises.push(
|
promises.push(
|
||||||
internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
|
internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
|
||||||
.then((cert_info) => {
|
.then((cert_info) => {
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
@@ -204,7 +204,7 @@ const internalCertificate = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point, the letsencrypt cert should exist on disk.
|
// At this point, the letsencrypt cert should exist on disk.
|
||||||
// Lets get the expiry date from the file and update the row silently
|
// Lets get the expiry date from the file and update the row silently
|
||||||
return internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
|
return internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
|
||||||
.then((cert_info) => {
|
.then((cert_info) => {
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
@@ -354,7 +354,7 @@ const internalCertificate = {
|
|||||||
})
|
})
|
||||||
.then((certificate) => {
|
.then((certificate) => {
|
||||||
if (certificate.provider === 'letsencrypt') {
|
if (certificate.provider === 'letsencrypt') {
|
||||||
const zipDirectory = '/etc/letsencrypt/live/npm-' + data.id;
|
const zipDirectory = '/data/letsencrypt/live/npm-' + data.id;
|
||||||
|
|
||||||
if (!fs.existsSync(zipDirectory)) {
|
if (!fs.existsSync(zipDirectory)) {
|
||||||
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
|
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
|
||||||
@@ -548,6 +548,14 @@ const internalCertificate = {
|
|||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fs.writeFile(dir + '/chain.pem', certificate.meta.intermediate_certificate, function (err) {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -868,12 +876,12 @@ const internalCertificate = {
|
|||||||
throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`);
|
throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
logger.info(`Requesting Let's Encrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||||
|
|
||||||
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentialsLocation = '/data/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
// Escape single quotes and backslashes
|
// Escape single quotes and backslashes
|
||||||
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
||||||
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
const credentialsCmd = 'mkdir -p /data/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
||||||
let prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
|
let prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
|
||||||
|
|
||||||
// Special case for cloudflare
|
// Special case for cloudflare
|
||||||
@@ -946,7 +954,7 @@ const internalCertificate = {
|
|||||||
|
|
||||||
return renewMethod(certificate)
|
return renewMethod(certificate)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem');
|
return internalCertificate.getCertificateInfoFromFile('/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem');
|
||||||
})
|
})
|
||||||
.then((cert_info) => {
|
.then((cert_info) => {
|
||||||
return certificateModel
|
return certificateModel
|
||||||
@@ -1008,7 +1016,7 @@ const internalCertificate = {
|
|||||||
throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`);
|
throw Error(`Unknown DNS provider '${certificate.meta.dns_provider}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
logger.info(`Renewing Let's Encrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||||
|
|
||||||
let mainCmd = certbotCommand + ' renew ' +
|
let mainCmd = certbotCommand + ' renew ' +
|
||||||
'--config "' + letsencryptConfig + '" ' +
|
'--config "' + letsencryptConfig + '" ' +
|
||||||
@@ -1019,7 +1027,7 @@ const internalCertificate = {
|
|||||||
|
|
||||||
// Prepend the path to the credentials file as an environment variable
|
// Prepend the path to the credentials file as an environment variable
|
||||||
if (certificate.meta.dns_provider === 'route53') {
|
if (certificate.meta.dns_provider === 'route53') {
|
||||||
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentialsLocation = '/data/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
|
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1042,12 +1050,12 @@ const internalCertificate = {
|
|||||||
|
|
||||||
const mainCmd = certbotCommand + ' revoke ' +
|
const mainCmd = certbotCommand + ' revoke ' +
|
||||||
'--config "' + letsencryptConfig + '" ' +
|
'--config "' + letsencryptConfig + '" ' +
|
||||||
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
|
'--cert-path "/data/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
|
||||||
'--delete-after-revoke ' +
|
'--delete-after-revoke ' +
|
||||||
(letsencryptStaging ? '--staging' : '');
|
(letsencryptStaging ? '--staging' : '');
|
||||||
|
|
||||||
// Don't fail command if file does not exist
|
// Don't fail command if file does not exist
|
||||||
const delete_credentialsCmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`;
|
const delete_credentialsCmd = `rm -f '/data/letsencrypt/credentials/credentials-${certificate.id}' || true`;
|
||||||
|
|
||||||
logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd);
|
logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd);
|
||||||
|
|
||||||
@@ -1071,7 +1079,7 @@ const internalCertificate = {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
hasLetsEncryptSslCerts: (certificate) => {
|
hasLetsEncryptSslCerts: (certificate) => {
|
||||||
const letsencryptPath = '/etc/letsencrypt/live/npm-' + certificate.id;
|
const letsencryptPath = '/data/letsencrypt/live/npm-' + certificate.id;
|
||||||
|
|
||||||
return fs.existsSync(letsencryptPath + '/fullchain.pem') && fs.existsSync(letsencryptPath + '/privkey.pem');
|
return fs.existsSync(letsencryptPath + '/fullchain.pem') && fs.existsSync(letsencryptPath + '/privkey.pem');
|
||||||
},
|
},
|
||||||
@@ -1147,7 +1155,7 @@ const internalCertificate = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a test challenge file
|
// Create a test challenge file
|
||||||
const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge';
|
const testChallengeDir = '/tmp/letsencrypt-acme-challenge/.well-known/acme-challenge';
|
||||||
const testChallengeFile = testChallengeDir + '/test-challenge';
|
const testChallengeFile = testChallengeDir + '/test-challenge';
|
||||||
fs.mkdirSync(testChallengeDir, {recursive: true});
|
fs.mkdirSync(testChallengeDir, {recursive: true});
|
||||||
fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'});
|
fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'});
|
||||||
|
@@ -125,7 +125,7 @@ const internalIpRanges = {
|
|||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let filename = '/etc/nginx/conf.d/include/ip_ranges.conf';
|
let filename = '/usr/local/nginx/conf/conf.d/include/ip_ranges.conf';
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/ip_ranges.conf', {encoding: 'utf8'});
|
template = fs.readFileSync(__dirname + '/../templates/ip_ranges.conf', {encoding: 'utf8'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@@ -59,7 +59,7 @@ const internalNginx = {
|
|||||||
let valid_lines = [];
|
let valid_lines = [];
|
||||||
let err_lines = err.message.split('\n');
|
let err_lines = err.message.split('\n');
|
||||||
err_lines.map(function (line) {
|
err_lines.map(function (line) {
|
||||||
if (line.indexOf('/var/log/nginx/error.log') === -1) {
|
if (line.indexOf('/data/nginx/error.log') === -1) {
|
||||||
valid_lines.push(line);
|
valid_lines.push(line);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -101,7 +101,7 @@ const internalNginx = {
|
|||||||
logger.info('Testing Nginx configuration');
|
logger.info('Testing Nginx configuration');
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.exec('/usr/sbin/nginx -t -g "error_log off;"');
|
return utils.exec('nginx -t -g "error_log off;"');
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +111,7 @@ const internalNginx = {
|
|||||||
return internalNginx.test()
|
return internalNginx.test()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('Reloading Nginx');
|
logger.info('Reloading Nginx');
|
||||||
return utils.exec('/usr/sbin/nginx -s reload');
|
return utils.exec('nginx -s reload');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ const internalNginx = {
|
|||||||
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
||||||
|
|
||||||
if (host_type === 'default') {
|
if (host_type === 'default') {
|
||||||
return '/data/nginx/default_host/site.conf';
|
return '/data/nginx/default.conf';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '/data/nginx/' + host_type + '/' + host_id + '.conf';
|
return '/data/nginx/' + host_type + '/' + host_id + '.conf';
|
||||||
@@ -287,7 +287,7 @@ const internalNginx = {
|
|||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let filename = '/data/nginx/temp/letsencrypt_' + certificate.id + '.conf';
|
let filename = '/usr/local/nginx/conf/conf.d/letsencrypt_' + certificate.id + '.conf';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/letsencrypt-request.conf', {encoding: 'utf8'});
|
template = fs.readFileSync(__dirname + '/../templates/letsencrypt-request.conf', {encoding: 'utf8'});
|
||||||
@@ -329,7 +329,7 @@ const internalNginx = {
|
|||||||
deleteLetsEncryptRequestConfig: (certificate, throw_errors) => {
|
deleteLetsEncryptRequestConfig: (certificate, throw_errors) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
let config_file = '/data/nginx/temp/letsencrypt_' + certificate.id + '.conf';
|
let config_file = '/usr/local/nginx/conf/conf.d/letsencrypt_' + certificate.id + '.conf';
|
||||||
|
|
||||||
if (debug_mode) {
|
if (debug_mode) {
|
||||||
logger.warn('Deleting nginx config: ' + config_file);
|
logger.warn('Deleting nginx config: ' + config_file);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
const error = require('../error');
|
const error = require('../error');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const parser = require('json-schema-ref-parser');
|
const parser = require('@apidevtools/json-schema-ref-parser');
|
||||||
|
|
||||||
const ajv = require('ajv')({
|
const ajv = require('ajv')({
|
||||||
verbose: true,
|
verbose: true,
|
||||||
|
@@ -95,7 +95,7 @@ class AccessList extends Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get passauth() {
|
get passauth() {
|
||||||
return this.pass_auth ? '' : 'proxy_set_header Authorization "";';
|
return this.pass_auth ? 'proxy_set_header Authorization "";' : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,40 +4,35 @@
|
|||||||
"description": "A beautiful interface for creating Nginx endpoints",
|
"description": "A beautiful interface for creating Nginx endpoints",
|
||||||
"main": "js/index.js",
|
"main": "js/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.0",
|
"@apidevtools/json-schema-ref-parser": "9.1.0",
|
||||||
"archiver": "^5.3.0",
|
"ajv": "6.12.6",
|
||||||
"batchflow": "^0.4.0",
|
"archiver": "5.3.1",
|
||||||
"bcrypt": "^5.0.0",
|
"batchflow": "0.4.0",
|
||||||
"body-parser": "^1.19.0",
|
"bcrypt": "5.1.0",
|
||||||
"compression": "^1.7.4",
|
"body-parser": "1.20.1",
|
||||||
"config": "^3.3.1",
|
"compression": "1.7.4",
|
||||||
"express": "^4.17.1",
|
"config": "3.3.8",
|
||||||
"express-fileupload": "^1.1.9",
|
"express": "4.18.2",
|
||||||
"gravatar": "^1.8.0",
|
"express-fileupload": "1.4.0",
|
||||||
"json-schema-ref-parser": "^8.0.0",
|
"gravatar": "1.8.2",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "8.5.1",
|
||||||
"knex": "^0.20.13",
|
"knex": "2.3.0",
|
||||||
"liquidjs": "^9.11.10",
|
"liquidjs": "9.43.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "4.17.21",
|
||||||
"moment": "^2.29.4",
|
"moment": "2.29.4",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "2.18.1",
|
||||||
"node-rsa": "^1.0.8",
|
"node-rsa": "1.1.1",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "2.0.20",
|
||||||
"objection": "^2.2.16",
|
"objection": "2.2.18",
|
||||||
"path": "^0.12.7",
|
"path": "0.12.7",
|
||||||
"signale": "^1.4.0",
|
"signale": "1.4.0",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "5.1.4",
|
||||||
"temp-write": "^4.0.0"
|
"temp-write": "4.0.0"
|
||||||
},
|
},
|
||||||
"signale": {
|
"signale": {
|
||||||
"displayDate": true,
|
"displayDate": true,
|
||||||
"displayTimestamp": true
|
"displayTimestamp": true
|
||||||
},
|
},
|
||||||
"author": "Jamie Curnow <jc@jc21.com>",
|
"author": "Jamie Curnow <jc@jc21.com>",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"devDependencies": {
|
|
||||||
"eslint": "^6.8.0",
|
|
||||||
"eslint-plugin-align-assignments": "^1.1.2",
|
|
||||||
"prettier": "^2.0.4"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -80,7 +80,7 @@ const setupDefaultUser = () => {
|
|||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row.count) {
|
if (!row.count) {
|
||||||
// Create a new user and set password
|
// Create a new user and set password
|
||||||
logger.info('Creating a new user: admin@example.com with password: changeme');
|
logger.info('Creating a new user: admin@example.com with password: 9KcvfmAvcVonB7YOMqdjJGsTG2JL058Rx6xFNMintAeaGETsRBRlSbfXdi1inoCa');
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
is_deleted: 0,
|
is_deleted: 0,
|
||||||
@@ -100,7 +100,7 @@ const setupDefaultUser = () => {
|
|||||||
.insert({
|
.insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
type: 'password',
|
type: 'password',
|
||||||
secret: 'changeme',
|
secret: '9KcvfmAvcVonB7YOMqdjJGsTG2JL058Rx6xFNMintAeaGETsRBRlSbfXdi1inoCa',
|
||||||
meta: {},
|
meta: {},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -185,10 +185,10 @@ const setupCertbotPlugins = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure credentials file exists
|
// Make sure credentials file exists
|
||||||
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentials_loc = '/data/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
// Escape single quotes and backslashes
|
// Escape single quotes and backslashes
|
||||||
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
||||||
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
|
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /data/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
|
||||||
promises.push(utils.exec(credentials_cmd));
|
promises.push(utils.exec(credentials_cmd));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -212,31 +212,9 @@ const setupCertbotPlugins = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a timer to call run the logrotation binary every two days
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
const setupLogrotation = () => {
|
|
||||||
const intervalTimeout = 1000 * 60 * 60 * 24 * 2; // 2 days
|
|
||||||
|
|
||||||
const runLogrotate = async () => {
|
|
||||||
try {
|
|
||||||
await utils.exec('logrotate /etc/logrotate.d/nginx-proxy-manager');
|
|
||||||
logger.info('Logrotate completed.');
|
|
||||||
} catch (e) { logger.warn(e); }
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.info('Logrotate Timer initialized');
|
|
||||||
setInterval(runLogrotate, intervalTimeout);
|
|
||||||
// And do this now as well
|
|
||||||
return runLogrotate();
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return setupJwt()
|
return setupJwt()
|
||||||
.then(setupDefaultUser)
|
.then(setupDefaultUser)
|
||||||
.then(setupDefaultSettings)
|
.then(setupDefaultSettings)
|
||||||
.then(setupCertbotPlugins)
|
.then(setupCertbotPlugins);
|
||||||
.then(setupLogrotation);
|
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
{% if caching_enabled == 1 or caching_enabled == true -%}
|
|
||||||
# Asset Caching
|
|
||||||
include conf.d/include/assets.conf;
|
|
||||||
{% endif %}
|
|
@@ -1,14 +1,19 @@
|
|||||||
{% if certificate and certificate_id > 0 -%}
|
{% if certificate and certificate_id > 0 -%}
|
||||||
{% if certificate.provider == "letsencrypt" %}
|
{% if certificate.provider == "letsencrypt" %}
|
||||||
# Let's Encrypt SSL
|
# Let's Encrypt SSL
|
||||||
include conf.d/include/letsencrypt-acme-challenge.conf;
|
|
||||||
include conf.d/include/ssl-ciphers.conf;
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
ssl_certificate /etc/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem;
|
ssl_certificate /data/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/npm-{{ certificate_id }}/privkey.pem;
|
ssl_certificate_key /data/letsencrypt/live/npm-{{ certificate_id }}/privkey.pem;
|
||||||
|
ssl_trusted_certificate /data/letsencrypt/live/npm-{{ certificate_id }}/chain.pem;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
{% else %}
|
{% else %}
|
||||||
# Custom SSL
|
# Custom SSL
|
||||||
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
ssl_certificate /data/custom_ssl/npm-{{ certificate_id }}/fullchain.pem;
|
ssl_certificate /data/custom_ssl/npm-{{ certificate_id }}/fullchain.pem;
|
||||||
ssl_certificate_key /data/custom_ssl/npm-{{ certificate_id }}/privkey.pem;
|
ssl_certificate_key /data/custom_ssl/npm-{{ certificate_id }}/privkey.pem;
|
||||||
|
ssl_trusted_certificate /data/custom_ssl/npm-{{ certificate_id }}/chain.pem;
|
||||||
|
ssl_stapling on;
|
||||||
|
ssl_stapling_verify on;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
{% if certificate and certificate_id > 0 -%}
|
{% if certificate and certificate_id > 0 -%}
|
||||||
{% if ssl_forced == 1 or ssl_forced == true %}
|
{% if ssl_forced == 1 or ssl_forced == true %}
|
||||||
{% if hsts_enabled == 1 or hsts_enabled == true %}
|
{% if hsts_enabled == 1 or hsts_enabled == true %}
|
||||||
# HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years)
|
security_headers on;
|
||||||
add_header Strict-Transport-Security "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload" always;
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -1,15 +1,14 @@
|
|||||||
listen 80;
|
listen 80;
|
||||||
{% if ipv6 -%}
|
|
||||||
listen [::]:80;
|
listen [::]:80;
|
||||||
{% else -%}
|
|
||||||
#listen [::]:80;
|
|
||||||
{% endif %}
|
|
||||||
{% if certificate -%}
|
{% if certificate -%}
|
||||||
listen 443 ssl{% if http2_support %} http2{% endif %};
|
listen 443 ssl{% if http2_support %} http2{% endif %};
|
||||||
{% if ipv6 -%}
|
|
||||||
listen [::]:443 ssl{% if http2_support %} http2{% endif %};
|
listen [::]:443 ssl{% if http2_support %} http2{% endif %};
|
||||||
{% else -%}
|
{% if http2_support -%}
|
||||||
#listen [::]:443;
|
listen 443 http3;
|
||||||
|
listen [::]:443 http3;
|
||||||
|
|
||||||
|
add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400';
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
server_name {{ domain_names | join: " " }};
|
server_name {{ domain_names | join: " " }};
|
||||||
|
@@ -1,9 +1,11 @@
|
|||||||
location {{ path }} {
|
location {{ path }} {
|
||||||
|
proxy_set_header Accept-Encoding "";
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
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 X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_http_version 1.1;
|
||||||
proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
|
proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
|
||||||
|
|
||||||
{% if access_list_id > 0 %}
|
{% if access_list_id > 0 %}
|
||||||
@@ -27,19 +29,10 @@
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% include "_assets.conf" %}
|
|
||||||
{% include "_exploits.conf" %}
|
|
||||||
|
|
||||||
{% include "_forced_ssl.conf" %}
|
|
||||||
{% include "_hsts.conf" %}
|
|
||||||
|
|
||||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection $http_connection;
|
proxy_set_header Connection $connection_upgrade;
|
||||||
proxy_http_version 1.1;
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,14 +7,11 @@ server {
|
|||||||
{% include "_hsts.conf" %}
|
{% include "_hsts.conf" %}
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
|
|
||||||
access_log /data/logs/dead-host-{{ id }}_access.log standard;
|
|
||||||
error_log /data/logs/dead-host-{{ id }}_error.log warn;
|
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
{% if use_default_location %}
|
{% if use_default_location %}
|
||||||
location / {
|
location / {
|
||||||
{% include "_hsts.conf" %}
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -5,36 +5,73 @@
|
|||||||
# Skipping output, congratulations page configration is baked in.
|
# Skipping output, congratulations page configration is baked in.
|
||||||
{%- else %}
|
{%- else %}
|
||||||
server {
|
server {
|
||||||
listen 80 default;
|
listen 80 default_server;
|
||||||
{% if ipv6 -%}
|
listen [::]:80 default_server;
|
||||||
listen [::]:80 default;
|
|
||||||
{% else -%}
|
listen 443 ssl http2 default_server;
|
||||||
#listen [::]:80 default;
|
listen [::]:443 ssl http2 default_server;
|
||||||
{% endif %}
|
|
||||||
server_name default-host.localhost;
|
listen 443 http3 default_server;
|
||||||
access_log /data/logs/default-host_access.log combined;
|
listen [::]:443 http3 default_server;
|
||||||
error_log /data/logs/default-host_error.log warn;
|
|
||||||
{% include "_exploits.conf" %}
|
server_name default-host;
|
||||||
|
|
||||||
|
include conf.d/include/force-ssl.conf;
|
||||||
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
include conf.d/include/letsencrypt-acme-challenge.conf;
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
include conf.d/include/block-exploits.conf;
|
||||||
|
add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400';
|
||||||
|
|
||||||
|
ssl_certificate /data/nginx/dummycert.pem;
|
||||||
|
ssl_certificate_key /data/nginx/dummykey.pem;
|
||||||
|
|
||||||
{%- if value == "404" %}
|
{%- if value == "404" %}
|
||||||
location / {
|
location / {
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{%- if value == "redirect" %}
|
{%- if value == "redirect" %}
|
||||||
location / {
|
location / {
|
||||||
return 301 {{ meta.redirect }};
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
return 307 {{ meta.redirect }};
|
||||||
}
|
}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- if value == "html" %}
|
{%- if value == "html" %}
|
||||||
root /data/nginx/default_www;
|
root /data/nginx/default_www;
|
||||||
location / {
|
location / {
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
try_files $uri /index.html;
|
try_files $uri /index.html;
|
||||||
}
|
}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# prevent processing requests with undefined server names
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
|
||||||
|
listen 443 http3;
|
||||||
|
listen [::]:443 http3;
|
||||||
|
|
||||||
|
server_name "";
|
||||||
|
return 444;
|
||||||
|
|
||||||
|
include conf.d/include/force-ssl.conf;
|
||||||
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
include conf.d/include/block-exploits.conf;
|
||||||
|
add_header alt-svc 'h3=":443"; ma=86400, h3-29=":443"; ma=86400';
|
||||||
|
|
||||||
|
ssl_certificate /data/nginx/dummycert.pem;
|
||||||
|
ssl_certificate_key /data/nginx/dummykey.pem;
|
||||||
|
}
|
||||||
|
@@ -2,18 +2,14 @@
|
|||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
{% if ipv6 -%}
|
|
||||||
listen [::]:80;
|
listen [::]:80;
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
server_name {{ domain_names | join: " " }};
|
server_name {{ domain_names | join: " " }};
|
||||||
|
|
||||||
access_log /data/logs/letsencrypt-requests_access.log standard;
|
|
||||||
error_log /data/logs/letsencrypt-requests_error.log warn;
|
|
||||||
|
|
||||||
include conf.d/include/letsencrypt-acme-challenge.conf;
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
return 404;
|
return 404;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,28 +8,23 @@ server {
|
|||||||
|
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
{% include "_assets.conf" %}
|
|
||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
{% include "_hsts.conf" %}
|
{% include "_hsts.conf" %}
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
|
|
||||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection $http_connection;
|
proxy_set_header Connection $http_connection;
|
||||||
proxy_http_version 1.1;
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
access_log /data/logs/proxy-host-{{ id }}_access.log proxy;
|
|
||||||
error_log /data/logs/proxy-host-{{ id }}_error.log warn;
|
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
|
|
||||||
{{ locations }}
|
{{ locations }}
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
{% if use_default_location %}
|
{% if use_default_location %}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
{% if access_list_id > 0 %}
|
{% if access_list_id > 0 %}
|
||||||
{% if access_list.items.length > 0 %}
|
{% if access_list.items.length > 0 %}
|
||||||
# Authorization
|
# Authorization
|
||||||
@@ -51,12 +46,9 @@ proxy_http_version 1.1;
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% include "_hsts.conf" %}
|
|
||||||
|
|
||||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
proxy_set_header Connection $http_connection;
|
proxy_set_header Connection $connection_upgrade;
|
||||||
proxy_http_version 1.1;
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# Proxy!
|
# Proxy!
|
||||||
@@ -65,6 +57,6 @@ proxy_http_version 1.1;
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_proxy[.]conf;
|
include /data/nginx/custom/server_proxy.conf;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -4,20 +4,15 @@
|
|||||||
server {
|
server {
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
{% include "_assets.conf" %}
|
|
||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
{% include "_hsts.conf" %}
|
{% include "_hsts.conf" %}
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
|
|
||||||
access_log /data/logs/redirection-host-{{ id }}_access.log standard;
|
|
||||||
error_log /data/logs/redirection-host-{{ id }}_error.log warn;
|
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
{% if use_default_location %}
|
{% if use_default_location %}
|
||||||
location / {
|
location / {
|
||||||
{% include "_hsts.conf" %}
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
|
||||||
{% if preserve_path == 1 or preserve_path == true %}
|
{% if preserve_path == 1 or preserve_path == true %}
|
||||||
return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}$request_uri;
|
return {{ forward_http_code }} {{ forward_scheme }}://{{ forward_domain_name }}$request_uri;
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -27,6 +22,6 @@ server {
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_redirect[.]conf;
|
include /data/nginx/custom/server_redirect.conf;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -6,32 +6,24 @@
|
|||||||
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
||||||
server {
|
server {
|
||||||
listen {{ incoming_port }};
|
listen {{ incoming_port }};
|
||||||
{% if ipv6 -%}
|
|
||||||
listen [::]:{{ incoming_port }};
|
listen [::]:{{ incoming_port }};
|
||||||
{% else -%}
|
|
||||||
#listen [::]:{{ incoming_port }};
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_stream[.]conf;
|
include /data/nginx/custom/server_stream.conf;
|
||||||
include /data/nginx/custom/server_stream_tcp[.]conf;
|
include /data/nginx/custom/server_stream_tcp.conf;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if udp_forwarding == 1 or udp_forwarding == true %}
|
{% if udp_forwarding == 1 or udp_forwarding == true %}
|
||||||
server {
|
server {
|
||||||
listen {{ incoming_port }} udp;
|
listen {{ incoming_port }} udp;
|
||||||
{% if ipv6 -%}
|
|
||||||
listen [::]:{{ incoming_port }} udp;
|
listen [::]:{{ incoming_port }} udp;
|
||||||
{% else -%}
|
|
||||||
#listen [::]:{{ incoming_port }} udp;
|
|
||||||
{% endif %}
|
|
||||||
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_stream[.]conf;
|
include /data/nginx/custom/server_stream.conf;
|
||||||
include /data/nginx/custom/server_stream_udp[.]conf;
|
include /data/nginx/custom/server_stream_udp.conf;
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
3754
backend/yarn.lock
15
compose.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
version: "3"
|
||||||
|
services:
|
||||||
|
nginx-proxy-manager:
|
||||||
|
container_name: nginx-proxy-manager
|
||||||
|
image: zoeyvid/nginx-proxy-manager
|
||||||
|
restart: always
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- "/opt/npm:/data"
|
||||||
|
- "/opt/npm-letsencrypt:/etc/letsencrypt" # Only needed for first time migration from original nginx-proxy-manager to this fork
|
||||||
|
- "/var/www:/var/www" # optional, if you want to use it as webserver for html
|
||||||
|
environment:
|
||||||
|
- "TZ=Europe/Berlin"
|
||||||
|
# - "NGINX_LOG_NOT_FOUND=true" # Allow logging of 404 errors
|
||||||
|
# - "NPM_LISTEN_LOCALHOST=true" # Bind the NPM Dashboard on Port 81 only to localhost
|
@@ -1,14 +0,0 @@
|
|||||||
rules:
|
|
||||||
# If the efficiency is measured below X%, mark as failed.
|
|
||||||
# Expressed as a ratio between 0-1.
|
|
||||||
lowestEfficiency: 0.99
|
|
||||||
|
|
||||||
# If the amount of wasted space is at least X or larger than X, mark as failed.
|
|
||||||
# Expressed in B, KB, MB, and GB.
|
|
||||||
highestWastedBytes: 15MB
|
|
||||||
|
|
||||||
# If the amount of wasted space makes up for X% or more of the image, mark as failed.
|
|
||||||
# Note: the base image layer is NOT included in the total image size.
|
|
||||||
# Expressed as a ratio between 0-1; fails if the threshold is met or crossed.
|
|
||||||
highestUserWastedPercent: 0.02
|
|
||||||
|
|
@@ -1,63 +0,0 @@
|
|||||||
# This is a Dockerfile intended to be built using `docker buildx`
|
|
||||||
# for multi-arch support. Building with `docker build` may have unexpected results.
|
|
||||||
|
|
||||||
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
|
||||||
|
|
||||||
FROM nginxproxymanager/nginx-full:certbot-node
|
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
|
||||||
ARG BUILD_VERSION
|
|
||||||
ARG BUILD_COMMIT
|
|
||||||
ARG BUILD_DATE
|
|
||||||
|
|
||||||
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
|
|
||||||
S6_FIX_ATTRS_HIDDEN=1 \
|
|
||||||
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
|
|
||||||
NODE_ENV=production \
|
|
||||||
NPM_BUILD_VERSION="${BUILD_VERSION}" \
|
|
||||||
NPM_BUILD_COMMIT="${BUILD_COMMIT}" \
|
|
||||||
NPM_BUILD_DATE="${BUILD_DATE}"
|
|
||||||
|
|
||||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get install -y --no-install-recommends jq logrotate \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# s6 overlay
|
|
||||||
COPY scripts/install-s6 /tmp/install-s6
|
|
||||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
|
||||||
|
|
||||||
COPY backend /app
|
|
||||||
COPY frontend/dist /app/frontend
|
|
||||||
COPY global /app/global
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
RUN yarn install
|
|
||||||
|
|
||||||
# add late to limit cache-busting by modifications
|
|
||||||
COPY docker/rootfs /
|
|
||||||
|
|
||||||
# Remove frontend service not required for prod, dev nginx config as well
|
|
||||||
RUN rm -rf /etc/services.d/frontend /etc/nginx/conf.d/dev.conf
|
|
||||||
|
|
||||||
# Change permission of logrotate config file
|
|
||||||
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
|
||||||
|
|
||||||
# fix for pip installs
|
|
||||||
# https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1769
|
|
||||||
RUN pip uninstall --yes setuptools \
|
|
||||||
&& pip install "setuptools==58.0.0"
|
|
||||||
|
|
||||||
VOLUME [ "/data", "/etc/letsencrypt" ]
|
|
||||||
ENTRYPOINT [ "/init" ]
|
|
||||||
|
|
||||||
LABEL org.label-schema.schema-version="1.0" \
|
|
||||||
org.label-schema.license="MIT" \
|
|
||||||
org.label-schema.name="nginx-proxy-manager" \
|
|
||||||
org.label-schema.description="Docker container for managing Nginx proxy hosts with a simple, powerful interface " \
|
|
||||||
org.label-schema.url="https://github.com/jc21/nginx-proxy-manager" \
|
|
||||||
org.label-schema.vcs-url="https://github.com/jc21/nginx-proxy-manager.git" \
|
|
||||||
org.label-schema.cmd="docker run --rm -ti jc21/nginx-proxy-manager:latest"
|
|
@@ -1,29 +0,0 @@
|
|||||||
FROM nginxproxymanager/nginx-full:certbot-node
|
|
||||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
|
||||||
|
|
||||||
ENV S6_LOGGING=0 \
|
|
||||||
SUPPRESS_NO_CONFIG_WARNING=1 \
|
|
||||||
S6_FIX_ATTRS_HIDDEN=1
|
|
||||||
|
|
||||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get install -y certbot jq python3-pip logrotate \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Task
|
|
||||||
RUN cd /usr \
|
|
||||||
&& curl -sL https://taskfile.dev/install.sh | sh \
|
|
||||||
&& cd /root
|
|
||||||
|
|
||||||
COPY rootfs /
|
|
||||||
RUN rm -f /etc/nginx/conf.d/production.conf
|
|
||||||
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
|
||||||
|
|
||||||
# s6 overlay
|
|
||||||
RUN curl -L -o /tmp/s6-overlay-amd64.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v1.22.1.0/s6-overlay-amd64.tar.gz" \
|
|
||||||
&& tar -xzf /tmp/s6-overlay-amd64.tar.gz -C /
|
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
|
||||||
ENTRYPOINT [ "/init" ]
|
|
||||||
|
|
@@ -1,80 +0,0 @@
|
|||||||
# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
|
|
||||||
version: "3"
|
|
||||||
services:
|
|
||||||
|
|
||||||
fullstack-mysql:
|
|
||||||
image: ${IMAGE}:ci-${BUILD_NUMBER}
|
|
||||||
environment:
|
|
||||||
NODE_ENV: "development"
|
|
||||||
FORCE_COLOR: 1
|
|
||||||
DB_MYSQL_HOST: "db"
|
|
||||||
DB_MYSQL_PORT: 3306
|
|
||||||
DB_MYSQL_USER: "npm"
|
|
||||||
DB_MYSQL_PASSWORD: "npm"
|
|
||||||
DB_MYSQL_NAME: "npm"
|
|
||||||
volumes:
|
|
||||||
- npm_data:/data
|
|
||||||
expose:
|
|
||||||
- 81
|
|
||||||
- 80
|
|
||||||
- 443
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "/bin/check-health"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 3s
|
|
||||||
|
|
||||||
fullstack-sqlite:
|
|
||||||
image: ${IMAGE}:ci-${BUILD_NUMBER}
|
|
||||||
environment:
|
|
||||||
NODE_ENV: "development"
|
|
||||||
FORCE_COLOR: 1
|
|
||||||
DB_SQLITE_FILE: "/data/database.sqlite"
|
|
||||||
volumes:
|
|
||||||
- npm_data:/data
|
|
||||||
expose:
|
|
||||||
- 81
|
|
||||||
- 80
|
|
||||||
- 443
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "/bin/check-health"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 3s
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: jc21/mariadb-aria
|
|
||||||
environment:
|
|
||||||
MYSQL_ROOT_PASSWORD: "npm"
|
|
||||||
MYSQL_DATABASE: "npm"
|
|
||||||
MYSQL_USER: "npm"
|
|
||||||
MYSQL_PASSWORD: "npm"
|
|
||||||
volumes:
|
|
||||||
- db_data:/var/lib/mysql
|
|
||||||
|
|
||||||
cypress-mysql:
|
|
||||||
image: ${IMAGE}-cypress:ci-${BUILD_NUMBER}
|
|
||||||
build:
|
|
||||||
context: ../test/
|
|
||||||
dockerfile: cypress/Dockerfile
|
|
||||||
environment:
|
|
||||||
CYPRESS_baseUrl: "http://fullstack-mysql:81"
|
|
||||||
volumes:
|
|
||||||
- cypress-logs:/results
|
|
||||||
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
|
||||||
|
|
||||||
cypress-sqlite:
|
|
||||||
image: ${IMAGE}-cypress:ci-${BUILD_NUMBER}
|
|
||||||
build:
|
|
||||||
context: ../test/
|
|
||||||
dockerfile: cypress/Dockerfile
|
|
||||||
environment:
|
|
||||||
CYPRESS_baseUrl: "http://fullstack-sqlite:81"
|
|
||||||
volumes:
|
|
||||||
- cypress-logs:/results
|
|
||||||
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
cypress-logs:
|
|
||||||
npm_data:
|
|
||||||
db_data:
|
|
@@ -1,62 +0,0 @@
|
|||||||
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
|
|
||||||
version: "3.5"
|
|
||||||
services:
|
|
||||||
npm:
|
|
||||||
image: nginxproxymanager:dev
|
|
||||||
container_name: npm_core
|
|
||||||
build:
|
|
||||||
context: ./
|
|
||||||
dockerfile: ./dev/Dockerfile
|
|
||||||
ports:
|
|
||||||
- 3080:80
|
|
||||||
- 3081:81
|
|
||||||
- 3443:443
|
|
||||||
networks:
|
|
||||||
- nginx_proxy_manager
|
|
||||||
environment:
|
|
||||||
NODE_ENV: "development"
|
|
||||||
FORCE_COLOR: 1
|
|
||||||
DEVELOPMENT: "true"
|
|
||||||
DB_MYSQL_HOST: "db"
|
|
||||||
DB_MYSQL_PORT: 3306
|
|
||||||
DB_MYSQL_USER: "npm"
|
|
||||||
DB_MYSQL_PASSWORD: "npm"
|
|
||||||
DB_MYSQL_NAME: "npm"
|
|
||||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
|
||||||
# DISABLE_IPV6: "true"
|
|
||||||
volumes:
|
|
||||||
- npm_data:/data
|
|
||||||
- le_data:/etc/letsencrypt
|
|
||||||
- ../backend:/app
|
|
||||||
- ../frontend:/app/frontend
|
|
||||||
- ../global:/app/global
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
working_dir: /app
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: jc21/mariadb-aria
|
|
||||||
container_name: npm_db
|
|
||||||
ports:
|
|
||||||
- 33306:3306
|
|
||||||
networks:
|
|
||||||
- nginx_proxy_manager
|
|
||||||
environment:
|
|
||||||
MYSQL_ROOT_PASSWORD: "npm"
|
|
||||||
MYSQL_DATABASE: "npm"
|
|
||||||
MYSQL_USER: "npm"
|
|
||||||
MYSQL_PASSWORD: "npm"
|
|
||||||
volumes:
|
|
||||||
- db_data:/var/lib/mysql
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
npm_data:
|
|
||||||
name: npm_core_data
|
|
||||||
le_data:
|
|
||||||
name: npm_le_data
|
|
||||||
db_data:
|
|
||||||
name: npm_db_data
|
|
||||||
|
|
||||||
networks:
|
|
||||||
nginx_proxy_manager:
|
|
||||||
name: npm_network
|
|
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
OK=$(curl --silent http://127.0.0.1:81/api/ | jq --raw-output '.status')
|
|
||||||
|
|
||||||
if [ "$OK" == "OK" ]; then
|
|
||||||
echo "OK"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
echo "NOT OK"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
@@ -1,46 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This command reads the `DISABLE_IPV6` env var and will either enable
|
|
||||||
# or disable ipv6 in all nginx configs based on this setting.
|
|
||||||
|
|
||||||
# Lowercase
|
|
||||||
DISABLE_IPV6=$(echo "${DISABLE_IPV6:-}" | tr '[:upper:]' '[:lower:]')
|
|
||||||
|
|
||||||
CYAN='\E[1;36m'
|
|
||||||
BLUE='\E[1;34m'
|
|
||||||
YELLOW='\E[1;33m'
|
|
||||||
RED='\E[1;31m'
|
|
||||||
RESET='\E[0m'
|
|
||||||
|
|
||||||
FOLDER=$1
|
|
||||||
if [ "$FOLDER" == "" ]; then
|
|
||||||
echo -e "${RED}❯ $0 requires a absolute folder path as the first argument!${RESET}"
|
|
||||||
echo -e "${YELLOW} ie: $0 /data/nginx${RESET}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
FILES=$(find "$FOLDER" -type f -name "*.conf")
|
|
||||||
if [ "$DISABLE_IPV6" == "true" ] || [ "$DISABLE_IPV6" == "on" ] || [ "$DISABLE_IPV6" == "1" ] || [ "$DISABLE_IPV6" == "yes" ]; then
|
|
||||||
# IPV6 is disabled
|
|
||||||
echo "Disabling IPV6 in hosts"
|
|
||||||
echo -e "${BLUE}❯ ${CYAN}Disabling IPV6 in hosts: ${YELLOW}${FOLDER}${RESET}"
|
|
||||||
|
|
||||||
# Iterate over configs and run the regex
|
|
||||||
for FILE in $FILES
|
|
||||||
do
|
|
||||||
echo -e " ${BLUE}❯ ${YELLOW}${FILE}${RESET}"
|
|
||||||
sed -E -i 's/^([^#]*)listen \[::\]/\1#listen [::]/g' "$FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
else
|
|
||||||
# IPV6 is enabled
|
|
||||||
echo -e "${BLUE}❯ ${CYAN}Enabling IPV6 in hosts: ${YELLOW}${FOLDER}${RESET}"
|
|
||||||
|
|
||||||
# Iterate over configs and run the regex
|
|
||||||
for FILE in $FILES
|
|
||||||
do
|
|
||||||
echo -e " ${BLUE}❯ ${YELLOW}${FILE}${RESET}"
|
|
||||||
sed -E -i 's/^(\s*)#listen \[::\]/\1listen [::]/g' "$FILE"
|
|
||||||
done
|
|
||||||
|
|
||||||
fi
|
|
2
docker/rootfs/etc/cont-finish.d/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
3
docker/rootfs/etc/cont-init.d/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
||||||
!*.sh
|
|
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
mkdir -p /data/logs
|
|
||||||
echo "Changing ownership of /data/logs to $(id -u):$(id -g)"
|
|
||||||
chown -R "$(id -u):$(id -g)" /data/logs
|
|
||||||
|
|
@@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
# ref: https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/cont-init.d/01-envfile
|
|
||||||
|
|
||||||
# in s6, environmental variables are written as text files for s6 to monitor
|
|
||||||
# search through full-path filenames for files ending in "__FILE"
|
|
||||||
for FILENAME in $(find /var/run/s6/container_environment/ | grep "__FILE$"); do
|
|
||||||
echo "[secret-init] Evaluating ${FILENAME##*/} ..."
|
|
||||||
|
|
||||||
# set SECRETFILE to the contents of the full-path textfile
|
|
||||||
SECRETFILE=$(cat ${FILENAME})
|
|
||||||
# SECRETFILE=${FILENAME}
|
|
||||||
# echo "[secret-init] Set SECRETFILE to ${SECRETFILE}" # DEBUG - rm for prod!
|
|
||||||
|
|
||||||
# if SECRETFILE exists / is not null
|
|
||||||
if [[ -f ${SECRETFILE} ]]; then
|
|
||||||
# strip the appended "__FILE" from environmental variable name ...
|
|
||||||
STRIPFILE=$(echo ${FILENAME} | sed "s/__FILE//g")
|
|
||||||
# echo "[secret-init] Set STRIPFILE to ${STRIPFILE}" # DEBUG - rm for prod!
|
|
||||||
|
|
||||||
# ... and set value to contents of secretfile
|
|
||||||
# since s6 uses text files, this is effectively "export ..."
|
|
||||||
printf $(cat ${SECRETFILE}) > ${STRIPFILE}
|
|
||||||
# echo "[secret-init] Set ${STRIPFILE##*/} to $(cat ${STRIPFILE})" # DEBUG - rm for prod!"
|
|
||||||
echo "[secret-init] Success! ${STRIPFILE##*/} set from ${FILENAME##*/}"
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "[secret-init] cannot find secret in ${FILENAME}"
|
|
||||||
fi
|
|
||||||
done
|
|
2
docker/rootfs/etc/fix-attrs.d/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
*
|
|
||||||
!.gitignore
|
|
@@ -1,25 +0,0 @@
|
|||||||
/data/logs/*_access.log /data/logs/*/access.log {
|
|
||||||
create 0644 root root
|
|
||||||
weekly
|
|
||||||
rotate 4
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
compress
|
|
||||||
sharedscripts
|
|
||||||
postrotate
|
|
||||||
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
|
|
||||||
endscript
|
|
||||||
}
|
|
||||||
|
|
||||||
/data/logs/*_error.log /data/logs/*/error.log {
|
|
||||||
create 0644 root root
|
|
||||||
weekly
|
|
||||||
rotate 10
|
|
||||||
missingok
|
|
||||||
notifempty
|
|
||||||
compress
|
|
||||||
sharedscripts
|
|
||||||
postrotate
|
|
||||||
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
|
|
||||||
endscript
|
|
||||||
}
|
|
@@ -1,40 +0,0 @@
|
|||||||
# "You are not configured" page, which is the default if another default doesn't exist
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
|
|
||||||
set $forward_scheme "http";
|
|
||||||
set $server "127.0.0.1";
|
|
||||||
set $port "80";
|
|
||||||
|
|
||||||
server_name localhost-nginx-proxy-manager;
|
|
||||||
access_log /data/logs/fallback_access.log standard;
|
|
||||||
error_log /data/logs/fallback_error.log warn;
|
|
||||||
include conf.d/include/assets.conf;
|
|
||||||
include conf.d/include/block-exploits.conf;
|
|
||||||
include conf.d/include/letsencrypt-acme-challenge.conf;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
index index.html;
|
|
||||||
root /var/www/html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# First 443 Host, which is the default if another default doesn't exist
|
|
||||||
server {
|
|
||||||
listen 443 ssl;
|
|
||||||
listen [::]:443 ssl;
|
|
||||||
|
|
||||||
set $forward_scheme "https";
|
|
||||||
set $server "127.0.0.1";
|
|
||||||
set $port "443";
|
|
||||||
|
|
||||||
server_name localhost;
|
|
||||||
access_log /data/logs/fallback_access.log standard;
|
|
||||||
error_log /dev/null crit;
|
|
||||||
ssl_certificate /data/nginx/dummycert.pem;
|
|
||||||
ssl_certificate_key /data/nginx/dummykey.pem;
|
|
||||||
include conf.d/include/ssl-ciphers.conf;
|
|
||||||
|
|
||||||
return 444;
|
|
||||||
}
|
|
@@ -1,29 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 81 default;
|
|
||||||
listen [::]:81 default;
|
|
||||||
|
|
||||||
server_name nginxproxymanager-dev;
|
|
||||||
root /app/frontend/dist;
|
|
||||||
access_log /dev/null;
|
|
||||||
|
|
||||||
location /api {
|
|
||||||
return 302 /api/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
add_header X-Served-By $host;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
|
||||||
proxy_pass http://127.0.0.1:3000/;
|
|
||||||
|
|
||||||
proxy_read_timeout 15m;
|
|
||||||
proxy_send_timeout 15m;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
index index.html;
|
|
||||||
try_files $uri $uri.html $uri/ /index.html;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
resolvers.conf
|
|
@@ -1,31 +0,0 @@
|
|||||||
location ~* ^.*\.(css|js|jpe?g|gif|png|webp|woff|eot|ttf|svg|ico|css\.map|js\.map)$ {
|
|
||||||
if_modified_since off;
|
|
||||||
|
|
||||||
# use the public cache
|
|
||||||
proxy_cache public-cache;
|
|
||||||
proxy_cache_key $host$request_uri;
|
|
||||||
|
|
||||||
# ignore these headers for media
|
|
||||||
proxy_ignore_headers Set-Cookie Cache-Control Expires X-Accel-Expires;
|
|
||||||
|
|
||||||
# cache 200s and also 404s (not ideal but there are a few 404 images for some reason)
|
|
||||||
proxy_cache_valid any 30m;
|
|
||||||
proxy_cache_valid 404 1m;
|
|
||||||
|
|
||||||
# strip this header to avoid If-Modified-Since requests
|
|
||||||
proxy_hide_header Last-Modified;
|
|
||||||
proxy_hide_header Cache-Control;
|
|
||||||
proxy_hide_header Vary;
|
|
||||||
|
|
||||||
proxy_cache_bypass 0;
|
|
||||||
proxy_no_cache 0;
|
|
||||||
|
|
||||||
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504 http_404;
|
|
||||||
proxy_connect_timeout 5s;
|
|
||||||
proxy_read_timeout 45s;
|
|
||||||
|
|
||||||
expires @30m;
|
|
||||||
access_log off;
|
|
||||||
|
|
||||||
include conf.d/include/proxy.conf;
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
if ($scheme = "http") {
|
|
||||||
return 301 https://$host$request_uri;
|
|
||||||
}
|
|
@@ -1,2 +0,0 @@
|
|||||||
# This should be left blank is it is populated programatically
|
|
||||||
# by the application backend.
|
|
@@ -1,30 +0,0 @@
|
|||||||
# Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx)
|
|
||||||
# We use ^~ here, so that we don't check other regexes (for speed-up). We actually MUST cancel
|
|
||||||
# other regex checks, because in our other config files have regex rule that denies access to files with dotted names.
|
|
||||||
location ^~ /.well-known/acme-challenge/ {
|
|
||||||
# Since this is for letsencrypt authentication of a domain and they do not give IP ranges of their infrastructure
|
|
||||||
# we need to open up access by turning off auth and IP ACL for this location.
|
|
||||||
auth_basic off;
|
|
||||||
auth_request off;
|
|
||||||
allow all;
|
|
||||||
|
|
||||||
# Set correct content type. According to this:
|
|
||||||
# https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/29
|
|
||||||
# Current specification requires "text/plain" or no content header at all.
|
|
||||||
# It seems that "text/plain" is a safe option.
|
|
||||||
default_type "text/plain";
|
|
||||||
|
|
||||||
# This directory must be the same as in /etc/letsencrypt/cli.ini
|
|
||||||
# as "webroot-path" parameter. Also don't forget to set "authenticator" parameter
|
|
||||||
# there to "webroot".
|
|
||||||
# Do NOT use alias, use root! Target directory is located here:
|
|
||||||
# /var/www/common/letsencrypt/.well-known/acme-challenge/
|
|
||||||
root /data/letsencrypt-acme-challenge;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Hide /acme-challenge subdirectory and return 404 on all requests.
|
|
||||||
# It is somewhat more secure than letting Nginx return 403.
|
|
||||||
# Ending slash is important!
|
|
||||||
location = /.well-known/acme-challenge/ {
|
|
||||||
return 404;
|
|
||||||
}
|
|
@@ -1,8 +0,0 @@
|
|||||||
add_header X-Served-By $host;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_pass $forward_scheme://$server:$port$request_uri;
|
|
||||||
|
|
@@ -1,7 +0,0 @@
|
|||||||
ssl_session_timeout 5m;
|
|
||||||
ssl_session_cache shared:SSL:50m;
|
|
||||||
|
|
||||||
# intermediate configuration. tweak to your needs.
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
|
|
||||||
ssl_prefer_server_ciphers off;
|
|
@@ -1,33 +0,0 @@
|
|||||||
# Admin Interface
|
|
||||||
server {
|
|
||||||
listen 81 default;
|
|
||||||
listen [::]:81 default;
|
|
||||||
|
|
||||||
server_name nginxproxymanager;
|
|
||||||
root /app/frontend;
|
|
||||||
access_log /dev/null;
|
|
||||||
|
|
||||||
location /api {
|
|
||||||
return 302 /api/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /api/ {
|
|
||||||
add_header X-Served-By $host;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
|
||||||
proxy_pass http://127.0.0.1:3000/;
|
|
||||||
|
|
||||||
proxy_read_timeout 15m;
|
|
||||||
proxy_send_timeout 15m;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
index index.html;
|
|
||||||
if ($request_uri ~ ^/(.*)\.html$) {
|
|
||||||
return 302 /$1;
|
|
||||||
}
|
|
||||||
try_files $uri $uri.html $uri/ /index.html;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,96 +0,0 @@
|
|||||||
types {
|
|
||||||
text/html html htm shtml;
|
|
||||||
text/css css;
|
|
||||||
text/xml xml;
|
|
||||||
image/gif gif;
|
|
||||||
image/jpeg jpeg jpg;
|
|
||||||
application/javascript js;
|
|
||||||
application/atom+xml atom;
|
|
||||||
application/rss+xml rss;
|
|
||||||
|
|
||||||
text/mathml mml;
|
|
||||||
text/plain txt;
|
|
||||||
text/vnd.sun.j2me.app-descriptor jad;
|
|
||||||
text/vnd.wap.wml wml;
|
|
||||||
text/x-component htc;
|
|
||||||
|
|
||||||
image/png png;
|
|
||||||
image/svg+xml svg svgz;
|
|
||||||
image/tiff tif tiff;
|
|
||||||
image/vnd.wap.wbmp wbmp;
|
|
||||||
image/webp webp;
|
|
||||||
image/x-icon ico;
|
|
||||||
image/x-jng jng;
|
|
||||||
image/x-ms-bmp bmp;
|
|
||||||
|
|
||||||
font/woff woff;
|
|
||||||
font/woff2 woff2;
|
|
||||||
|
|
||||||
application/java-archive jar war ear;
|
|
||||||
application/json json;
|
|
||||||
application/mac-binhex40 hqx;
|
|
||||||
application/msword doc;
|
|
||||||
application/pdf pdf;
|
|
||||||
application/postscript ps eps ai;
|
|
||||||
application/rtf rtf;
|
|
||||||
application/vnd.apple.mpegurl m3u8;
|
|
||||||
application/vnd.google-earth.kml+xml kml;
|
|
||||||
application/vnd.google-earth.kmz kmz;
|
|
||||||
application/vnd.ms-excel xls;
|
|
||||||
application/vnd.ms-fontobject eot;
|
|
||||||
application/vnd.ms-powerpoint ppt;
|
|
||||||
application/vnd.oasis.opendocument.graphics odg;
|
|
||||||
application/vnd.oasis.opendocument.presentation odp;
|
|
||||||
application/vnd.oasis.opendocument.spreadsheet ods;
|
|
||||||
application/vnd.oasis.opendocument.text odt;
|
|
||||||
application/vnd.openxmlformats-officedocument.presentationml.presentation
|
|
||||||
pptx;
|
|
||||||
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
|
||||||
xlsx;
|
|
||||||
application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
|
||||||
docx;
|
|
||||||
application/vnd.wap.wmlc wmlc;
|
|
||||||
application/x-7z-compressed 7z;
|
|
||||||
application/x-cocoa cco;
|
|
||||||
application/x-java-archive-diff jardiff;
|
|
||||||
application/x-java-jnlp-file jnlp;
|
|
||||||
application/x-makeself run;
|
|
||||||
application/x-perl pl pm;
|
|
||||||
application/x-pilot prc pdb;
|
|
||||||
application/x-rar-compressed rar;
|
|
||||||
application/x-redhat-package-manager rpm;
|
|
||||||
application/x-sea sea;
|
|
||||||
application/x-shockwave-flash swf;
|
|
||||||
application/x-stuffit sit;
|
|
||||||
application/x-tcl tcl tk;
|
|
||||||
application/x-x509-ca-cert der pem crt;
|
|
||||||
application/x-xpinstall xpi;
|
|
||||||
application/xhtml+xml xhtml;
|
|
||||||
application/xspf+xml xspf;
|
|
||||||
application/zip zip;
|
|
||||||
|
|
||||||
application/octet-stream bin exe dll;
|
|
||||||
application/octet-stream deb;
|
|
||||||
application/octet-stream dmg;
|
|
||||||
application/octet-stream iso img;
|
|
||||||
application/octet-stream msi msp msm;
|
|
||||||
|
|
||||||
audio/midi mid midi kar;
|
|
||||||
audio/mpeg mp3;
|
|
||||||
audio/ogg ogg;
|
|
||||||
audio/x-m4a m4a;
|
|
||||||
audio/x-realaudio ra;
|
|
||||||
|
|
||||||
video/3gpp 3gpp 3gp;
|
|
||||||
video/mp2t ts;
|
|
||||||
video/mp4 mp4;
|
|
||||||
video/mpeg mpeg mpg;
|
|
||||||
video/quicktime mov;
|
|
||||||
video/webm webm;
|
|
||||||
video/x-flv flv;
|
|
||||||
video/x-m4v m4v;
|
|
||||||
video/x-mng mng;
|
|
||||||
video/x-ms-asf asx asf;
|
|
||||||
video/x-ms-wmv wmv;
|
|
||||||
video/x-msvideo avi;
|
|
||||||
}
|
|
@@ -1,95 +0,0 @@
|
|||||||
# run nginx in foreground
|
|
||||||
daemon off;
|
|
||||||
|
|
||||||
user root;
|
|
||||||
|
|
||||||
# Set number of worker processes automatically based on number of CPU cores.
|
|
||||||
worker_processes auto;
|
|
||||||
|
|
||||||
# Enables the use of JIT for regular expressions to speed-up their processing.
|
|
||||||
pcre_jit on;
|
|
||||||
|
|
||||||
error_log /data/logs/fallback_error.log warn;
|
|
||||||
|
|
||||||
# Includes files with directives to load dynamic modules.
|
|
||||||
include /etc/nginx/modules/*.conf;
|
|
||||||
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
sendfile on;
|
|
||||||
server_tokens off;
|
|
||||||
tcp_nopush on;
|
|
||||||
tcp_nodelay on;
|
|
||||||
client_body_temp_path /tmp/nginx/body 1 2;
|
|
||||||
keepalive_timeout 90s;
|
|
||||||
proxy_connect_timeout 90s;
|
|
||||||
proxy_send_timeout 90s;
|
|
||||||
proxy_read_timeout 90s;
|
|
||||||
ssl_prefer_server_ciphers on;
|
|
||||||
gzip on;
|
|
||||||
proxy_ignore_client_abort off;
|
|
||||||
client_max_body_size 2000m;
|
|
||||||
server_names_hash_bucket_size 1024;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header Accept-Encoding "";
|
|
||||||
proxy_cache off;
|
|
||||||
proxy_cache_path /var/lib/nginx/cache/public levels=1:2 keys_zone=public-cache:30m max_size=192m;
|
|
||||||
proxy_cache_path /var/lib/nginx/cache/private levels=1:2 keys_zone=private-cache:5m max_size=1024m;
|
|
||||||
|
|
||||||
log_format proxy '[$time_local] $upstream_cache_status $upstream_status $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] [Sent-to $server] "$http_user_agent" "$http_referer"';
|
|
||||||
log_format standard '[$time_local] $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] "$http_user_agent" "$http_referer"';
|
|
||||||
|
|
||||||
access_log /data/logs/fallback_access.log proxy;
|
|
||||||
|
|
||||||
# Dynamically generated resolvers file
|
|
||||||
include /etc/nginx/conf.d/include/resolvers.conf;
|
|
||||||
|
|
||||||
# Default upstream scheme
|
|
||||||
map $host $forward_scheme {
|
|
||||||
default http;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Real IP Determination
|
|
||||||
|
|
||||||
# Local subnets:
|
|
||||||
set_real_ip_from 10.0.0.0/8;
|
|
||||||
set_real_ip_from 172.16.0.0/12; # Includes Docker subnet
|
|
||||||
set_real_ip_from 192.168.0.0/16;
|
|
||||||
# NPM generated CDN ip ranges:
|
|
||||||
include conf.d/include/ip_ranges.conf;
|
|
||||||
# always put the following 2 lines after ip subnets:
|
|
||||||
real_ip_header X-Real-IP;
|
|
||||||
real_ip_recursive on;
|
|
||||||
|
|
||||||
# Custom
|
|
||||||
include /data/nginx/custom/http_top[.]conf;
|
|
||||||
|
|
||||||
# Files generated by NPM
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
|
||||||
include /data/nginx/default_host/*.conf;
|
|
||||||
include /data/nginx/proxy_host/*.conf;
|
|
||||||
include /data/nginx/redirection_host/*.conf;
|
|
||||||
include /data/nginx/dead_host/*.conf;
|
|
||||||
include /data/nginx/temp/*.conf;
|
|
||||||
|
|
||||||
# Custom
|
|
||||||
include /data/nginx/custom/http[.]conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream {
|
|
||||||
# Files generated by NPM
|
|
||||||
include /data/nginx/stream/*.conf;
|
|
||||||
|
|
||||||
# Custom
|
|
||||||
include /data/nginx/custom/stream[.]conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Custom
|
|
||||||
include /data/nginx/custom/root[.]conf;
|
|
@@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/execlineb -S1
|
|
||||||
if { s6-test ${1} -ne 0 }
|
|
||||||
if { s6-test ${1} -ne 256 }
|
|
||||||
|
|
||||||
s6-svscanctl -t /var/run/s6/services
|
|
||||||
|
|
@@ -1,12 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
# This service is DEVELOPMENT only.
|
|
||||||
|
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
|
||||||
cd /app/frontend || exit 1
|
|
||||||
# If yarn install fails: add --verbose --network-concurrency 1
|
|
||||||
yarn install
|
|
||||||
yarn watch
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
@@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
s6-svscanctl -t /var/run/s6/services
|
|
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
mkdir -p /data/letsencrypt-acme-challenge
|
|
||||||
|
|
||||||
cd /app || echo
|
|
||||||
|
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
|
||||||
cd /app || exit 1
|
|
||||||
# If yarn install fails: add --verbose --network-concurrency 1
|
|
||||||
yarn install
|
|
||||||
node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js
|
|
||||||
else
|
|
||||||
cd /app || exit 1
|
|
||||||
while :
|
|
||||||
do
|
|
||||||
node --abort_on_uncaught_exception --max_old_space_size=250 index.js
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
fi
|
|
@@ -1 +0,0 @@
|
|||||||
/bin/true
|
|
@@ -1,53 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
# Create required folders
|
|
||||||
mkdir -p /tmp/nginx/body \
|
|
||||||
/run/nginx \
|
|
||||||
/var/log/nginx \
|
|
||||||
/data/nginx \
|
|
||||||
/data/custom_ssl \
|
|
||||||
/data/logs \
|
|
||||||
/data/access \
|
|
||||||
/data/nginx/default_host \
|
|
||||||
/data/nginx/default_www \
|
|
||||||
/data/nginx/proxy_host \
|
|
||||||
/data/nginx/redirection_host \
|
|
||||||
/data/nginx/stream \
|
|
||||||
/data/nginx/dead_host \
|
|
||||||
/data/nginx/temp \
|
|
||||||
/var/lib/nginx/cache/public \
|
|
||||||
/var/lib/nginx/cache/private \
|
|
||||||
/var/cache/nginx/proxy_temp
|
|
||||||
|
|
||||||
touch /var/log/nginx/error.log && chmod 777 /var/log/nginx/error.log && chmod -R 777 /var/cache/nginx
|
|
||||||
chown root /tmp/nginx
|
|
||||||
|
|
||||||
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
|
|
||||||
# thanks @tfmm
|
|
||||||
if [ "$DISABLE_IPV6" == "true" ] || [ "$DISABLE_IPV6" == "on" ] || [ "$DISABLE_IPV6" == "1" ] || [ "$DISABLE_IPV6" == "yes" ];
|
|
||||||
then
|
|
||||||
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) ipv6=off valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf
|
|
||||||
else
|
|
||||||
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf
|
|
||||||
fi
|
|
||||||
# Generate dummy self-signed certificate.
|
|
||||||
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]
|
|
||||||
then
|
|
||||||
echo "Generating dummy SSL certificate..."
|
|
||||||
openssl req \
|
|
||||||
-new \
|
|
||||||
-newkey rsa:2048 \
|
|
||||||
-days 3650 \
|
|
||||||
-nodes \
|
|
||||||
-x509 \
|
|
||||||
-subj '/O=localhost/OU=localhost/CN=localhost' \
|
|
||||||
-keyout /data/nginx/dummykey.pem \
|
|
||||||
-out /data/nginx/dummycert.pem
|
|
||||||
echo "Complete"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Handle IPV6 settings
|
|
||||||
/bin/handle-ipv6-setting /etc/nginx/conf.d
|
|
||||||
/bin/handle-ipv6-setting /data/nginx
|
|
||||||
|
|
||||||
exec nginx
|
|
@@ -1,22 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ -t 1 ]; then
|
|
||||||
export PS1="\e[1;34m[\e[1;33m\u@\e[1;32mdocker-\h\e[1;37m:\w\[\e[1;34m]\e[1;36m\\$ \e[0m"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Aliases
|
|
||||||
alias l='ls -lAsh --color'
|
|
||||||
alias ls='ls -C1 --color'
|
|
||||||
alias cp='cp -ip'
|
|
||||||
alias rm='rm -i'
|
|
||||||
alias mv='mv -i'
|
|
||||||
alias h='cd ~;clear;'
|
|
||||||
|
|
||||||
. /etc/os-release
|
|
||||||
|
|
||||||
echo -e -n '\E[1;34m'
|
|
||||||
figlet -w 120 "NginxProxyManager"
|
|
||||||
echo -e "\E[1;36mVersion \E[1;32m${NPM_BUILD_VERSION:-2.0.0-dev} (${NPM_BUILD_COMMIT:-dev}) ${NPM_BUILD_DATE:-0000-00-00}\E[1;36m, OpenResty \E[1;32m${OPENRESTY_VERSION:-unknown}\E[1;36m, ${ID:-debian} \E[1;32m${VERSION:-unknown}\E[1;36m, Certbot \E[1;32m$(certbot --version)\E[0m"
|
|
||||||
echo -e -n '\E[1;34m'
|
|
||||||
cat /built-for-arch
|
|
||||||
echo -e '\E[0m'
|
|
3
docs/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
.vuepress/dist
|
|
||||||
node_modules
|
|
||||||
ts
|
|
@@ -1,82 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
locales: {
|
|
||||||
"/": {
|
|
||||||
lang: "en-US",
|
|
||||||
title: "Nginx Proxy Manager",
|
|
||||||
description: "Expose your services easily and securely"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
head: [
|
|
||||||
["link", { rel: "icon", href: "/icon.png" }],
|
|
||||||
["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }],
|
|
||||||
["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
|
|
||||||
["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
|
|
||||||
["meta", { property: "og:type", content: "website" }],
|
|
||||||
["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
|
|
||||||
["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
|
|
||||||
["meta", { name: "twitter:card", content: "summary"}],
|
|
||||||
["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
|
|
||||||
["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
|
|
||||||
["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
|
|
||||||
["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
|
|
||||||
],
|
|
||||||
themeConfig: {
|
|
||||||
logo: "/icon.png",
|
|
||||||
// the GitHub repo path
|
|
||||||
repo: "jc21/nginx-proxy-manager",
|
|
||||||
// the label linking to the repo
|
|
||||||
repoLabel: "GitHub",
|
|
||||||
// if your docs are not at the root of the repo:
|
|
||||||
docsDir: "docs",
|
|
||||||
// defaults to false, set to true to enable
|
|
||||||
editLinks: true,
|
|
||||||
locales: {
|
|
||||||
"/": {
|
|
||||||
// text for the language dropdown
|
|
||||||
selectText: "Languages",
|
|
||||||
// label for this locale in the language dropdown
|
|
||||||
label: "English",
|
|
||||||
// Custom text for edit link. Defaults to "Edit this page"
|
|
||||||
editLinkText: "Edit this page on GitHub",
|
|
||||||
// Custom navbar values
|
|
||||||
nav: [{ text: "Setup", link: "/setup/" }],
|
|
||||||
// Custom sidebar values
|
|
||||||
sidebar: [
|
|
||||||
"/",
|
|
||||||
["/guide/", "Guide"],
|
|
||||||
["/screenshots/", "Screenshots"],
|
|
||||||
["/setup/", "Setup Instructions"],
|
|
||||||
["/advanced-config/", "Advanced Configuration"],
|
|
||||||
["/upgrading/", "Upgrading"],
|
|
||||||
["/faq/", "Frequently Asked Questions"],
|
|
||||||
["/third-party/", "Third Party"]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
[
|
|
||||||
"@vuepress/google-analytics",
|
|
||||||
{
|
|
||||||
ga: "UA-99675467-4"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"sitemap",
|
|
||||||
{
|
|
||||||
hostname: "https://nginxproxymanager.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'vuepress-plugin-zooming',
|
|
||||||
{
|
|
||||||
selector: '.zooming',
|
|
||||||
delay: 1000,
|
|
||||||
options: {
|
|
||||||
bgColor: 'black',
|
|
||||||
zIndex: 10000,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]
|
|
||||||
};
|
|
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 13 KiB |
@@ -1,2 +0,0 @@
|
|||||||
User-agent: *
|
|
||||||
Disallow:
|
|
Before Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 173 KiB |
Before Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 151 KiB |
Before Width: | Height: | Size: 207 KiB |
Before Width: | Height: | Size: 181 KiB |
Before Width: | Height: | Size: 162 KiB |
@@ -1,23 +0,0 @@
|
|||||||
.home .hero img
|
|
||||||
max-width: 500px !important
|
|
||||||
min-width: 300px
|
|
||||||
width: 100%
|
|
||||||
|
|
||||||
.center
|
|
||||||
margin 0 auto;
|
|
||||||
width: 80%
|
|
||||||
|
|
||||||
#main-title
|
|
||||||
display: none
|
|
||||||
|
|
||||||
.hero
|
|
||||||
margin: 150px 25px 70px
|
|
||||||
|
|
||||||
@font-face
|
|
||||||
font-family: 'Nerd Font';
|
|
||||||
src: url("/nerd-font.woff2") format("woff2");
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal
|
|
||||||
|
|
||||||
code
|
|
||||||
font-family: 'Nerd Font', source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
|
@@ -1,4 +0,0 @@
|
|||||||
$accentColor = #f15833
|
|
||||||
$textColor = #663015
|
|
||||||
$borderColor = #eaecef
|
|
||||||
$codeBgColor = #282c34
|
|
@@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
home: true
|
|
||||||
heroImage: /logo.png
|
|
||||||
actionText: Get Started →
|
|
||||||
actionLink: /guide/
|
|
||||||
footer: MIT Licensed | Copyright © 2016-present jc21.com
|
|
||||||
---
|
|
||||||
|
|
||||||
<div class="features">
|
|
||||||
<div class="feature">
|
|
||||||
<h2>Get Connected</h2>
|
|
||||||
<p>
|
|
||||||
Expose web services on your network ·
|
|
||||||
Free SSL with Let's Encrypt ·
|
|
||||||
Designed with security in mind ·
|
|
||||||
Perfect for home networks
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h2>Proxy Hosts</h2>
|
|
||||||
<p>Expose your private network Web services and get connected anywhere.</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h2>Beautiful UI</h2>
|
|
||||||
<p>Based on Tabler, the interface is a pleasure to use. Configuring a server has never been so fun.</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h2>Free SSL</h2>
|
|
||||||
<p>Built in Let’s Encrypt support allows you to secure your Web services at no cost to you. The certificates even renew themselves!</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h2>Docker FTW</h2>
|
|
||||||
<p>Built as a Docker Image, Nginx Proxy Manager only requires a database.</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h2>Multiple Users</h2>
|
|
||||||
<p>Configure other users to either view or manage their own hosts. Full access permissions are available.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@@ -1,174 +0,0 @@
|
|||||||
# Advanced Configuration
|
|
||||||
|
|
||||||
## Best Practice: Use a Docker network
|
|
||||||
|
|
||||||
For those who have a few of their upstream services running in Docker on the same Docker
|
|
||||||
host as NPM, here's a trick to secure things a bit better. By creating a custom Docker network,
|
|
||||||
you don't need to publish ports for your upstream services to all of the Docker host's interfaces.
|
|
||||||
|
|
||||||
Create a network, ie "scoobydoo":
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker network create scoobydoo
|
|
||||||
```
|
|
||||||
|
|
||||||
Then add the following to the `docker-compose.yml` file for both NPM and any other
|
|
||||||
services running on this Docker host:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: scoobydoo
|
|
||||||
```
|
|
||||||
|
|
||||||
Let's look at a Portainer example:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
version: '3'
|
|
||||||
services:
|
|
||||||
|
|
||||||
portainer:
|
|
||||||
image: portainer/portainer
|
|
||||||
privileged: true
|
|
||||||
volumes:
|
|
||||||
- './data:/data'
|
|
||||||
- '/var/run/docker.sock:/var/run/docker.sock'
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
external: true
|
|
||||||
name: scoobydoo
|
|
||||||
```
|
|
||||||
|
|
||||||
Now in the NPM UI you can create a proxy host with `portainer` as the hostname,
|
|
||||||
and port `9000` as the port. Even though this port isn't listed in the docker-compose
|
|
||||||
file, it's "exposed" by the Portainer Docker image for you and not available on
|
|
||||||
the Docker host outside of this Docker network. The service name is used as the
|
|
||||||
hostname, so make sure your service names are unique when using the same network.
|
|
||||||
|
|
||||||
## Docker Healthcheck
|
|
||||||
|
|
||||||
The `Dockerfile` that builds this project does not include a `HEALTHCHECK` but you can opt in to this
|
|
||||||
feature by adding the following to the service in your `docker-compose.yml` file:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "/bin/check-health"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 3s
|
|
||||||
```
|
|
||||||
|
|
||||||
## Docker Secrets
|
|
||||||
|
|
||||||
This image supports the use of Docker secrets to import from file and keep sensitive usernames or passwords from being passed or preserved in plaintext.
|
|
||||||
|
|
||||||
You can set any environment variable from a file by appending `__FILE` (double-underscore FILE) to the environmental variable name.
|
|
||||||
|
|
||||||
```yml
|
|
||||||
version: "3.7"
|
|
||||||
|
|
||||||
secrets:
|
|
||||||
# Secrets are single-line text files where the sole content is the secret
|
|
||||||
# Paths in this example assume that secrets are kept in local folder called ".secrets"
|
|
||||||
DB_ROOT_PWD:
|
|
||||||
file: .secrets/db_root_pwd.txt
|
|
||||||
MYSQL_PWD:
|
|
||||||
file: .secrets/mysql_pwd.txt
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'jc21/nginx-proxy-manager:latest'
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
# Public HTTP Port:
|
|
||||||
- '80:80'
|
|
||||||
# Public HTTPS Port:
|
|
||||||
- '443:443'
|
|
||||||
# Admin Web Port:
|
|
||||||
- '81:81'
|
|
||||||
environment:
|
|
||||||
# These are the settings to access your db
|
|
||||||
DB_MYSQL_HOST: "db"
|
|
||||||
DB_MYSQL_PORT: 3306
|
|
||||||
DB_MYSQL_USER: "npm"
|
|
||||||
# DB_MYSQL_PASSWORD: "npm" # use secret instead
|
|
||||||
DB_MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD
|
|
||||||
DB_MYSQL_NAME: "npm"
|
|
||||||
# If you would rather use Sqlite uncomment this
|
|
||||||
# and remove all DB_MYSQL_* lines above
|
|
||||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
|
||||||
# Uncomment this if IPv6 is not enabled on your host
|
|
||||||
# DISABLE_IPV6: 'true'
|
|
||||||
volumes:
|
|
||||||
- ./data:/data
|
|
||||||
- ./letsencrypt:/etc/letsencrypt
|
|
||||||
secrets:
|
|
||||||
- MYSQL_PWD
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
db:
|
|
||||||
image: jc21/mariadb-aria
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
# MYSQL_ROOT_PASSWORD: "npm" # use secret instead
|
|
||||||
MYSQL_ROOT_PASSWORD__FILE: /run/secrets/DB_ROOT_PWD
|
|
||||||
MYSQL_DATABASE: "npm"
|
|
||||||
MYSQL_USER: "npm"
|
|
||||||
# MYSQL_PASSWORD: "npm" # use secret instead
|
|
||||||
MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD
|
|
||||||
volumes:
|
|
||||||
- ./data/mysql:/var/lib/mysql
|
|
||||||
secrets:
|
|
||||||
- DB_ROOT_PWD
|
|
||||||
- MYSQL_PWD
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Disabling IPv6
|
|
||||||
|
|
||||||
On some Docker hosts IPv6 may not be enabled. In these cases, the following message may be seen in the log:
|
|
||||||
|
|
||||||
> Address family not supported by protocol
|
|
||||||
|
|
||||||
The easy fix is to add a Docker environment variable to the Nginx Proxy Manager stack:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
environment:
|
|
||||||
DISABLE_IPV6: 'true'
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Custom Nginx Configurations
|
|
||||||
|
|
||||||
If you are a more advanced user, you might be itching for extra Nginx customizability.
|
|
||||||
|
|
||||||
NPM has the ability to include different custom configuration snippets in different places.
|
|
||||||
|
|
||||||
You can add your custom configuration snippet files at `/data/nginx/custom` as follow:
|
|
||||||
|
|
||||||
- `/data/nginx/custom/root.conf`: Included at the very end of nginx.conf
|
|
||||||
- `/data/nginx/custom/http_top.conf`: Included at the top of the main http block
|
|
||||||
- `/data/nginx/custom/http.conf`: Included at the end of the main http block
|
|
||||||
- `/data/nginx/custom/stream.conf`: Included at the end of the main stream block
|
|
||||||
- `/data/nginx/custom/server_proxy.conf`: Included at the end of every proxy server block
|
|
||||||
- `/data/nginx/custom/server_redirect.conf`: Included at the end of every redirection server block
|
|
||||||
- `/data/nginx/custom/server_stream.conf`: Included at the end of every stream server block
|
|
||||||
- `/data/nginx/custom/server_stream_tcp.conf`: Included at the end of every TCP stream server block
|
|
||||||
- `/data/nginx/custom/server_stream_udp.conf`: Included at the end of every UDP stream server block
|
|
||||||
|
|
||||||
Every file is optional.
|
|
||||||
|
|
||||||
|
|
||||||
## X-FRAME-OPTIONS Header
|
|
||||||
|
|
||||||
You can configure the [`X-FRAME-OPTIONS`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) header
|
|
||||||
value by specifying it as a Docker environment variable. The default if not specified is `deny`.
|
|
||||||
|
|
||||||
```yml
|
|
||||||
...
|
|
||||||
environment:
|
|
||||||
X_FRAME_OPTIONS: "sameorigin"
|
|
||||||
...
|
|
||||||
```
|
|
@@ -1,26 +0,0 @@
|
|||||||
# FAQ
|
|
||||||
|
|
||||||
## Do I have to use Docker?
|
|
||||||
|
|
||||||
Yes, that's how this project is packaged.
|
|
||||||
|
|
||||||
This makes it easier to support the project when I have control over the version of Nginx and NodeJS
|
|
||||||
being used. In future this could change if the backend was no longer using NodeJS and it's long list
|
|
||||||
of dependencies.
|
|
||||||
|
|
||||||
|
|
||||||
## Can I run it on a Raspberry Pi?
|
|
||||||
|
|
||||||
Yes! The docker image is multi-arch and is built for a variety of architectures. If yours is
|
|
||||||
[not listed](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags) please open a
|
|
||||||
[GitHub issue](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
|
|
||||||
|
|
||||||
## I can't get my service to proxy properly?
|
|
||||||
|
|
||||||
Your best bet is to ask the [Reddit community for support](https://www.reddit.com/r/nginxproxymanager/). There's safety in numbers.
|
|
||||||
|
|
||||||
Gitter is best left for anyone contributing to the project to ask for help about internals, code reviews etc.
|
|
||||||
|
|
||||||
## When adding username and password access control to a proxy host, I can no longer login into the app.
|
|
||||||
|
|
||||||
Having an Access Control List (ACL) with username and password requires the browser to always send this username and password in the `Authorization` header on each request. If your proxied app also requires authentication (like Nginx Proxy Manager itself), most likely the app will also use the `Authorization` header to transmit this information, as this is the standardized header meant for this kind of information. However having multiples of the same headers is not allowed in the [internet standard](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2) and almost all apps do not support multiple values in the `Authorization` header. Hence one of the two logins will be broken. This can only be fixed by either removing one of the logins or by changing the app to use other non-standard headers for authorization.
|
|
@@ -1 +0,0 @@
|
|||||||
../../README.md
|
|
@@ -1,777 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "docs",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"dependencies": {
|
|
||||||
"@vuepress/plugin-google-analytics": "^1.5.3",
|
|
||||||
"abbrev": "^1.1.1",
|
|
||||||
"accepts": "^1.3.7",
|
|
||||||
"acorn": "^7.4.0",
|
|
||||||
"agentkeepalive": "^4.1.3",
|
|
||||||
"ajv": "^6.12.3",
|
|
||||||
"ajv-errors": "^1.0.1",
|
|
||||||
"ajv-keywords": "^3.5.2",
|
|
||||||
"algoliasearch": "^4.3.1",
|
|
||||||
"alphanum-sort": "^1.0.2",
|
|
||||||
"ansi-colors": "^4.1.1",
|
|
||||||
"ansi-escapes": "^4.3.1",
|
|
||||||
"ansi-html": "^0.0.7",
|
|
||||||
"ansi-regex": "^5.0.0",
|
|
||||||
"ansi-styles": "^4.2.1",
|
|
||||||
"anymatch": "^3.1.1",
|
|
||||||
"aproba": "^2.0.0",
|
|
||||||
"argparse": "^1.0.10",
|
|
||||||
"arr-diff": "^4.0.0",
|
|
||||||
"arr-flatten": "^1.1.0",
|
|
||||||
"arr-union": "^3.1.0",
|
|
||||||
"array-flatten": "^3.0.0",
|
|
||||||
"array-union": "^2.1.0",
|
|
||||||
"array-uniq": "^2.1.0",
|
|
||||||
"array-unique": "^0.3.2",
|
|
||||||
"asn1": "^0.2.4",
|
|
||||||
"asn1.js": "^5.4.1",
|
|
||||||
"assert": "^2.0.0",
|
|
||||||
"assert-plus": "^1.0.0",
|
|
||||||
"assign-symbols": "^2.0.2",
|
|
||||||
"async": "^3.2.0",
|
|
||||||
"async-each": "^1.0.3",
|
|
||||||
"async-limiter": "^2.0.0",
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"atob": "^2.1.2",
|
|
||||||
"autocomplete.js": "^0.37.1",
|
|
||||||
"autoprefixer": "^9.8.6",
|
|
||||||
"aws-sign2": "^0.7.0",
|
|
||||||
"aws4": "^1.10.0",
|
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
||||||
"babel-plugin-module-resolver": "^4.0.0",
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"base": "^3.0.0",
|
|
||||||
"base64-js": "^1.3.1",
|
|
||||||
"batch": "^0.6.1",
|
|
||||||
"bcrypt-pbkdf": "^1.0.2",
|
|
||||||
"big.js": "^5.2.2",
|
|
||||||
"binary-extensions": "^2.1.0",
|
|
||||||
"bluebird": "^3.7.2",
|
|
||||||
"bn.js": "^5.1.2",
|
|
||||||
"body-parser": "^1.19.0",
|
|
||||||
"bonjour": "^3.5.0",
|
|
||||||
"boolbase": "^1.0.0",
|
|
||||||
"brace-expansion": "^1.1.11",
|
|
||||||
"braces": "^3.0.2",
|
|
||||||
"brorand": "^1.1.0",
|
|
||||||
"browserify-aes": "^1.2.0",
|
|
||||||
"browserify-cipher": "^1.0.1",
|
|
||||||
"browserify-des": "^1.0.2",
|
|
||||||
"browserify-rsa": "^4.0.1",
|
|
||||||
"browserify-sign": "^4.2.1",
|
|
||||||
"browserify-zlib": "^0.2.0",
|
|
||||||
"browserslist": "^4.13.0",
|
|
||||||
"buffer": "^5.6.0",
|
|
||||||
"buffer-from": "^1.1.1",
|
|
||||||
"buffer-indexof": "^1.1.1",
|
|
||||||
"buffer-json": "^2.0.0",
|
|
||||||
"buffer-xor": "^2.0.2",
|
|
||||||
"builtin-status-codes": "^3.0.0",
|
|
||||||
"bytes": "^3.1.0",
|
|
||||||
"cac": "^6.6.1",
|
|
||||||
"cacache": "^15.0.5",
|
|
||||||
"cache-base": "^4.0.0",
|
|
||||||
"cache-loader": "^4.1.0",
|
|
||||||
"call-me-maybe": "^1.0.1",
|
|
||||||
"caller-callsite": "^4.1.0",
|
|
||||||
"caller-path": "^3.0.0",
|
|
||||||
"callsites": "^3.1.0",
|
|
||||||
"camel-case": "^4.1.1",
|
|
||||||
"camelcase": "^6.0.0",
|
|
||||||
"caniuse-api": "^3.0.0",
|
|
||||||
"caniuse-lite": "^1.0.30001111",
|
|
||||||
"caseless": "^0.12.0",
|
|
||||||
"chalk": "^4.1.0",
|
|
||||||
"chokidar": "^3.4.1",
|
|
||||||
"chownr": "^2.0.0",
|
|
||||||
"chrome-trace-event": "^1.0.2",
|
|
||||||
"ci-info": "^2.0.0",
|
|
||||||
"cipher-base": "^1.0.4",
|
|
||||||
"class-utils": "^0.3.6",
|
|
||||||
"clean-css": "^4.2.3",
|
|
||||||
"clipboard": "^2.0.6",
|
|
||||||
"cliui": "^6.0.0",
|
|
||||||
"coa": "^2.0.2",
|
|
||||||
"code-point-at": "^1.1.0",
|
|
||||||
"collection-visit": "^1.0.0",
|
|
||||||
"color": "^3.1.2",
|
|
||||||
"color-convert": "^2.0.1",
|
|
||||||
"color-name": "^1.1.4",
|
|
||||||
"color-string": "^1.5.3",
|
|
||||||
"combined-stream": "^1.0.8",
|
|
||||||
"commander": "^6.0.0",
|
|
||||||
"commondir": "^1.0.1",
|
|
||||||
"component-emitter": "^1.3.0",
|
|
||||||
"compressible": "^2.0.18",
|
|
||||||
"compression": "^1.7.4",
|
|
||||||
"concat-map": "^0.0.1",
|
|
||||||
"concat-stream": "^2.0.0",
|
|
||||||
"connect-history-api-fallback": "^1.6.0",
|
|
||||||
"consola": "^2.15.0",
|
|
||||||
"console-browserify": "^1.2.0",
|
|
||||||
"consolidate": "^0.15.1",
|
|
||||||
"constants-browserify": "^1.0.0",
|
|
||||||
"content-disposition": "^0.5.3",
|
|
||||||
"content-type": "^1.0.4",
|
|
||||||
"convert-source-map": "^1.7.0",
|
|
||||||
"cookie": "^0.4.1",
|
|
||||||
"cookie-signature": "^1.1.0",
|
|
||||||
"copy-concurrently": "^1.0.5",
|
|
||||||
"copy-descriptor": "^0.1.1",
|
|
||||||
"copy-webpack-plugin": "^6.0.3",
|
|
||||||
"core-js": "^3.6.5",
|
|
||||||
"core-util-is": "^1.0.2",
|
|
||||||
"cosmiconfig": "^7.0.0",
|
|
||||||
"create-ecdh": "^4.0.4",
|
|
||||||
"create-hash": "^1.2.0",
|
|
||||||
"create-hmac": "^1.1.7",
|
|
||||||
"cross-spawn": "^7.0.3",
|
|
||||||
"crypto-browserify": "^3.12.0",
|
|
||||||
"css": "^3.0.0",
|
|
||||||
"css-color-names": "^1.0.1",
|
|
||||||
"css-declaration-sorter": "^5.1.2",
|
|
||||||
"css-loader": "^4.2.0",
|
|
||||||
"css-parse": "^2.0.0",
|
|
||||||
"css-select": "^2.1.0",
|
|
||||||
"css-select-base-adapter": "^0.1.1",
|
|
||||||
"css-tree": "^1.0.0-alpha.39",
|
|
||||||
"css-unit-converter": "^1.1.2",
|
|
||||||
"css-what": "^5.0.1",
|
|
||||||
"cssesc": "^3.0.0",
|
|
||||||
"cssnano": "^4.1.10",
|
|
||||||
"cssnano-preset-default": "^4.0.7",
|
|
||||||
"cssnano-util-get-arguments": "^4.0.0",
|
|
||||||
"cssnano-util-get-match": "^4.0.0",
|
|
||||||
"cssnano-util-raw-cache": "^4.0.1",
|
|
||||||
"cssnano-util-same-parent": "^4.0.1",
|
|
||||||
"csso": "^4.0.3",
|
|
||||||
"cyclist": "^1.0.1",
|
|
||||||
"dashdash": "^1.14.1",
|
|
||||||
"de-indent": "^1.0.2",
|
|
||||||
"debug": "^4.1.1",
|
|
||||||
"decamelize": "^4.0.0",
|
|
||||||
"decode-uri-component": "^0.2.0",
|
|
||||||
"deep-equal": "^2.0.3",
|
|
||||||
"deepmerge": "^4.2.2",
|
|
||||||
"default-gateway": "^6.0.1",
|
|
||||||
"define-properties": "^1.1.3",
|
|
||||||
"define-property": "^2.0.2",
|
|
||||||
"del": "^5.1.0",
|
|
||||||
"delayed-stream": "^1.0.0",
|
|
||||||
"delegate": "^3.2.0",
|
|
||||||
"depd": "^2.0.0",
|
|
||||||
"des.js": "^1.0.1",
|
|
||||||
"destroy": "^1.0.4",
|
|
||||||
"detect-node": "^2.0.4",
|
|
||||||
"diacritics": "^1.3.0",
|
|
||||||
"diffie-hellman": "^5.0.3",
|
|
||||||
"dir-glob": "^3.0.1",
|
|
||||||
"dns-equal": "^1.0.0",
|
|
||||||
"dns-packet": "^5.2.1",
|
|
||||||
"dns-txt": "^2.0.2",
|
|
||||||
"docsearch.js": "^2.6.3",
|
|
||||||
"dom-converter": "^0.2.0",
|
|
||||||
"dom-serializer": "^1.0.1",
|
|
||||||
"dom-walk": "^0.1.2",
|
|
||||||
"domain-browser": "^4.16.0",
|
|
||||||
"domelementtype": "^2.0.1",
|
|
||||||
"domhandler": "^3.0.0",
|
|
||||||
"domutils": "^2.1.0",
|
|
||||||
"dot-prop": "^5.2.0",
|
|
||||||
"duplexify": "^4.1.1",
|
|
||||||
"ecc-jsbn": "^0.2.0",
|
|
||||||
"ee-first": "^1.1.1",
|
|
||||||
"electron-to-chromium": "^1.3.522",
|
|
||||||
"elliptic": "^6.5.3",
|
|
||||||
"emoji-regex": "^9.0.0",
|
|
||||||
"emojis-list": "^3.0.0",
|
|
||||||
"encodeurl": "^1.0.2",
|
|
||||||
"end-of-stream": "^1.4.4",
|
|
||||||
"enhanced-resolve": "^4.3.0",
|
|
||||||
"entities": "^2.0.3",
|
|
||||||
"envify": "^4.1.0",
|
|
||||||
"envinfo": "^7.7.2",
|
|
||||||
"errno": "^0.1.7",
|
|
||||||
"error-ex": "^1.3.2",
|
|
||||||
"es-abstract": "^1.17.6",
|
|
||||||
"es-to-primitive": "^1.2.1",
|
|
||||||
"es6-promise": "^4.2.8",
|
|
||||||
"escape-html": "^1.0.3",
|
|
||||||
"escape-string-regexp": "^4.0.0",
|
|
||||||
"eslint-scope": "^5.1.0",
|
|
||||||
"esprima": "^4.0.1",
|
|
||||||
"esrecurse": "^4.2.1",
|
|
||||||
"estraverse": "^5.2.0",
|
|
||||||
"esutils": "^2.0.3",
|
|
||||||
"etag": "^1.8.1",
|
|
||||||
"eventemitter3": "^4.0.4",
|
|
||||||
"events": "^3.2.0",
|
|
||||||
"eventsource": "^2.0.2",
|
|
||||||
"evp_bytestokey": "^1.0.3",
|
|
||||||
"execa": "^4.0.3",
|
|
||||||
"expand-brackets": "^4.0.0",
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"extend": "^3.0.2",
|
|
||||||
"extend-shallow": "^3.0.2",
|
|
||||||
"extglob": "^3.0.0",
|
|
||||||
"extsprintf": "^1.4.0",
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"fast-glob": "^3.2.4",
|
|
||||||
"fast-json-stable-stringify": "^2.1.0",
|
|
||||||
"faye-websocket": "^0.11.3",
|
|
||||||
"figgy-pudding": "^3.5.2",
|
|
||||||
"figures": "^3.2.0",
|
|
||||||
"file-loader": "^6.0.0",
|
|
||||||
"fill-range": "^7.0.1",
|
|
||||||
"finalhandler": "^1.1.2",
|
|
||||||
"find-babel-config": "^1.2.0",
|
|
||||||
"find-cache-dir": "^3.3.1",
|
|
||||||
"find-up": "^4.1.0",
|
|
||||||
"flush-write-stream": "^2.0.0",
|
|
||||||
"follow-redirects": "^1.12.1",
|
|
||||||
"for-in": "^1.0.2",
|
|
||||||
"foreach": "^2.0.5",
|
|
||||||
"forever-agent": "^0.6.1",
|
|
||||||
"form-data": "^3.0.0",
|
|
||||||
"forwarded": "^0.1.2",
|
|
||||||
"fragment-cache": "^0.2.1",
|
|
||||||
"fresh": "^0.5.2",
|
|
||||||
"from2": "^2.3.0",
|
|
||||||
"fs-extra": "^9.0.1",
|
|
||||||
"fs-write-stream-atomic": "^1.0.10",
|
|
||||||
"fs.realpath": "^1.0.0",
|
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"gensync": "^1.0.0-beta.1",
|
|
||||||
"get-caller-file": "^2.0.5",
|
|
||||||
"get-stream": "^5.1.0",
|
|
||||||
"get-value": "^3.0.1",
|
|
||||||
"getpass": "^0.1.7",
|
|
||||||
"glob": "^7.1.6",
|
|
||||||
"glob-parent": "^5.1.1",
|
|
||||||
"glob-to-regexp": "^0.4.1",
|
|
||||||
"global": "^4.4.0",
|
|
||||||
"globals": "^13.1.0",
|
|
||||||
"globby": "^11.0.1",
|
|
||||||
"good-listener": "^1.2.2",
|
|
||||||
"graceful-fs": "^4.2.4",
|
|
||||||
"gray-matter": "^4.0.2",
|
|
||||||
"handle-thing": "^2.0.1",
|
|
||||||
"har-schema": "^2.0.0",
|
|
||||||
"har-validator": "^5.1.5",
|
|
||||||
"has": "^1.0.3",
|
|
||||||
"has-ansi": "^4.0.0",
|
|
||||||
"has-flag": "^4.0.0",
|
|
||||||
"has-symbols": "^1.0.1",
|
|
||||||
"has-value": "^2.0.2",
|
|
||||||
"has-values": "^2.0.1",
|
|
||||||
"hash-base": "^3.1.0",
|
|
||||||
"hash-sum": "^2.0.0",
|
|
||||||
"hash.js": "^1.1.7",
|
|
||||||
"he": "^1.2.0",
|
|
||||||
"hex-color-regex": "^1.1.0",
|
|
||||||
"hmac-drbg": "^1.0.1",
|
|
||||||
"hogan.js": "^3.0.2",
|
|
||||||
"hpack.js": "^2.1.6",
|
|
||||||
"hsl-regex": "^1.0.0",
|
|
||||||
"hsla-regex": "^1.0.0",
|
|
||||||
"html-comment-regex": "^1.1.2",
|
|
||||||
"html-entities": "^1.3.1",
|
|
||||||
"html-minifier": "^4.0.0",
|
|
||||||
"html-tags": "^3.1.0",
|
|
||||||
"htmlparser2": "^4.1.0",
|
|
||||||
"http-deceiver": "^1.2.7",
|
|
||||||
"http-errors": "^1.8.0",
|
|
||||||
"http-parser-js": "^0.5.2",
|
|
||||||
"http-proxy": "^1.18.1",
|
|
||||||
"http-proxy-middleware": "^1.0.5",
|
|
||||||
"http-signature": "^1.3.4",
|
|
||||||
"https-browserify": "^1.0.0",
|
|
||||||
"iconv-lite": "^0.6.2",
|
|
||||||
"icss-replace-symbols": "^1.1.0",
|
|
||||||
"icss-utils": "^4.1.1",
|
|
||||||
"ieee754": "^1.1.13",
|
|
||||||
"iferr": "^1.0.2",
|
|
||||||
"ignore": "^5.1.8",
|
|
||||||
"immediate": "^3.3.0",
|
|
||||||
"import-cwd": "^3.0.0",
|
|
||||||
"import-fresh": "^3.2.1",
|
|
||||||
"import-from": "^3.0.0",
|
|
||||||
"import-local": "^3.0.2",
|
|
||||||
"imurmurhash": "^0.1.4",
|
|
||||||
"indexes-of": "^1.0.1",
|
|
||||||
"infer-owner": "^1.0.4",
|
|
||||||
"inflight": "^1.0.6",
|
|
||||||
"inherits": "^2.0.4",
|
|
||||||
"internal-ip": "^6.1.0",
|
|
||||||
"invariant": "^2.2.4",
|
|
||||||
"invert-kv": "^3.0.1",
|
|
||||||
"ip": "^1.1.5",
|
|
||||||
"ip-regex": "^4.1.0",
|
|
||||||
"ipaddr.js": "^1.9.1",
|
|
||||||
"is-absolute-url": "^3.0.3",
|
|
||||||
"is-accessor-descriptor": "^3.0.1",
|
|
||||||
"is-arguments": "^1.0.4",
|
|
||||||
"is-arrayish": "^0.3.2",
|
|
||||||
"is-binary-path": "^2.1.0",
|
|
||||||
"is-buffer": "^2.0.4",
|
|
||||||
"is-callable": "^1.2.0",
|
|
||||||
"is-color-stop": "^1.1.0",
|
|
||||||
"is-data-descriptor": "^2.0.0",
|
|
||||||
"is-date-object": "^1.0.2",
|
|
||||||
"is-descriptor": "^3.0.0",
|
|
||||||
"is-directory": "^0.3.1",
|
|
||||||
"is-extendable": "^1.0.1",
|
|
||||||
"is-extglob": "^2.1.1",
|
|
||||||
"is-fullwidth-code-point": "^3.0.0",
|
|
||||||
"is-glob": "^4.0.1",
|
|
||||||
"is-number": "^7.0.0",
|
|
||||||
"is-obj": "^2.0.0",
|
|
||||||
"is-path-cwd": "^2.2.0",
|
|
||||||
"is-path-in-cwd": "^3.0.0",
|
|
||||||
"is-path-inside": "^3.0.2",
|
|
||||||
"is-plain-obj": "^2.1.0",
|
|
||||||
"is-plain-object": "^4.1.1",
|
|
||||||
"is-regex": "^1.1.1",
|
|
||||||
"is-resolvable": "^1.1.0",
|
|
||||||
"is-stream": "^2.0.0",
|
|
||||||
"is-svg": "^4.2.1",
|
|
||||||
"is-symbol": "^1.0.3",
|
|
||||||
"is-typedarray": "^1.0.0",
|
|
||||||
"is-windows": "^1.0.2",
|
|
||||||
"is-wsl": "^2.2.0",
|
|
||||||
"isarray": "^2.0.5",
|
|
||||||
"isexe": "^2.0.0",
|
|
||||||
"isobject": "^4.0.0",
|
|
||||||
"isstream": "^0.1.2",
|
|
||||||
"javascript-stringify": "^2.0.1",
|
|
||||||
"js-levenshtein": "^1.1.6",
|
|
||||||
"js-tokens": "^6.0.0",
|
|
||||||
"js-yaml": "^3.14.0",
|
|
||||||
"jsbn": "^1.1.0",
|
|
||||||
"jsesc": "^3.0.1",
|
|
||||||
"json-parse-better-errors": "^1.0.2",
|
|
||||||
"json-schema": "^0.4.0",
|
|
||||||
"json-schema-traverse": "^0.4.1",
|
|
||||||
"json-stringify-safe": "^5.0.1",
|
|
||||||
"json3": "^3.3.3",
|
|
||||||
"json5": "^2.1.3",
|
|
||||||
"jsonfile": "^6.0.1",
|
|
||||||
"jsprim": "^2.0.0",
|
|
||||||
"killable": "^1.0.1",
|
|
||||||
"kind-of": "^6.0.3",
|
|
||||||
"last-call-webpack-plugin": "^3.0.0",
|
|
||||||
"lcid": "^3.1.1",
|
|
||||||
"linkify-it": "^3.0.2",
|
|
||||||
"load-script": "^1.0.0",
|
|
||||||
"loader-runner": "^4.0.0",
|
|
||||||
"loader-utils": "^2.0.0",
|
|
||||||
"locate-path": "^5.0.0",
|
|
||||||
"lodash": "^4.17.19",
|
|
||||||
"lodash._reinterpolate": "^3.0.0",
|
|
||||||
"lodash.chunk": "^4.2.0",
|
|
||||||
"lodash.clonedeep": "^4.5.0",
|
|
||||||
"lodash.debounce": "^4.0.8",
|
|
||||||
"lodash.kebabcase": "^4.1.1",
|
|
||||||
"lodash.memoize": "^4.1.2",
|
|
||||||
"lodash.padstart": "^4.6.1",
|
|
||||||
"lodash.sortby": "^4.7.0",
|
|
||||||
"lodash.template": "^4.5.0",
|
|
||||||
"lodash.templatesettings": "^4.2.0",
|
|
||||||
"lodash.uniq": "^4.5.0",
|
|
||||||
"loglevel": "^1.6.8",
|
|
||||||
"loose-envify": "^1.4.0",
|
|
||||||
"lower-case": "^2.0.1",
|
|
||||||
"lru-cache": "^6.0.0",
|
|
||||||
"make-dir": "^3.1.0",
|
|
||||||
"mamacro": "^0.0.7",
|
|
||||||
"map-age-cleaner": "^0.1.3",
|
|
||||||
"map-cache": "^0.2.2",
|
|
||||||
"map-visit": "^1.0.0",
|
|
||||||
"markdown-it": "^12.3.2",
|
|
||||||
"markdown-it-anchor": "^5.3.0",
|
|
||||||
"markdown-it-chain": "^1.3.0",
|
|
||||||
"markdown-it-container": "^3.0.0",
|
|
||||||
"markdown-it-emoji": "^1.4.0",
|
|
||||||
"markdown-it-table-of-contents": "^0.4.4",
|
|
||||||
"md5.js": "^1.3.5",
|
|
||||||
"mdn-data": "^2.0.11",
|
|
||||||
"mdurl": "^1.0.1",
|
|
||||||
"media-typer": "^1.1.0",
|
|
||||||
"mem": "^6.1.0",
|
|
||||||
"memory-fs": "^0.5.0",
|
|
||||||
"merge-descriptors": "^1.0.1",
|
|
||||||
"merge-source-map": "^1.1.0",
|
|
||||||
"merge2": "^1.4.1",
|
|
||||||
"methods": "^1.1.2",
|
|
||||||
"micromatch": "^4.0.2",
|
|
||||||
"miller-rabin": "^4.0.1",
|
|
||||||
"mime": "^2.4.6",
|
|
||||||
"mime-db": "^1.44.0",
|
|
||||||
"mime-types": "^2.1.27",
|
|
||||||
"mimic-fn": "^3.1.0",
|
|
||||||
"min-document": "^2.19.0",
|
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
|
||||||
"minimalistic-assert": "^1.0.1",
|
|
||||||
"minimalistic-crypto-utils": "^1.0.1",
|
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"minimist": "^1.2.5",
|
|
||||||
"mississippi": "^4.0.0",
|
|
||||||
"mixin-deep": "^2.0.1",
|
|
||||||
"mkdirp": "^1.0.4",
|
|
||||||
"move-concurrently": "^1.0.1",
|
|
||||||
"ms": "^2.1.2",
|
|
||||||
"multicast-dns": "^7.2.2",
|
|
||||||
"multicast-dns-service-types": "^1.1.0",
|
|
||||||
"nanomatch": "^1.2.13",
|
|
||||||
"negotiator": "^0.6.2",
|
|
||||||
"neo-async": "^2.6.2",
|
|
||||||
"nice-try": "^2.0.1",
|
|
||||||
"no-case": "^3.0.3",
|
|
||||||
"node-forge": "^1.0.0",
|
|
||||||
"node-libs-browser": "^2.2.1",
|
|
||||||
"node-releases": "^1.1.60",
|
|
||||||
"nopt": "^4.0.3",
|
|
||||||
"normalize-path": "^3.0.0",
|
|
||||||
"normalize-range": "^0.1.2",
|
|
||||||
"normalize-url": "^5.1.0",
|
|
||||||
"npm-run-path": "^4.0.1",
|
|
||||||
"nprogress": "^0.2.0",
|
|
||||||
"nth-check": "^2.0.1",
|
|
||||||
"num2fraction": "^1.2.2",
|
|
||||||
"number-is-nan": "^2.0.0",
|
|
||||||
"oauth-sign": "^0.9.0",
|
|
||||||
"object-assign": "^4.1.1",
|
|
||||||
"object-copy": "^1.0.0",
|
|
||||||
"object-inspect": "^1.8.0",
|
|
||||||
"object-is": "^1.1.2",
|
|
||||||
"object-keys": "^1.1.1",
|
|
||||||
"object-visit": "^1.0.1",
|
|
||||||
"object.assign": "^4.1.0",
|
|
||||||
"object.getownpropertydescriptors": "^2.1.0",
|
|
||||||
"object.pick": "^1.3.0",
|
|
||||||
"object.values": "^1.1.1",
|
|
||||||
"obuf": "^1.1.2",
|
|
||||||
"on-finished": "^2.3.0",
|
|
||||||
"on-headers": "^1.0.2",
|
|
||||||
"once": "^1.4.0",
|
|
||||||
"opencollective-postinstall": "^2.0.3",
|
|
||||||
"opn": "^6.0.0",
|
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
|
||||||
"original": "^1.0.2",
|
|
||||||
"os-browserify": "^0.3.0",
|
|
||||||
"os-locale": "^5.0.0",
|
|
||||||
"p-defer": "^3.0.0",
|
|
||||||
"p-finally": "^2.0.1",
|
|
||||||
"p-is-promise": "^3.0.0",
|
|
||||||
"p-limit": "^3.0.2",
|
|
||||||
"p-locate": "^4.1.0",
|
|
||||||
"p-map": "^4.0.0",
|
|
||||||
"p-retry": "^4.2.0",
|
|
||||||
"p-try": "^2.2.0",
|
|
||||||
"pako": "^1.0.11",
|
|
||||||
"parallel-transform": "^1.2.0",
|
|
||||||
"param-case": "^3.0.3",
|
|
||||||
"parse-asn1": "^5.1.5",
|
|
||||||
"parse-json": "^5.0.1",
|
|
||||||
"parseurl": "^1.3.3",
|
|
||||||
"pascalcase": "^1.0.0",
|
|
||||||
"path-browserify": "^1.0.1",
|
|
||||||
"path-dirname": "^1.0.2",
|
|
||||||
"path-exists": "^4.0.0",
|
|
||||||
"path-is-absolute": "^2.0.0",
|
|
||||||
"path-is-inside": "^1.0.2",
|
|
||||||
"path-key": "^3.1.1",
|
|
||||||
"path-parse": "^1.0.6",
|
|
||||||
"path-to-regexp": "^6.1.0",
|
|
||||||
"path-type": "^4.0.0",
|
|
||||||
"pbkdf2": "^3.1.1",
|
|
||||||
"performance-now": "^2.1.0",
|
|
||||||
"pify": "^5.0.0",
|
|
||||||
"pinkie": "^2.0.4",
|
|
||||||
"pinkie-promise": "^2.0.1",
|
|
||||||
"pkg-dir": "^4.2.0",
|
|
||||||
"pkg-up": "^3.1.0",
|
|
||||||
"portfinder": "^1.0.28",
|
|
||||||
"posix-character-classes": "^1.0.0",
|
|
||||||
"postcss": "^8.2.10",
|
|
||||||
"postcss-calc": "^7.0.2",
|
|
||||||
"postcss-colormin": "^4.0.3",
|
|
||||||
"postcss-convert-values": "^4.0.1",
|
|
||||||
"postcss-discard-comments": "^4.0.2",
|
|
||||||
"postcss-discard-duplicates": "^4.0.2",
|
|
||||||
"postcss-discard-empty": "^4.0.1",
|
|
||||||
"postcss-discard-overridden": "^4.0.1",
|
|
||||||
"postcss-load-config": "^2.1.0",
|
|
||||||
"postcss-loader": "^3.0.0",
|
|
||||||
"postcss-merge-longhand": "^4.0.11",
|
|
||||||
"postcss-merge-rules": "^4.0.3",
|
|
||||||
"postcss-minify-font-values": "^4.0.2",
|
|
||||||
"postcss-minify-gradients": "^4.0.2",
|
|
||||||
"postcss-minify-params": "^4.0.2",
|
|
||||||
"postcss-minify-selectors": "^4.0.2",
|
|
||||||
"postcss-modules-extract-imports": "^2.0.0",
|
|
||||||
"postcss-modules-local-by-default": "^3.0.3",
|
|
||||||
"postcss-modules-scope": "^2.2.0",
|
|
||||||
"postcss-modules-values": "^3.0.0",
|
|
||||||
"postcss-normalize-charset": "^4.0.1",
|
|
||||||
"postcss-normalize-display-values": "^4.0.2",
|
|
||||||
"postcss-normalize-positions": "^4.0.2",
|
|
||||||
"postcss-normalize-repeat-style": "^4.0.2",
|
|
||||||
"postcss-normalize-string": "^4.0.2",
|
|
||||||
"postcss-normalize-timing-functions": "^4.0.2",
|
|
||||||
"postcss-normalize-unicode": "^4.0.1",
|
|
||||||
"postcss-normalize-url": "^4.0.1",
|
|
||||||
"postcss-normalize-whitespace": "^4.0.2",
|
|
||||||
"postcss-ordered-values": "^4.1.2",
|
|
||||||
"postcss-reduce-initial": "^4.0.3",
|
|
||||||
"postcss-reduce-transforms": "^4.0.2",
|
|
||||||
"postcss-safe-parser": "^4.0.2",
|
|
||||||
"postcss-selector-parser": "^6.0.2",
|
|
||||||
"postcss-svgo": "^4.0.2",
|
|
||||||
"postcss-unique-selectors": "^4.0.1",
|
|
||||||
"postcss-value-parser": "^4.1.0",
|
|
||||||
"prepend-http": "^3.0.1",
|
|
||||||
"prettier": "^2.0.5",
|
|
||||||
"pretty-error": "^2.1.1",
|
|
||||||
"pretty-time": "^1.1.0",
|
|
||||||
"prismjs": "^1.20.0",
|
|
||||||
"private": "^0.1.8",
|
|
||||||
"process": "^0.11.10",
|
|
||||||
"process-nextick-args": "^2.0.1",
|
|
||||||
"promise-inflight": "^1.0.1",
|
|
||||||
"proxy-addr": "^2.0.6",
|
|
||||||
"prr": "^1.0.1",
|
|
||||||
"pseudomap": "^1.0.2",
|
|
||||||
"psl": "^1.8.0",
|
|
||||||
"public-encrypt": "^4.0.3",
|
|
||||||
"pump": "^3.0.0",
|
|
||||||
"pumpify": "^2.0.1",
|
|
||||||
"punycode": "^2.1.1",
|
|
||||||
"q": "^1.5.1",
|
|
||||||
"qs": "^6.9.4",
|
|
||||||
"query-string": "^6.13.1",
|
|
||||||
"querystring": "^0.2.0",
|
|
||||||
"querystring-es3": "^0.2.1",
|
|
||||||
"querystringify": "^2.1.1",
|
|
||||||
"randombytes": "^2.1.0",
|
|
||||||
"randomfill": "^1.0.4",
|
|
||||||
"range-parser": "^1.2.1",
|
|
||||||
"raw-body": "^2.4.1",
|
|
||||||
"readable-stream": "^3.6.0",
|
|
||||||
"readdirp": "^3.4.0",
|
|
||||||
"reduce": "^1.0.2",
|
|
||||||
"regenerate": "^1.4.1",
|
|
||||||
"regenerate-unicode-properties": "^8.2.0",
|
|
||||||
"regenerator-runtime": "^0.13.7",
|
|
||||||
"regenerator-transform": "^0.14.5",
|
|
||||||
"regex-not": "^1.0.2",
|
|
||||||
"regexp.prototype.flags": "^1.3.0",
|
|
||||||
"regexpu-core": "^4.7.0",
|
|
||||||
"regjsgen": "^0.5.2",
|
|
||||||
"regjsparser": "^0.6.4",
|
|
||||||
"relateurl": "^0.2.7",
|
|
||||||
"remove-trailing-separator": "^1.1.0",
|
|
||||||
"renderkid": "^2.0.3",
|
|
||||||
"repeat-element": "^1.1.3",
|
|
||||||
"repeat-string": "^1.6.1",
|
|
||||||
"request": "^2.88.2",
|
|
||||||
"require-directory": "^2.1.1",
|
|
||||||
"require-main-filename": "^2.0.0",
|
|
||||||
"requires-port": "^1.0.0",
|
|
||||||
"reselect": "^4.0.0",
|
|
||||||
"resolve": "^1.17.0",
|
|
||||||
"resolve-cwd": "^3.0.0",
|
|
||||||
"resolve-from": "^5.0.0",
|
|
||||||
"resolve-url": "^0.2.1",
|
|
||||||
"ret": "^0.3.1",
|
|
||||||
"retry": "^0.12.0",
|
|
||||||
"rgb-regex": "^1.0.1",
|
|
||||||
"rgba-regex": "^1.0.0",
|
|
||||||
"rimraf": "^3.0.2",
|
|
||||||
"ripemd160": "^2.0.2",
|
|
||||||
"run-queue": "^2.0.1",
|
|
||||||
"safe-buffer": "^5.2.1",
|
|
||||||
"safe-regex": "^2.1.1",
|
|
||||||
"safer-buffer": "^2.1.2",
|
|
||||||
"sax": "^1.2.4",
|
|
||||||
"schema-utils": "^2.7.0",
|
|
||||||
"section-matter": "^1.0.0",
|
|
||||||
"select": "^1.1.2",
|
|
||||||
"select-hose": "^2.0.0",
|
|
||||||
"selfsigned": "^1.10.7",
|
|
||||||
"semver": "^7.3.2",
|
|
||||||
"send": "^0.17.1",
|
|
||||||
"serialize-javascript": "^4.0.0",
|
|
||||||
"serve-index": "^1.9.1",
|
|
||||||
"serve-static": "^1.14.1",
|
|
||||||
"set-blocking": "^2.0.0",
|
|
||||||
"set-value": "^4.0.1",
|
|
||||||
"setimmediate": "^1.0.5",
|
|
||||||
"setprototypeof": "^1.2.0",
|
|
||||||
"sha.js": "^2.4.11",
|
|
||||||
"shebang-command": "^2.0.0",
|
|
||||||
"shebang-regex": "^3.0.0",
|
|
||||||
"signal-exit": "^3.0.3",
|
|
||||||
"simple-swizzle": "^0.2.2",
|
|
||||||
"sitemap": "^6.2.0",
|
|
||||||
"slash": "^3.0.0",
|
|
||||||
"smoothscroll-polyfill": "^0.4.4",
|
|
||||||
"snapdragon": "^0.12.0",
|
|
||||||
"snapdragon-node": "^3.0.0",
|
|
||||||
"snapdragon-util": "^5.0.1",
|
|
||||||
"sockjs": "^0.3.21",
|
|
||||||
"sockjs-client": "^1.5.0",
|
|
||||||
"sort-keys": "^4.0.0",
|
|
||||||
"source-list-map": "^2.0.1",
|
|
||||||
"source-map": "^0.7.3",
|
|
||||||
"source-map-resolve": "^0.6.0",
|
|
||||||
"source-map-support": "^0.5.19",
|
|
||||||
"source-map-url": "^0.4.0",
|
|
||||||
"spdy": "^4.0.2",
|
|
||||||
"spdy-transport": "^3.0.0",
|
|
||||||
"split-string": "^6.1.0",
|
|
||||||
"sprintf-js": "^1.1.2",
|
|
||||||
"sshpk": "^1.16.1",
|
|
||||||
"ssri": "^8.0.0",
|
|
||||||
"stable": "^0.1.8",
|
|
||||||
"stack-utils": "^2.0.2",
|
|
||||||
"static-extend": "^0.1.2",
|
|
||||||
"statuses": "^2.0.0",
|
|
||||||
"std-env": "^2.2.1",
|
|
||||||
"stream-browserify": "^3.0.0",
|
|
||||||
"stream-each": "^1.2.3",
|
|
||||||
"stream-http": "^3.1.1",
|
|
||||||
"stream-shift": "^1.0.1",
|
|
||||||
"strict-uri-encode": "^2.0.0",
|
|
||||||
"string-width": "^4.2.0",
|
|
||||||
"string.prototype.trimleft": "^2.1.2",
|
|
||||||
"string.prototype.trimright": "^2.1.2",
|
|
||||||
"string_decoder": "^1.3.0",
|
|
||||||
"strip-ansi": "^6.0.0",
|
|
||||||
"strip-bom-string": "^1.0.0",
|
|
||||||
"strip-eof": "^2.0.0",
|
|
||||||
"stylehacks": "^4.0.3",
|
|
||||||
"stylus": "^0.54.8",
|
|
||||||
"stylus-loader": "^3.0.2",
|
|
||||||
"supports-color": "^7.1.0",
|
|
||||||
"svg-tags": "^1.0.0",
|
|
||||||
"svgo": "^1.3.2",
|
|
||||||
"tapable": "^1.1.3",
|
|
||||||
"terser": "^5.0.0",
|
|
||||||
"terser-webpack-plugin": "^4.0.0",
|
|
||||||
"text-table": "^0.2.0",
|
|
||||||
"through": "^2.3.8",
|
|
||||||
"through2": "^4.0.2",
|
|
||||||
"thunky": "^1.1.0",
|
|
||||||
"timers-browserify": "^2.0.11",
|
|
||||||
"timsort": "^0.3.0",
|
|
||||||
"tiny-emitter": "^2.1.0",
|
|
||||||
"to-arraybuffer": "^1.0.1",
|
|
||||||
"to-factory": "^1.0.0",
|
|
||||||
"to-fast-properties": "^3.0.1",
|
|
||||||
"to-object-path": "^0.3.0",
|
|
||||||
"to-regex": "^3.0.2",
|
|
||||||
"to-regex-range": "^5.0.1",
|
|
||||||
"toidentifier": "^1.0.0",
|
|
||||||
"toml": "^3.0.0",
|
|
||||||
"toposort": "^2.0.2",
|
|
||||||
"tough-cookie": "^4.0.0",
|
|
||||||
"tr46": "^2.0.2",
|
|
||||||
"tslib": "^2.0.0",
|
|
||||||
"tty-browserify": "^0.0.1",
|
|
||||||
"tunnel-agent": "^0.6.0",
|
|
||||||
"tweetnacl": "^1.0.3",
|
|
||||||
"type-fest": "^0.16.0",
|
|
||||||
"type-is": "^1.6.18",
|
|
||||||
"typedarray": "^0.0.6",
|
|
||||||
"uc.micro": "^1.0.6",
|
|
||||||
"uglify-js": "^3.10.1",
|
|
||||||
"unicode-canonical-property-names-ecmascript": "^1.0.4",
|
|
||||||
"unicode-match-property-ecmascript": "^1.0.4",
|
|
||||||
"unicode-match-property-value-ecmascript": "^1.2.0",
|
|
||||||
"unicode-property-aliases-ecmascript": "^1.1.0",
|
|
||||||
"union-value": "^2.0.1",
|
|
||||||
"uniq": "^1.0.1",
|
|
||||||
"uniqs": "^2.0.0",
|
|
||||||
"unique-filename": "^1.1.1",
|
|
||||||
"unique-slug": "^2.0.2",
|
|
||||||
"universalify": "^2.0.0",
|
|
||||||
"unpipe": "^1.0.0",
|
|
||||||
"unquote": "^1.1.1",
|
|
||||||
"unset-value": "^1.0.0",
|
|
||||||
"upath": "^1.2.0",
|
|
||||||
"upper-case": "^2.0.1",
|
|
||||||
"uri-js": "^4.2.2",
|
|
||||||
"urix": "^0.1.0",
|
|
||||||
"url": "^0.11.0",
|
|
||||||
"url-loader": "^4.1.0",
|
|
||||||
"url-parse": "^1.4.7",
|
|
||||||
"use": "^3.1.1",
|
|
||||||
"util": "^0.12.3",
|
|
||||||
"util-deprecate": "^1.0.2",
|
|
||||||
"util.promisify": "^1.0.1",
|
|
||||||
"utila": "^0.4.0",
|
|
||||||
"utils-merge": "^1.0.1",
|
|
||||||
"uuid": "^8.3.0",
|
|
||||||
"vary": "^1.1.2",
|
|
||||||
"vendors": "^1.0.4",
|
|
||||||
"verror": "^1.10.0",
|
|
||||||
"vm-browserify": "^1.1.2",
|
|
||||||
"vue": "^2.6.11",
|
|
||||||
"vue-hot-reload-api": "^2.3.4",
|
|
||||||
"vue-loader": "^15.9.3",
|
|
||||||
"vue-router": "^3.4.0",
|
|
||||||
"vue-server-renderer": "^2.6.11",
|
|
||||||
"vue-style-loader": "^4.1.2",
|
|
||||||
"vue-template-compiler": "^2.6.11",
|
|
||||||
"vue-template-es2015-compiler": "^1.9.1",
|
|
||||||
"vuepress": "^1.5.3",
|
|
||||||
"vuepress-html-webpack-plugin": "^3.2.0",
|
|
||||||
"vuepress-plugin-container": "^2.1.4",
|
|
||||||
"vuepress-plugin-sitemap": "^2.3.1",
|
|
||||||
"vuepress-plugin-smooth-scroll": "^0.0.9",
|
|
||||||
"vuepress-plugin-zooming": "^1.1.7",
|
|
||||||
"watchpack": "^1.7.4",
|
|
||||||
"wbuf": "^1.7.3",
|
|
||||||
"webidl-conversions": "^6.1.0",
|
|
||||||
"webpack": "^4.44.1",
|
|
||||||
"webpack-chain": "^6.5.1",
|
|
||||||
"webpack-dev-middleware": "^3.7.2",
|
|
||||||
"webpack-dev-server": "^3.11.0",
|
|
||||||
"webpack-log": "^3.0.1",
|
|
||||||
"webpack-merge": "^5.1.1",
|
|
||||||
"webpack-sources": "^1.4.3",
|
|
||||||
"webpackbar": "^4.0.0",
|
|
||||||
"websocket-driver": "^0.7.4",
|
|
||||||
"websocket-extensions": "^0.1.4",
|
|
||||||
"whatwg-url": "^8.1.0",
|
|
||||||
"when": "^3.7.8",
|
|
||||||
"which": "^2.0.2",
|
|
||||||
"which-module": "^2.0.0",
|
|
||||||
"worker-farm": "^1.7.0",
|
|
||||||
"wrap-ansi": "^7.0.0",
|
|
||||||
"wrappy": "^1.0.2",
|
|
||||||
"ws": "^7.3.1",
|
|
||||||
"xmlbuilder": "^15.1.1",
|
|
||||||
"xtend": "^4.0.2",
|
|
||||||
"y18n": "^4.0.0",
|
|
||||||
"yallist": "^4.0.0",
|
|
||||||
"yargs": "^15.4.1",
|
|
||||||
"yargs-parser": "^18.1.3",
|
|
||||||
"zepto": "^1.2.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {},
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vuepress dev",
|
|
||||||
"build": "vuepress build"
|
|
||||||
},
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC"
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
# Screenshots
|
|
||||||
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/login.png" alt="Login" title="Login" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/dashboard.png" alt="Dashboard" title="Dashboard" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts.png" alt="Proxy Hosts" title="Proxy Hosts" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts-add.png" alt="Add Proxy Host" title="Add Proxy Host" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/redirection-hosts.png" alt="Redirection Hosts" title="Redirection Hosts" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/dead-hosts.png" alt="404 Hosts" title="404 Hosts" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/permissions.png" alt="User Permissions" title="User Permissions" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/certificates.png" alt="Certificates" title="Certificates" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/audit-log.png" alt="Audit Log" title="Audit Log" width="200"/>
|
|
||||||
<img class="no-medium-zoom zooming" src="/screenshots/custom-settings.png" alt="Custom Settings" title="Custom Settings" width="200"/>
|
|
@@ -1,182 +0,0 @@
|
|||||||
# Full Setup Instructions
|
|
||||||
|
|
||||||
## Running the App
|
|
||||||
|
|
||||||
Create a `docker-compose.yml` file:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
version: "3"
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'jc21/nginx-proxy-manager:latest'
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
# These ports are in format <host-port>:<container-port>
|
|
||||||
- '80:80' # Public HTTP Port
|
|
||||||
- '443:443' # Public HTTPS Port
|
|
||||||
- '81:81' # Admin Web Port
|
|
||||||
# Add any other Stream port you want to expose
|
|
||||||
# - '21:21' # FTP
|
|
||||||
|
|
||||||
# Uncomment the next line if you uncomment anything in the section
|
|
||||||
# environment:
|
|
||||||
# Uncomment this if you want to change the location of
|
|
||||||
# the SQLite DB file within the container
|
|
||||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
|
||||||
|
|
||||||
# Uncomment this if IPv6 is not enabled on your host
|
|
||||||
# DISABLE_IPV6: 'true'
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
- ./data:/data
|
|
||||||
- ./letsencrypt:/etc/letsencrypt
|
|
||||||
```
|
|
||||||
|
|
||||||
Then:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using MySQL / MariaDB Database
|
|
||||||
|
|
||||||
If you opt for the MySQL configuration you will have to provide the database server yourself. You can also use MariaDB. Here are the minimum supported versions:
|
|
||||||
|
|
||||||
- MySQL v5.7.8+
|
|
||||||
- MariaDB v10.2.7+
|
|
||||||
|
|
||||||
It's easy to use another docker container for your database also and link it as part of the docker stack, so that's what the following examples
|
|
||||||
are going to use.
|
|
||||||
|
|
||||||
Here is an example of what your `docker-compose.yml` will look like when using a MariaDB container:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
version: "3"
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'jc21/nginx-proxy-manager:latest'
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
# These ports are in format <host-port>:<container-port>
|
|
||||||
- '80:80' # Public HTTP Port
|
|
||||||
- '443:443' # Public HTTPS Port
|
|
||||||
- '81:81' # Admin Web Port
|
|
||||||
# Add any other Stream port you want to expose
|
|
||||||
# - '21:21' # FTP
|
|
||||||
environment:
|
|
||||||
DB_MYSQL_HOST: "db"
|
|
||||||
DB_MYSQL_PORT: 3306
|
|
||||||
DB_MYSQL_USER: "npm"
|
|
||||||
DB_MYSQL_PASSWORD: "npm"
|
|
||||||
DB_MYSQL_NAME: "npm"
|
|
||||||
# Uncomment this if IPv6 is not enabled on your host
|
|
||||||
# DISABLE_IPV6: 'true'
|
|
||||||
volumes:
|
|
||||||
- ./data:/data
|
|
||||||
- ./letsencrypt:/etc/letsencrypt
|
|
||||||
depends_on:
|
|
||||||
- db
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: 'jc21/mariadb-aria:latest'
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
MYSQL_ROOT_PASSWORD: 'npm'
|
|
||||||
MYSQL_DATABASE: 'npm'
|
|
||||||
MYSQL_USER: 'npm'
|
|
||||||
MYSQL_PASSWORD: 'npm'
|
|
||||||
volumes:
|
|
||||||
- ./data/mysql:/var/lib/mysql
|
|
||||||
```
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
|
|
||||||
Please note, that `DB_MYSQL_*` environment variables will take precedent over `DB_SQLITE_*` variables. So if you keep the MySQL variables, you will not be able to use SQLite.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Running on Raspberry PI / ARM devices
|
|
||||||
|
|
||||||
The docker images support the following architectures:
|
|
||||||
- amd64
|
|
||||||
- arm64
|
|
||||||
- armv7
|
|
||||||
|
|
||||||
The docker images are a manifest of all the architecture docker builds supported, so this means
|
|
||||||
you don't have to worry about doing anything special and you can follow the common instructions above.
|
|
||||||
|
|
||||||
Check out the [dockerhub tags](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags)
|
|
||||||
for a list of supported architectures and if you want one that doesn't exist,
|
|
||||||
[create a feature request](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
|
|
||||||
|
|
||||||
Also, if you don't know how to already, follow [this guide to install docker and docker-compose](https://manre-universe.net/how-to-run-docker-and-docker-compose-on-raspbian/)
|
|
||||||
on Raspbian.
|
|
||||||
|
|
||||||
Please note that the `jc21/mariadb-aria:latest` image might have some problems on some ARM devices, if you want a separate database container, use the `yobasystems/alpine-mariadb:latest` image.
|
|
||||||
|
|
||||||
## Initial Run
|
|
||||||
|
|
||||||
After the app is running for the first time, the following will happen:
|
|
||||||
|
|
||||||
1. The database will initialize with table structures
|
|
||||||
2. GPG keys will be generated and saved in the configuration file
|
|
||||||
3. A default admin user will be created
|
|
||||||
|
|
||||||
This process can take a couple of minutes depending on your machine.
|
|
||||||
|
|
||||||
|
|
||||||
## Default Administrator User
|
|
||||||
|
|
||||||
```
|
|
||||||
Email: admin@example.com
|
|
||||||
Password: changeme
|
|
||||||
```
|
|
||||||
|
|
||||||
Immediately after logging in with this default user you will be asked to modify your details and change your password.
|
|
||||||
|
|
||||||
## Configuration File
|
|
||||||
|
|
||||||
::: warning
|
|
||||||
|
|
||||||
This section is meant for advanced users
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
If you would like more control over the database settings you can define a custom config JSON file.
|
|
||||||
|
|
||||||
|
|
||||||
Here's an example for `sqlite` configuration as it is generated from the environment variables:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"database": {
|
|
||||||
"engine": "knex-native",
|
|
||||||
"knex": {
|
|
||||||
"client": "sqlite3",
|
|
||||||
"connection": {
|
|
||||||
"filename": "/data/database.sqlite"
|
|
||||||
},
|
|
||||||
"useNullAsDefault": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
You can modify the `knex` object with your custom configuration, but note that not all knex clients might be installed in the image.
|
|
||||||
|
|
||||||
Once you've created your configuration file you can mount it to `/app/config/production.json` inside you container using:
|
|
||||||
|
|
||||||
```
|
|
||||||
[...]
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: 'jc21/nginx-proxy-manager:latest'
|
|
||||||
[...]
|
|
||||||
volumes:
|
|
||||||
- ./config.json:/app/config/production.json
|
|
||||||
[...]
|
|
||||||
[...]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** After the first run of the application, the config file will be altered to include generated encryption keys unique to your installation.
|
|
||||||
These keys affect the login and session management of the application. If these keys change for any reason, all users will be logged out.
|
|
16
docs/third-party/README.md
vendored
@@ -1,16 +0,0 @@
|
|||||||
# Third Party
|
|
||||||
|
|
||||||
As this software gains popularity it's common to see it integrated with other platforms. Please be aware that unless specifically mentioned in the documentation of those
|
|
||||||
integrations, they are *not supported* by me.
|
|
||||||
|
|
||||||
Known integrations:
|
|
||||||
|
|
||||||
- [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager)
|
|
||||||
- [UnRaid / Synology](https://github.com/jlesage/docker-nginx-proxy-manager)
|
|
||||||
- [Proxmox Scripts](https://github.com/ej52/proxmox-scripts/tree/main/lxc/nginx-proxy-manager)
|
|
||||||
- [nginxproxymanagerGraf](https://github.com/ma-karai/nginxproxymanagerGraf)
|
|
||||||
|
|
||||||
|
|
||||||
If you would like your integration of NPM listed, please open a
|
|
||||||
[Github issue](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)
|
|
||||||
|
|
@@ -1,11 +0,0 @@
|
|||||||
# Upgrading
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose pull
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
This project will automatically update any databases or other requirements so you don't have to follow
|
|
||||||
any crazy instructions. These steps above will pull the latest updates and recreate the docker
|
|
||||||
containers.
|
|
||||||
|
|
10448
docs/yarn.lock
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |