mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-06-18 18:16:26 +00:00
Compare commits
212 Commits
v2.10.0
...
671817d640
Author | SHA1 | Date | |
---|---|---|---|
671817d640 | |||
c39e580e81 | |||
da29cd2e0e | |||
72abe50799 | |||
a92624d086 | |||
c6465a5090 | |||
d40f9e06fc | |||
69ec017a53 | |||
fa67f257ef | |||
0dcd648c9d | |||
c989a282e3 | |||
5aff969c04 | |||
bfbf7519ec | |||
bf36c7966a | |||
63cd9ba08f | |||
e3d4882c3d | |||
3e1b73143e | |||
10ece3548d | |||
0503a6af75 | |||
55d765e785 | |||
1fb9a75a33 | |||
9c2e838d61 | |||
40d81d6e44 | |||
1c84eaac02 | |||
577954ef8c | |||
f0c75641d8 | |||
e42e2acf12 | |||
eaa11fe460 | |||
5b53825ccb | |||
a94660120f | |||
39f4836485 | |||
209c1b3334 | |||
58138fbac4 | |||
da820db4e1 | |||
47b868bfc6 | |||
89a405f60c | |||
0353051436 | |||
a3630a6286 | |||
10d9760242 | |||
c722eb1cea | |||
0472abacd2 | |||
a2e85ceed8 | |||
cddd6fb985 | |||
db23c9a52f | |||
8646cb5a19 | |||
fe0c04610f | |||
9f16dae2ff | |||
00264bcfb2 | |||
834fb1a361 | |||
1be87f48c1 | |||
9c54d1b718 | |||
f7d1c490b3 | |||
fe4bd9fed6 | |||
58ef9a688e | |||
d19ebf5925 | |||
96fc6a20bb | |||
e69684919c | |||
be39253a6f | |||
30772a48bd | |||
33c867895c | |||
a7fe687bae | |||
4028120f55 | |||
d1119ec63f | |||
4c906283df | |||
8ec0c76f51 | |||
c70f65d349 | |||
883a272b0a | |||
6aee2bbcba | |||
025fc9776b | |||
b699f05f47 | |||
f7c87f63bd | |||
e4ef095254 | |||
09d5e2c94f | |||
459b7a2223 | |||
9c813bcce3 | |||
b8596ac01c | |||
082c4e1008 | |||
2273eae6ee | |||
997e9d431b | |||
b3564b6d4b | |||
4e27cdabc4 | |||
965873adc5 | |||
5de95a8c90 | |||
fa557d8159 | |||
bc8211a6a9 | |||
1c498f84ad | |||
ea6e9757e3 | |||
1308ae42c2 | |||
7be548575b | |||
c6aab8d4e6 | |||
da55e93183 | |||
af475ab5d4 | |||
7d85463dae | |||
13d4f98fdb | |||
388fff84f2 | |||
49a765516c | |||
27bc8c4e33 | |||
881a067aff | |||
1975e4a151 | |||
4704bd6a38 | |||
ca56e0483f | |||
3b8cb86d72 | |||
5165de4a91 | |||
1ab3575c68 | |||
ccf9cce825 | |||
3ad2188f78 | |||
33dbffb974 | |||
289e438c59 | |||
e08a4d4490 | |||
d1d1819677 | |||
4e0768d56c | |||
3666364418 | |||
9052502a17 | |||
b608d3392d | |||
edb81ecce0 | |||
e24181936f | |||
940d06cac9 | |||
134902d127 | |||
2df4620d05 | |||
f41b1069ae | |||
004a93fbc3 | |||
2d9f04edcd | |||
53dbe258a5 | |||
e4ba22f0f8 | |||
3197de41de | |||
0f7be7987b | |||
853c48dff6 | |||
410c3484ab | |||
44e9f377f9 | |||
0f3b76f607 | |||
f426e64569 | |||
4867db078c | |||
6b565e628f | |||
881d70502b | |||
62e4edddf0 | |||
4b9c02cc0c | |||
5af834e40b | |||
6f8db95249 | |||
fe93cb3474 | |||
fa851b61da | |||
3333a32612 | |||
9a79fce498 | |||
b1180f5077 | |||
5454352fe5 | |||
aee93a2f6f | |||
f38cb5b500 | |||
f1b7156c89 | |||
98465cf1b0 | |||
137e865b66 | |||
e740fb4064 | |||
f91f0ee8db | |||
1c9f751512 | |||
a602bdd514 | |||
f7b2be68cc | |||
ab4586fc6b | |||
a984a68065 | |||
52875fca6e | |||
63b50fcd95 | |||
5ab4aea03f | |||
d73135378e | |||
e19d685cb6 | |||
c8caaa56d9 | |||
11a98f4c12 | |||
4a85d4ac4e | |||
3138ba46ce | |||
cdd0b2e6d3 | |||
f458730d87 | |||
d20873dcbb | |||
d1e9407e4d | |||
63ee69f432 | |||
f39e527680 | |||
2dd4434ceb | |||
81054631f9 | |||
53d61bd626 | |||
847e879b3f | |||
4c59400731 | |||
824c837a38 | |||
2a06384a4a | |||
05307aa253 | |||
3d2406ac3d | |||
0127dc7f03 | |||
4349d42636 | |||
4b6f9d9419 | |||
c3f019c911 | |||
ecf0290203 | |||
4f41fe0c95 | |||
c3735fdbbb | |||
c432c34fb3 | |||
a1245bc161 | |||
db4ab1d548 | |||
86ddd9c83c | |||
67208e43cc | |||
ddf80302c6 | |||
5f2576946d | |||
9fe07fa6c3 | |||
d9b9af543e | |||
eb2e2e0478 | |||
9225d5d442 | |||
308a7149ed | |||
8a4a7d0caf | |||
5d03ede100 | |||
4a86bb42cc | |||
dad8561ea1 | |||
56a92e5c0e | |||
9d672f5813 | |||
d5ed70dbb6 | |||
c197e66d62 | |||
91cf3c8873 | |||
7f5e0414ac | |||
d179887c15 | |||
35abb4d7ae | |||
61b290e220 |
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: 'Close stale issues and PRs'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 1 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9
|
||||||
|
with:
|
||||||
|
stale-issue-label: 'stale'
|
||||||
|
stale-pr-label: 'stale'
|
||||||
|
stale-issue-message: 'Issue is now considered stale. If you want to keep it open, please comment :+1:'
|
||||||
|
stale-pr-message: 'PR is now considered stale. If you want to keep it open, please comment :+1:'
|
||||||
|
close-issue-message: 'Issue was closed due to inactivity.'
|
||||||
|
close-pr-message: 'PR was closed due to inactivity.'
|
||||||
|
days-before-stale: 182
|
||||||
|
days-before-close: 365
|
||||||
|
operations-per-run: 50
|
248
Jenkinsfile
vendored
248
Jenkinsfile
vendored
@ -17,13 +17,11 @@ pipeline {
|
|||||||
IMAGE = 'nginx-proxy-manager'
|
IMAGE = 'nginx-proxy-manager'
|
||||||
BUILD_VERSION = getVersion()
|
BUILD_VERSION = getVersion()
|
||||||
MAJOR_VERSION = '2'
|
MAJOR_VERSION = '2'
|
||||||
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('/', '-')}"
|
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
|
||||||
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
|
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
|
||||||
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
|
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
|
||||||
COMPOSE_INTERACTIVE_NO_CLI = 1
|
COMPOSE_INTERACTIVE_NO_CLI = 1
|
||||||
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
|
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
|
||||||
DOCS_BUCKET = 'jc21-npm-site'
|
|
||||||
DOCS_CDN = 'EN1G6DEWZUTDT'
|
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Environment') {
|
stage('Environment') {
|
||||||
@ -62,99 +60,114 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Build and Test') {
|
stage('Builds') {
|
||||||
steps {
|
parallel {
|
||||||
script {
|
stage('Project') {
|
||||||
// Frontend and Backend
|
steps {
|
||||||
def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: '''
|
script {
|
||||||
set -e
|
// Frontend and Backend
|
||||||
./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1
|
def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: '''
|
||||||
./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1
|
set -e
|
||||||
''')
|
./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1
|
||||||
shOutput = readFile "${env.WORKSPACE}/tmp-sh-build"
|
./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1
|
||||||
if (shStatusCode != 0) {
|
''')
|
||||||
error "${shOutput}"
|
shOutput = readFile "${env.WORKSPACE}/tmp-sh-build"
|
||||||
|
if (shStatusCode != 0) {
|
||||||
|
error "${shOutput}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
sh 'rm -f ${WORKSPACE}/tmp-sh-build'
|
||||||
|
}
|
||||||
|
failure {
|
||||||
|
npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Docs') {
|
||||||
|
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('Cypress') {
|
||||||
|
steps {
|
||||||
|
// Creating will also create the network prior to
|
||||||
|
// using it in parallel stages below and mitigating
|
||||||
|
// a race condition.
|
||||||
|
sh 'docker-compose build cypress-sqlite'
|
||||||
|
sh 'docker-compose build cypress-mysql'
|
||||||
|
sh 'docker-compose create cypress-sqlite'
|
||||||
|
sh 'docker-compose create cypress-mysql'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
post {
|
|
||||||
always {
|
|
||||||
sh 'rm -f ${WORKSPACE}/tmp-sh-build'
|
|
||||||
}
|
|
||||||
failure {
|
|
||||||
npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
stage('Integration Tests Sqlite') {
|
stage('Integration Tests') {
|
||||||
steps {
|
parallel {
|
||||||
// Bring up a stack
|
stage('Sqlite') {
|
||||||
sh 'docker-compose up -d fullstack-sqlite'
|
steps {
|
||||||
sh './scripts/wait-healthy $(docker-compose ps -q fullstack-sqlite) 120'
|
// Bring up a stack
|
||||||
|
sh 'docker-compose up -d fullstack-sqlite'
|
||||||
|
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
|
||||||
|
// Stop and Start it, as this will test it's ability to restart with existing data
|
||||||
|
sh 'docker-compose stop fullstack-sqlite'
|
||||||
|
sh 'docker-compose start fullstack-sqlite'
|
||||||
|
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
|
||||||
|
|
||||||
// Run tests
|
// Run tests
|
||||||
sh 'rm -rf test/results'
|
sh 'rm -rf test/results-sqlite'
|
||||||
sh 'docker-compose up cypress-sqlite'
|
sh 'docker-compose up cypress-sqlite'
|
||||||
// Get results
|
// Get results
|
||||||
sh 'docker cp -L "$(docker-compose ps -q cypress-sqlite):/test/results" test/'
|
sh 'docker cp -L "$(docker-compose ps --all -q cypress-sqlite):/test/results" test/results-sqlite'
|
||||||
}
|
|
||||||
post {
|
|
||||||
always {
|
|
||||||
// Dumps to analyze later
|
|
||||||
sh 'mkdir -p debug'
|
|
||||||
sh 'docker-compose logs fullstack-sqlite > debug/docker_fullstack_sqlite.log'
|
|
||||||
sh 'docker-compose logs db > debug/docker_db.log'
|
|
||||||
// Cypress videos and screenshot artifacts
|
|
||||||
dir(path: 'test/results') {
|
|
||||||
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
|
||||||
}
|
}
|
||||||
junit 'test/results/junit/*'
|
post {
|
||||||
}
|
always {
|
||||||
}
|
// Dumps to analyze later
|
||||||
}
|
sh 'mkdir -p debug/sqlite'
|
||||||
stage('Integration Tests Mysql') {
|
sh 'docker-compose logs fullstack-sqlite > debug/sqlite/docker_fullstack_sqlite.log'
|
||||||
steps {
|
// Cypress videos and screenshot artifacts
|
||||||
// Bring up a stack
|
dir(path: 'test/results-sqlite') {
|
||||||
sh 'docker-compose up -d fullstack-mysql'
|
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
||||||
sh './scripts/wait-healthy $(docker-compose ps -q fullstack-mysql) 120'
|
}
|
||||||
|
junit 'test/results-sqlite/junit/*'
|
||||||
// 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 > debug/docker_fullstack_mysql.log'
|
|
||||||
sh 'docker-compose logs db > debug/docker_db.log'
|
|
||||||
// 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'
|
|
||||||
}
|
}
|
||||||
|
stage('Mysql') {
|
||||||
|
steps {
|
||||||
|
// Bring up a stack
|
||||||
|
sh 'docker-compose up -d fullstack-mysql'
|
||||||
|
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-mysql) 120'
|
||||||
|
|
||||||
dir(path: 'docs/.vuepress/dist') {
|
// Run tests
|
||||||
sh 'tar -czf ../../docs.tgz *'
|
sh 'rm -rf test/results-mysql'
|
||||||
|
sh 'docker-compose up cypress-mysql'
|
||||||
|
// Get results
|
||||||
|
sh 'docker cp -L "$(docker-compose ps --all -q cypress-mysql):/test/results" test/results-mysql'
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
// Dumps to analyze later
|
||||||
|
sh 'mkdir -p debug/mysql'
|
||||||
|
sh 'docker-compose logs fullstack-mysql > debug/mysql/docker_fullstack_mysql.log'
|
||||||
|
sh 'docker-compose logs db > debug/mysql/docker_db.log'
|
||||||
|
// Cypress videos and screenshot artifacts
|
||||||
|
dir(path: 'test/results-mysql') {
|
||||||
|
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
||||||
|
}
|
||||||
|
junit 'test/results-mysql/junit/*'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('MultiArch Build') {
|
stage('MultiArch Build') {
|
||||||
@ -170,31 +183,48 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Docs Deploy') {
|
stage('Docs / Comment') {
|
||||||
when {
|
parallel {
|
||||||
allOf {
|
stage('Master Docs') {
|
||||||
branch 'master'
|
when {
|
||||||
not {
|
allOf {
|
||||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
branch 'master'
|
||||||
|
not {
|
||||||
|
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
npmDocsReleaseMaster()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
stage('Develop Docs') {
|
||||||
steps {
|
when {
|
||||||
npmDocsRelease("$DOCS_BUCKET", "$DOCS_CDN")
|
allOf {
|
||||||
}
|
branch 'develop'
|
||||||
}
|
not {
|
||||||
stage('PR Comment') {
|
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||||
when {
|
}
|
||||||
allOf {
|
}
|
||||||
changeRequest()
|
}
|
||||||
not {
|
steps {
|
||||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
npmDocsReleaseDevelop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
stage('PR Comment') {
|
||||||
steps {
|
when {
|
||||||
script {
|
allOf {
|
||||||
npmGithubPrComment("Docker 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.", true)
|
changeRequest()
|
||||||
|
not {
|
||||||
|
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
script {
|
||||||
|
npmGithubPrComment("Docker 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.", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,12 +240,12 @@ pipeline {
|
|||||||
sh 'figlet "SUCCESS"'
|
sh 'figlet "SUCCESS"'
|
||||||
}
|
}
|
||||||
failure {
|
failure {
|
||||||
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
|
archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
|
||||||
juxtapose event: 'failure'
|
juxtapose event: 'failure'
|
||||||
sh 'figlet "FAILURE"'
|
sh 'figlet "FAILURE"'
|
||||||
}
|
}
|
||||||
unstable {
|
unstable {
|
||||||
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
|
archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
|
||||||
juxtapose event: 'unstable'
|
juxtapose event: 'unstable'
|
||||||
sh 'figlet "UNSTABLE"'
|
sh 'figlet "UNSTABLE"'
|
||||||
}
|
}
|
||||||
|
27
README.md
27
README.md
@ -1,7 +1,7 @@
|
|||||||
<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.10.0-green.svg?style=for-the-badge">
|
<img src="https://img.shields.io/badge/version-2.11.1-green.svg?style=for-the-badge">
|
||||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
<a href="https://hub.docker.com/repository/docker/jc21/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/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
@ -19,7 +19,7 @@ running at home or otherwise, including free SSL, without having to know too muc
|
|||||||
|
|
||||||
## Project Goal
|
## Project Goal
|
||||||
|
|
||||||
I created this project to fill a personal need to provide users with a easy way to accomplish reverse
|
I created this project to fill a personal need to provide users with an easy way to accomplish reverse
|
||||||
proxying hosts with SSL termination and it had to be so easy that a monkey could do it. This goal hasn't changed.
|
proxying hosts with SSL termination and it had to be so easy that a monkey could do it. This goal hasn't changed.
|
||||||
While there might be advanced options they are optional and the project should be as simple as possible
|
While there might be advanced options they are optional and the project should be as simple as possible
|
||||||
so that the barrier for entry here is low.
|
so that the barrier for entry here is low.
|
||||||
@ -59,7 +59,7 @@ I won't go in to too much detail here but here are the basics for someone new to
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: 'jc21/nginx-proxy-manager:latest'
|
image: 'docker.io/jc21/nginx-proxy-manager:latest'
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- '80:80'
|
- '80:80'
|
||||||
@ -98,7 +98,23 @@ Password: changeme
|
|||||||
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.
|
||||||
|
|
||||||
|
|
||||||
## Contributors
|
## Contributing
|
||||||
|
|
||||||
|
All are welcome to create pull requests for this project, against the `develop` branch. Official releases are created from the `master` branch.
|
||||||
|
|
||||||
|
Run the following commands to test locally:
|
||||||
|
|
||||||
|
- `cd backend && npm i && node_modules/eslint/bin/eslint.js .`
|
||||||
|
- `cd test && npm i && npm run cypress`
|
||||||
|
|
||||||
|
CI is used in this project. All PR's must pass before being considered. After passing,
|
||||||
|
docker builds for PR's are available on dockerhub for manual verifications.
|
||||||
|
|
||||||
|
Documentation within the `develop` branch is available for preview at
|
||||||
|
[https://develop.nginxproxymanager.com](https://develop.nginxproxymanager.com)
|
||||||
|
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
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).
|
||||||
|
|
||||||
@ -107,5 +123,4 @@ Special thanks to [all of our contributors](https://github.com/NginxProxyManager
|
|||||||
|
|
||||||
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
|
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
|
||||||
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
|
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
|
||||||
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community)
|
3. [Reddit](https://reddit.com/r/nginxproxymanager)
|
||||||
4. [Reddit](https://reddit.com/r/nginxproxymanager)
|
|
||||||
|
@ -40,6 +40,214 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/nginx/proxy-hosts": {
|
||||||
|
"get": {
|
||||||
|
"operationId": "getProxyHosts",
|
||||||
|
"summary": "Get all proxy hosts",
|
||||||
|
"tags": ["Proxy Hosts"],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": ["users"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "expand",
|
||||||
|
"description": "Expansions",
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["access_list", "owner", "certificate"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "200 response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"examples": {
|
||||||
|
"default": {
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"created_on": "2023-03-30T01:12:23.000Z",
|
||||||
|
"modified_on": "2023-03-30T02:15:40.000Z",
|
||||||
|
"owner_user_id": 1,
|
||||||
|
"domain_names": ["aasdasdad"],
|
||||||
|
"forward_host": "asdasd",
|
||||||
|
"forward_port": 80,
|
||||||
|
"access_list_id": 0,
|
||||||
|
"certificate_id": 0,
|
||||||
|
"ssl_forced": 0,
|
||||||
|
"caching_enabled": 0,
|
||||||
|
"block_exploits": 0,
|
||||||
|
"advanced_config": "sdfsdfsdf",
|
||||||
|
"meta": {
|
||||||
|
"letsencrypt_agree": false,
|
||||||
|
"dns_challenge": false,
|
||||||
|
"nginx_online": false,
|
||||||
|
"nginx_err": "Command failed: /usr/sbin/nginx -t -g \"error_log off;\"\nnginx: [emerg] unknown directive \"sdfsdfsdf\" in /data/nginx/proxy_host/1.conf:37\nnginx: configuration file /etc/nginx/nginx.conf test failed\n"
|
||||||
|
},
|
||||||
|
"allow_websocket_upgrade": 0,
|
||||||
|
"enable_proxy_protocol": 0,
|
||||||
|
"load_balancer_ip": "",
|
||||||
|
"http2_support": 0,
|
||||||
|
"forward_scheme": "http",
|
||||||
|
"enabled": 1,
|
||||||
|
"locations": [],
|
||||||
|
"hsts_enabled": 0,
|
||||||
|
"hsts_subdomains": 0,
|
||||||
|
"owner": {
|
||||||
|
"id": 1,
|
||||||
|
"created_on": "2023-03-30T01:11:50.000Z",
|
||||||
|
"modified_on": "2023-03-30T01:11:50.000Z",
|
||||||
|
"is_deleted": 0,
|
||||||
|
"is_disabled": 0,
|
||||||
|
"email": "admin@example.com",
|
||||||
|
"name": "Administrator",
|
||||||
|
"nickname": "Admin",
|
||||||
|
"avatar": "",
|
||||||
|
"roles": ["admin"]
|
||||||
|
},
|
||||||
|
"access_list": null,
|
||||||
|
"certificate": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"created_on": "2023-03-30T02:11:49.000Z",
|
||||||
|
"modified_on": "2023-03-30T02:11:49.000Z",
|
||||||
|
"owner_user_id": 1,
|
||||||
|
"domain_names": ["test.example.com"],
|
||||||
|
"forward_host": "1.1.1.1",
|
||||||
|
"forward_port": 80,
|
||||||
|
"access_list_id": 0,
|
||||||
|
"certificate_id": 0,
|
||||||
|
"ssl_forced": 0,
|
||||||
|
"caching_enabled": 0,
|
||||||
|
"block_exploits": 0,
|
||||||
|
"advanced_config": "",
|
||||||
|
"meta": {
|
||||||
|
"letsencrypt_agree": false,
|
||||||
|
"dns_challenge": false,
|
||||||
|
"nginx_online": true,
|
||||||
|
"nginx_err": null
|
||||||
|
},
|
||||||
|
"allow_websocket_upgrade": 0,
|
||||||
|
"http2_support": 0,
|
||||||
|
"forward_scheme": "http",
|
||||||
|
"enabled": 1,
|
||||||
|
"locations": [],
|
||||||
|
"hsts_enabled": 0,
|
||||||
|
"hsts_subdomains": 0,
|
||||||
|
"owner": {
|
||||||
|
"id": 1,
|
||||||
|
"created_on": "2023-03-30T01:11:50.000Z",
|
||||||
|
"modified_on": "2023-03-30T01:11:50.000Z",
|
||||||
|
"is_deleted": 0,
|
||||||
|
"is_disabled": 0,
|
||||||
|
"email": "admin@example.com",
|
||||||
|
"name": "Administrator",
|
||||||
|
"nickname": "Admin",
|
||||||
|
"avatar": "",
|
||||||
|
"roles": ["admin"]
|
||||||
|
},
|
||||||
|
"access_list": null,
|
||||||
|
"certificate": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProxyHostsList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"operationId": "createProxyHost",
|
||||||
|
"summary": "Create a Proxy Host",
|
||||||
|
"tags": ["Proxy Hosts"],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"BearerAuth": ["users"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "proxyhost",
|
||||||
|
"description": "Proxy Host Payload",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProxyHostObject"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"description": "201 response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"examples": {
|
||||||
|
"default": {
|
||||||
|
"value": {
|
||||||
|
"id": 3,
|
||||||
|
"created_on": "2023-03-30T02:31:27.000Z",
|
||||||
|
"modified_on": "2023-03-30T02:31:27.000Z",
|
||||||
|
"owner_user_id": 1,
|
||||||
|
"domain_names": ["test2.example.com"],
|
||||||
|
"forward_host": "1.1.1.1",
|
||||||
|
"forward_port": 80,
|
||||||
|
"access_list_id": 0,
|
||||||
|
"certificate_id": 0,
|
||||||
|
"ssl_forced": 0,
|
||||||
|
"caching_enabled": 0,
|
||||||
|
"block_exploits": 0,
|
||||||
|
"advanced_config": "",
|
||||||
|
"meta": {
|
||||||
|
"letsencrypt_agree": false,
|
||||||
|
"dns_challenge": false
|
||||||
|
},
|
||||||
|
"allow_websocket_upgrade": 0,
|
||||||
|
"enable_proxy_protocol": 0,
|
||||||
|
"load_balancer_ip": "",
|
||||||
|
"http2_support": 0,
|
||||||
|
"forward_scheme": "http",
|
||||||
|
"enabled": 1,
|
||||||
|
"locations": [],
|
||||||
|
"hsts_enabled": 0,
|
||||||
|
"hsts_subdomains": 0,
|
||||||
|
"certificate": null,
|
||||||
|
"owner": {
|
||||||
|
"id": 1,
|
||||||
|
"created_on": "2023-03-30T01:11:50.000Z",
|
||||||
|
"modified_on": "2023-03-30T01:11:50.000Z",
|
||||||
|
"is_deleted": 0,
|
||||||
|
"is_disabled": 0,
|
||||||
|
"email": "admin@example.com",
|
||||||
|
"name": "Administrator",
|
||||||
|
"nickname": "Admin",
|
||||||
|
"avatar": "",
|
||||||
|
"roles": ["admin"]
|
||||||
|
},
|
||||||
|
"access_list": null,
|
||||||
|
"use_default_location": true,
|
||||||
|
"ipv6": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ProxyHostObject"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/schema": {
|
"/schema": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "schema",
|
"operationId": "schema",
|
||||||
@ -55,14 +263,10 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"operationId": "refreshToken",
|
"operationId": "refreshToken",
|
||||||
"summary": "Refresh your access token",
|
"summary": "Refresh your access token",
|
||||||
"tags": [
|
"tags": ["Tokens"],
|
||||||
"Tokens"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["tokens"]
|
||||||
"tokens"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -104,19 +308,14 @@
|
|||||||
"scope": {
|
"scope": {
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": ["user"]
|
||||||
"user"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"secret": {
|
"secret": {
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": ["identity", "secret"],
|
||||||
"identity",
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,23 +343,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"summary": "Request a new access token from credentials",
|
"summary": "Request a new access token from credentials",
|
||||||
"tags": [
|
"tags": ["Tokens"]
|
||||||
"Tokens"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/settings": {
|
"/settings": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getSettings",
|
"operationId": "getSettings",
|
||||||
"summary": "Get all settings",
|
"summary": "Get all settings",
|
||||||
"tags": [
|
"tags": ["Settings"],
|
||||||
"Settings"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["settings"]
|
||||||
"settings"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -194,14 +387,10 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"operationId": "getSetting",
|
"operationId": "getSetting",
|
||||||
"summary": "Get a setting",
|
"summary": "Get a setting",
|
||||||
"tags": [
|
"tags": ["Settings"],
|
||||||
"Settings"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["settings"]
|
||||||
"settings"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -244,14 +433,10 @@
|
|||||||
"put": {
|
"put": {
|
||||||
"operationId": "updateSetting",
|
"operationId": "updateSetting",
|
||||||
"summary": "Update a setting",
|
"summary": "Update a setting",
|
||||||
"tags": [
|
"tags": ["Settings"],
|
||||||
"Settings"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["settings"]
|
||||||
"settings"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -305,14 +490,10 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"operationId": "getUsers",
|
"operationId": "getUsers",
|
||||||
"summary": "Get all users",
|
"summary": "Get all users",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -322,9 +503,7 @@
|
|||||||
"description": "Expansions",
|
"description": "Expansions",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": ["permissions"]
|
||||||
"permissions"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -345,9 +524,7 @@
|
|||||||
"name": "Jamie Curnow",
|
"name": "Jamie Curnow",
|
||||||
"nickname": "James",
|
"nickname": "James",
|
||||||
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
||||||
"roles": [
|
"roles": ["admin"]
|
||||||
"admin"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -362,9 +539,7 @@
|
|||||||
"name": "Jamie Curnow",
|
"name": "Jamie Curnow",
|
||||||
"nickname": "James",
|
"nickname": "James",
|
||||||
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
||||||
"roles": [
|
"roles": ["admin"],
|
||||||
"admin"
|
|
||||||
],
|
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"visibility": "all",
|
"visibility": "all",
|
||||||
"proxy_hosts": "manage",
|
"proxy_hosts": "manage",
|
||||||
@ -389,14 +564,10 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"operationId": "createUser",
|
"operationId": "createUser",
|
||||||
"summary": "Create a User",
|
"summary": "Create a User",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -426,9 +597,7 @@
|
|||||||
"name": "Jamie Curnow",
|
"name": "Jamie Curnow",
|
||||||
"nickname": "James",
|
"nickname": "James",
|
||||||
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
||||||
"roles": [
|
"roles": ["admin"],
|
||||||
"admin"
|
|
||||||
],
|
|
||||||
"permissions": {
|
"permissions": {
|
||||||
"visibility": "all",
|
"visibility": "all",
|
||||||
"proxy_hosts": "manage",
|
"proxy_hosts": "manage",
|
||||||
@ -454,14 +623,10 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"operationId": "getUser",
|
"operationId": "getUser",
|
||||||
"summary": "Get a user",
|
"summary": "Get a user",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -501,9 +666,7 @@
|
|||||||
"name": "Jamie Curnow",
|
"name": "Jamie Curnow",
|
||||||
"nickname": "James",
|
"nickname": "James",
|
||||||
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
||||||
"roles": [
|
"roles": ["admin"]
|
||||||
"admin"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -518,14 +681,10 @@
|
|||||||
"put": {
|
"put": {
|
||||||
"operationId": "updateUser",
|
"operationId": "updateUser",
|
||||||
"summary": "Update a User",
|
"summary": "Update a User",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -574,9 +733,7 @@
|
|||||||
"name": "Jamie Curnow",
|
"name": "Jamie Curnow",
|
||||||
"nickname": "James",
|
"nickname": "James",
|
||||||
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
|
||||||
"roles": [
|
"roles": ["admin"]
|
||||||
"admin"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -591,14 +748,10 @@
|
|||||||
"delete": {
|
"delete": {
|
||||||
"operationId": "deleteUser",
|
"operationId": "deleteUser",
|
||||||
"summary": "Delete a User",
|
"summary": "Delete a User",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -637,14 +790,10 @@
|
|||||||
"put": {
|
"put": {
|
||||||
"operationId": "updateUserAuth",
|
"operationId": "updateUserAuth",
|
||||||
"summary": "Update a User's Authentication",
|
"summary": "Update a User's Authentication",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -700,14 +849,10 @@
|
|||||||
"put": {
|
"put": {
|
||||||
"operationId": "updateUserPermissions",
|
"operationId": "updateUserPermissions",
|
||||||
"summary": "Update a User's Permissions",
|
"summary": "Update a User's Permissions",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -755,14 +900,10 @@
|
|||||||
"put": {
|
"put": {
|
||||||
"operationId": "loginAsUser",
|
"operationId": "loginAsUser",
|
||||||
"summary": "Login as this user",
|
"summary": "Login as this user",
|
||||||
"tags": [
|
"tags": ["Users"],
|
||||||
"Users"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["users"]
|
||||||
"users"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": [
|
"parameters": [
|
||||||
@ -797,9 +938,7 @@
|
|||||||
"name": "Jamie Curnow",
|
"name": "Jamie Curnow",
|
||||||
"nickname": "James",
|
"nickname": "James",
|
||||||
"avatar": "//www.gravatar.com/avatar/3c8d73f45fd8763f827b964c76e6032a?default=mm",
|
"avatar": "//www.gravatar.com/avatar/3c8d73f45fd8763f827b964c76e6032a?default=mm",
|
||||||
"roles": [
|
"roles": ["admin"]
|
||||||
"admin"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -807,11 +946,7 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Login object",
|
"description": "Login object",
|
||||||
"required": [
|
"required": ["expires", "token", "user"],
|
||||||
"expires",
|
|
||||||
"token",
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"expires": {
|
"expires": {
|
||||||
@ -840,14 +975,10 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"operationId": "reportsHosts",
|
"operationId": "reportsHosts",
|
||||||
"summary": "Report on Host Statistics",
|
"summary": "Report on Host Statistics",
|
||||||
"tags": [
|
"tags": ["Reports"],
|
||||||
"Reports"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["reports"]
|
||||||
"reports"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -878,14 +1009,10 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"operationId": "getAuditLog",
|
"operationId": "getAuditLog",
|
||||||
"summary": "Get Audit Log",
|
"summary": "Get Audit Log",
|
||||||
"tags": [
|
"tags": ["Audit Log"],
|
||||||
"Audit Log"
|
|
||||||
],
|
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": [
|
"BearerAuth": ["audit-log"]
|
||||||
"audit-log"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
@ -925,10 +1052,7 @@
|
|||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Health object",
|
"description": "Health object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": ["status", "version"],
|
||||||
"status",
|
|
||||||
"version"
|
|
||||||
],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"status": {
|
"status": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -944,11 +1068,7 @@
|
|||||||
"revision": 0
|
"revision": 0
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": ["major", "minor", "revision"],
|
||||||
"major",
|
|
||||||
"minor",
|
|
||||||
"revision"
|
|
||||||
],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"major": {
|
"major": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@ -969,10 +1089,7 @@
|
|||||||
"TokenObject": {
|
"TokenObject": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Token object",
|
"description": "Token object",
|
||||||
"required": [
|
"required": ["expires", "token"],
|
||||||
"expires",
|
|
||||||
"token"
|
|
||||||
],
|
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"expires": {
|
"expires": {
|
||||||
@ -988,16 +1105,155 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ProxyHostObject": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Proxy Host object",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"created_on",
|
||||||
|
"modified_on",
|
||||||
|
"owner_user_id",
|
||||||
|
"domain_names",
|
||||||
|
"forward_host",
|
||||||
|
"forward_port",
|
||||||
|
"access_list_id",
|
||||||
|
"certificate_id",
|
||||||
|
"ssl_forced",
|
||||||
|
"caching_enabled",
|
||||||
|
"block_exploits",
|
||||||
|
"advanced_config",
|
||||||
|
"meta",
|
||||||
|
"allow_websocket_upgrade",
|
||||||
|
"enable_proxy_protocol",
|
||||||
|
"load_balancer_ip",
|
||||||
|
"http2_support",
|
||||||
|
"forward_scheme",
|
||||||
|
"enabled",
|
||||||
|
"locations",
|
||||||
|
"hsts_enabled",
|
||||||
|
"hsts_subdomains",
|
||||||
|
"certificate",
|
||||||
|
"use_default_location",
|
||||||
|
"ipv6"
|
||||||
|
],
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Proxy Host ID",
|
||||||
|
"minimum": 1,
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Created Date",
|
||||||
|
"example": "2020-01-30T09:36:08.000Z"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Modified Date",
|
||||||
|
"example": "2020-01-30T09:41:04.000Z"
|
||||||
|
},
|
||||||
|
"owner_user_id": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"example": 1
|
||||||
|
},
|
||||||
|
"domain_names": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems": 1,
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"forward_port": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1
|
||||||
|
},
|
||||||
|
"access_list_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"certificate_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"ssl_forced": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"caching_enabled": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"block_exploits": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"advanced_config": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"allow_websocket_upgrade": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"forward_scheme": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"locations": {
|
||||||
|
"type": "array"
|
||||||
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"certificate": {
|
||||||
|
"type": "object",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"owner": {
|
||||||
|
"type": "object",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"access_list": {
|
||||||
|
"type": "object",
|
||||||
|
"nullable": true
|
||||||
|
},
|
||||||
|
"use_default_location": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"ipv6": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ProxyHostsList": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Proxyn Hosts list",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ProxyHostObject"
|
||||||
|
}
|
||||||
|
},
|
||||||
"SettingObject": {
|
"SettingObject": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Setting object",
|
"description": "Setting object",
|
||||||
"required": [
|
"required": ["id", "name", "description", "value", "meta"],
|
||||||
"id",
|
|
||||||
"name",
|
|
||||||
"description",
|
|
||||||
"value",
|
|
||||||
"meta"
|
|
||||||
],
|
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
@ -1057,17 +1313,7 @@
|
|||||||
"UserObject": {
|
"UserObject": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "User object",
|
"description": "User object",
|
||||||
"required": [
|
"required": ["id", "created_on", "modified_on", "is_disabled", "email", "name", "nickname", "avatar", "roles"],
|
||||||
"id",
|
|
||||||
"created_on",
|
|
||||||
"modified_on",
|
|
||||||
"is_disabled",
|
|
||||||
"email",
|
|
||||||
"name",
|
|
||||||
"nickname",
|
|
||||||
"avatar",
|
|
||||||
"roles"
|
|
||||||
],
|
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
@ -1117,9 +1363,7 @@
|
|||||||
},
|
},
|
||||||
"roles": {
|
"roles": {
|
||||||
"description": "Roles applied",
|
"description": "Roles applied",
|
||||||
"example": [
|
"example": ["admin"],
|
||||||
"admin"
|
|
||||||
],
|
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@ -1137,10 +1381,7 @@
|
|||||||
"AuthObject": {
|
"AuthObject": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Authentication Object",
|
"description": "Authentication Object",
|
||||||
"required": [
|
"required": ["type", "secret"],
|
||||||
"type",
|
|
||||||
"secret"
|
|
||||||
],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -1167,64 +1408,37 @@
|
|||||||
"visibility": {
|
"visibility": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Visibility Type",
|
"description": "Visibility Type",
|
||||||
"enum": [
|
"enum": ["all", "user"]
|
||||||
"all",
|
|
||||||
"user"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"access_lists": {
|
"access_lists": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Access Lists Permissions",
|
"description": "Access Lists Permissions",
|
||||||
"enum": [
|
"enum": ["hidden", "view", "manage"]
|
||||||
"hidden",
|
|
||||||
"view",
|
|
||||||
"manage"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"dead_hosts": {
|
"dead_hosts": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "404 Hosts Permissions",
|
"description": "404 Hosts Permissions",
|
||||||
"enum": [
|
"enum": ["hidden", "view", "manage"]
|
||||||
"hidden",
|
|
||||||
"view",
|
|
||||||
"manage"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"proxy_hosts": {
|
"proxy_hosts": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Proxy Hosts Permissions",
|
"description": "Proxy Hosts Permissions",
|
||||||
"enum": [
|
"enum": ["hidden", "view", "manage"]
|
||||||
"hidden",
|
|
||||||
"view",
|
|
||||||
"manage"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"redirection_hosts": {
|
"redirection_hosts": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Redirection Permissions",
|
"description": "Redirection Permissions",
|
||||||
"enum": [
|
"enum": ["hidden", "view", "manage"]
|
||||||
"hidden",
|
|
||||||
"view",
|
|
||||||
"manage"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"streams": {
|
"streams": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Streams Permissions",
|
"description": "Streams Permissions",
|
||||||
"enum": [
|
"enum": ["hidden", "view", "manage"]
|
||||||
"hidden",
|
|
||||||
"view",
|
|
||||||
"manage"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"certificates": {
|
"certificates": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Certificates Permissions",
|
"description": "Certificates Permissions",
|
||||||
"enum": [
|
"enum": ["hidden", "view", "manage"]
|
||||||
"hidden",
|
|
||||||
"view",
|
|
||||||
"manage"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -204,7 +204,6 @@ const internalAccessList = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(internalNginx.reload)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
@ -227,7 +226,7 @@ const internalAccessList = {
|
|||||||
if (row.proxy_host_count) {
|
if (row.proxy_host_count) {
|
||||||
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
||||||
}
|
}
|
||||||
})
|
}).then(internalNginx.reload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalAccessList.maskItems(row);
|
return internalAccessList.maskItems(row);
|
||||||
});
|
});
|
||||||
|
@ -8,10 +8,12 @@ const config = require('../lib/config');
|
|||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
const utils = require('../lib/utils');
|
const utils = require('../lib/utils');
|
||||||
const certificateModel = require('../models/certificate');
|
const certificateModel = require('../models/certificate');
|
||||||
const dnsPlugins = require('../global/certbot-dns-plugins');
|
const tokenModel = require('../models/token');
|
||||||
|
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
||||||
const internalAuditLog = require('./audit-log');
|
const internalAuditLog = require('./audit-log');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const internalHost = require('./host');
|
const internalHost = require('./host');
|
||||||
|
const certbot = require('../lib/certbot');
|
||||||
const archiver = require('archiver');
|
const archiver = require('archiver');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { isArray } = require('lodash');
|
const { isArray } = require('lodash');
|
||||||
@ -26,10 +28,11 @@ function omissions() {
|
|||||||
|
|
||||||
const internalCertificate = {
|
const internalCertificate = {
|
||||||
|
|
||||||
allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
|
allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
|
||||||
intervalTimeout: 1000 * 60 * 60, // 1 hour
|
intervalTimeout: 1000 * 60 * 60, // 1 hour
|
||||||
interval: null,
|
interval: null,
|
||||||
intervalProcessing: false,
|
intervalProcessing: false,
|
||||||
|
renewBeforeExpirationBy: [30, 'days'],
|
||||||
|
|
||||||
initTimer: () => {
|
initTimer: () => {
|
||||||
logger.info('Let\'s Encrypt Renewal Timer initialized');
|
logger.info('Let\'s Encrypt Renewal Timer initialized');
|
||||||
@ -44,62 +47,51 @@ const internalCertificate = {
|
|||||||
processExpiringHosts: () => {
|
processExpiringHosts: () => {
|
||||||
if (!internalCertificate.intervalProcessing) {
|
if (!internalCertificate.intervalProcessing) {
|
||||||
internalCertificate.intervalProcessing = true;
|
internalCertificate.intervalProcessing = true;
|
||||||
logger.info('Renewing SSL certs close to expiry...');
|
logger.info('Renewing SSL certs expiring within ' + internalCertificate.renewBeforeExpirationBy[0] + ' ' + internalCertificate.renewBeforeExpirationBy[1] + ' ...');
|
||||||
|
|
||||||
const cmd = certbotCommand + ' renew --non-interactive --quiet ' +
|
const expirationThreshold = moment().add(internalCertificate.renewBeforeExpirationBy[0], internalCertificate.renewBeforeExpirationBy[1]).format('YYYY-MM-DD HH:mm:ss');
|
||||||
'--config "' + letsencryptConfig + '" ' +
|
|
||||||
'--work-dir "/tmp/letsencrypt-lib" ' +
|
|
||||||
'--logs-dir "/tmp/letsencrypt-log" ' +
|
|
||||||
'--preferred-challenges "dns,http" ' +
|
|
||||||
'--disable-hook-validation ' +
|
|
||||||
(letsencryptStaging ? '--staging' : '');
|
|
||||||
|
|
||||||
return utils.exec(cmd)
|
// Fetch all the letsencrypt certs from the db that will expire within the configured threshold
|
||||||
.then((result) => {
|
certificateModel
|
||||||
if (result) {
|
.query()
|
||||||
logger.info('Renew Result: ' + result);
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('provider', 'letsencrypt')
|
||||||
|
.andWhere('expires_on', '<', expirationThreshold)
|
||||||
|
.then((certificates) => {
|
||||||
|
if (!certificates || !certificates.length) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return internalNginx.reload()
|
/**
|
||||||
.then(() => {
|
* Renews must be run sequentially or we'll get an error 'Another
|
||||||
logger.info('Renew Complete');
|
* instance of Certbot is already running.'
|
||||||
return result;
|
*/
|
||||||
});
|
let sequence = Promise.resolve();
|
||||||
})
|
|
||||||
.then(() => {
|
certificates.forEach(function (certificate) {
|
||||||
// Now go and fetch all the letsencrypt certs from the db and query the files and update expiry times
|
sequence = sequence.then(() =>
|
||||||
return certificateModel
|
internalCertificate
|
||||||
.query()
|
.renew(
|
||||||
.where('is_deleted', 0)
|
{
|
||||||
.andWhere('provider', 'letsencrypt')
|
can: () =>
|
||||||
.then((certificates) => {
|
Promise.resolve({
|
||||||
if (certificates && certificates.length) {
|
permission_visibility: 'all',
|
||||||
let promises = [];
|
}),
|
||||||
|
token: new tokenModel(),
|
||||||
certificates.map(function (certificate) {
|
},
|
||||||
promises.push(
|
{ id: certificate.id },
|
||||||
internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
|
)
|
||||||
.then((cert_info) => {
|
.catch((err) => {
|
||||||
return certificateModel
|
// Don't want to stop the train here, just log the error
|
||||||
.query()
|
logger.error(err.message);
|
||||||
.where('id', certificate.id)
|
}),
|
||||||
.andWhere('provider', 'letsencrypt')
|
);
|
||||||
.patch({
|
});
|
||||||
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
});
|
return sequence;
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
// Don't want to stop the train here, just log the error
|
|
||||||
logger.error(err.message);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
logger.info('Completed SSL cert renew process');
|
||||||
internalCertificate.intervalProcessing = false;
|
internalCertificate.intervalProcessing = false;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@ -858,26 +850,20 @@ const internalCertificate = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} certificate the certificate row
|
* @param {Object} certificate the certificate row
|
||||||
* @param {String} dns_provider the dns provider name (key used in `certbot-dns-plugins.js`)
|
* @param {String} dns_provider the dns provider name (key used in `certbot-dns-plugins.json`)
|
||||||
* @param {String | null} credentials the content of this providers credentials file
|
* @param {String | null} credentials the content of this providers credentials file
|
||||||
* @param {String} propagation_seconds the cloudflare api token
|
* @param {String} propagation_seconds
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
requestLetsEncryptSslWithDnsChallenge: (certificate) => {
|
requestLetsEncryptSslWithDnsChallenge: async (certificate) => {
|
||||||
const dns_plugin = dnsPlugins[certificate.meta.dns_provider];
|
await certbot.installPlugin(certificate.meta.dns_provider);
|
||||||
|
const dnsPlugin = dnsPlugins[certificate.meta.dns_provider];
|
||||||
if (!dns_plugin) {
|
logger.info(`Requesting Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||||
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(', ')}`);
|
|
||||||
|
|
||||||
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentialsLocation = '/etc/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 /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
||||||
// we call `. /opt/certbot/bin/activate` (`.` is alternative to `source` in dash) to access certbot venv
|
|
||||||
const prepareCmd = '. /opt/certbot/bin/activate && pip install --no-cache-dir --user ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies + ' && deactivate';
|
|
||||||
|
|
||||||
// Whether the plugin has a --<name>-credentials argument
|
// Whether the plugin has a --<name>-credentials argument
|
||||||
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
||||||
@ -890,15 +876,15 @@ const internalCertificate = {
|
|||||||
'--agree-tos ' +
|
'--agree-tos ' +
|
||||||
'--email "' + certificate.meta.letsencrypt_email + '" ' +
|
'--email "' + certificate.meta.letsencrypt_email + '" ' +
|
||||||
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
||||||
'--authenticator ' + dns_plugin.full_plugin_name + ' ' +
|
'--authenticator ' + dnsPlugin.full_plugin_name + ' ' +
|
||||||
(
|
(
|
||||||
hasConfigArg
|
hasConfigArg
|
||||||
? '--' + dns_plugin.full_plugin_name + '-credentials "' + credentialsLocation + '"'
|
? '--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"'
|
||||||
: ''
|
: ''
|
||||||
) +
|
) +
|
||||||
(
|
(
|
||||||
certificate.meta.propagation_seconds !== undefined
|
certificate.meta.propagation_seconds !== undefined
|
||||||
? ' --' + dns_plugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
|
? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
|
||||||
: ''
|
: ''
|
||||||
) +
|
) +
|
||||||
(letsencryptStaging ? ' --staging' : '');
|
(letsencryptStaging ? ' --staging' : '');
|
||||||
@ -908,24 +894,23 @@ const internalCertificate = {
|
|||||||
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
|
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('Command:', `${credentialsCmd} && ${prepareCmd} && ${mainCmd}`);
|
if (certificate.meta.dns_provider === 'duckdns') {
|
||||||
|
mainCmd = mainCmd + ' --dns-duckdns-no-txt-restore';
|
||||||
|
}
|
||||||
|
|
||||||
return utils.exec(credentialsCmd)
|
logger.info('Command:', `${credentialsCmd} && && ${mainCmd}`);
|
||||||
.then(() => {
|
|
||||||
return utils.exec(prepareCmd)
|
try {
|
||||||
.then(() => {
|
await utils.exec(credentialsCmd);
|
||||||
return utils.exec(mainCmd)
|
const result = await utils.exec(mainCmd);
|
||||||
.then(async (result) => {
|
logger.info(result);
|
||||||
logger.info(result);
|
return result;
|
||||||
return result;
|
} catch (err) {
|
||||||
});
|
// Don't fail if file does not exist
|
||||||
});
|
const delete_credentialsCmd = `rm -f '${credentialsLocation}' || true`;
|
||||||
}).catch(async (err) => {
|
await utils.exec(delete_credentialsCmd);
|
||||||
// Don't fail if file does not exist
|
throw err;
|
||||||
const delete_credentialsCmd = `rm -f '${credentialsLocation}' || true`;
|
}
|
||||||
await utils.exec(delete_credentialsCmd);
|
|
||||||
throw err;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -1004,15 +989,15 @@ const internalCertificate = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
renewLetsEncryptSslWithDnsChallenge: (certificate) => {
|
renewLetsEncryptSslWithDnsChallenge: (certificate) => {
|
||||||
const dns_plugin = dnsPlugins[certificate.meta.dns_provider];
|
const dnsPlugin = dnsPlugins[certificate.meta.dns_provider];
|
||||||
|
|
||||||
if (!dns_plugin) {
|
if (!dnsPlugin) {
|
||||||
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'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||||
|
|
||||||
let mainCmd = certbotCommand + ' renew ' +
|
let mainCmd = certbotCommand + ' renew --force-renewal ' +
|
||||||
'--config "' + letsencryptConfig + '" ' +
|
'--config "' + letsencryptConfig + '" ' +
|
||||||
'--work-dir "/tmp/letsencrypt-lib" ' +
|
'--work-dir "/tmp/letsencrypt-lib" ' +
|
||||||
'--logs-dir "/tmp/letsencrypt-log" ' +
|
'--logs-dir "/tmp/letsencrypt-log" ' +
|
||||||
@ -1046,6 +1031,8 @@ const internalCertificate = {
|
|||||||
|
|
||||||
const mainCmd = certbotCommand + ' revoke ' +
|
const mainCmd = certbotCommand + ' revoke ' +
|
||||||
'--config "' + letsencryptConfig + '" ' +
|
'--config "' + letsencryptConfig + '" ' +
|
||||||
|
'--work-dir "/tmp/letsencrypt-lib" ' +
|
||||||
|
'--logs-dir "/tmp/letsencrypt-log" ' +
|
||||||
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
|
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
|
||||||
'--delete-after-revoke ' +
|
'--delete-after-revoke ' +
|
||||||
(letsencryptStaging ? '--staging' : '');
|
(letsencryptStaging ? '--staging' : '');
|
||||||
@ -1163,6 +1150,7 @@ const internalCertificate = {
|
|||||||
const options = {
|
const options = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0',
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
'Content-Length': Buffer.byteLength(formBody)
|
'Content-Length': Buffer.byteLength(formBody)
|
||||||
}
|
}
|
||||||
@ -1175,12 +1163,22 @@ const internalCertificate = {
|
|||||||
|
|
||||||
res.on('data', (chunk) => responseBody = responseBody + chunk);
|
res.on('data', (chunk) => responseBody = responseBody + chunk);
|
||||||
res.on('end', function () {
|
res.on('end', function () {
|
||||||
const parsedBody = JSON.parse(responseBody + '');
|
try {
|
||||||
if (res.statusCode !== 200) {
|
const parsedBody = JSON.parse(responseBody + '');
|
||||||
logger.warn(`Failed to test HTTP challenge for domain ${domain}`, res);
|
if (res.statusCode !== 200) {
|
||||||
|
logger.warn(`Failed to test HTTP challenge for domain ${domain} because HTTP status code ${res.statusCode} was returned: ${parsedBody.message}`);
|
||||||
|
resolve(undefined);
|
||||||
|
} else {
|
||||||
|
resolve(parsedBody);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (res.statusCode !== 200) {
|
||||||
|
logger.warn(`Failed to test HTTP challenge for domain ${domain} because HTTP status code ${res.statusCode} was returned`);
|
||||||
|
} else {
|
||||||
|
logger.warn(`Failed to test HTTP challenge for domain ${domain} because response failed to be parsed: ${err.message}`);
|
||||||
|
}
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
}
|
}
|
||||||
resolve(parsedBody);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1194,6 +1192,9 @@ const internalCertificate = {
|
|||||||
if (!result) {
|
if (!result) {
|
||||||
// Some error occurred while trying to get the data
|
// Some error occurred while trying to get the data
|
||||||
return 'failed';
|
return 'failed';
|
||||||
|
} else if (result.error) {
|
||||||
|
logger.info(`HTTP challenge test failed for domain ${domain} because error was returned: ${result.error.msg}`);
|
||||||
|
return `other:${result.error.msg}`;
|
||||||
} else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') {
|
} else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') {
|
||||||
// Server exists and has responded with the correct data
|
// Server exists and has responded with the correct data
|
||||||
return 'ok';
|
return 'ok';
|
||||||
|
@ -155,6 +155,7 @@ const internalNginx = {
|
|||||||
let locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
|
let locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
|
||||||
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
|
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
|
||||||
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
|
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
|
||||||
|
{enable_proxy_protocol: host.enable_proxy_protocol}, {load_balancer_ip: host.load_balancer_ip},
|
||||||
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
|
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
|
||||||
{certificate: host.certificate}, host.locations[i]);
|
{certificate: host.certificate}, host.locations[i]);
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ const internalProxyHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowGraph('[owner,access_list,access_list.[clients,items],certificate]')
|
.allowGraph('[owner,access_list.[clients,items],certificate]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
78
backend/lib/certbot.js
Normal file
78
backend/lib/certbot.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
||||||
|
const utils = require('./utils');
|
||||||
|
const error = require('./error');
|
||||||
|
const logger = require('../logger').certbot;
|
||||||
|
const batchflow = require('batchflow');
|
||||||
|
|
||||||
|
const CERTBOT_VERSION_REPLACEMENT = '$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')';
|
||||||
|
|
||||||
|
const certbot = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {array} pluginKeys
|
||||||
|
*/
|
||||||
|
installPlugins: async function (pluginKeys) {
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (pluginKeys.length === 0) {
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
batchflow(pluginKeys).sequential()
|
||||||
|
.each((i, pluginKey, next) => {
|
||||||
|
certbot.installPlugin(pluginKey)
|
||||||
|
.then(() => {
|
||||||
|
next();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
hasErrors = true;
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.error((err) => {
|
||||||
|
logger.error(err.message);
|
||||||
|
})
|
||||||
|
.end(() => {
|
||||||
|
if (hasErrors) {
|
||||||
|
reject(new error.CommandError('Some plugins failed to install. Please check the logs above', 1));
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs a cerbot plugin given the key for the object from
|
||||||
|
* ../global/certbot-dns-plugins.json
|
||||||
|
*
|
||||||
|
* @param {string} pluginKey
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
installPlugin: async function (pluginKey) {
|
||||||
|
if (typeof dnsPlugins[pluginKey] === 'undefined') {
|
||||||
|
// throw Error(`Certbot plugin ${pluginKey} not found`);
|
||||||
|
throw new error.ItemNotFoundError(pluginKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin = dnsPlugins[pluginKey];
|
||||||
|
logger.start(`Installing ${pluginKey}...`);
|
||||||
|
|
||||||
|
plugin.version = plugin.version.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT);
|
||||||
|
plugin.dependencies = plugin.dependencies.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT);
|
||||||
|
|
||||||
|
const cmd = '. /opt/certbot/bin/activate && pip install --no-cache-dir ' + plugin.dependencies + ' ' + plugin.package_name + plugin.version + ' ' + ' && deactivate';
|
||||||
|
return utils.exec(cmd)
|
||||||
|
.then((result) => {
|
||||||
|
logger.complete(`Installed ${pluginKey}`);
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = certbot;
|
@ -82,7 +82,16 @@ module.exports = {
|
|||||||
this.message = message;
|
this.message = message;
|
||||||
this.public = false;
|
this.public = false;
|
||||||
this.status = 400;
|
this.status = 400;
|
||||||
}
|
},
|
||||||
|
|
||||||
|
CommandError: function (stdErr, code, previous) {
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
this.previous = previous;
|
||||||
|
this.message = stdErr;
|
||||||
|
this.code = code;
|
||||||
|
this.public = false;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
_.forEach(module.exports, function (error) {
|
_.forEach(module.exports, function (error) {
|
||||||
|
@ -3,23 +3,27 @@ const exec = require('child_process').exec;
|
|||||||
const execFile = require('child_process').execFile;
|
const execFile = require('child_process').execFile;
|
||||||
const { Liquid } = require('liquidjs');
|
const { Liquid } = require('liquidjs');
|
||||||
const logger = require('../logger').global;
|
const logger = require('../logger').global;
|
||||||
|
const error = require('./error');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
/**
|
exec: async function(cmd, options = {}) {
|
||||||
* @param {String} cmd
|
logger.debug('CMD:', cmd);
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
const { stdout, stderr } = await new Promise((resolve, reject) => {
|
||||||
exec: function (cmd) {
|
const child = exec(cmd, options, (isError, stdout, stderr) => {
|
||||||
return new Promise((resolve, reject) => {
|
if (isError) {
|
||||||
exec(cmd, function (err, stdout, /*stderr*/) {
|
reject(new error.CommandError(stderr, isError));
|
||||||
if (err && typeof err === 'object') {
|
|
||||||
reject(err);
|
|
||||||
} else {
|
} else {
|
||||||
resolve(stdout.trim());
|
resolve({ stdout, stderr });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
child.on('error', (e) => {
|
||||||
|
reject(new error.CommandError(stderr, 1, e));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
return stdout;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +32,8 @@ module.exports = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
execFile: function (cmd, args) {
|
execFile: function (cmd, args) {
|
||||||
logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : ''));
|
// logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : ''));
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
execFile(cmd, args, function (err, stdout, /*stderr*/) {
|
execFile(cmd, args, function (err, stdout, /*stderr*/) {
|
||||||
if (err && typeof err === 'object') {
|
if (err && typeof err === 'object') {
|
||||||
|
@ -7,6 +7,7 @@ module.exports = {
|
|||||||
access: new Signale({scope: 'Access '}),
|
access: new Signale({scope: 'Access '}),
|
||||||
nginx: new Signale({scope: 'Nginx '}),
|
nginx: new Signale({scope: 'Nginx '}),
|
||||||
ssl: new Signale({scope: 'SSL '}),
|
ssl: new Signale({scope: 'SSL '}),
|
||||||
|
certbot: new Signale({scope: 'Certbot '}),
|
||||||
import: new Signale({scope: 'Importer '}),
|
import: new Signale({scope: 'Importer '}),
|
||||||
setup: new Signale({scope: 'Setup '}),
|
setup: new Signale({scope: 'Setup '}),
|
||||||
ip_ranges: new Signale({scope: 'IP Ranges'})
|
ip_ranges: new Signale({scope: 'IP Ranges'})
|
||||||
|
41
backend/migrations/20240310085523_proxy_protocol.js
Normal file
41
backend/migrations/20240310085523_proxy_protocol.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const migrate_name = 'proxy_protocol';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.integer('enable_proxy_protocol').notNull().unsigned().defaultTo(0);
|
||||||
|
proxy_host.string('load_balancer_ip').notNull().defaultTo('');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex/*, Promise*/) {
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.dropColumn('enable_proxy_protocol');
|
||||||
|
proxy_host.dropColumn('load_balancer_ip');
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
});
|
||||||
|
};
|
41
backend/migrations/20240310100432_proxy_protocol_streams.js
Normal file
41
backend/migrations/20240310100432_proxy_protocol_streams.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const migrate_name = 'proxy_protocol_streams';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('stream', function (stream) {
|
||||||
|
stream.integer('enable_proxy_protocol').notNull().unsigned().defaultTo(0);
|
||||||
|
stream.string('load_balancer_ip').notNull().defaultTo('');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] stream Table altered');
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex/*, Promise*/) {
|
||||||
|
return knex.schema.table('stream', function (stream) {
|
||||||
|
stream.dropColumn('enable_proxy_protocol');
|
||||||
|
stream.dropColumn('load_balancer_ip');
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
logger.info('[' + migrate_name + '] stream Table altered');
|
||||||
|
});
|
||||||
|
};
|
@ -172,7 +172,7 @@
|
|||||||
"description": "Domain Names separated by a comma",
|
"description": "Domain Names separated by a comma",
|
||||||
"example": "*.jc21.com,blog.jc21.com",
|
"example": "*.jc21.com,blog.jc21.com",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"maxItems": 15,
|
"maxItems": 100,
|
||||||
"uniqueItems": true,
|
"uniqueItems": true,
|
||||||
"items": {
|
"items": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -58,6 +58,16 @@
|
|||||||
"example": true,
|
"example": true,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"description": "Enable PROXY Protocol support",
|
||||||
|
"example": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 255
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "../definitions.json#/definitions/access_list_id"
|
"$ref": "../definitions.json#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
@ -155,6 +165,12 @@
|
|||||||
"allow_websocket_upgrade": {
|
"allow_websocket_upgrade": {
|
||||||
"$ref": "#/definitions/allow_websocket_upgrade"
|
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"$ref": "#/definitions/enable_proxy_protocol"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"$ref": "#/definitions/load_balancer_ip"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "#/definitions/access_list_id"
|
"$ref": "#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
@ -245,6 +261,12 @@
|
|||||||
"allow_websocket_upgrade": {
|
"allow_websocket_upgrade": {
|
||||||
"$ref": "#/definitions/allow_websocket_upgrade"
|
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"$ref": "#/definitions/enable_proxy_protocol"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"$ref": "#/definitions/load_balancer_ip"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "#/definitions/access_list_id"
|
"$ref": "#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
@ -318,6 +340,12 @@
|
|||||||
"allow_websocket_upgrade": {
|
"allow_websocket_upgrade": {
|
||||||
"$ref": "#/definitions/allow_websocket_upgrade"
|
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"$ref": "#/definitions/enable_proxy_protocol"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"$ref": "#/definitions/load_balancer_ip"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "#/definitions/access_list_id"
|
"$ref": "#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
|
@ -46,6 +46,16 @@
|
|||||||
"udp_forwarding": {
|
"udp_forwarding": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"description": "Enable PROXY Protocol support",
|
||||||
|
"example": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 0,
|
||||||
|
"maxLength": 255
|
||||||
|
},
|
||||||
"enabled": {
|
"enabled": {
|
||||||
"$ref": "../definitions.json#/definitions/enabled"
|
"$ref": "../definitions.json#/definitions/enabled"
|
||||||
},
|
},
|
||||||
@ -78,6 +88,12 @@
|
|||||||
"udp_forwarding": {
|
"udp_forwarding": {
|
||||||
"$ref": "#/definitions/udp_forwarding"
|
"$ref": "#/definitions/udp_forwarding"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"$ref": "#/definitions/enable_proxy_protocol"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"$ref": "#/definitions/load_balancer_ip"
|
||||||
|
},
|
||||||
"enabled": {
|
"enabled": {
|
||||||
"$ref": "#/definitions/enabled"
|
"$ref": "#/definitions/enabled"
|
||||||
},
|
},
|
||||||
@ -137,6 +153,12 @@
|
|||||||
"udp_forwarding": {
|
"udp_forwarding": {
|
||||||
"$ref": "#/definitions/udp_forwarding"
|
"$ref": "#/definitions/udp_forwarding"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"$ref": "#/definitions/enable_proxy_protocol"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"$ref": "#/definitions/load_balancer_ip"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -177,6 +199,12 @@
|
|||||||
"udp_forwarding": {
|
"udp_forwarding": {
|
||||||
"$ref": "#/definitions/udp_forwarding"
|
"$ref": "#/definitions/udp_forwarding"
|
||||||
},
|
},
|
||||||
|
"enable_proxy_protocol": {
|
||||||
|
"$ref": "#/definitions/enable_proxy_protocol"
|
||||||
|
},
|
||||||
|
"load_balancer_ip": {
|
||||||
|
"$ref": "#/definitions/load_balancer_ip"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
|
49
backend/scripts/install-certbot-plugins
Executable file
49
backend/scripts/install-certbot-plugins
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/node
|
||||||
|
|
||||||
|
// Usage:
|
||||||
|
// Install all plugins defined in `certbot-dns-plugins.json`:
|
||||||
|
// ./install-certbot-plugins
|
||||||
|
// Install one or more specific plugins:
|
||||||
|
// ./install-certbot-plugins route53 cloudflare
|
||||||
|
//
|
||||||
|
// Usage with a running docker container:
|
||||||
|
// docker exec npm_core /command/s6-setuidgid 1000:1000 bash -c "/app/scripts/install-certbot-plugins"
|
||||||
|
//
|
||||||
|
|
||||||
|
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
||||||
|
const certbot = require('../lib/certbot');
|
||||||
|
const logger = require('../logger').certbot;
|
||||||
|
const batchflow = require('batchflow');
|
||||||
|
|
||||||
|
let hasErrors = false;
|
||||||
|
let failingPlugins = [];
|
||||||
|
|
||||||
|
let pluginKeys = Object.keys(dnsPlugins);
|
||||||
|
if (process.argv.length > 2) {
|
||||||
|
pluginKeys = process.argv.slice(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
batchflow(pluginKeys).sequential()
|
||||||
|
.each((i, pluginKey, next) => {
|
||||||
|
certbot.installPlugin(pluginKey)
|
||||||
|
.then(() => {
|
||||||
|
next();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
hasErrors = true;
|
||||||
|
failingPlugins.push(pluginKey);
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.error((err) => {
|
||||||
|
logger.error(err.message);
|
||||||
|
})
|
||||||
|
.end(() => {
|
||||||
|
if (hasErrors) {
|
||||||
|
logger.error('Some plugins failed to install. Please check the logs above. Failing plugins: ' + '\n - ' + failingPlugins.join('\n - '));
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
logger.complete('Plugins installed successfully');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
});
|
@ -6,8 +6,7 @@ const userPermissionModel = require('./models/user_permission');
|
|||||||
const utils = require('./lib/utils');
|
const utils = require('./lib/utils');
|
||||||
const authModel = require('./models/auth');
|
const authModel = require('./models/auth');
|
||||||
const settingModel = require('./models/setting');
|
const settingModel = require('./models/setting');
|
||||||
const dns_plugins = require('./global/certbot-dns-plugins');
|
const certbot = require('./lib/certbot');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a default admin users if one doesn't already exist in the database
|
* Creates a default admin users if one doesn't already exist in the database
|
||||||
*
|
*
|
||||||
@ -116,10 +115,9 @@ const setupCertbotPlugins = () => {
|
|||||||
|
|
||||||
certificates.map(function (certificate) {
|
certificates.map(function (certificate) {
|
||||||
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
||||||
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
|
if (plugins.indexOf(certificate.meta.dns_provider) === -1) {
|
||||||
|
plugins.push(certificate.meta.dns_provider);
|
||||||
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
|
}
|
||||||
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
|
|
||||||
|
|
||||||
// Make sure credentials file exists
|
// Make sure credentials file exists
|
||||||
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
@ -130,17 +128,15 @@ const setupCertbotPlugins = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (plugins.length) {
|
return certbot.installPlugins(plugins)
|
||||||
const install_cmd = '. /opt/certbot/bin/activate && pip install --no-cache-dir --user ' + plugins.join(' ') + ' && deactivate';
|
.then(() => {
|
||||||
promises.push(utils.exec(install_cmd));
|
if (promises.length) {
|
||||||
}
|
return Promise.all(promises)
|
||||||
|
.then(() => {
|
||||||
if (promises.length) {
|
logger.info('Added Certbot plugins ' + plugins.join(', '));
|
||||||
return Promise.all(promises)
|
});
|
||||||
.then(() => {
|
}
|
||||||
logger.info('Added Certbot plugins ' + plugins.join(', '));
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{% 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)
|
# HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years)
|
||||||
add_header Strict-Transport-Security "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload" always;
|
add_header Strict-Transport-Security $hsts_header always;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
3
backend/templates/_hsts_map.conf
Normal file
3
backend/templates/_hsts_map.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
map $scheme $hsts_header {
|
||||||
|
https "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload";
|
||||||
|
}
|
@ -1,15 +1,24 @@
|
|||||||
listen 80;
|
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true -%}
|
||||||
{% if ipv6 -%}
|
{% assign port_number_http = "88" -%}
|
||||||
listen [::]:80;
|
{% assign port_number_https = "444" -%}
|
||||||
|
{% assign listen_extra_args = "proxy_protocol" -%}
|
||||||
{% else -%}
|
{% else -%}
|
||||||
#listen [::]:80;
|
{% assign port_number_http = "80" -%}
|
||||||
{% endif %}
|
{% assign port_number_https = "443" -%}
|
||||||
|
{% assign listen_extra_args = "" -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
listen {{ port_number_http }} {{ listen_extra_args }};
|
||||||
|
{% if ipv6 -%}
|
||||||
|
listen [::]:{{ port_number_http }} {{ listen_extra_args }};
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
{% if certificate -%}
|
{% if certificate -%}
|
||||||
listen 443 ssl{% if http2_support %} http2{% endif %};
|
{% capture listen_extra_args_https %}ssl{% if http2_support %} http2{% endif %} {{ listen_extra_args }}{% endcapture -%}
|
||||||
|
listen {{ port_number_https }} {{ listen_extra_args_https }};
|
||||||
{% if ipv6 -%}
|
{% if ipv6 -%}
|
||||||
listen [::]:443 ssl{% if http2_support %} http2{% endif %};
|
listen [::]:{{ port_number_https }} {{ listen_extra_args_https }};
|
||||||
{% else -%}
|
{% endif -%}
|
||||||
#listen [::]:443;
|
{% endif -%}
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
server_name {{ domain_names | join: " " }};
|
server_name {{ domain_names | join: " " }};
|
||||||
|
6
backend/templates/_proxy_protocol.conf
Normal file
6
backend/templates/_proxy_protocol.conf
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true %}
|
||||||
|
{% if load_balancer_ip != '' %}
|
||||||
|
set_real_ip_from {{ load_balancer_ip }};
|
||||||
|
real_ip_header proxy_protocol;
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
@ -1,6 +1,9 @@
|
|||||||
{% include "_header_comment.conf" %}
|
{% include "_header_comment.conf" %}
|
||||||
|
|
||||||
{% if enabled %}
|
{% if enabled %}
|
||||||
|
|
||||||
|
{% include "_hsts_map.conf" %}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
|
@ -24,6 +24,12 @@ server {
|
|||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{%- if value == "444" %}
|
||||||
|
location / {
|
||||||
|
return 444;
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{%- if value == "redirect" %}
|
{%- if value == "redirect" %}
|
||||||
location / {
|
location / {
|
||||||
return 301 {{ meta.redirect }};
|
return 301 {{ meta.redirect }};
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{% include "_header_comment.conf" %}
|
{% include "_header_comment.conf" %}
|
||||||
|
|
||||||
{% if enabled %}
|
{% if enabled %}
|
||||||
|
|
||||||
|
{% include "_hsts_map.conf" %}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
set $forward_scheme {{ forward_scheme }};
|
set $forward_scheme {{ forward_scheme }};
|
||||||
set $server "{{ forward_host }}";
|
set $server "{{ forward_host }}";
|
||||||
@ -12,6 +15,7 @@ server {
|
|||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
{% include "_hsts.conf" %}
|
{% include "_hsts.conf" %}
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
|
{% include "_proxy_protocol.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;
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
{% include "_header_comment.conf" %}
|
{% include "_header_comment.conf" %}
|
||||||
|
|
||||||
{% if enabled %}
|
{% if enabled %}
|
||||||
|
|
||||||
|
{% include "_hsts_map.conf" %}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
|
@ -1,31 +1,38 @@
|
|||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
|
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true -%}
|
||||||
|
{% capture listen_extra_args %}proxy_protocol{% endcapture -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
{% if enabled %}
|
{% if enabled %}
|
||||||
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
||||||
server {
|
server {
|
||||||
listen {{ incoming_port }};
|
listen {{ incoming_port }} {{ listen_extra_args }};
|
||||||
{% if ipv6 -%}
|
{% if ipv6 -%}
|
||||||
listen [::]:{{ incoming_port }};
|
listen [::]:{{ incoming_port }} {{ listen_extra_args }};
|
||||||
{% else -%}
|
{% else -%}
|
||||||
#listen [::]:{{ incoming_port }};
|
#listen [::]:{{ incoming_port }} {{ listen_extra_args }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||||
|
|
||||||
|
{% include '_proxy_protocol.conf' %}
|
||||||
|
|
||||||
# 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 %}
|
||||||
|
{% # Proxy Protocol is not supported for UDP %}
|
||||||
|
{% assign listen_extra_args = "" %}
|
||||||
server {
|
server {
|
||||||
listen {{ incoming_port }} udp;
|
listen {{ incoming_port }} udp {{ listen_extra_args }};
|
||||||
{% if ipv6 -%}
|
{% if ipv6 -%}
|
||||||
listen [::]:{{ incoming_port }} udp;
|
listen [::]:{{ incoming_port }} udp {{ listen_extra_args }};
|
||||||
{% else -%}
|
{% else -%}
|
||||||
#listen [::]:{{ incoming_port }} udp;
|
#listen [::]:{{ incoming_port }} udp {{ listen_extra_args }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||||
|
|
||||||
|
@ -2850,19 +2850,19 @@ semver-diff@^3.1.1:
|
|||||||
semver "^6.3.0"
|
semver "^6.3.0"
|
||||||
|
|
||||||
semver@^5.3.0, semver@^5.7.1:
|
semver@^5.3.0, semver@^5.7.1:
|
||||||
version "5.7.1"
|
version "5.7.2"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||||
|
|
||||||
semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
|
semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
|
||||||
version "6.3.0"
|
version "6.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.3.5, semver@^7.3.8:
|
semver@^7.3.5, semver@^7.3.8:
|
||||||
version "7.3.8"
|
version "7.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||||
dependencies:
|
dependencies:
|
||||||
lru-cache "^6.0.0"
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
@ -3396,9 +3396,9 @@ widest-line@^3.1.0:
|
|||||||
string-width "^4.0.0"
|
string-width "^4.0.0"
|
||||||
|
|
||||||
word-wrap@^1.2.3:
|
word-wrap@^1.2.3:
|
||||||
version "1.2.3"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
|
||||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
|
||||||
|
|
||||||
wrap-ansi@^6.2.0:
|
wrap-ansi@^6.2.0:
|
||||||
version "6.2.0"
|
version "6.2.0"
|
||||||
|
@ -3,20 +3,25 @@
|
|||||||
|
|
||||||
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
||||||
|
|
||||||
FROM jc21/nginx-full:certbot-node
|
FROM nginxproxymanager/nginx-full:certbot-node
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
ARG BUILD_VERSION
|
ARG BUILD_VERSION
|
||||||
ARG BUILD_COMMIT
|
ARG BUILD_COMMIT
|
||||||
ARG BUILD_DATE
|
ARG BUILD_DATE
|
||||||
|
|
||||||
|
# See: https://github.com/just-containers/s6-overlay/blob/master/README.md
|
||||||
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
|
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
|
||||||
S6_FIX_ATTRS_HIDDEN=1 \
|
|
||||||
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
|
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
|
||||||
|
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
||||||
|
S6_FIX_ATTRS_HIDDEN=1 \
|
||||||
|
S6_KILL_FINISH_MAXTIME=10000 \
|
||||||
|
S6_VERBOSITY=1 \
|
||||||
NODE_ENV=production \
|
NODE_ENV=production \
|
||||||
NPM_BUILD_VERSION="${BUILD_VERSION}" \
|
NPM_BUILD_VERSION="${BUILD_VERSION}" \
|
||||||
NPM_BUILD_COMMIT="${BUILD_COMMIT}" \
|
NPM_BUILD_COMMIT="${BUILD_COMMIT}" \
|
||||||
NPM_BUILD_DATE="${BUILD_DATE}"
|
NPM_BUILD_DATE="${BUILD_DATE}" \
|
||||||
|
NODE_OPTIONS="--openssl-legacy-provider"
|
||||||
|
|
||||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
@ -28,7 +33,7 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
|||||||
COPY docker/scripts/install-s6 /tmp/install-s6
|
COPY docker/scripts/install-s6 /tmp/install-s6
|
||||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
EXPOSE 80 81 88 443 444
|
||||||
|
|
||||||
COPY backend /app
|
COPY backend /app
|
||||||
COPY frontend/dist /app/frontend
|
COPY frontend/dist /app/frontend
|
||||||
@ -42,12 +47,10 @@ RUN yarn install \
|
|||||||
COPY docker/rootfs /
|
COPY docker/rootfs /
|
||||||
|
|
||||||
# Remove frontend service not required for prod, dev nginx config as well
|
# 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 \
|
RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \
|
||||||
&& chmod 644 /etc/logrotate.d/nginx-proxy-manager \
|
&& chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
||||||
&& pip uninstall --yes setuptools \
|
|
||||||
&& pip install --no-cache-dir "setuptools==58.0.0"
|
|
||||||
|
|
||||||
VOLUME [ "/data", "/etc/letsencrypt" ]
|
VOLUME [ "/data" ]
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
|
|
||||||
LABEL org.label-schema.schema-version="1.0" \
|
LABEL org.label-schema.schema-version="1.0" \
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
FROM jc21/nginx-full:certbot-node
|
FROM nginxproxymanager/nginx-full:certbot-node
|
||||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||||
|
|
||||||
ENV S6_LOGGING=0 \
|
# See: https://github.com/just-containers/s6-overlay/blob/master/README.md
|
||||||
SUPPRESS_NO_CONFIG_WARNING=1 \
|
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
|
||||||
S6_FIX_ATTRS_HIDDEN=1
|
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
|
||||||
|
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
||||||
|
S6_FIX_ATTRS_HIDDEN=1 \
|
||||||
|
S6_KILL_FINISH_MAXTIME=10000 \
|
||||||
|
S6_VERBOSITY=2 \
|
||||||
|
NODE_OPTIONS="--openssl-legacy-provider"
|
||||||
|
|
||||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
@ -24,5 +29,5 @@ RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
|||||||
COPY scripts/install-s6 /tmp/install-s6
|
COPY scripts/install-s6 /tmp/install-s6
|
||||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
EXPOSE 80 81 88 443 444
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
|
@ -14,15 +14,18 @@ services:
|
|||||||
DB_MYSQL_PASSWORD: 'npm'
|
DB_MYSQL_PASSWORD: 'npm'
|
||||||
DB_MYSQL_NAME: 'npm'
|
DB_MYSQL_NAME: 'npm'
|
||||||
volumes:
|
volumes:
|
||||||
- npm_data:/data
|
- npm_data_mysql:/data
|
||||||
|
- npm_le_mysql:/etc/letsencrypt
|
||||||
expose:
|
expose:
|
||||||
- 81
|
- 81
|
||||||
- 80
|
- 80
|
||||||
|
- 88
|
||||||
- 443
|
- 443
|
||||||
|
- 444
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "/bin/check-health"]
|
test: ["CMD", "/usr/bin/check-health"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
|
|
||||||
@ -33,14 +36,20 @@ services:
|
|||||||
LE_STAGING: 'true'
|
LE_STAGING: 'true'
|
||||||
FORCE_COLOR: 1
|
FORCE_COLOR: 1
|
||||||
DB_SQLITE_FILE: '/data/mydb.sqlite'
|
DB_SQLITE_FILE: '/data/mydb.sqlite'
|
||||||
|
PUID: 1000
|
||||||
|
PGID: 1000
|
||||||
|
DISABLE_IPV6: 'true'
|
||||||
volumes:
|
volumes:
|
||||||
- npm_data:/data
|
- npm_data_sqlite:/data
|
||||||
|
- npm_le_sqlite:/etc/letsencrypt
|
||||||
expose:
|
expose:
|
||||||
- 81
|
- 81
|
||||||
- 80
|
- 80
|
||||||
|
- 88
|
||||||
- 443
|
- 443
|
||||||
|
- 444
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "/bin/check-health"]
|
test: ["CMD", "/usr/bin/check-health"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
|
|
||||||
@ -52,7 +61,7 @@ services:
|
|||||||
MYSQL_USER: 'npm'
|
MYSQL_USER: 'npm'
|
||||||
MYSQL_PASSWORD: 'npm'
|
MYSQL_PASSWORD: 'npm'
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- mysql_data:/var/lib/mysql
|
||||||
|
|
||||||
cypress-mysql:
|
cypress-mysql:
|
||||||
image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
|
image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
|
||||||
@ -62,7 +71,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
CYPRESS_baseUrl: 'http://fullstack-mysql:81'
|
CYPRESS_baseUrl: 'http://fullstack-mysql:81'
|
||||||
volumes:
|
volumes:
|
||||||
- cypress-logs:/results
|
- cypress_logs_mysql:/results
|
||||||
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
||||||
|
|
||||||
cypress-sqlite:
|
cypress-sqlite:
|
||||||
@ -73,10 +82,14 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
CYPRESS_baseUrl: "http://fullstack-sqlite:81"
|
CYPRESS_baseUrl: "http://fullstack-sqlite:81"
|
||||||
volumes:
|
volumes:
|
||||||
- cypress-logs:/results
|
- cypress_logs_sqlite:/results
|
||||||
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
cypress-logs:
|
cypress_logs_mysql:
|
||||||
npm_data:
|
cypress_logs_sqlite:
|
||||||
db_data:
|
npm_data_mysql:
|
||||||
|
npm_data_sqlite:
|
||||||
|
npm_le_sqlite:
|
||||||
|
npm_le_mysql:
|
||||||
|
mysql_data:
|
||||||
|
@ -11,7 +11,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 3080:80
|
- 3080:80
|
||||||
- 3081:81
|
- 3081:81
|
||||||
|
- 3088:88
|
||||||
- 3443:443
|
- 3443:443
|
||||||
|
- 3444:444
|
||||||
networks:
|
networks:
|
||||||
- nginx_proxy_manager
|
- nginx_proxy_manager
|
||||||
environment:
|
environment:
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
CYAN='\E[1;36m'
|
|
||||||
BLUE='\E[1;34m'
|
|
||||||
YELLOW='\E[1;33m'
|
|
||||||
RED='\E[1;31m'
|
|
||||||
RESET='\E[0m'
|
|
||||||
export CYAN BLUE YELLOW RED RESET
|
|
||||||
|
|
||||||
log_info () {
|
|
||||||
echo -e "${BLUE}❯ ${CYAN}$1${RESET}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error () {
|
|
||||||
echo -e "${RED}❯ $1${RESET}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# The `run` file will only execute 1 line so this helps keep things
|
|
||||||
# logically separated
|
|
||||||
|
|
||||||
log_fatal () {
|
|
||||||
echo -e "${RED}--------------------------------------${RESET}"
|
|
||||||
echo -e "${RED}ERROR: $1${RESET}"
|
|
||||||
echo -e "${RED}--------------------------------------${RESET}"
|
|
||||||
/run/s6/basedir/bin/halt
|
|
||||||
exit 1
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
/data/logs/*_access.log /data/logs/*/access.log {
|
/data/logs/*_access.log /data/logs/*/access.log {
|
||||||
create 0644 root root
|
su npm npm
|
||||||
|
create 0644
|
||||||
weekly
|
weekly
|
||||||
rotate 4
|
rotate 4
|
||||||
missingok
|
missingok
|
||||||
@ -12,7 +13,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/data/logs/*_error.log /data/logs/*/error.log {
|
/data/logs/*_error.log /data/logs/*/error.log {
|
||||||
create 0644 root root
|
su npm npm
|
||||||
|
create 0644
|
||||||
weekly
|
weekly
|
||||||
rotate 10
|
rotate 10
|
||||||
missingok
|
missingok
|
||||||
|
@ -32,6 +32,7 @@ server {
|
|||||||
server_name localhost;
|
server_name localhost;
|
||||||
access_log /data/logs/fallback_access.log standard;
|
access_log /data/logs/fallback_access.log standard;
|
||||||
error_log /dev/null crit;
|
error_log /dev/null crit;
|
||||||
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
ssl_reject_handshake on;
|
ssl_reject_handshake on;
|
||||||
|
|
||||||
return 444;
|
return 444;
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
set $test "";
|
||||||
if ($scheme = "http") {
|
if ($scheme = "http") {
|
||||||
|
set $test "H";
|
||||||
|
}
|
||||||
|
if ($request_uri = /.well-known/acme-challenge/test-challenge) {
|
||||||
|
set $test "${test}T";
|
||||||
|
}
|
||||||
|
if ($test = H) {
|
||||||
return 301 https://$host$request_uri;
|
return 301 https://$host$request_uri;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# run nginx in foreground
|
# run nginx in foreground
|
||||||
daemon off;
|
daemon off;
|
||||||
pid /run/nginx/nginx.pid;
|
pid /run/nginx/nginx.pid;
|
||||||
|
user npm;
|
||||||
|
|
||||||
# Set number of worker processes automatically based on number of CPU cores.
|
# Set number of worker processes automatically based on number of CPU cores.
|
||||||
worker_processes auto;
|
worker_processes auto;
|
||||||
|
@ -3,20 +3,19 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
. /bin/common.sh
|
. /usr/bin/common.sh
|
||||||
|
|
||||||
|
cd /app || exit 1
|
||||||
|
|
||||||
log_info 'Starting backend ...'
|
log_info 'Starting backend ...'
|
||||||
|
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
if [ "${DEVELOPMENT:-}" = 'true' ]; then
|
||||||
cd /app || exit 1
|
s6-setuidgid "$PUID:$PGID" yarn install
|
||||||
# If yarn install fails: add --verbose --network-concurrency 1
|
exec s6-setuidgid "$PUID:$PGID" bash -c "export HOME=$NPMHOME;node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js"
|
||||||
s6-setuidgid npmuser yarn install
|
|
||||||
exec s6-setuidgid npmuser bash -c 'export HOME=/tmp/npmuserhome;node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js'
|
|
||||||
else
|
else
|
||||||
cd /app || exit 1
|
|
||||||
while :
|
while :
|
||||||
do
|
do
|
||||||
s6-setuidgid npmuser bash -c 'export HOME=/tmp/npmuserhome;node --abort_on_uncaught_exception --max_old_space_size=250 index.js'
|
s6-setuidgid "$PUID:$PGID" bash -c "export HOME=$NPMHOME;node --abort_on_uncaught_exception --max_old_space_size=250 index.js"
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
@ -5,17 +5,17 @@ set -e
|
|||||||
|
|
||||||
# This service is DEVELOPMENT only.
|
# This service is DEVELOPMENT only.
|
||||||
|
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
if [ "$DEVELOPMENT" = 'true' ]; then
|
||||||
. /bin/common.sh
|
. /usr/bin/common.sh
|
||||||
cd /app/frontend || exit 1
|
cd /app/frontend || exit 1
|
||||||
log_info 'Starting frontend ...'
|
HOME=$NPMHOME
|
||||||
HOME=/tmp/npmuserhome
|
|
||||||
export HOME
|
export HOME
|
||||||
mkdir -p /app/frontend/dist
|
mkdir -p /app/frontend/dist
|
||||||
chown -R npmuser:npmuser /app/frontend/dist
|
chown -R "$PUID:$PGID" /app/frontend/dist
|
||||||
# If yarn install fails: add --verbose --network-concurrency 1
|
|
||||||
s6-setuidgid npmuser yarn install
|
log_info 'Starting frontend ...'
|
||||||
exec s6-setuidgid npmuser yarn watch
|
s6-setuidgid "$PUID:$PGID" yarn install
|
||||||
|
exec s6-setuidgid "$PUID:$PGID" yarn watch
|
||||||
else
|
else
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
. /bin/common.sh
|
. /usr/bin/common.sh
|
||||||
|
|
||||||
log_info 'Starting nginx ...'
|
log_info 'Starting nginx ...'
|
||||||
|
exec s6-setuidgid "$PUID:$PGID" nginx
|
||||||
exec s6-setuidgid npmuser nginx
|
|
||||||
|
@ -3,13 +3,17 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
. /bin/common.sh
|
. /usr/bin/common.sh
|
||||||
|
|
||||||
if [ "$(id -u)" != "0" ]; then
|
if [ "$(id -u)" != "0" ]; then
|
||||||
log_fatal "This docker container must be run as root, do not specify a user.\nYou can specify PUID and PGID env vars to run processes as that user and group after initialization."
|
log_fatal "This docker container must be run as root, do not specify a user.\nYou can specify PUID and PGID env vars to run processes as that user and group after initialization."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
. /etc/s6-overlay/s6-rc.d/prepare/10-npmuser.sh
|
if [ "$DEBUG" = "true" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
. /etc/s6-overlay/s6-rc.d/prepare/10-usergroup.sh
|
||||||
. /etc/s6-overlay/s6-rc.d/prepare/20-paths.sh
|
. /etc/s6-overlay/s6-rc.d/prepare/20-paths.sh
|
||||||
. /etc/s6-overlay/s6-rc.d/prepare/30-ownership.sh
|
. /etc/s6-overlay/s6-rc.d/prepare/30-ownership.sh
|
||||||
. /etc/s6-overlay/s6-rc.d/prepare/40-dynamic.sh
|
. /etc/s6-overlay/s6-rc.d/prepare/40-dynamic.sh
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
#!/command/with-contenv bash
|
|
||||||
# shellcheck shell=bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
PUID=${PUID:-911}
|
|
||||||
PGID=${PGID:-911}
|
|
||||||
|
|
||||||
log_info 'Configuring npmuser ...'
|
|
||||||
|
|
||||||
groupmod -g 1000 users || exit 1
|
|
||||||
|
|
||||||
if id -u npmuser; then
|
|
||||||
# user already exists
|
|
||||||
usermod -u "${PUID}" npmuser || exit 1
|
|
||||||
else
|
|
||||||
# Add npmuser user
|
|
||||||
useradd -u "${PUID}" -U -d /tmp/npmuserhome -s /bin/false npmuser || exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
usermod -G users npmuser || exit 1
|
|
||||||
groupmod -o -g "${PGID}" npmuser || exit 1
|
|
||||||
# Home for npmuser
|
|
||||||
mkdir -p /tmp/npmuserhome
|
|
||||||
chown -R npmuser:npmuser /tmp/npmuserhome
|
|
40
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/10-usergroup.sh
Executable file
40
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/10-usergroup.sh
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#!/command/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
log_info "Configuring $NPMUSER user ..."
|
||||||
|
|
||||||
|
if id -u "$NPMUSER" 2>/dev/null; then
|
||||||
|
# user already exists
|
||||||
|
usermod -u "$PUID" "$NPMUSER"
|
||||||
|
else
|
||||||
|
# Add user
|
||||||
|
useradd -o -u "$PUID" -U -d "$NPMHOME" -s /bin/false "$NPMUSER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Configuring $NPMGROUP group ..."
|
||||||
|
if [ "$(get_group_id "$NPMGROUP")" = '' ]; then
|
||||||
|
# Add group. This will not set the id properly if it's already taken
|
||||||
|
groupadd -f -g "$PGID" "$NPMGROUP"
|
||||||
|
else
|
||||||
|
groupmod -o -g "$PGID" "$NPMGROUP"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set the group ID and check it
|
||||||
|
groupmod -o -g "$PGID" "$NPMGROUP"
|
||||||
|
if [ "$(get_group_id "$NPMGROUP")" != "$PGID" ]; then
|
||||||
|
echo "ERROR: Unable to set group id properly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set the group against the user and check it
|
||||||
|
usermod -G "$PGID" "$NPMGROUP"
|
||||||
|
if [ "$(id -g "$NPMUSER")" != "$PGID" ] ; then
|
||||||
|
echo "ERROR: Unable to set group against the user properly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Home for user
|
||||||
|
mkdir -p "$NPMHOME"
|
||||||
|
chown -R "$PUID:$PGID" "$NPMHOME"
|
@ -8,14 +8,21 @@ log_info 'Setting ownership ...'
|
|||||||
# root
|
# root
|
||||||
chown root /tmp/nginx
|
chown root /tmp/nginx
|
||||||
|
|
||||||
# npmuser
|
# npm user and group
|
||||||
chown -R npmuser:npmuser \
|
chown -R "$PUID:$PGID" /data
|
||||||
/data \
|
chown -R "$PUID:$PGID" /etc/letsencrypt
|
||||||
/etc/letsencrypt \
|
chown -R "$PUID:$PGID" /run/nginx
|
||||||
/etc/nginx \
|
chown -R "$PUID:$PGID" /tmp/nginx
|
||||||
/run/nginx \
|
chown -R "$PUID:$PGID" /var/cache/nginx
|
||||||
/tmp/nginx \
|
chown -R "$PUID:$PGID" /var/lib/logrotate
|
||||||
/var/cache/nginx \
|
chown -R "$PUID:$PGID" /var/lib/nginx
|
||||||
/var/lib/logrotate \
|
chown -R "$PUID:$PGID" /var/log/nginx
|
||||||
/var/lib/nginx \
|
|
||||||
/var/log/nginx
|
# Don't chown entire /etc/nginx folder as this causes crashes on some systems
|
||||||
|
chown -R "$PUID:$PGID" /etc/nginx/nginx
|
||||||
|
chown -R "$PUID:$PGID" /etc/nginx/nginx.conf
|
||||||
|
chown -R "$PUID:$PGID" /etc/nginx/conf.d
|
||||||
|
|
||||||
|
# Prevents errors when installing python certbot plugins when non-root
|
||||||
|
chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
|
||||||
|
chown -R "$PUID:$PGID" /opt/certbot/lib/python*/site-packages
|
||||||
|
11
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/50-ipv6.sh
Normal file → Executable file
11
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/50-ipv6.sh
Normal file → Executable file
@ -1,8 +1,11 @@
|
|||||||
#!/bin/bash
|
#!/command/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
# This command reads the `DISABLE_IPV6` env var and will either enable
|
# This command reads the `DISABLE_IPV6` env var and will either enable
|
||||||
# or disable ipv6 in all nginx configs based on this setting.
|
# or disable ipv6 in all nginx configs based on this setting.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
log_info 'IPv6 ...'
|
log_info 'IPv6 ...'
|
||||||
|
|
||||||
# Lowercase
|
# Lowercase
|
||||||
@ -25,11 +28,11 @@ process_folder () {
|
|||||||
for FILE in $FILES
|
for FILE in $FILES
|
||||||
do
|
do
|
||||||
echo "- ${FILE}"
|
echo "- ${FILE}"
|
||||||
sed -E -i "$SED_REGEX" "$FILE"
|
echo "$(sed -E "$SED_REGEX" "$FILE")" > $FILE
|
||||||
done
|
done
|
||||||
|
|
||||||
# ensure the files are still owned by the npmuser
|
# ensure the files are still owned by the npm user
|
||||||
chown -R npmuser:npmuser "$1"
|
chown -R "$PUID:$PGID" "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
process_folder /etc/nginx/conf.d
|
process_folder /etc/nginx/conf.d
|
||||||
|
@ -2,16 +2,17 @@
|
|||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
set +x
|
||||||
|
|
||||||
echo
|
echo "
|
||||||
echo "-------------------------------------
|
-------------------------------------
|
||||||
_ _ ____ __ __
|
_ _ ____ __ __
|
||||||
| \ | | _ \| \/ |
|
| \ | | _ \| \/ |
|
||||||
| \| | |_) | |\/| |
|
| \| | |_) | |\/| |
|
||||||
| |\ | __/| | | |
|
| |\ | __/| | | |
|
||||||
|_| \_|_| |_| |_|
|
|_| \_|_| |_| |_|
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
User UID: $(id -u npmuser)
|
User: $NPMUSER PUID:$PUID ID:$(id -u "$NPMUSER") GROUP:$(id -g "$NPMUSER")
|
||||||
User GID: $(id -g npmuser)
|
Group: $NPMGROUP PGID:$PGID ID:$(get_group_id "$NPMGROUP")
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
"
|
"
|
||||||
|
58
docker/rootfs/usr/bin/common.sh
Normal file
58
docker/rootfs/usr/bin/common.sh
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CYAN='\E[1;36m'
|
||||||
|
BLUE='\E[1;34m'
|
||||||
|
YELLOW='\E[1;33m'
|
||||||
|
RED='\E[1;31m'
|
||||||
|
RESET='\E[0m'
|
||||||
|
export CYAN BLUE YELLOW RED RESET
|
||||||
|
|
||||||
|
PUID=${PUID:-0}
|
||||||
|
PGID=${PGID:-0}
|
||||||
|
|
||||||
|
# If changing the username and group name below,
|
||||||
|
# ensure all references to this user is also changed.
|
||||||
|
# See docker/rootfs/etc/logrotate.d/nginx-proxy-manager
|
||||||
|
# and docker/rootfs/etc/nginx/nginx.conf
|
||||||
|
NPMUSER=npm
|
||||||
|
NPMGROUP=npm
|
||||||
|
NPMHOME=/tmp/npmuserhome
|
||||||
|
export NPMUSER NPMGROUP NPMHOME
|
||||||
|
|
||||||
|
if [[ "$PUID" -ne '0' ]] && [ "$PGID" = '0' ]; then
|
||||||
|
# set group id to same as user id,
|
||||||
|
# the user probably forgot to specify the group id and
|
||||||
|
# it would be rediculous to intentionally use the root group
|
||||||
|
# for a non-root user
|
||||||
|
PGID=$PUID
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PUID PGID
|
||||||
|
|
||||||
|
log_info () {
|
||||||
|
echo -e "${BLUE}❯ ${CYAN}$1${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
log_error () {
|
||||||
|
echo -e "${RED}❯ $1${RESET}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# The `run` file will only execute 1 line so this helps keep things
|
||||||
|
# logically separated
|
||||||
|
|
||||||
|
log_fatal () {
|
||||||
|
echo -e "${RED}--------------------------------------${RESET}"
|
||||||
|
echo -e "${RED}ERROR: $1${RESET}"
|
||||||
|
echo -e "${RED}--------------------------------------${RESET}"
|
||||||
|
/run/s6/basedir/bin/halt
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# param $1: group_name
|
||||||
|
get_group_id () {
|
||||||
|
if [ "${1:-}" != '' ]; then
|
||||||
|
getent group "$1" | cut -d: -f3
|
||||||
|
fi
|
||||||
|
}
|
@ -8,8 +8,8 @@ BLUE='\E[1;34m'
|
|||||||
GREEN='\E[1;32m'
|
GREEN='\E[1;32m'
|
||||||
RESET='\E[0m'
|
RESET='\E[0m'
|
||||||
|
|
||||||
S6_OVERLAY_VERSION=3.1.4.1
|
S6_OVERLAY_VERSION=3.1.5.0
|
||||||
TARGETPLATFORM=${1:unspecified}
|
TARGETPLATFORM=${1:-linux/amd64}
|
||||||
|
|
||||||
# Determine the correct binary file for the architecture given
|
# Determine the correct binary file for the architecture given
|
||||||
case $TARGETPLATFORM in
|
case $TARGETPLATFORM in
|
||||||
|
10
docs/.gitignore
vendored
10
docs/.gitignore
vendored
@ -1,3 +1,13 @@
|
|||||||
.vuepress/dist
|
.vuepress/dist
|
||||||
node_modules
|
node_modules
|
||||||
ts
|
ts
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/sdks
|
||||||
|
!.yarn/versions
|
||||||
|
*.gz
|
||||||
|
*.tgz
|
@ -1,82 +1,120 @@
|
|||||||
module.exports = {
|
import { defineUserConfig } from 'vuepress';
|
||||||
locales: {
|
import { defaultTheme } from 'vuepress'
|
||||||
"/": {
|
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics';
|
||||||
lang: "en-US",
|
import { searchPlugin } from '@vuepress/plugin-search'
|
||||||
title: "Nginx Proxy Manager",
|
import { sitemapPlugin } from 'vuepress-plugin-sitemap2';
|
||||||
description: "Expose your services easily and securely"
|
import zoomingPlugin from 'vuepress-plugin-zooming';
|
||||||
}
|
|
||||||
},
|
export default defineUserConfig({
|
||||||
head: [
|
locales: {
|
||||||
["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" }],
|
lang: "en-US",
|
||||||
["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
|
title: "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"}],
|
description: "Expose your services easily and securely",
|
||||||
["meta", { property: "og:type", content: "website" }],
|
},
|
||||||
["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
|
},
|
||||||
["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
|
head: [
|
||||||
["meta", { name: "twitter:card", content: "summary"}],
|
["link", { rel: "icon", href: "/icon.png" }],
|
||||||
["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
|
["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", { 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", { property: "og:title", content: "Nginx Proxy Manager" }],
|
||||||
["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
|
["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", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
|
["meta", { property: "og:type", content: "website" }],
|
||||||
],
|
["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
|
||||||
themeConfig: {
|
["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
|
||||||
logo: "/icon.png",
|
["meta", { name: "twitter:card", content: "summary"}],
|
||||||
// the GitHub repo path
|
["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
|
||||||
repo: "jc21/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"}],
|
||||||
// the label linking to the repo
|
["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
|
||||||
repoLabel: "GitHub",
|
["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
|
||||||
// if your docs are not at the root of the repo:
|
],
|
||||||
docsDir: "docs",
|
theme: defaultTheme({
|
||||||
// defaults to false, set to true to enable
|
logo: '/icon.png',
|
||||||
editLinks: true,
|
repo: "jc21/nginx-proxy-manager",
|
||||||
locales: {
|
docsRepo: 'https://github.com/jc21/nginx-proxy-manager',
|
||||||
"/": {
|
docsBranch: 'develop',
|
||||||
// text for the language dropdown
|
docsDir: 'docs',
|
||||||
selectText: "Languages",
|
editLinkPattern: ':repo/edit/:branch/:path',
|
||||||
// label for this locale in the language dropdown
|
locales: {
|
||||||
label: "English",
|
'/': {
|
||||||
// Custom text for edit link. Defaults to "Edit this page"
|
label: 'English',
|
||||||
editLinkText: "Edit this page on GitHub",
|
selectLanguageText: 'Languages',
|
||||||
// Custom navbar values
|
selectLanguageName: 'English',
|
||||||
nav: [{ text: "Setup", link: "/setup/" }],
|
editLinkText: 'Edit this page on GitHub',
|
||||||
// Custom sidebar values
|
navbar: [
|
||||||
sidebar: [
|
{ text: 'Setup', link: '/setup/' }
|
||||||
"/",
|
],
|
||||||
["/guide/", "Guide"],
|
sidebar: {
|
||||||
["/screenshots/", "Screenshots"],
|
'/': [
|
||||||
["/setup/", "Setup Instructions"],
|
{
|
||||||
["/advanced-config/", "Advanced Configuration"],
|
text: 'Home',
|
||||||
["/upgrading/", "Upgrading"],
|
link: '/'
|
||||||
["/faq/", "Frequently Asked Questions"],
|
},
|
||||||
["/third-party/", "Third Party"]
|
{
|
||||||
]
|
text: 'Guide',
|
||||||
}
|
link: '/guide/',
|
||||||
}
|
collapsible: true,
|
||||||
},
|
},
|
||||||
plugins: [
|
{
|
||||||
[
|
text: 'Screenshots',
|
||||||
"@vuepress/google-analytics",
|
link: '/screenshots/',
|
||||||
{
|
collapsible: true,
|
||||||
ga: "UA-99675467-4"
|
},
|
||||||
}
|
{
|
||||||
],
|
text: 'Setup Instructions',
|
||||||
[
|
link: '/setup/',
|
||||||
"sitemap",
|
collapsible: true,
|
||||||
{
|
},
|
||||||
hostname: "https://nginxproxymanager.com"
|
{
|
||||||
}
|
text: 'Advanced Configuration',
|
||||||
],
|
link: '/advanced-config/',
|
||||||
[
|
collapsible: true,
|
||||||
'vuepress-plugin-zooming',
|
},
|
||||||
{
|
{
|
||||||
selector: '.zooming',
|
text: 'Upgrading',
|
||||||
delay: 1000,
|
link: '/upgrading/',
|
||||||
options: {
|
collapsible: true,
|
||||||
bgColor: 'black',
|
},
|
||||||
zIndex: 10000,
|
{
|
||||||
},
|
text: 'Frequently Asked Questions',
|
||||||
},
|
link: '/faq/',
|
||||||
],
|
collapsible: true,
|
||||||
]
|
},
|
||||||
};
|
{
|
||||||
|
text: 'Third Party',
|
||||||
|
link: '/third-party/',
|
||||||
|
collapsible: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
markdown: {
|
||||||
|
code: {
|
||||||
|
lineNumbers: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
googleAnalyticsPlugin({
|
||||||
|
id: 'UA-99675467-4'
|
||||||
|
}),
|
||||||
|
sitemapPlugin({
|
||||||
|
hostname: "https://nginxproxymanager.com",
|
||||||
|
}),
|
||||||
|
zoomingPlugin({
|
||||||
|
selector: '.zooming',
|
||||||
|
delay: 1000,
|
||||||
|
options: {
|
||||||
|
bgColor: 'black',
|
||||||
|
zIndex: 10000,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
searchPlugin({
|
||||||
|
locales: {
|
||||||
|
'/': {
|
||||||
|
placeholder: 'Search',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
258
docs/.vuepress/styles/index.scss
Normal file
258
docs/.vuepress/styles/index.scss
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
:root {
|
||||||
|
// brand colors
|
||||||
|
--c-brand: #f15833;
|
||||||
|
--c-brand-light: #f15833;
|
||||||
|
|
||||||
|
// background colors
|
||||||
|
--c-bg: #ffffff;
|
||||||
|
--c-bg-light: #f3f4f5;
|
||||||
|
--c-bg-lighter: #eeeeee;
|
||||||
|
--c-bg-dark: #ebebec;
|
||||||
|
--c-bg-darker: #e6e6e6;
|
||||||
|
--c-bg-navbar: var(--c-bg);
|
||||||
|
--c-bg-sidebar: var(--c-bg);
|
||||||
|
--c-bg-arrow: #cccccc;
|
||||||
|
|
||||||
|
// text colors
|
||||||
|
--c-text: #663015;
|
||||||
|
--c-text-accent: var(--c-brand);
|
||||||
|
--c-text-light: #863f1c;
|
||||||
|
--c-text-lighter: #b65626;
|
||||||
|
--c-text-lightest: #f15833;
|
||||||
|
--c-text-quote: #999999;
|
||||||
|
|
||||||
|
// border colors
|
||||||
|
--c-border: #eaecef;
|
||||||
|
--c-border-dark: #dfe2e5;
|
||||||
|
|
||||||
|
// custom container colors
|
||||||
|
--c-tip: #42b983;
|
||||||
|
--c-tip-bg: var(--c-bg-light);
|
||||||
|
--c-tip-title: var(--c-text);
|
||||||
|
--c-tip-text: var(--c-text);
|
||||||
|
--c-tip-text-accent: var(--c-text-accent);
|
||||||
|
--c-warning: #ffc310;
|
||||||
|
--c-warning-bg: #fffae3;
|
||||||
|
--c-warning-bg-light: #fff3ba;
|
||||||
|
--c-warning-bg-lighter: #fff0b0;
|
||||||
|
--c-warning-border-dark: #f7dc91;
|
||||||
|
--c-warning-details-bg: #fff5ca;
|
||||||
|
--c-warning-title: #f1b300;
|
||||||
|
--c-warning-text: #746000;
|
||||||
|
--c-warning-text-accent: #edb100;
|
||||||
|
--c-warning-text-light: #c1971c;
|
||||||
|
--c-warning-text-quote: #ccab49;
|
||||||
|
--c-danger: #f11e37;
|
||||||
|
--c-danger-bg: #ffe0e0;
|
||||||
|
--c-danger-bg-light: #ffcfde;
|
||||||
|
--c-danger-bg-lighter: #ffc9c9;
|
||||||
|
--c-danger-border-dark: #f1abab;
|
||||||
|
--c-danger-details-bg: #ffd4d4;
|
||||||
|
--c-danger-title: #ed1e2c;
|
||||||
|
--c-danger-text: #660000;
|
||||||
|
--c-danger-text-accent: #bd1a1a;
|
||||||
|
--c-danger-text-light: #b5474d;
|
||||||
|
--c-danger-text-quote: #c15b5b;
|
||||||
|
--c-details-bg: #eeeeee;
|
||||||
|
|
||||||
|
// badge component colors
|
||||||
|
--c-badge-tip: var(--c-tip);
|
||||||
|
--c-badge-warning: #ecc808;
|
||||||
|
--c-badge-warning-text: var(--c-bg);
|
||||||
|
--c-badge-danger: #dc2626;
|
||||||
|
--c-badge-danger-text: var(--c-bg);
|
||||||
|
|
||||||
|
// transition vars
|
||||||
|
--t-color: 0.3s ease;
|
||||||
|
--t-transform: 0.3s ease;
|
||||||
|
|
||||||
|
// code blocks vars
|
||||||
|
--code-bg-color: #282c34;
|
||||||
|
--code-hl-bg-color: rgba(0, 0, 0, 0.66);
|
||||||
|
--code-ln-color: #9e9e9e;
|
||||||
|
--code-ln-wrapper-width: 3.5rem;
|
||||||
|
|
||||||
|
// font vars
|
||||||
|
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||||
|
Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
--font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||||
|
|
||||||
|
// layout vars
|
||||||
|
--navbar-height: 3.6rem;
|
||||||
|
--navbar-padding-v: 0.7rem;
|
||||||
|
--navbar-padding-h: 1.5rem;
|
||||||
|
--sidebar-width: 20rem;
|
||||||
|
--sidebar-width-mobile: calc(var(--sidebar-width) * 0.82);
|
||||||
|
--content-width: 740px;
|
||||||
|
--homepage-width: 960px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark {
|
||||||
|
// brand colors
|
||||||
|
--c-brand: #f15833;
|
||||||
|
--c-brand-light: #f15833;
|
||||||
|
|
||||||
|
// background colors
|
||||||
|
--c-bg: #22272e;
|
||||||
|
--c-bg-light: #2b313a;
|
||||||
|
--c-bg-lighter: #262c34;
|
||||||
|
--c-bg-dark: #343b44;
|
||||||
|
--c-bg-darker: #37404c;
|
||||||
|
|
||||||
|
// text colors
|
||||||
|
--c-text: #adbac7;
|
||||||
|
--c-text-light: #96a7b7;
|
||||||
|
--c-text-lighter: #8b9eb0;
|
||||||
|
--c-text-lightest: #8094a8;
|
||||||
|
|
||||||
|
// border colors
|
||||||
|
--c-border: #3e4c5a;
|
||||||
|
--c-border-dark: #34404c;
|
||||||
|
|
||||||
|
// custom container colors
|
||||||
|
--c-tip: #318a62;
|
||||||
|
--c-warning: #e0ad15;
|
||||||
|
--c-warning-bg: #2d2f2d;
|
||||||
|
--c-warning-bg-light: #423e2a;
|
||||||
|
--c-warning-bg-lighter: #44442f;
|
||||||
|
--c-warning-border-dark: #957c35;
|
||||||
|
--c-warning-details-bg: #39392d;
|
||||||
|
--c-warning-title: #fdca31;
|
||||||
|
--c-warning-text: #d8d96d;
|
||||||
|
--c-warning-text-accent: #ffbf00;
|
||||||
|
--c-warning-text-light: #ddb84b;
|
||||||
|
--c-warning-text-quote: #ccab49;
|
||||||
|
--c-danger: #fc1e38;
|
||||||
|
--c-danger-bg: #39232c;
|
||||||
|
--c-danger-bg-light: #4b2b35;
|
||||||
|
--c-danger-bg-lighter: #553040;
|
||||||
|
--c-danger-border-dark: #a25151;
|
||||||
|
--c-danger-details-bg: #482936;
|
||||||
|
--c-danger-title: #fc2d3b;
|
||||||
|
--c-danger-text: #ea9ca0;
|
||||||
|
--c-danger-text-accent: #fd3636;
|
||||||
|
--c-danger-text-light: #d9777c;
|
||||||
|
--c-danger-text-quote: #d56b6b;
|
||||||
|
--c-details-bg: #323843;
|
||||||
|
|
||||||
|
// badge component colors
|
||||||
|
--c-badge-warning: var(--c-warning);
|
||||||
|
--c-badge-warning-text: #3c2e05;
|
||||||
|
--c-badge-danger: var(--c-danger);
|
||||||
|
--c-badge-danger-text: #401416;
|
||||||
|
|
||||||
|
// code blocks vars
|
||||||
|
--code-hl-bg-color: #363b46;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// plugin-back-to-top
|
||||||
|
.back-to-top {
|
||||||
|
--back-to-top-color: var(--c-brand);
|
||||||
|
--back-to-top-color-hover: var(--c-brand-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin-docsearch
|
||||||
|
.DocSearch {
|
||||||
|
--docsearch-primary-color: var(--c-brand);
|
||||||
|
--docsearch-text-color: var(--c-text);
|
||||||
|
--docsearch-highlight-color: var(--c-brand);
|
||||||
|
--docsearch-muted-color: var(--c-text-quote);
|
||||||
|
--docsearch-container-background: rgba(9, 10, 17, 0.8);
|
||||||
|
--docsearch-modal-background: var(--c-bg-light);
|
||||||
|
--docsearch-searchbox-background: var(--c-bg-lighter);
|
||||||
|
--docsearch-searchbox-focus-background: var(--c-bg);
|
||||||
|
--docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);
|
||||||
|
--docsearch-hit-color: var(--c-text-light);
|
||||||
|
--docsearch-hit-active-color: var(--c-bg);
|
||||||
|
--docsearch-hit-background: var(--c-bg);
|
||||||
|
--docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);
|
||||||
|
--docsearch-footer-background: var(--c-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dark plugin-docsearch
|
||||||
|
html.dark .DocSearch {
|
||||||
|
--docsearch-logo-color: var(--c-text);
|
||||||
|
--docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;
|
||||||
|
--docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d,
|
||||||
|
0 2px 2px 0 rgba(3, 4, 9, 0.3);
|
||||||
|
--docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);
|
||||||
|
--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
|
||||||
|
0 -4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin-external-link-icon
|
||||||
|
.external-link-icon {
|
||||||
|
--external-link-icon-color: var(--c-text-quote);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin-medium-zoom
|
||||||
|
.medium-zoom-overlay {
|
||||||
|
--medium-zoom-bg-color: var(--c-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin-nprogress
|
||||||
|
#nprogress {
|
||||||
|
--nprogress-color: var(--c-brand);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin-pwa-popup
|
||||||
|
.pwa-popup {
|
||||||
|
--pwa-popup-text-color: var(--c-text);
|
||||||
|
--pwa-popup-bg-color: var(--c-bg);
|
||||||
|
--pwa-popup-border-color: var(--c-brand);
|
||||||
|
--pwa-popup-shadow: 0 4px 16px var(--c-brand);
|
||||||
|
--pwa-popup-btn-text-color: var(--c-bg);
|
||||||
|
--pwa-popup-btn-bg-color: var(--c-brand);
|
||||||
|
--pwa-popup-btn-hover-bg-color: var(--c-brand-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plugin-search
|
||||||
|
.search-box {
|
||||||
|
--search-bg-color: var(--c-bg);
|
||||||
|
--search-accent-color: var(--c-brand);
|
||||||
|
--search-text-color: var(--c-text);
|
||||||
|
--search-border-color: var(--c-border);
|
||||||
|
|
||||||
|
--search-item-text-color: var(--c-text-lighter);
|
||||||
|
--search-item-focus-bg-color: var(--c-bg-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.home .hero img {
|
||||||
|
max-width: 500px !important;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 80%
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-title {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.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,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
|
|
893
docs/.yarn/releases/yarn-4.0.2.cjs
vendored
Normal file
893
docs/.yarn/releases/yarn-4.0.2.cjs
vendored
Normal file
File diff suppressed because one or more lines are too long
3
docs/.yarnrc.yml
Normal file
3
docs/.yarnrc.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
nodeLinker: node-modules
|
||||||
|
|
||||||
|
yarnPath: .yarn/releases/yarn-4.0.2.cjs
|
@ -1,8 +1,10 @@
|
|||||||
---
|
---
|
||||||
home: true
|
home: true
|
||||||
heroImage: /logo.png
|
heroImage: /logo.png
|
||||||
actionText: Get Started →
|
actions:
|
||||||
actionLink: /guide/
|
- text: Get Started
|
||||||
|
link: /guide/
|
||||||
|
type: primary
|
||||||
footer: MIT Licensed | Copyright © 2016-present jc21.com
|
footer: MIT Licensed | Copyright © 2016-present jc21.com
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1,5 +1,26 @@
|
|||||||
# Advanced Configuration
|
# Advanced Configuration
|
||||||
|
|
||||||
|
## Running processes as a user/group
|
||||||
|
|
||||||
|
By default, the services (nginx etc) will run as `root` user inside the docker container.
|
||||||
|
You can change this behaviour by setting the following environment variables.
|
||||||
|
Not only will they run the services as this user/group, they will change the ownership
|
||||||
|
on the `data` and `letsencrypt` folders at startup.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: 'jc21/nginx-proxy-manager:latest'
|
||||||
|
environment:
|
||||||
|
PUID: 1000
|
||||||
|
PGID: 1000
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
This may have the side effect of a failed container start due to permission denied trying
|
||||||
|
to open port 80 on some systems. The only course to fix that is to remove the variables
|
||||||
|
and run as the default root user.
|
||||||
|
|
||||||
## Best Practice: Use a Docker network
|
## Best Practice: Use a Docker network
|
||||||
|
|
||||||
For those who have a few of their upstream services running in Docker on the same Docker
|
For those who have a few of their upstream services running in Docker on the same Docker
|
||||||
@ -55,7 +76,7 @@ feature by adding the following to the service in your `docker-compose.yml` file
|
|||||||
|
|
||||||
```yml
|
```yml
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "/bin/check-health"]
|
test: ["CMD", "/usr/bin/check-health"]
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
```
|
```
|
||||||
@ -117,8 +138,9 @@ services:
|
|||||||
MYSQL_USER: "npm"
|
MYSQL_USER: "npm"
|
||||||
# MYSQL_PASSWORD: "npm" # use secret instead
|
# MYSQL_PASSWORD: "npm" # use secret instead
|
||||||
MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD
|
MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD
|
||||||
|
MARIADB_AUTO_UPGRADE: '1'
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/mysql:/var/lib/mysql
|
- ./mysql:/var/lib/mysql
|
||||||
secrets:
|
secrets:
|
||||||
- DB_ROOT_PWD
|
- DB_ROOT_PWD
|
||||||
- MYSQL_PWD
|
- MYSQL_PWD
|
||||||
@ -172,3 +194,41 @@ value by specifying it as a Docker environment variable. The default if not spec
|
|||||||
X_FRAME_OPTIONS: "sameorigin"
|
X_FRAME_OPTIONS: "sameorigin"
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Customising logrotate settings
|
||||||
|
|
||||||
|
By default, NPM rotates the access- and error logs weekly and keeps 4 and 10 log files respectively.
|
||||||
|
Depending on the usage, this can lead to large log files, especially access logs.
|
||||||
|
You can customise the logrotate configuration through a mount (if your custom config is `logrotate.custom`):
|
||||||
|
|
||||||
|
```yml
|
||||||
|
volumes:
|
||||||
|
...
|
||||||
|
- ./logrotate.custom:/etc/logrotate.d/nginx-proxy-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
For reference, the default configuration can be found [here](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/develop/docker/rootfs/etc/logrotate.d/nginx-proxy-manager).
|
||||||
|
|
||||||
|
## Enabling PROXY protocol for Proxy Hosts
|
||||||
|
|
||||||
|
When running NPM behind a load balancer, you might want to use the [PROXY procotol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) to receive client information such as the source IP address (useful for banning IPs).
|
||||||
|
|
||||||
|
When configuring the PROXY protocol for proxy hosts, NPM uses the ports 88 for http and 444 for https traffic to allow you to decide on a per host basis whether to use the PROSY protocol.
|
||||||
|
|
||||||
|
To enable the PROXY protocol for your hosts you need to perform the following steps:
|
||||||
|
|
||||||
|
1. Expose the ports `88` (and `444` is applicable) by adjusting your `docker-compose.yml`
|
||||||
|
2. Edit your proxy hosts to enable the PROXY protocol
|
||||||
|
3. Edit your upstream load balancer to redirect traffic to the port `88`/`444` and enable the PROXY protocol
|
||||||
|
|
||||||
|
## Enabling PROXY protocol for Streams
|
||||||
|
|
||||||
|
When running NPM behind a load balancer, you might want to use the [PROXY procotol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) to receive client information such as the source IP address (useful for banning IPs).
|
||||||
|
|
||||||
|
Keep in mind that the PROXY procotol cannot be enabled for udp endpoints.
|
||||||
|
|
||||||
|
To enable the PROXY protocol for streams:
|
||||||
|
|
||||||
|
1. Expose the desired port by adjusting you `docker-compose.yml`
|
||||||
|
2. Edit the Stream to enable the PROXY protocol
|
||||||
|
3. Edit your upstream load balancer to enable the PROXY protocol
|
||||||
|
@ -3,775 +3,21 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
"@vuepress/plugin-google-analytics": "^1.5.3",
|
"vuepress": "^2.0.0-rc.0"
|
||||||
"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.8",
|
|
||||||
"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": {
|
"scripts": {
|
||||||
"dev": "vuepress dev",
|
"dev": "vuepress dev",
|
||||||
"build": "vuepress build"
|
"build": "vuepress build"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC"
|
"license": "ISC",
|
||||||
|
"packageManager": "yarn@4.0.2",
|
||||||
|
"dependencies": {
|
||||||
|
"@vuepress/plugin-google-analytics": "2.0.0-rc.0",
|
||||||
|
"@vuepress/plugin-search": "2.0.0-rc.0",
|
||||||
|
"@vuepress/theme-default": "^2.0.0-rc.0",
|
||||||
|
"vuepress-plugin-sitemap2": "^2.0.0-rc.5",
|
||||||
|
"vuepress-plugin-zooming": "^1.1.8"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ services:
|
|||||||
Then:
|
Then:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using MySQL / MariaDB Database
|
## Using MySQL / MariaDB Database
|
||||||
@ -61,12 +61,11 @@ services:
|
|||||||
- '80:80' # Public HTTP Port
|
- '80:80' # Public HTTP Port
|
||||||
- '443:443' # Public HTTPS Port
|
- '443:443' # Public HTTPS Port
|
||||||
- '81:81' # Admin Web Port
|
- '81:81' # Admin Web Port
|
||||||
|
# - '88:88' # Public HTTP Port with proxy_protocol enabled
|
||||||
|
# - '444:444' # Public HTTPS Port with proxy_protocol enabled
|
||||||
# Add any other Stream port you want to expose
|
# Add any other Stream port you want to expose
|
||||||
# - '21:21' # FTP
|
# - '21:21' # FTP
|
||||||
environment:
|
environment:
|
||||||
# Unix user and group IDs, optional
|
|
||||||
PUID: 1000
|
|
||||||
PGID: 1000
|
|
||||||
# Mysql/Maria connection parameters:
|
# Mysql/Maria connection parameters:
|
||||||
DB_MYSQL_HOST: "db"
|
DB_MYSQL_HOST: "db"
|
||||||
DB_MYSQL_PORT: 3306
|
DB_MYSQL_PORT: 3306
|
||||||
@ -89,8 +88,9 @@ services:
|
|||||||
MYSQL_DATABASE: 'npm'
|
MYSQL_DATABASE: 'npm'
|
||||||
MYSQL_USER: 'npm'
|
MYSQL_USER: 'npm'
|
||||||
MYSQL_PASSWORD: 'npm'
|
MYSQL_PASSWORD: 'npm'
|
||||||
|
MARIADB_AUTO_UPGRADE: '1'
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/mysql:/var/lib/mysql
|
- ./mysql:/var/lib/mysql
|
||||||
```
|
```
|
||||||
|
|
||||||
::: warning
|
::: warning
|
||||||
@ -122,7 +122,7 @@ Please note that the `jc21/mariadb-aria:latest` image might have some problems o
|
|||||||
|
|
||||||
After the app is running for the first time, the following will happen:
|
After the app is running for the first time, the following will happen:
|
||||||
|
|
||||||
1. GPG keys will be generated and saved in the data folder
|
1. JWT keys will be generated and saved in the data folder
|
||||||
2. The database will initialize with table structures
|
2. The database will initialize with table structures
|
||||||
3. A default admin user will be created
|
3. A default admin user will be created
|
||||||
|
|
||||||
|
2
docs/third-party/README.md
vendored
2
docs/third-party/README.md
vendored
@ -7,7 +7,7 @@ Known integrations:
|
|||||||
|
|
||||||
- [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager)
|
- [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager)
|
||||||
- [UnRaid / Synology](https://github.com/jlesage/docker-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)
|
- [Proxmox Scripts](https://github.com/ej52/proxmox-scripts/tree/main/apps/nginx-proxy-manager)
|
||||||
- [nginxproxymanagerGraf](https://github.com/ma-karai/nginxproxymanagerGraf)
|
- [nginxproxymanagerGraf](https://github.com/ma-karai/nginxproxymanagerGraf)
|
||||||
|
|
||||||
|
|
||||||
|
13843
docs/yarn.lock
13843
docs/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@
|
|||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<meta name="HandheldFriendly" content="True">
|
<meta name="HandheldFriendly" content="True">
|
||||||
<meta name="MobileOptimized" content="320">
|
<meta name="MobileOptimized" content="320">
|
||||||
|
<meta name="robots" content="noindex">
|
||||||
<title><%- title %></title>
|
<title><%- title %></title>
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/images/favicons/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="/images/favicons/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicons/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicons/favicon-32x32.png">
|
||||||
|
@ -74,7 +74,7 @@
|
|||||||
<option
|
<option
|
||||||
value="<%- plugin_name %>"
|
value="<%- plugin_name %>"
|
||||||
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
||||||
><%- plugin_info.display_name %></option>
|
><%- plugin_info.name %></option>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,7 +11,7 @@ require('selectize');
|
|||||||
|
|
||||||
function sortProvidersAlphabetically(obj) {
|
function sortProvidersAlphabetically(obj) {
|
||||||
return Object.entries(obj)
|
return Object.entries(obj)
|
||||||
.sort((a,b) => a[1].display_name.toLowerCase() > b[1].display_name.toLowerCase())
|
.sort((a,b) => a[1].name.toLowerCase() > b[1].name.toLowerCase())
|
||||||
.reduce((result, entry) => {
|
.reduce((result, entry) => {
|
||||||
result[entry[0]] = entry[1];
|
result[entry[0]] = entry[1];
|
||||||
return result;
|
return result;
|
||||||
@ -265,7 +265,7 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.domain_names.selectize({
|
this.ui.domain_names.selectize({
|
||||||
delimiter: ',',
|
delimiter: ',',
|
||||||
persist: false,
|
persist: false,
|
||||||
maxOptions: 15,
|
maxOptions: 100,
|
||||||
create: function (input) {
|
create: function (input) {
|
||||||
return {
|
return {
|
||||||
value: input,
|
value: input,
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <%- dns_providers[meta.dns_provider].display_name %><% } %>
|
<%- i18n('ssl', provider) %><% if (meta.dns_provider) { %> - <%- dns_providers[meta.dns_provider].name %><% } %>
|
||||||
</td>
|
</td>
|
||||||
<td class="<%- isExpired() ? 'text-danger' : '' %>">
|
<td class="<%- isExpired() ? 'text-danger' : '' %>">
|
||||||
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
|
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
<option
|
<option
|
||||||
value="<%- plugin_name %>"
|
value="<%- plugin_name %>"
|
||||||
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
||||||
><%- plugin_info.display_name %></option>
|
><%- plugin_info.name %></option>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -233,7 +233,7 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.domain_names.selectize({
|
this.ui.domain_names.selectize({
|
||||||
delimiter: ',',
|
delimiter: ',',
|
||||||
persist: false,
|
persist: false,
|
||||||
maxOptions: 15,
|
maxOptions: 100,
|
||||||
create: function (input) {
|
create: function (input) {
|
||||||
return {
|
return {
|
||||||
value: input,
|
value: input,
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-6 col-md-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="custom-switch">
|
<label class="custom-switch">
|
||||||
<input type="checkbox" class="custom-switch-input" name="allow_websocket_upgrade" value="1"<%- allow_websocket_upgrade ? ' checked' : '' %>>
|
<input type="checkbox" class="custom-switch-input" name="allow_websocket_upgrade" value="1"<%- allow_websocket_upgrade ? ' checked' : '' %>>
|
||||||
@ -81,6 +81,22 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="enable_proxy_protocol" value="1"<%- enable_proxy_protocol ? ' checked' : '' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'enable-proxy-protocol') %><a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#introduction" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('proxy-hosts', 'load-balancer-ip') %> <a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#changing-the-load-balancers-ip-address-to-the-client-ip-address" target="_blank"><i class="fe fe-help-circle"></i></a></label>
|
||||||
|
<input type="text" name="load_balancer_ip" class="form-control text-monospace" placeholder="" value="<%- load_balancer_ip %>" autocomplete="off" maxlength="255" <%- enable_proxy_protocol ? '' : ' disabled' %>>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -182,7 +198,7 @@
|
|||||||
<option
|
<option
|
||||||
value="<%- plugin_name %>"
|
value="<%- plugin_name %>"
|
||||||
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
||||||
><%- plugin_info.display_name %></option>
|
><%- plugin_info.name %></option>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,6 +43,8 @@ module.exports = Mn.View.extend({
|
|||||||
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
|
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
|
||||||
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
|
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
|
||||||
forward_scheme: 'select[name="forward_scheme"]',
|
forward_scheme: 'select[name="forward_scheme"]',
|
||||||
|
enable_proxy_protocol: 'input[name="enable_proxy_protocol"]',
|
||||||
|
load_balancer_ip: 'input[name="load_balancer_ip"]',
|
||||||
letsencrypt: '.letsencrypt'
|
letsencrypt: '.letsencrypt'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -51,6 +53,13 @@ module.exports = Mn.View.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
'change @ui.enable_proxy_protocol': function () {
|
||||||
|
let checked = this.ui.enable_proxy_protocol.prop('checked');
|
||||||
|
this.ui.load_balancer_ip
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
},
|
||||||
'change @ui.certificate_select': function () {
|
'change @ui.certificate_select': function () {
|
||||||
let id = this.ui.certificate_select.val();
|
let id = this.ui.certificate_select.val();
|
||||||
if (id === 'new') {
|
if (id === 'new') {
|
||||||
@ -163,6 +172,7 @@ module.exports = Mn.View.extend({
|
|||||||
data.block_exploits = !!data.block_exploits;
|
data.block_exploits = !!data.block_exploits;
|
||||||
data.caching_enabled = !!data.caching_enabled;
|
data.caching_enabled = !!data.caching_enabled;
|
||||||
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
|
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
|
||||||
|
data.enable_proxy_protocol = !!data.enable_proxy_protocol;
|
||||||
data.http2_support = !!data.http2_support;
|
data.http2_support = !!data.http2_support;
|
||||||
data.hsts_enabled = !!data.hsts_enabled;
|
data.hsts_enabled = !!data.hsts_enabled;
|
||||||
data.hsts_subdomains = !!data.hsts_subdomains;
|
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||||
@ -264,6 +274,7 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
|
this.ui.enable_proxy_protocol.trigger('change');
|
||||||
this.ui.ssl_forced.trigger('change');
|
this.ui.ssl_forced.trigger('change');
|
||||||
this.ui.hsts_enabled.trigger('change');
|
this.ui.hsts_enabled.trigger('change');
|
||||||
|
|
||||||
@ -271,7 +282,7 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.domain_names.selectize({
|
this.ui.domain_names.selectize({
|
||||||
delimiter: ',',
|
delimiter: ',',
|
||||||
persist: false,
|
persist: false,
|
||||||
maxOptions: 15,
|
maxOptions: 100,
|
||||||
create: function (input) {
|
create: function (input) {
|
||||||
return {
|
return {
|
||||||
value: input,
|
value: input,
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<div class="col-sm-4 col-md-4">
|
<div class="col-sm-4 col-md-4">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label"><%- i18n('proxy-hosts', 'forward-port') %> <span class="form-required">*</span></label>
|
<label class="form-label"><%- i18n('proxy-hosts', 'forward-port') %> <span class="form-required">*</span></label>
|
||||||
<input name="forward_port" type="number" class="form-control text-monospace model" placeholder="80" value="<%- forward_port %>" required>
|
<input name="forward_port" type="number" class="form-control text-monospace model" placeholder="80" min="1" max="65535" value="<%- forward_port %>" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -161,7 +161,7 @@
|
|||||||
<option
|
<option
|
||||||
value="<%- plugin_name %>"
|
value="<%- plugin_name %>"
|
||||||
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
|
||||||
><%- plugin_info.display_name %></option>
|
><%- plugin_info.name %></option>
|
||||||
<% }); %>
|
<% }); %>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -235,7 +235,7 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.domain_names.selectize({
|
this.ui.domain_names.selectize({
|
||||||
delimiter: ',',
|
delimiter: ',',
|
||||||
persist: false,
|
persist: false,
|
||||||
maxOptions: 15,
|
maxOptions: 100,
|
||||||
create: function (input) {
|
create: function (input) {
|
||||||
return {
|
return {
|
||||||
value: input,
|
value: input,
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label"><%- i18n('streams', 'incoming-port') %> <span class="form-required">*</span></label>
|
<label class="form-label"><%- i18n('streams', 'incoming-port') %> <span class="form-required">*</span></label>
|
||||||
<input name="incoming_port" type="number" class="form-control text-monospace" placeholder="eg: 8080" value="<%- incoming_port %>" required>
|
<input name="incoming_port" type="number" class="form-control text-monospace" placeholder="eg: 8080" min="1" max="65535" value="<%- incoming_port %>" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-8 col-md-8">
|
<div class="col-sm-8 col-md-8">
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<div class="col-sm-4 col-md-4">
|
<div class="col-sm-4 col-md-4">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label"><%- i18n('streams', 'forwarding-port') %> <span class="form-required">*</span></label>
|
<label class="form-label"><%- i18n('streams', 'forwarding-port') %> <span class="form-required">*</span></label>
|
||||||
<input name="forwarding_port" type="number" class="form-control text-monospace" placeholder="eg: 80" value="<%- forwarding_port %>" required>
|
<input name="forwarding_port" type="number" class="form-control text-monospace" placeholder="eg: 80" min="1" max="65535" value="<%- forwarding_port %>" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 col-md-6">
|
<div class="col-sm-6 col-md-6">
|
||||||
@ -42,6 +42,22 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="enable_proxy_protocol" value="1"<%- enable_proxy_protocol ? ' checked' : '' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('streams', 'enable-proxy-protocol') %><a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#introduction" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('streams', 'load-balancer-ip') %><a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#changing-the-load-balancers-ip-address-to-the-client-ip-address" target="_blank"><i class="fe fe-help-circle"></i></a></label>
|
||||||
|
<input type="text" name="load_balancer_ip" class="form-control text-monospace" placeholder="" value="<%- load_balancer_ip %>" autocomplete="off" maxlength="255" <%- enable_proxy_protocol ? '' : ' disabled' %>>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="forward-type-error invalid-feedback"><%- i18n('streams', 'forward-type-error') %></div>
|
<div class="forward-type-error invalid-feedback"><%- i18n('streams', 'forward-type-error') %></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,6 +14,8 @@ module.exports = Mn.View.extend({
|
|||||||
ui: {
|
ui: {
|
||||||
form: 'form',
|
form: 'form',
|
||||||
forwarding_host: 'input[name="forwarding_host"]',
|
forwarding_host: 'input[name="forwarding_host"]',
|
||||||
|
enable_proxy_protocol: 'input[name="enable_proxy_protocol"]',
|
||||||
|
load_balancer_ip: 'input[name="load_balancer_ip"]',
|
||||||
type_error: '.forward-type-error',
|
type_error: '.forward-type-error',
|
||||||
buttons: '.modal-footer button',
|
buttons: '.modal-footer button',
|
||||||
switches: '.custom-switch-input',
|
switches: '.custom-switch-input',
|
||||||
@ -22,6 +24,13 @@ module.exports = Mn.View.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
'change @ui.enable_proxy_protocol': function () {
|
||||||
|
let checked = this.ui.enable_proxy_protocol.prop('checked');
|
||||||
|
this.ui.load_balancer_ip
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
},
|
||||||
'change @ui.switches': function () {
|
'change @ui.switches': function () {
|
||||||
this.ui.type_error.hide();
|
this.ui.type_error.hide();
|
||||||
},
|
},
|
||||||
@ -47,6 +56,7 @@ module.exports = Mn.View.extend({
|
|||||||
data.forwarding_port = parseInt(data.forwarding_port, 10);
|
data.forwarding_port = parseInt(data.forwarding_port, 10);
|
||||||
data.tcp_forwarding = !!data.tcp_forwarding;
|
data.tcp_forwarding = !!data.tcp_forwarding;
|
||||||
data.udp_forwarding = !!data.udp_forwarding;
|
data.udp_forwarding = !!data.udp_forwarding;
|
||||||
|
data.enable_proxy_protocol = !!data.enable_proxy_protocol;
|
||||||
|
|
||||||
let method = App.Api.Nginx.Streams.create;
|
let method = App.Api.Nginx.Streams.create;
|
||||||
let is_new = true;
|
let is_new = true;
|
||||||
@ -76,6 +86,10 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.ui.enable_proxy_protocol.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
if (typeof options.model === 'undefined' || !options.model) {
|
if (typeof options.model === 'undefined' || !options.model) {
|
||||||
this.model = new StreamModel.Model();
|
this.model = new StreamModel.Model();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="form-label"><%- description %></div>
|
<div class="form-label"><%- i18n('settings', 'default-site-description') %></div>
|
||||||
<div class="custom-controls-stacked">
|
<div class="custom-controls-stacked">
|
||||||
<label class="custom-control custom-radio">
|
<label class="custom-control custom-radio">
|
||||||
<input class="custom-control-input" name="value" value="congratulations" type="radio" required <%- value === 'congratulations' ? 'checked' : '' %>>
|
<input class="custom-control-input" name="value" value="congratulations" type="radio" required <%- value === 'congratulations' ? 'checked' : '' %>>
|
||||||
@ -18,6 +18,10 @@
|
|||||||
<input class="custom-control-input" name="value" value="404" type="radio" required <%- value === '404' ? 'checked' : '' %>>
|
<input class="custom-control-input" name="value" value="404" type="radio" required <%- value === '404' ? 'checked' : '' %>>
|
||||||
<div class="custom-control-label"><%- i18n('settings', 'default-site-404') %></div>
|
<div class="custom-control-label"><%- i18n('settings', 'default-site-404') %></div>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="custom-control custom-radio">
|
||||||
|
<input class="custom-control-input" name="value" value="444" type="radio" required <%- value === '444' ? 'checked' : '' %>>
|
||||||
|
<div class="custom-control-label"><%- i18n('settings', 'default-site-444') %></div>
|
||||||
|
</label>
|
||||||
<label class="custom-control custom-radio">
|
<label class="custom-control custom-radio">
|
||||||
<input class="custom-control-input" name="value" value="redirect" type="radio" required <%- value === 'redirect' ? 'checked' : '' %>>
|
<input class="custom-control-input" name="value" value="redirect" type="radio" required <%- value === 'redirect' ? 'checked' : '' %>>
|
||||||
<div class="custom-control-label"><%- i18n('settings', 'default-site-redirect') %></div>
|
<div class="custom-control-label"><%- i18n('settings', 'default-site-redirect') %></div>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<td>
|
<td>
|
||||||
<div><%- name %></div>
|
<div><%- i18n('settings', 'default-site') %></div>
|
||||||
<div class="small text-muted">
|
<div class="small text-muted">
|
||||||
<%- description %>
|
<%- i18n('settings', 'default-site-description') %>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"fork-me": "Fork me on Github",
|
"fork-me": "Fork me on Github",
|
||||||
"copy": "© 2022 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
|
"copy": "© 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
|
||||||
"theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
|
"theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
@ -131,6 +131,8 @@
|
|||||||
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional SSL termination for your service that might not have SSL support built in.\nProxy Hosts are the most common use for the Nginx Proxy Manager.",
|
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional SSL termination for your service that might not have SSL support built in.\nProxy Hosts are the most common use for the Nginx Proxy Manager.",
|
||||||
"access-list": "Access List",
|
"access-list": "Access List",
|
||||||
"allow-websocket-upgrade": "Websockets Support",
|
"allow-websocket-upgrade": "Websockets Support",
|
||||||
|
"enable-proxy-protocol": "Enable Proxy Protocol",
|
||||||
|
"load-balancer-ip": "Load balancer or TCP proxy IP / CIDR range",
|
||||||
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL",
|
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL",
|
||||||
"custom-forward-host-help": "Add a path for sub-folder forwarding.\nExample: 203.0.113.25/path/",
|
"custom-forward-host-help": "Add a path for sub-folder forwarding.\nExample: 203.0.113.25/path/",
|
||||||
"search": "Search Host…"
|
"search": "Search Host…"
|
||||||
@ -175,6 +177,8 @@
|
|||||||
"protocol": "Protocol",
|
"protocol": "Protocol",
|
||||||
"tcp": "TCP",
|
"tcp": "TCP",
|
||||||
"udp": "UDP",
|
"udp": "UDP",
|
||||||
|
"enable-proxy-protocol": "Enable Proxy Protocol",
|
||||||
|
"load-balancer-ip": "Load balancer or TCP proxy IP / CIDR range",
|
||||||
"delete": "Delete Stream",
|
"delete": "Delete Stream",
|
||||||
"delete-confirm": "Are you sure you want to delete this Stream?",
|
"delete-confirm": "Are you sure you want to delete this Stream?",
|
||||||
"help-title": "What is a Stream?",
|
"help-title": "What is a Stream?",
|
||||||
@ -285,8 +289,10 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"title": "Settings",
|
"title": "Settings",
|
||||||
"default-site": "Default Site",
|
"default-site": "Default Site",
|
||||||
|
"default-site-description": "What to show when Nginx is hit with an unknown Host",
|
||||||
"default-site-congratulations": "Congratulations Page",
|
"default-site-congratulations": "Congratulations Page",
|
||||||
"default-site-404": "404 Page",
|
"default-site-404": "404 Page",
|
||||||
|
"default-site-444": "No Response (444)",
|
||||||
"default-site-html": "Custom Page",
|
"default-site-html": "Custom Page",
|
||||||
"default-site-redirect": "Redirect"
|
"default-site-redirect": "Redirect"
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ const model = Backbone.Model.extend({
|
|||||||
hsts_subdomains: false,
|
hsts_subdomains: false,
|
||||||
caching_enabled: false,
|
caching_enabled: false,
|
||||||
allow_websocket_upgrade: false,
|
allow_websocket_upgrade: false,
|
||||||
|
enable_proxy_protocol: false,
|
||||||
|
load_balancer_ip: '',
|
||||||
block_exploits: false,
|
block_exploits: false,
|
||||||
http2_support: false,
|
http2_support: false,
|
||||||
advanced_config: '',
|
advanced_config: '',
|
||||||
|
@ -5,18 +5,20 @@ const model = Backbone.Model.extend({
|
|||||||
|
|
||||||
defaults: function () {
|
defaults: function () {
|
||||||
return {
|
return {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
created_on: null,
|
created_on: null,
|
||||||
modified_on: null,
|
modified_on: null,
|
||||||
incoming_port: null,
|
incoming_port: null,
|
||||||
forwarding_host: null,
|
forwarding_host: null,
|
||||||
forwarding_port: null,
|
forwarding_port: null,
|
||||||
tcp_forwarding: true,
|
tcp_forwarding: true,
|
||||||
udp_forwarding: false,
|
udp_forwarding: false,
|
||||||
enabled: true,
|
enable_proxy_protocol: false,
|
||||||
meta: {},
|
load_balancer_ip: "",
|
||||||
|
enabled: true,
|
||||||
|
meta: {},
|
||||||
// The following are expansions:
|
// The following are expansions:
|
||||||
owner: null
|
owner: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -27,10 +27,10 @@
|
|||||||
"messageformat-loader": "^0.8.1",
|
"messageformat-loader": "^0.8.1",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^9.0.0",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.2",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"sass-loader": "10.2.0",
|
"sass-loader": "^10.0.0",
|
||||||
"style-loader": "^1.1.3",
|
"style-loader": "^1.1.3",
|
||||||
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
|
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
|
||||||
"underscore": "^1.12.1",
|
"underscore": "^1.12.1",
|
||||||
|
1278
frontend/yarn.lock
1278
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
21
global/README.md
Normal file
21
global/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# certbot-dns-plugins
|
||||||
|
|
||||||
|
This file contains info about available Certbot DNS plugins.
|
||||||
|
This only works for plugins which use the standard argument structure, so:
|
||||||
|
--authenticator <plugin-name> --<plugin-name>-credentials <FILE> --<plugin-name>-propagation-seconds <number>
|
||||||
|
|
||||||
|
File Structure:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cloudflare": {
|
||||||
|
"display_name": "Name displayed to the user",
|
||||||
|
"package_name": "Package name in PyPi repo",
|
||||||
|
"version_requirement": "Optional package version requirements (e.g. ==1.3 or >=1.2,<2.0, see https://www.python.org/dev/peps/pep-0440/#version-specifiers)",
|
||||||
|
"dependencies": "Additional dependencies, space separated (as you would pass it to pip install)",
|
||||||
|
"credentials": "Template of the credentials file",
|
||||||
|
"full_plugin_name": "The full plugin name as used in the commandline with certbot, e.g. 'dns-njalla'"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
@ -1,563 +0,0 @@
|
|||||||
/**
|
|
||||||
* This file contains info about available Certbot DNS plugins.
|
|
||||||
* This only works for plugins which use the standard argument structure, so:
|
|
||||||
* --authenticator <plugin-name> --<plugin-name>-credentials <FILE> --<plugin-name>-propagation-seconds <number>
|
|
||||||
*
|
|
||||||
* File Structure:
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* cloudflare: {
|
|
||||||
* display_name: "Name displayed to the user",
|
|
||||||
* package_name: "Package name in PyPi repo",
|
|
||||||
* version_requirement: "Optional package version requirements (e.g. ==1.3 or >=1.2,<2.0, see https://www.python.org/dev/peps/pep-0440/#version-specifiers)",
|
|
||||||
* dependencies: "Additional dependencies, space separated (as you would pass it to pip install)",
|
|
||||||
* credentials: `Template of the credentials file`,
|
|
||||||
* full_plugin_name: "The full plugin name as used in the commandline with certbot, e.g. 'dns-njalla'",
|
|
||||||
* },
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
//####################################################//
|
|
||||||
acmedns: {
|
|
||||||
display_name: 'ACME-DNS',
|
|
||||||
package_name: 'certbot-dns-acmedns',
|
|
||||||
version_requirement: '~=0.1.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_acmedns_api_url = http://acmedns-server/
|
|
||||||
dns_acmedns_registration_file = /data/acme-registration.json`,
|
|
||||||
full_plugin_name: 'dns-acmedns',
|
|
||||||
},
|
|
||||||
aliyun: {
|
|
||||||
display_name: 'Aliyun',
|
|
||||||
package_name: 'certbot-dns-aliyun',
|
|
||||||
version_requirement: '~=0.38.1',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_aliyun_access_key = 12345678
|
|
||||||
dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`,
|
|
||||||
full_plugin_name: 'dns-aliyun',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
azure: {
|
|
||||||
display_name: 'Azure',
|
|
||||||
package_name: 'certbot-dns-azure',
|
|
||||||
version_requirement: '~=1.2.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.
|
|
||||||
# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.
|
|
||||||
# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.
|
|
||||||
|
|
||||||
# Using a service principal (option 1)
|
|
||||||
dns_azure_sp_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5
|
|
||||||
dns_azure_sp_client_secret = E-xqXU83Y-jzTI6xe9fs2YC~mck3ZzUih9
|
|
||||||
dns_azure_tenant_id = ed1090f3-ab18-4b12-816c-599af8a88cf7
|
|
||||||
|
|
||||||
# Using used assigned MSI (option 2)
|
|
||||||
# dns_azure_msi_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5
|
|
||||||
|
|
||||||
# Using system assigned MSI (option 3)
|
|
||||||
# dns_azure_msi_system_assigned = true
|
|
||||||
|
|
||||||
# Zones (at least one always required)
|
|
||||||
dns_azure_zone1 = example.com:/subscriptions/c135abce-d87d-48df-936c-15596c6968a5/resourceGroups/dns1
|
|
||||||
dns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf2744622/resourceGroups/dns2`,
|
|
||||||
full_plugin_name: 'dns-azure',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
cloudflare: {
|
|
||||||
display_name: 'Cloudflare',
|
|
||||||
package_name: 'certbot-dns-cloudflare',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: 'cloudflare',
|
|
||||||
credentials: `# Cloudflare API token
|
|
||||||
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
|
|
||||||
full_plugin_name: 'dns-cloudflare',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
cloudns: {
|
|
||||||
display_name: 'ClouDNS',
|
|
||||||
package_name: 'certbot-dns-cloudns',
|
|
||||||
version_requirement: '~=0.4.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `# Target user ID (see https://www.cloudns.net/api-settings/)
|
|
||||||
dns_cloudns_auth_id=1234
|
|
||||||
# Alternatively, one of the following two options can be set:
|
|
||||||
# dns_cloudns_sub_auth_id=1234
|
|
||||||
# dns_cloudns_sub_auth_user=foobar
|
|
||||||
|
|
||||||
# API password
|
|
||||||
dns_cloudns_auth_password=password1`,
|
|
||||||
full_plugin_name: 'dns-cloudns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
cloudxns: {
|
|
||||||
display_name: 'CloudXNS',
|
|
||||||
package_name: 'certbot-dns-cloudxns',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
|
|
||||||
dns_cloudxns_secret_key = 1122334455667788`,
|
|
||||||
full_plugin_name: 'dns-cloudxns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
constellix: {
|
|
||||||
display_name: 'Constellix',
|
|
||||||
package_name: 'certbot-dns-constellix',
|
|
||||||
version_requirement: '~=0.2.1',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_constellix_apikey = 5fb4e76f-ac91-43e5-f982458bc595
|
|
||||||
dns_constellix_secretkey = 47d99fd0-32e7-4e07-85b46d08e70b
|
|
||||||
dns_constellix_endpoint = https://api.dns.constellix.com/v1`,
|
|
||||||
full_plugin_name: 'dns-constellix',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
corenetworks: {
|
|
||||||
display_name: 'Core Networks',
|
|
||||||
package_name: 'certbot-dns-corenetworks',
|
|
||||||
version_requirement: '~=0.1.4',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_corenetworks_username = asaHB12r
|
|
||||||
dns_corenetworks_password = secure_password`,
|
|
||||||
full_plugin_name: 'dns-corenetworks',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
cpanel: {
|
|
||||||
display_name: 'cPanel',
|
|
||||||
package_name: 'certbot-dns-cpanel',
|
|
||||||
version_requirement: '~=0.2.2',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `cpanel_url = https://cpanel.example.com:2083
|
|
||||||
cpanel_username = user
|
|
||||||
cpanel_password = hunter2`,
|
|
||||||
full_plugin_name: 'cpanel',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
desec: {
|
|
||||||
display_name: 'deSEC',
|
|
||||||
package_name: 'certbot-dns-desec',
|
|
||||||
version_requirement: '~=1.2.1',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_desec_token = YOUR_DESEC_API_TOKEN
|
|
||||||
dns_desec_endpoint = https://desec.io/api/v1/`,
|
|
||||||
full_plugin_name: 'dns-desec',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
duckdns: {
|
|
||||||
display_name: 'DuckDNS',
|
|
||||||
package_name: 'certbot-dns-duckdns',
|
|
||||||
version_requirement: '~=0.9',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_duckdns_token=your-duckdns-token',
|
|
||||||
full_plugin_name: 'dns-duckdns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
digitalocean: {
|
|
||||||
display_name: 'DigitalOcean',
|
|
||||||
package_name: 'certbot-dns-digitalocean',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff',
|
|
||||||
full_plugin_name: 'dns-digitalocean',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
directadmin: {
|
|
||||||
display_name: 'DirectAdmin',
|
|
||||||
package_name: 'certbot-dns-directadmin',
|
|
||||||
version_requirement: '~=0.0.23',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `directadmin_url = https://my.directadminserver.com:2222
|
|
||||||
directadmin_username = username
|
|
||||||
directadmin_password = aSuperStrongPassword`,
|
|
||||||
full_plugin_name: 'directadmin',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
dnsimple: {
|
|
||||||
display_name: 'DNSimple',
|
|
||||||
package_name: 'certbot-dns-dnsimple',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw',
|
|
||||||
full_plugin_name: 'dns-dnsimple',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
dnsmadeeasy: {
|
|
||||||
display_name: 'DNS Made Easy',
|
|
||||||
package_name: 'certbot-dns-dnsmadeeasy',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
|
|
||||||
dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
|
|
||||||
full_plugin_name: 'dns-dnsmadeeasy',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
dnspod: {
|
|
||||||
display_name: 'DNSPod',
|
|
||||||
package_name: 'certbot-dns-dnspod',
|
|
||||||
version_requirement: '~=0.1.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_dnspod_email = "email@example.com"
|
|
||||||
dns_dnspod_api_token = "id,key"`,
|
|
||||||
full_plugin_name: 'dns-dnspod',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
domainoffensive: {
|
|
||||||
display_name: 'DomainOffensive (do.de)',
|
|
||||||
package_name: 'certbot-dns-do',
|
|
||||||
version_requirement: '~=0.31.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_do_api_token = YOUR_DO_DE_AUTH_TOKEN',
|
|
||||||
full_plugin_name: 'dns-do',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
domeneshop: {
|
|
||||||
display_name: 'Domeneshop',
|
|
||||||
package_name: 'certbot-dns-domeneshop',
|
|
||||||
version_requirement: '~=0.2.8',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_domeneshop_client_token=YOUR_DOMENESHOP_CLIENT_TOKEN
|
|
||||||
dns_domeneshop_client_secret=YOUR_DOMENESHOP_CLIENT_SECRET`,
|
|
||||||
full_plugin_name: 'dns-domeneshop',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
dynu: {
|
|
||||||
display_name: 'Dynu',
|
|
||||||
package_name: 'certbot-dns-dynu',
|
|
||||||
version_requirement: '~=0.0.1',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN',
|
|
||||||
full_plugin_name: 'dns-dynu',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
eurodns: {
|
|
||||||
display_name: 'EuroDNS',
|
|
||||||
package_name: 'certbot-dns-eurodns',
|
|
||||||
version_requirement: '~=0.0.4',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_eurodns_applicationId = myuser
|
|
||||||
dns_eurodns_apiKey = mysecretpassword
|
|
||||||
dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`,
|
|
||||||
full_plugin_name: 'dns-eurodns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
gandi: {
|
|
||||||
display_name: 'Gandi Live DNS',
|
|
||||||
package_name: 'certbot_plugin_gandi',
|
|
||||||
version_requirement: '~=1.3.2',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `# live dns v5 api key
|
|
||||||
dns_gandi_api_key=APIKEY
|
|
||||||
|
|
||||||
# optional organization id, remove it if not used
|
|
||||||
dns_gandi_sharing_id=SHARINGID`,
|
|
||||||
full_plugin_name: 'dns-gandi',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
godaddy: {
|
|
||||||
display_name: 'GoDaddy',
|
|
||||||
package_name: 'certbot-dns-godaddy',
|
|
||||||
version_requirement: '~=0.2.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567
|
|
||||||
dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`,
|
|
||||||
full_plugin_name: 'dns-godaddy',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
google: {
|
|
||||||
display_name: 'Google',
|
|
||||||
package_name: 'certbot-dns-google',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `{
|
|
||||||
"type": "service_account",
|
|
||||||
...
|
|
||||||
}`,
|
|
||||||
full_plugin_name: 'dns-google',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
googledomains: {
|
|
||||||
display_name: 'GoogleDomainsDNS',
|
|
||||||
package_name: 'certbot-dns-google-domains',
|
|
||||||
version_requirement: '~=0.1.5',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_google_domains_access_token = 0123456789abcdef0123456789abcdef01234567
|
|
||||||
dns_google_domains_zone = "example.com"`,
|
|
||||||
full_plugin_name: 'dns-google-domains',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
hetzner: {
|
|
||||||
display_name: 'Hetzner',
|
|
||||||
package_name: 'certbot-dns-hetzner',
|
|
||||||
version_requirement: '~=1.0.4',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_hetzner_api_token = 0123456789abcdef0123456789abcdef',
|
|
||||||
full_plugin_name: 'dns-hetzner',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
infomaniak: {
|
|
||||||
display_name: 'Infomaniak',
|
|
||||||
package_name: 'certbot-dns-infomaniak',
|
|
||||||
version_requirement: '~=0.1.12',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
|
||||||
full_plugin_name: 'dns-infomaniak',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
inwx: {
|
|
||||||
display_name: 'INWX',
|
|
||||||
package_name: 'certbot-dns-inwx',
|
|
||||||
version_requirement: '~=2.1.2',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_inwx_url = https://api.domrobot.com/xmlrpc/
|
|
||||||
dns_inwx_username = your_username
|
|
||||||
dns_inwx_password = your_password
|
|
||||||
dns_inwx_shared_secret = your_shared_secret optional`,
|
|
||||||
full_plugin_name: 'dns-inwx',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
ionos: {
|
|
||||||
display_name: 'IONOS',
|
|
||||||
package_name: 'certbot-dns-ionos',
|
|
||||||
version_requirement: '==2022.11.24',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_ionos_prefix = myapikeyprefix
|
|
||||||
dns_ionos_secret = verysecureapikeysecret
|
|
||||||
dns_ionos_endpoint = https://api.hosting.ionos.com`,
|
|
||||||
full_plugin_name: 'dns-ionos',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
ispconfig: {
|
|
||||||
display_name: 'ISPConfig',
|
|
||||||
package_name: 'certbot-dns-ispconfig',
|
|
||||||
version_requirement: '~=0.2.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_ispconfig_username = myremoteuser
|
|
||||||
dns_ispconfig_password = verysecureremoteuserpassword
|
|
||||||
dns_ispconfig_endpoint = https://localhost:8080`,
|
|
||||||
full_plugin_name: 'dns-ispconfig',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
isset: {
|
|
||||||
display_name: 'Isset',
|
|
||||||
package_name: 'certbot-dns-isset',
|
|
||||||
version_requirement: '~=0.0.3',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_isset_endpoint="https://customer.isset.net/api"
|
|
||||||
dns_isset_token="<token>"`,
|
|
||||||
full_plugin_name: 'dns-isset',
|
|
||||||
},
|
|
||||||
joker: {
|
|
||||||
display_name: 'Joker',
|
|
||||||
package_name: 'certbot-dns-joker',
|
|
||||||
version_requirement: '~=1.1.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_joker_username = <Dynamic DNS Authentication Username>
|
|
||||||
dns_joker_password = <Dynamic DNS Authentication Password>
|
|
||||||
dns_joker_domain = <Dynamic DNS Domain>`,
|
|
||||||
full_plugin_name: 'dns-joker',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
linode: {
|
|
||||||
display_name: 'Linode',
|
|
||||||
package_name: 'certbot-dns-linode',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
|
|
||||||
dns_linode_version = [<blank>|3|4]`,
|
|
||||||
full_plugin_name: 'dns-linode',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
loopia: {
|
|
||||||
display_name: 'Loopia',
|
|
||||||
package_name: 'certbot-dns-loopia',
|
|
||||||
version_requirement: '~=1.0.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_loopia_user = user@loopiaapi
|
|
||||||
dns_loopia_password = abcdef0123456789abcdef01234567abcdef0123`,
|
|
||||||
full_plugin_name: 'dns-loopia',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
luadns: {
|
|
||||||
display_name: 'LuaDNS',
|
|
||||||
package_name: 'certbot-dns-luadns',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_luadns_email = user@example.com
|
|
||||||
dns_luadns_token = 0123456789abcdef0123456789abcdef`,
|
|
||||||
full_plugin_name: 'dns-luadns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
namecheap: {
|
|
||||||
display_name: 'Namecheap',
|
|
||||||
package_name: 'certbot-dns-namecheap',
|
|
||||||
version_requirement: '~=1.0.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_namecheap_username = 123456
|
|
||||||
dns_namecheap_api_key = 0123456789abcdef0123456789abcdef01234567`,
|
|
||||||
full_plugin_name: 'dns-namecheap',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
netcup: {
|
|
||||||
display_name: 'netcup',
|
|
||||||
package_name: 'certbot-dns-netcup',
|
|
||||||
version_requirement: '~=1.0.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_netcup_customer_id = 123456
|
|
||||||
dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
|
|
||||||
dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
|
|
||||||
full_plugin_name: 'dns-netcup',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
njalla: {
|
|
||||||
display_name: 'Njalla',
|
|
||||||
package_name: 'certbot-dns-njalla',
|
|
||||||
version_requirement: '~=1.0.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
|
|
||||||
full_plugin_name: 'dns-njalla',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
nsone: {
|
|
||||||
display_name: 'NS1',
|
|
||||||
package_name: 'certbot-dns-nsone',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw',
|
|
||||||
full_plugin_name: 'dns-nsone',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
oci: {
|
|
||||||
display_name: 'Oracle Cloud Infrastructure DNS',
|
|
||||||
package_name: 'certbot-dns-oci',
|
|
||||||
package_version: '0.3.6',
|
|
||||||
dependencies: 'oci',
|
|
||||||
credentials: `[DEFAULT]
|
|
||||||
user = ocid1.user.oc1...
|
|
||||||
fingerprint = xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
|
|
||||||
tenancy = ocid1.tenancy.oc1...
|
|
||||||
region = us-ashburn-1
|
|
||||||
key_file = ~/.oci/oci_api_key.pem`,
|
|
||||||
full_plugin_name: 'dns-oci',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
online: {
|
|
||||||
display_name: 'Online',
|
|
||||||
package_name: 'certbot-dns-online',
|
|
||||||
version_requirement: '~=0.0.8',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_online_token=0123456789abcdef0123456789abcdef01234567',
|
|
||||||
full_plugin_name: 'dns-online',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
ovh: {
|
|
||||||
display_name: 'OVH',
|
|
||||||
package_name: 'certbot-dns-ovh',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_ovh_endpoint = ovh-eu
|
|
||||||
dns_ovh_application_key = MDAwMDAwMDAwMDAw
|
|
||||||
dns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
|
|
||||||
dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
|
|
||||||
full_plugin_name: 'dns-ovh',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
porkbun: {
|
|
||||||
display_name: 'Porkbun',
|
|
||||||
package_name: 'certbot-dns-porkbun',
|
|
||||||
version_requirement: '~=0.2',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_porkbun_key=your-porkbun-api-key
|
|
||||||
dns_porkbun_secret=your-porkbun-api-secret`,
|
|
||||||
full_plugin_name: 'dns-porkbun',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
powerdns: {
|
|
||||||
display_name: 'PowerDNS',
|
|
||||||
package_name: 'certbot-dns-powerdns',
|
|
||||||
version_requirement: '~=0.2.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_powerdns_api_url = https://api.mypowerdns.example.org
|
|
||||||
dns_powerdns_api_key = AbCbASsd!@34`,
|
|
||||||
full_plugin_name: 'dns-powerdns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
regru: {
|
|
||||||
display_name: 'reg.ru',
|
|
||||||
package_name: 'certbot-regru',
|
|
||||||
version_requirement: '~=1.0.2',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_username=username
|
|
||||||
dns_password=password`,
|
|
||||||
full_plugin_name: 'dns',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
rfc2136: {
|
|
||||||
display_name: 'RFC 2136',
|
|
||||||
package_name: 'certbot-dns-rfc2136',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `# Target DNS server
|
|
||||||
dns_rfc2136_server = 192.0.2.1
|
|
||||||
# Target DNS port
|
|
||||||
dns_rfc2136_port = 53
|
|
||||||
# TSIG key name
|
|
||||||
dns_rfc2136_name = keyname.
|
|
||||||
# TSIG key secret
|
|
||||||
dns_rfc2136_secret = 4q4wM/2I180UXoMyN4INVhJNi8V9BCV+jMw2mXgZw/CSuxUT8C7NKKFs AmKd7ak51vWKgSl12ib86oQRPkpDjg==
|
|
||||||
# TSIG key algorithm
|
|
||||||
dns_rfc2136_algorithm = HMAC-SHA512`,
|
|
||||||
full_plugin_name: 'dns-rfc2136',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
route53: {
|
|
||||||
display_name: 'Route 53 (Amazon)',
|
|
||||||
package_name: 'certbot-dns-route53',
|
|
||||||
version_requirement: '==$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')', // official plugin, use certbot version
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `[default]
|
|
||||||
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
|
|
||||||
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
|
|
||||||
full_plugin_name: 'dns-route53',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
transip: {
|
|
||||||
display_name: 'TransIP',
|
|
||||||
package_name: 'certbot-dns-transip',
|
|
||||||
version_requirement: '~=0.4.3',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_transip_username = my_username
|
|
||||||
dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
|
|
||||||
full_plugin_name: 'dns-transip',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
tencentcloud: {
|
|
||||||
display_name: 'Tencent Cloud',
|
|
||||||
package_name: 'certbot-dns-tencentcloud',
|
|
||||||
version_requirement: '~=2.0.0',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_tencentcloud_secret_id = TENCENT_CLOUD_SECRET_ID
|
|
||||||
dns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY`,
|
|
||||||
full_plugin_name: 'dns-tencentcloud',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
vultr: {
|
|
||||||
display_name: 'Vultr',
|
|
||||||
package_name: 'certbot-dns-vultr',
|
|
||||||
version_requirement: '~=1.0.3',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: 'dns_vultr_key = YOUR_VULTR_API_KEY',
|
|
||||||
full_plugin_name: 'dns-vultr',
|
|
||||||
},
|
|
||||||
//####################################################//
|
|
||||||
websupportsk: {
|
|
||||||
display_name: 'Websupport.sk',
|
|
||||||
package_name: 'certbot-dns-websupportsk',
|
|
||||||
version_requirement: '~=0.1.6',
|
|
||||||
dependencies: '',
|
|
||||||
credentials: `dns_websupportsk_api_key = <api_key>
|
|
||||||
dns_websupportsk_secret = <secret>
|
|
||||||
dns_websupportsk_domain = example.com`,
|
|
||||||
full_plugin_name: 'dns-websupportsk',
|
|
||||||
},
|
|
||||||
};
|
|
450
global/certbot-dns-plugins.json
Normal file
450
global/certbot-dns-plugins.json
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
{
|
||||||
|
"acmedns": {
|
||||||
|
"name": "ACME-DNS",
|
||||||
|
"package_name": "certbot-dns-acmedns",
|
||||||
|
"version": "~=0.1.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_acmedns_api_url = http://acmedns-server/\ndns_acmedns_registration_file = /data/acme-registration.json",
|
||||||
|
"full_plugin_name": "dns-acmedns"
|
||||||
|
},
|
||||||
|
"aliyun": {
|
||||||
|
"name": "Aliyun",
|
||||||
|
"package_name": "certbot-dns-aliyun",
|
||||||
|
"version": "~=0.38.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_aliyun_access_key = 12345678\ndns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef",
|
||||||
|
"full_plugin_name": "dns-aliyun"
|
||||||
|
},
|
||||||
|
"azure": {
|
||||||
|
"name": "Azure",
|
||||||
|
"package_name": "certbot-dns-azure",
|
||||||
|
"version": "~=1.2.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.\n# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.\n# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.\n\n# Using a service principal (option 1)\ndns_azure_sp_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\ndns_azure_sp_client_secret = E-xqXU83Y-jzTI6xe9fs2YC~mck3ZzUih9\ndns_azure_tenant_id = ed1090f3-ab18-4b12-816c-599af8a88cf7\n\n# Using used assigned MSI (option 2)\n# dns_azure_msi_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\n\n# Using system assigned MSI (option 3)\n# dns_azure_msi_system_assigned = true\n\n# Zones (at least one always required)\ndns_azure_zone1 = example.com:/subscriptions/c135abce-d87d-48df-936c-15596c6968a5/resourceGroups/dns1\ndns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf2744622/resourceGroups/dns2",
|
||||||
|
"full_plugin_name": "dns-azure"
|
||||||
|
},
|
||||||
|
"bunny": {
|
||||||
|
"name": "bunny.net",
|
||||||
|
"package_name": "certbot-dns-bunny",
|
||||||
|
"version": "~=0.0.9",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "# Bunny API token used by Certbot (see https://dash.bunny.net/account/settings)\ndns_bunny_api_key = xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
|
||||||
|
"full_plugin_name": "dns-bunny"
|
||||||
|
},
|
||||||
|
"cloudflare": {
|
||||||
|
"name": "Cloudflare",
|
||||||
|
"package_name": "certbot-dns-cloudflare",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "cloudflare acme=={{certbot-version}}",
|
||||||
|
"credentials": "# Cloudflare API token\ndns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567",
|
||||||
|
"full_plugin_name": "dns-cloudflare"
|
||||||
|
},
|
||||||
|
"cloudns": {
|
||||||
|
"name": "ClouDNS",
|
||||||
|
"package_name": "certbot-dns-cloudns",
|
||||||
|
"version": "~=0.6.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "# Target user ID (see https://www.cloudns.net/api-settings/)\n\tdns_cloudns_auth_id=1234\n\t# Alternatively, one of the following two options can be set:\n\t# dns_cloudns_sub_auth_id=1234\n\t# dns_cloudns_sub_auth_user=foobar\n\n\t# API password\n\tdns_cloudns_auth_password=password1",
|
||||||
|
"full_plugin_name": "dns-cloudns"
|
||||||
|
},
|
||||||
|
"cloudxns": {
|
||||||
|
"name": "CloudXNS",
|
||||||
|
"package_name": "certbot-dns-cloudxns",
|
||||||
|
"version": "~=1.32.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef\ndns_cloudxns_secret_key = 1122334455667788",
|
||||||
|
"full_plugin_name": "dns-cloudxns"
|
||||||
|
},
|
||||||
|
"constellix": {
|
||||||
|
"name": "Constellix",
|
||||||
|
"package_name": "certbot-dns-constellix",
|
||||||
|
"version": "~=0.2.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_constellix_apikey = 5fb4e76f-ac91-43e5-f982458bc595\ndns_constellix_secretkey = 47d99fd0-32e7-4e07-85b46d08e70b\ndns_constellix_endpoint = https://api.dns.constellix.com/v1",
|
||||||
|
"full_plugin_name": "dns-constellix"
|
||||||
|
},
|
||||||
|
"corenetworks": {
|
||||||
|
"name": "Core Networks",
|
||||||
|
"package_name": "certbot-dns-corenetworks",
|
||||||
|
"version": "~=0.1.4",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_corenetworks_username = asaHB12r\ndns_corenetworks_password = secure_password",
|
||||||
|
"full_plugin_name": "dns-corenetworks"
|
||||||
|
},
|
||||||
|
"cpanel": {
|
||||||
|
"name": "cPanel",
|
||||||
|
"package_name": "certbot-dns-cpanel",
|
||||||
|
"version": "~=0.2.2",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "cpanel_url = https://cpanel.example.com:2083\ncpanel_username = user\ncpanel_password = hunter2",
|
||||||
|
"full_plugin_name": "cpanel"
|
||||||
|
},
|
||||||
|
"desec": {
|
||||||
|
"name": "deSEC",
|
||||||
|
"package_name": "certbot-dns-desec",
|
||||||
|
"version": "~=1.2.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_desec_token = YOUR_DESEC_API_TOKEN\ndns_desec_endpoint = https://desec.io/api/v1/",
|
||||||
|
"full_plugin_name": "dns-desec"
|
||||||
|
},
|
||||||
|
"duckdns": {
|
||||||
|
"name": "DuckDNS",
|
||||||
|
"package_name": "certbot-dns-duckdns",
|
||||||
|
"version": "~=0.9",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_duckdns_token=your-duckdns-token",
|
||||||
|
"full_plugin_name": "dns-duckdns"
|
||||||
|
},
|
||||||
|
"digitalocean": {
|
||||||
|
"name": "DigitalOcean",
|
||||||
|
"package_name": "certbot-dns-digitalocean",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff",
|
||||||
|
"full_plugin_name": "dns-digitalocean"
|
||||||
|
},
|
||||||
|
"directadmin": {
|
||||||
|
"name": "DirectAdmin",
|
||||||
|
"package_name": "certbot-dns-directadmin",
|
||||||
|
"version": "~=0.0.23",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "directadmin_url = https://my.directadminserver.com:2222\ndirectadmin_username = username\ndirectadmin_password = aSuperStrongPassword",
|
||||||
|
"full_plugin_name": "directadmin"
|
||||||
|
},
|
||||||
|
"dnsimple": {
|
||||||
|
"name": "DNSimple",
|
||||||
|
"package_name": "certbot-dns-dnsimple",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw",
|
||||||
|
"full_plugin_name": "dns-dnsimple"
|
||||||
|
},
|
||||||
|
"dnsmadeeasy": {
|
||||||
|
"name": "DNS Made Easy",
|
||||||
|
"package_name": "certbot-dns-dnsmadeeasy",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a\ndns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55",
|
||||||
|
"full_plugin_name": "dns-dnsmadeeasy"
|
||||||
|
},
|
||||||
|
"dnspod": {
|
||||||
|
"name": "DNSPod",
|
||||||
|
"package_name": "certbot-dns-dnspod",
|
||||||
|
"version": "~=0.1.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_dnspod_email = \"email@example.com\"\ndns_dnspod_api_token = \"id,key\"",
|
||||||
|
"full_plugin_name": "dns-dnspod"
|
||||||
|
},
|
||||||
|
"domainoffensive": {
|
||||||
|
"name": "DomainOffensive (do.de)",
|
||||||
|
"package_name": "certbot-dns-do",
|
||||||
|
"version": "~=0.31.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_do_api_token = YOUR_DO_DE_AUTH_TOKEN",
|
||||||
|
"full_plugin_name": "dns-do"
|
||||||
|
},
|
||||||
|
"domeneshop": {
|
||||||
|
"name": "Domeneshop",
|
||||||
|
"package_name": "certbot-dns-domeneshop",
|
||||||
|
"version": "~=0.2.8",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_domeneshop_client_token=YOUR_DOMENESHOP_CLIENT_TOKEN\ndns_domeneshop_client_secret=YOUR_DOMENESHOP_CLIENT_SECRET",
|
||||||
|
"full_plugin_name": "dns-domeneshop"
|
||||||
|
},
|
||||||
|
"dynu": {
|
||||||
|
"name": "Dynu",
|
||||||
|
"package_name": "certbot-dns-dynu",
|
||||||
|
"version": "~=0.0.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN",
|
||||||
|
"full_plugin_name": "dns-dynu"
|
||||||
|
},
|
||||||
|
"easydns": {
|
||||||
|
"name": "easyDNS",
|
||||||
|
"package_name": "certbot-dns-easydns",
|
||||||
|
"version": "~=0.1.2",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_easydns_usertoken = YOUR_EASYDNS_USERTOKEN\ndns_easydns_userkey = YOUR_EASYDNS_USERKEY\ndns_easydns_endpoint = https://rest.easydns.net",
|
||||||
|
"full_plugin_name": "dns-easydns"
|
||||||
|
},
|
||||||
|
"eurodns": {
|
||||||
|
"name": "EuroDNS",
|
||||||
|
"package_name": "certbot-dns-eurodns",
|
||||||
|
"version": "~=0.0.4",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_eurodns_applicationId = myuser\ndns_eurodns_apiKey = mysecretpassword\ndns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy",
|
||||||
|
"full_plugin_name": "dns-eurodns"
|
||||||
|
},
|
||||||
|
"freedns": {
|
||||||
|
"name": "FreeDNS",
|
||||||
|
"package_name": "certbot-dns-freedns",
|
||||||
|
"version": "~=0.1.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_freedns_username = myremoteuser\ndns_freedns_password = verysecureremoteuserpassword",
|
||||||
|
"full_plugin_name": "dns-freedns"
|
||||||
|
},
|
||||||
|
"gandi": {
|
||||||
|
"name": "Gandi Live DNS",
|
||||||
|
"package_name": "certbot_plugin_gandi",
|
||||||
|
"version": "~=1.5.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "# Gandi personal access token\ndns_gandi_token=PERSONAL_ACCESS_TOKEN",
|
||||||
|
"full_plugin_name": "dns-gandi"
|
||||||
|
},
|
||||||
|
"godaddy": {
|
||||||
|
"name": "GoDaddy",
|
||||||
|
"package_name": "certbot-dns-godaddy",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567\ndns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123",
|
||||||
|
"full_plugin_name": "dns-godaddy"
|
||||||
|
},
|
||||||
|
"google": {
|
||||||
|
"name": "Google",
|
||||||
|
"package_name": "certbot-dns-google",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "{\n\"type\": \"service_account\",\n...\n}",
|
||||||
|
"full_plugin_name": "dns-google"
|
||||||
|
},
|
||||||
|
"googledomains": {
|
||||||
|
"name": "GoogleDomainsDNS",
|
||||||
|
"package_name": "certbot-dns-google-domains",
|
||||||
|
"version": "~=0.1.5",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_google_domains_access_token = 0123456789abcdef0123456789abcdef01234567\ndns_google_domains_zone = \"example.com\"",
|
||||||
|
"full_plugin_name": "dns-google-domains"
|
||||||
|
},
|
||||||
|
"he": {
|
||||||
|
"name": "Hurricane Electric",
|
||||||
|
"package_name": "certbot-dns-he",
|
||||||
|
"version": "~=1.0.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_he_user = Me\ndns_he_pass = my HE password",
|
||||||
|
"full_plugin_name": "dns-he"
|
||||||
|
},
|
||||||
|
"hetzner": {
|
||||||
|
"name": "Hetzner",
|
||||||
|
"package_name": "certbot-dns-hetzner",
|
||||||
|
"version": "~=1.0.4",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_hetzner_api_token = 0123456789abcdef0123456789abcdef",
|
||||||
|
"full_plugin_name": "dns-hetzner"
|
||||||
|
},
|
||||||
|
"infomaniak": {
|
||||||
|
"name": "Infomaniak",
|
||||||
|
"package_name": "certbot-dns-infomaniak",
|
||||||
|
"version": "~=0.1.12",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||||
|
"full_plugin_name": "dns-infomaniak"
|
||||||
|
},
|
||||||
|
"inwx": {
|
||||||
|
"name": "INWX",
|
||||||
|
"package_name": "certbot-dns-inwx",
|
||||||
|
"version": "~=2.1.2",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_inwx_url = https://api.domrobot.com/xmlrpc/\ndns_inwx_username = your_username\ndns_inwx_password = your_password\ndns_inwx_shared_secret = your_shared_secret optional",
|
||||||
|
"full_plugin_name": "dns-inwx"
|
||||||
|
},
|
||||||
|
"ionos": {
|
||||||
|
"name": "IONOS",
|
||||||
|
"package_name": "certbot-dns-ionos",
|
||||||
|
"version": "==2022.11.24",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_ionos_prefix = myapikeyprefix\ndns_ionos_secret = verysecureapikeysecret\ndns_ionos_endpoint = https://api.hosting.ionos.com",
|
||||||
|
"full_plugin_name": "dns-ionos"
|
||||||
|
},
|
||||||
|
"ispconfig": {
|
||||||
|
"name": "ISPConfig",
|
||||||
|
"package_name": "certbot-dns-ispconfig",
|
||||||
|
"version": "~=0.2.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_ispconfig_username = myremoteuser\ndns_ispconfig_password = verysecureremoteuserpassword\ndns_ispconfig_endpoint = https://localhost:8080",
|
||||||
|
"full_plugin_name": "dns-ispconfig"
|
||||||
|
},
|
||||||
|
"isset": {
|
||||||
|
"name": "Isset",
|
||||||
|
"package_name": "certbot-dns-isset",
|
||||||
|
"version": "~=0.0.3",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_isset_endpoint=\"https://customer.isset.net/api\"\ndns_isset_token=\"<token>\"",
|
||||||
|
"full_plugin_name": "dns-isset"
|
||||||
|
},
|
||||||
|
"joker": {
|
||||||
|
"name": "Joker",
|
||||||
|
"package_name": "certbot-dns-joker",
|
||||||
|
"version": "~=1.1.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_joker_username = <Dynamic DNS Authentication Username>\ndns_joker_password = <Dynamic DNS Authentication Password>\ndns_joker_domain = <Dynamic DNS Domain>",
|
||||||
|
"full_plugin_name": "dns-joker"
|
||||||
|
},
|
||||||
|
"linode": {
|
||||||
|
"name": "Linode",
|
||||||
|
"package_name": "certbot-dns-linode",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64\ndns_linode_version = [<blank>|3|4]",
|
||||||
|
"full_plugin_name": "dns-linode"
|
||||||
|
},
|
||||||
|
"loopia": {
|
||||||
|
"name": "Loopia",
|
||||||
|
"package_name": "certbot-dns-loopia",
|
||||||
|
"version": "~=1.0.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_loopia_user = user@loopiaapi\ndns_loopia_password = abcdef0123456789abcdef01234567abcdef0123",
|
||||||
|
"full_plugin_name": "dns-loopia"
|
||||||
|
},
|
||||||
|
"luadns": {
|
||||||
|
"name": "LuaDNS",
|
||||||
|
"package_name": "certbot-dns-luadns",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_luadns_email = user@example.com\ndns_luadns_token = 0123456789abcdef0123456789abcdef",
|
||||||
|
"full_plugin_name": "dns-luadns"
|
||||||
|
},
|
||||||
|
"namecheap": {
|
||||||
|
"name": "Namecheap",
|
||||||
|
"package_name": "certbot-dns-namecheap",
|
||||||
|
"version": "~=1.0.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_namecheap_username = 123456\ndns_namecheap_api_key = 0123456789abcdef0123456789abcdef01234567",
|
||||||
|
"full_plugin_name": "dns-namecheap"
|
||||||
|
},
|
||||||
|
"netcup": {
|
||||||
|
"name": "netcup",
|
||||||
|
"package_name": "certbot-dns-netcup",
|
||||||
|
"version": "~=1.0.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_netcup_customer_id = 123456\ndns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567\ndns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123",
|
||||||
|
"full_plugin_name": "dns-netcup"
|
||||||
|
},
|
||||||
|
"njalla": {
|
||||||
|
"name": "Njalla",
|
||||||
|
"package_name": "certbot-dns-njalla",
|
||||||
|
"version": "~=1.0.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_njalla_token = 0123456789abcdef0123456789abcdef01234567",
|
||||||
|
"full_plugin_name": "dns-njalla"
|
||||||
|
},
|
||||||
|
"nsone": {
|
||||||
|
"name": "NS1",
|
||||||
|
"package_name": "certbot-dns-nsone",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw",
|
||||||
|
"full_plugin_name": "dns-nsone"
|
||||||
|
},
|
||||||
|
"oci": {
|
||||||
|
"name": "Oracle Cloud Infrastructure DNS",
|
||||||
|
"package_name": "certbot-dns-oci",
|
||||||
|
"version": "~=0.3.6",
|
||||||
|
"dependencies": "oci",
|
||||||
|
"credentials": "[DEFAULT]\nuser = ocid1.user.oc1...\nfingerprint = xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx\ntenancy = ocid1.tenancy.oc1...\nregion = us-ashburn-1\nkey_file = ~/.oci/oci_api_key.pem",
|
||||||
|
"full_plugin_name": "dns-oci"
|
||||||
|
},
|
||||||
|
"ovh": {
|
||||||
|
"name": "OVH",
|
||||||
|
"package_name": "certbot-dns-ovh",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "dns_ovh_endpoint = ovh-eu\ndns_ovh_application_key = MDAwMDAwMDAwMDAw\ndns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw\ndns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw",
|
||||||
|
"full_plugin_name": "dns-ovh"
|
||||||
|
},
|
||||||
|
"plesk": {
|
||||||
|
"name": "Plesk",
|
||||||
|
"package_name": "certbot-dns-plesk",
|
||||||
|
"version": "~=0.3.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_plesk_username = your-username\ndns_plesk_password = secret\ndns_plesk_api_url = https://plesk-api-host:8443",
|
||||||
|
"full_plugin_name": "dns-plesk"
|
||||||
|
},
|
||||||
|
"porkbun": {
|
||||||
|
"name": "Porkbun",
|
||||||
|
"package_name": "certbot-dns-porkbun",
|
||||||
|
"version": "~=0.2",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_porkbun_key=your-porkbun-api-key\ndns_porkbun_secret=your-porkbun-api-secret",
|
||||||
|
"full_plugin_name": "dns-porkbun"
|
||||||
|
},
|
||||||
|
"powerdns": {
|
||||||
|
"name": "PowerDNS",
|
||||||
|
"package_name": "certbot-dns-powerdns",
|
||||||
|
"version": "~=0.2.1",
|
||||||
|
"dependencies": "PyYAML==5.3.1",
|
||||||
|
"credentials": "dns_powerdns_api_url = https://api.mypowerdns.example.org\ndns_powerdns_api_key = AbCbASsd!@34",
|
||||||
|
"full_plugin_name": "dns-powerdns"
|
||||||
|
},
|
||||||
|
"regru": {
|
||||||
|
"name": "reg.ru",
|
||||||
|
"package_name": "certbot-regru",
|
||||||
|
"version": "~=1.0.2",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_username=username\ndns_password=password",
|
||||||
|
"full_plugin_name": "dns"
|
||||||
|
},
|
||||||
|
"rfc2136": {
|
||||||
|
"name": "RFC 2136",
|
||||||
|
"package_name": "certbot-dns-rfc2136",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "# Target DNS server\ndns_rfc2136_server = 192.0.2.1\n# Target DNS port\ndns_rfc2136_port = 53\n# TSIG key name\ndns_rfc2136_name = keyname.\n# TSIG key secret\ndns_rfc2136_secret = 4q4wM/2I180UXoMyN4INVhJNi8V9BCV+jMw2mXgZw/CSuxUT8C7NKKFs AmKd7ak51vWKgSl12ib86oQRPkpDjg==\n# TSIG key algorithm\ndns_rfc2136_algorithm = HMAC-SHA512",
|
||||||
|
"full_plugin_name": "dns-rfc2136"
|
||||||
|
},
|
||||||
|
"route53": {
|
||||||
|
"name": "Route 53 (Amazon)",
|
||||||
|
"package_name": "certbot-dns-route53",
|
||||||
|
"version": "=={{certbot-version}}",
|
||||||
|
"dependencies": "acme=={{certbot-version}}",
|
||||||
|
"credentials": "[default]\naws_access_key_id=AKIAIOSFODNN7EXAMPLE\naws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
||||||
|
"full_plugin_name": "dns-route53"
|
||||||
|
},
|
||||||
|
"strato": {
|
||||||
|
"name": "Strato",
|
||||||
|
"package_name": "certbot-dns-strato",
|
||||||
|
"version": "~=0.1.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_strato_username = user\ndns_strato_password = pass\n# uncomment if youre using two factor authentication:\n# dns_strato_totp_devicename = 2fa_device\n# dns_strato_totp_secret = 2fa_secret\n#\n# uncomment if domain name contains special characters\n# insert domain display name as seen on your account page here\n# dns_strato_domain_display_name = my-punicode-url.de\n#\n# if youre not using strato.de or another special endpoint you can customise it below\n# you will probably only need to adjust the host, but you can also change the complete endpoint url\n# dns_strato_custom_api_scheme = https\n# dns_strato_custom_api_host = www.strato.de\n# dns_strato_custom_api_port = 443\n# dns_strato_custom_api_path = \"/apps/CustomerService\"",
|
||||||
|
"full_plugin_name": "dns-strato"
|
||||||
|
},
|
||||||
|
"timeweb": {
|
||||||
|
"name": "Timeweb Cloud",
|
||||||
|
"package_name": "certbot-dns-timeweb",
|
||||||
|
"version": "~=1.0.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_timeweb_api_key = XXXXXXXXXXXXXXXXXXX",
|
||||||
|
"full_plugin_name": "dns-timeweb"
|
||||||
|
},
|
||||||
|
"transip": {
|
||||||
|
"name": "TransIP",
|
||||||
|
"package_name": "certbot-dns-transip",
|
||||||
|
"version": "~=0.4.3",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_transip_username = my_username\ndns_transip_key_file = /etc/letsencrypt/transip-rsa.key",
|
||||||
|
"full_plugin_name": "dns-transip"
|
||||||
|
},
|
||||||
|
"tencentcloud": {
|
||||||
|
"name": "Tencent Cloud",
|
||||||
|
"package_name": "certbot-dns-tencentcloud",
|
||||||
|
"version": "~=2.0.2",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_tencentcloud_secret_id = TENCENT_CLOUD_SECRET_ID\ndns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY",
|
||||||
|
"full_plugin_name": "dns-tencentcloud"
|
||||||
|
},
|
||||||
|
"vultr": {
|
||||||
|
"name": "Vultr",
|
||||||
|
"package_name": "certbot-dns-vultr",
|
||||||
|
"version": "~=1.1.0",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_vultr_key = YOUR_VULTR_API_KEY",
|
||||||
|
"full_plugin_name": "dns-vultr"
|
||||||
|
},
|
||||||
|
"websupport": {
|
||||||
|
"name": "Websupport.sk",
|
||||||
|
"package_name": "certbot-dns-websupport",
|
||||||
|
"version": "~=2.0.1",
|
||||||
|
"dependencies": "",
|
||||||
|
"credentials": "dns_websupport_identifier = <api_key>\ndns_websupport_secret_key = <secret>",
|
||||||
|
"full_plugin_name": "dns-websupport"
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,22 @@
|
|||||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
. "$DIR/../.common.sh"
|
. "$DIR/../.common.sh"
|
||||||
|
|
||||||
DOCKER_IMAGE=jc21/nginx-full:certbot-node
|
DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
|
||||||
|
|
||||||
# Ensure docker exists
|
# Ensure docker exists
|
||||||
if hash docker 2>/dev/null; then
|
if hash docker 2>/dev/null; then
|
||||||
docker pull "${DOCKER_IMAGE}"
|
docker pull "${DOCKER_IMAGE}"
|
||||||
cd "${DIR}/../.."
|
cd "${DIR}/../.."
|
||||||
echo -e "${BLUE}❯ ${CYAN}Building Frontend ...${RESET}"
|
echo -e "${BLUE}❯ ${CYAN}Building Frontend ...${RESET}"
|
||||||
docker run --rm -e CI=true -v "$(pwd)/frontend:/app/frontend" -v "$(pwd)/global:/app/global" -w /app/frontend "$DOCKER_IMAGE" sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
|
|
||||||
|
docker run --rm \
|
||||||
|
-e CI=true \
|
||||||
|
-e NODE_OPTIONS=--openssl-legacy-provider \
|
||||||
|
-v "$(pwd)/frontend:/app/frontend" \
|
||||||
|
-v "$(pwd)/global:/app/global" \
|
||||||
|
-w /app/frontend "$DOCKER_IMAGE" \
|
||||||
|
sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
|
||||||
|
|
||||||
echo -e "${BLUE}❯ ${GREEN}Building Frontend Complete${RESET}"
|
echo -e "${BLUE}❯ ${GREEN}Building Frontend Complete${RESET}"
|
||||||
else
|
else
|
||||||
echo -e "${RED}❯ docker command is not available${RESET}"
|
echo -e "${RED}❯ docker command is not available${RESET}"
|
||||||
|
@ -1,23 +1,31 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
|
|
||||||
DOCKER_IMAGE=jc21/nginx-full:certbot-node
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
. "$DIR/../.common.sh"
|
||||||
|
|
||||||
|
DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
|
||||||
docker pull "${DOCKER_IMAGE}"
|
docker pull "${DOCKER_IMAGE}"
|
||||||
|
|
||||||
# Test
|
# Test
|
||||||
|
echo -e "${BLUE}❯ ${CYAN}Testing backend ...${RESET}"
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v "$(pwd)/backend:/app" \
|
-v "$(pwd)/backend:/app" \
|
||||||
-v "$(pwd)/global:/app/global" \
|
-v "$(pwd)/global:/app/global" \
|
||||||
-w /app \
|
-w /app \
|
||||||
"${DOCKER_IMAGE}" \
|
"${DOCKER_IMAGE}" \
|
||||||
sh -c 'yarn install && yarn eslint . && rm -rf node_modules'
|
sh -c 'yarn install && yarn eslint . && rm -rf node_modules'
|
||||||
|
echo -e "${BLUE}❯ ${GREEN}Testing Complete${RESET}"
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
docker build --pull --no-cache --squash --compress \
|
echo -e "${BLUE}❯ ${CYAN}Building ...${RESET}"
|
||||||
|
docker build --pull --no-cache --compress \
|
||||||
-t "${IMAGE}:ci-${BUILD_NUMBER}" \
|
-t "${IMAGE}:ci-${BUILD_NUMBER}" \
|
||||||
-f docker/Dockerfile \
|
-f docker/Dockerfile \
|
||||||
|
--progress=plain \
|
||||||
--build-arg TARGETPLATFORM=linux/amd64 \
|
--build-arg TARGETPLATFORM=linux/amd64 \
|
||||||
--build-arg BUILDPLATFORM=linux/amd64 \
|
--build-arg BUILDPLATFORM=linux/amd64 \
|
||||||
--build-arg BUILD_VERSION="${BUILD_VERSION}" \
|
--build-arg BUILD_VERSION="${BUILD_VERSION}" \
|
||||||
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \
|
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \
|
||||||
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \
|
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \
|
||||||
.
|
.
|
||||||
|
echo -e "${BLUE}❯ ${GREEN}Building Complete${RESET}"
|
||||||
|
@ -7,7 +7,7 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
if hash docker 2>/dev/null; then
|
if hash docker 2>/dev/null; then
|
||||||
cd "${DIR}/.."
|
cd "${DIR}/.."
|
||||||
echo -e "${BLUE}❯ ${CYAN}Building Docs ...${RESET}"
|
echo -e "${BLUE}❯ ${CYAN}Building Docs ...${RESET}"
|
||||||
docker run --rm -e CI=true -v "$(pwd)/docs:/app/docs" -w /app/docs node:alpine sh -c "yarn install && yarn build && chown -R $(id -u):$(id -g) /app/docs"
|
docker run --rm -e CI=true -v "$(pwd)/docs:/app/docs" -w /app/docs node:alpine sh -c "yarn set version berry && yarn install && yarn build && chown -R $(id -u):$(id -g) /app/docs"
|
||||||
echo -e "${BLUE}❯ ${GREEN}Building Docs Complete${RESET}"
|
echo -e "${BLUE}❯ ${GREEN}Building Docs Complete${RESET}"
|
||||||
else
|
else
|
||||||
echo -e "${RED}❯ docker command is not available${RESET}"
|
echo -e "${RED}❯ docker command is not available${RESET}"
|
||||||
|
50
test/cypress/integration/api/Hosts.spec.js
Normal file
50
test/cypress/integration/api/Hosts.spec.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/// <reference types="Cypress" />
|
||||||
|
|
||||||
|
describe('Hosts endpoints', () => {
|
||||||
|
let token;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
cy.getToken().then((tok) => {
|
||||||
|
token = tok;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to create a http host', function() {
|
||||||
|
cy.task('backendApiPost', {
|
||||||
|
token: token,
|
||||||
|
path: '/api/nginx/proxy-hosts',
|
||||||
|
data: {
|
||||||
|
domain_names: ['test.example.com'],
|
||||||
|
forward_scheme: 'http',
|
||||||
|
forward_host: '1.1.1.1',
|
||||||
|
forward_port: 80,
|
||||||
|
access_list_id: '0',
|
||||||
|
certificate_id: 0,
|
||||||
|
meta: {
|
||||||
|
letsencrypt_agree: false,
|
||||||
|
dns_challenge: false
|
||||||
|
},
|
||||||
|
advanced_config: '',
|
||||||
|
locations: [],
|
||||||
|
block_exploits: false,
|
||||||
|
caching_enabled: false,
|
||||||
|
allow_websocket_upgrade: false,
|
||||||
|
enable_proxy_protocol: false,
|
||||||
|
load_balancer_ip: '',
|
||||||
|
http2_support: false,
|
||||||
|
hsts_enabled: false,
|
||||||
|
hsts_subdomains: false,
|
||||||
|
ssl_forced: false
|
||||||
|
}
|
||||||
|
}).then((data) => {
|
||||||
|
cy.validateSwaggerSchema('post', 201, '/nginx/proxy-hosts', data);
|
||||||
|
expect(data).to.have.property('id');
|
||||||
|
expect(data.id).to.be.greaterThan(0);
|
||||||
|
expect(data).to.have.property('enabled');
|
||||||
|
expect(data.enabled).to.be.greaterThan(0);
|
||||||
|
expect(data).to.have.property('meta');
|
||||||
|
expect(typeof data.meta.nginx_online).to.be.equal('undefined');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -126,7 +126,7 @@ BackendApi.prototype._putPostJson = function(fn, path, data, returnOnError) {
|
|||||||
logger('Response data:', data);
|
logger('Response data:', data);
|
||||||
if (!returnOnError && data instanceof Error) {
|
if (!returnOnError && data instanceof Error) {
|
||||||
reject(data);
|
reject(data);
|
||||||
} else if (!returnOnError && response.statusCode != 200) {
|
} else if (!returnOnError && (response.statusCode < 200 || response.statusCode >= 300)) {
|
||||||
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
|
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
|
||||||
reject(new Error(data.error.code + ': ' + data.error.message));
|
reject(new Error(data.error.code + ': ' + data.error.message));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2061,15 +2061,10 @@ sax@0.5.x:
|
|||||||
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
|
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
|
||||||
integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=
|
integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=
|
||||||
|
|
||||||
semver@^7.2.1:
|
semver@^7.2.1, semver@^7.3.2:
|
||||||
version "7.3.2"
|
version "7.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||||
|
|
||||||
semver@^7.3.2:
|
|
||||||
version "7.3.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
|
|
||||||
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
lru-cache "^6.0.0"
|
lru-cache "^6.0.0"
|
||||||
|
|
||||||
@ -2450,9 +2445,9 @@ wide-align@1.1.3:
|
|||||||
string-width "^1.0.2 || 2"
|
string-width "^1.0.2 || 2"
|
||||||
|
|
||||||
word-wrap@^1.2.3, word-wrap@~1.2.3:
|
word-wrap@^1.2.3, word-wrap@~1.2.3:
|
||||||
version "1.2.3"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
|
||||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
|
||||||
|
|
||||||
workerpool@6.0.0:
|
workerpool@6.0.0:
|
||||||
version "6.0.0"
|
version "6.0.0"
|
||||||
|
Reference in New Issue
Block a user