Compare commits
	
		
			18 Commits
		
	
	
		
			v2.11.2
			...
			51414ced3a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					51414ced3a | ||
| 
						 | 
					5e35e538af | ||
| 
						 | 
					13fec42d1f | ||
| 
						 | 
					b4560d7dde | ||
| 
						 | 
					d3a654b546 | ||
| 
						 | 
					bed387ebd4 | ||
| 
						 | 
					6ac9a82279 | ||
| 
						 | 
					3754a569ba | ||
| 
						 | 
					b383f46656 | ||
| 
						 | 
					516b4d991c | ||
| 
						 | 
					8d80af3a26 | ||
| 
						 | 
					1f45e6a5e9 | ||
| 
						 | 
					dcb9628c36 | ||
| 
						 | 
					029b184398 | ||
| 
						 | 
					2422587530 | ||
| 
						 | 
					4ee940d3dc | ||
| 
						 | 
					47dddc548b | ||
| 
						 | 
					280bac8b43 | 
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -3,3 +3,7 @@
 | 
				
			|||||||
._*
 | 
					._*
 | 
				
			||||||
.vscode
 | 
					.vscode
 | 
				
			||||||
certbot-help.txt
 | 
					certbot-help.txt
 | 
				
			||||||
 | 
					test/node_modules
 | 
				
			||||||
 | 
					*/node_modules
 | 
				
			||||||
 | 
					docker/dev/dnsrouter-config.json.tmp
 | 
				
			||||||
 | 
					docker/dev/resolv.conf
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										124
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -18,10 +18,8 @@ pipeline {
 | 
				
			|||||||
		BUILD_VERSION              = getVersion()
 | 
							BUILD_VERSION              = getVersion()
 | 
				
			||||||
		MAJOR_VERSION              = '2'
 | 
							MAJOR_VERSION              = '2'
 | 
				
			||||||
		BRANCH_LOWER               = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
 | 
							BRANCH_LOWER               = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
 | 
				
			||||||
		COMPOSE_PROJECT_NAME       = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
 | 
							BUILDX_NAME                = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
 | 
				
			||||||
		COMPOSE_FILE               = 'docker/docker-compose.ci.yml'
 | 
					 | 
				
			||||||
		COMPOSE_INTERACTIVE_NO_CLI = 1
 | 
							COMPOSE_INTERACTIVE_NO_CLI = 1
 | 
				
			||||||
		BUILDX_NAME                = "${COMPOSE_PROJECT_NAME}"
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	stages {
 | 
						stages {
 | 
				
			||||||
		stage('Environment') {
 | 
							stage('Environment') {
 | 
				
			||||||
@@ -92,81 +90,63 @@ pipeline {
 | 
				
			|||||||
							sh 'yarn install'
 | 
												sh 'yarn install'
 | 
				
			||||||
							sh 'yarn build'
 | 
												sh 'yarn build'
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						dir(path: 'docs/.vuepress/dist') {
 | 
					 | 
				
			||||||
							sh 'tar -czf ../../docs.tgz *'
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
						archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				stage('Cypress') {
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							stage('Test Sqlite') {
 | 
				
			||||||
 | 
								environment {
 | 
				
			||||||
 | 
									COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_sqlite"
 | 
				
			||||||
 | 
									COMPOSE_FILE         = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.sqlite.yml'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								when {
 | 
				
			||||||
 | 
									not {
 | 
				
			||||||
 | 
										equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			steps {
 | 
								steps {
 | 
				
			||||||
						// Creating will also create the network prior to
 | 
									sh 'rm -rf ./test/results/junit/*'
 | 
				
			||||||
						// using it in parallel stages below and mitigating
 | 
									sh './scripts/ci/fulltest-cypress'
 | 
				
			||||||
						// 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'
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		stage('Integration Tests') {
 | 
					 | 
				
			||||||
			parallel {
 | 
					 | 
				
			||||||
				stage('Sqlite') {
 | 
					 | 
				
			||||||
					steps {
 | 
					 | 
				
			||||||
						// 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
 | 
					 | 
				
			||||||
						sh 'rm -rf test/results-sqlite'
 | 
					 | 
				
			||||||
						sh 'docker-compose up cypress-sqlite'
 | 
					 | 
				
			||||||
						// Get results
 | 
					 | 
				
			||||||
						sh 'docker cp -L "$(docker-compose ps --all -q cypress-sqlite):/test/results" test/results-sqlite'
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			post {
 | 
								post {
 | 
				
			||||||
				always {
 | 
									always {
 | 
				
			||||||
					// Dumps to analyze later
 | 
										// Dumps to analyze later
 | 
				
			||||||
					sh 'mkdir -p debug/sqlite'
 | 
										sh 'mkdir -p debug/sqlite'
 | 
				
			||||||
							sh 'docker-compose logs fullstack-sqlite > debug/sqlite/docker_fullstack_sqlite.log'
 | 
										sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/sqlite/docker_fullstack.log 2>&1'
 | 
				
			||||||
							// Cypress videos and screenshot artifacts
 | 
										sh 'docker logs $(docker-compose ps --all -q stepca) > debug/sqlite/docker_stepca.log 2>&1'
 | 
				
			||||||
							dir(path: 'test/results-sqlite') {
 | 
										sh 'docker logs $(docker-compose ps --all -q pdns) > debug/sqlite/docker_pdns.log 2>&1'
 | 
				
			||||||
								archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
 | 
										sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/sqlite/docker_pdns-db.log 2>&1'
 | 
				
			||||||
							}
 | 
										sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/sqlite/docker_dnsrouter.log 2>&1'
 | 
				
			||||||
							junit 'test/results-sqlite/junit/*'
 | 
										junit 'test/results/junit/*'
 | 
				
			||||||
 | 
										sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
				stage('Mysql') {
 | 
							stage('Test Mysql') {
 | 
				
			||||||
 | 
								environment {
 | 
				
			||||||
 | 
									COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_mysql"
 | 
				
			||||||
 | 
									COMPOSE_FILE         = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.mysql.yml'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								when {
 | 
				
			||||||
 | 
									not {
 | 
				
			||||||
 | 
										equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			steps {
 | 
								steps {
 | 
				
			||||||
						// Bring up a stack
 | 
									sh 'rm -rf ./test/results/junit/*'
 | 
				
			||||||
						sh 'docker-compose up -d fullstack-mysql'
 | 
									sh './scripts/ci/fulltest-cypress'
 | 
				
			||||||
						sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-mysql) 120'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						// Run tests
 | 
					 | 
				
			||||||
						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 {
 | 
								post {
 | 
				
			||||||
				always {
 | 
									always {
 | 
				
			||||||
					// Dumps to analyze later
 | 
										// Dumps to analyze later
 | 
				
			||||||
					sh 'mkdir -p debug/mysql'
 | 
										sh 'mkdir -p debug/mysql'
 | 
				
			||||||
							sh 'docker-compose logs fullstack-mysql > debug/mysql/docker_fullstack_mysql.log'
 | 
										sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/mysql/docker_fullstack.log 2>&1'
 | 
				
			||||||
							sh 'docker-compose logs db > debug/mysql/docker_db.log'
 | 
										sh 'docker logs $(docker-compose ps --all -q stepca) > debug/mysql/docker_stepca.log 2>&1'
 | 
				
			||||||
							// Cypress videos and screenshot artifacts
 | 
										sh 'docker logs $(docker-compose ps --all -q pdns) > debug/mysql/docker_pdns.log 2>&1'
 | 
				
			||||||
							dir(path: 'test/results-mysql') {
 | 
										sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/mysql/docker_pdns-db.log 2>&1'
 | 
				
			||||||
								archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
 | 
										sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/mysql/docker_dnsrouter.log 2>&1'
 | 
				
			||||||
							}
 | 
										junit 'test/results/junit/*'
 | 
				
			||||||
							junit 'test/results-mysql/junit/*'
 | 
										sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -185,30 +165,17 @@ pipeline {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		stage('Docs / Comment') {
 | 
							stage('Docs / Comment') {
 | 
				
			||||||
			parallel {
 | 
								parallel {
 | 
				
			||||||
				stage('Master Docs') {
 | 
									stage('Docs Job') {
 | 
				
			||||||
					when {
 | 
										when {
 | 
				
			||||||
						allOf {
 | 
											allOf {
 | 
				
			||||||
							branch 'master'
 | 
												branch pattern: "^(develop|master)\$", comparator: "REGEXP"
 | 
				
			||||||
							not {
 | 
												not {
 | 
				
			||||||
								equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
													equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					steps {
 | 
										steps {
 | 
				
			||||||
						npmDocsReleaseMaster()
 | 
											build wait: false, job: 'nginx-proxy-manager-docs', parameters: [string(name: 'docs_branch', value: "$BRANCH_NAME")]
 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				stage('Develop Docs') {
 | 
					 | 
				
			||||||
					when {
 | 
					 | 
				
			||||||
						allOf {
 | 
					 | 
				
			||||||
							branch 'develop'
 | 
					 | 
				
			||||||
							not {
 | 
					 | 
				
			||||||
								equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
					 | 
				
			||||||
							}
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					steps {
 | 
					 | 
				
			||||||
						npmDocsReleaseDevelop()
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				stage('PR Comment') {
 | 
									stage('PR Comment') {
 | 
				
			||||||
@@ -231,9 +198,8 @@ pipeline {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	post {
 | 
						post {
 | 
				
			||||||
		always {
 | 
							always {
 | 
				
			||||||
			sh 'docker-compose down --remove-orphans --volumes -t 30'
 | 
					 | 
				
			||||||
			sh 'echo Reverting ownership'
 | 
								sh 'echo Reverting ownership'
 | 
				
			||||||
			sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
 | 
								sh 'docker run --rm -v "$(pwd):/data" jc21/ci-tools chown -R "$(id -u):$(id -g)" /data'
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		success {
 | 
							success {
 | 
				
			||||||
			juxtapose event: 'success'
 | 
								juxtapose event: 'success'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
  location {{ path }} {
 | 
					  location {{ path }} {
 | 
				
			||||||
 | 
					    {{ advanced_config }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proxy_set_header Host $host;
 | 
					    proxy_set_header Host $host;
 | 
				
			||||||
    proxy_set_header X-Forwarded-Scheme $scheme;
 | 
					    proxy_set_header X-Forwarded-Scheme $scheme;
 | 
				
			||||||
    proxy_set_header X-Forwarded-Proto  $scheme;
 | 
					    proxy_set_header X-Forwarded-Proto  $scheme;
 | 
				
			||||||
@@ -17,8 +19,5 @@
 | 
				
			|||||||
    proxy_set_header Connection $http_connection;
 | 
					    proxy_set_header Connection $http_connection;
 | 
				
			||||||
    proxy_http_version 1.1;
 | 
					    proxy_http_version 1.1;
 | 
				
			||||||
    {% endif %}
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    {{ advanced_config }}
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								docker/dev/dnsrouter-config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "log": {
 | 
				
			||||||
 | 
					        "format": "nice",
 | 
				
			||||||
 | 
					        "level": "debug"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "servers": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            "host": "0.0.0.0",
 | 
				
			||||||
 | 
					            "port": 53,
 | 
				
			||||||
 | 
					            "upstreams": [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "regex": "website[0-9]+.example\\.com",
 | 
				
			||||||
 | 
					                    "upstream": "127.0.0.11"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "regex": ".*\\.example\\.com",
 | 
				
			||||||
 | 
					                    "upstream": "1.1.1.1"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    "regex": "local",
 | 
				
			||||||
 | 
					                    "nxdomain": true
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "internal": null,
 | 
				
			||||||
 | 
					            "default_upstream": "127.0.0.11"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								docker/dev/letsencrypt.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					text = True
 | 
				
			||||||
 | 
					non-interactive = True
 | 
				
			||||||
 | 
					webroot-path = /data/letsencrypt-acme-challenge
 | 
				
			||||||
 | 
					key-type = ecdsa
 | 
				
			||||||
 | 
					elliptic-curve = secp384r1
 | 
				
			||||||
 | 
					preferred-chain = ISRG Root X1
 | 
				
			||||||
 | 
					server =
 | 
				
			||||||
							
								
								
									
										255
									
								
								docker/dev/pdns-db.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,255 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					How this was generated:
 | 
				
			||||||
 | 
					1. bring up an empty pdns stack
 | 
				
			||||||
 | 
					2. use api to create a zone ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					curl -X POST \
 | 
				
			||||||
 | 
					  'http://npm.dev:8081/api/v1/servers/localhost/zones' \
 | 
				
			||||||
 | 
					  --header 'X-API-Key: npm' \
 | 
				
			||||||
 | 
					  --header 'Content-Type: application/json' \
 | 
				
			||||||
 | 
					  --data-raw '{
 | 
				
			||||||
 | 
					  "name": "example.com.",
 | 
				
			||||||
 | 
					  "kind": "Native",
 | 
				
			||||||
 | 
					  "masters": [],
 | 
				
			||||||
 | 
					  "nameservers": [
 | 
				
			||||||
 | 
					    "ns1.pdns.",
 | 
				
			||||||
 | 
					    "ns2.pdns."
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. Dump sql:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					docker exec -ti npm.pdns.db mysqldump -u pdns -p pdns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					----------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
 | 
				
			||||||
 | 
					/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
 | 
				
			||||||
 | 
					/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
 | 
				
			||||||
 | 
					/*!40101 SET NAMES utf8mb4 */;
 | 
				
			||||||
 | 
					/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
 | 
				
			||||||
 | 
					/*!40103 SET TIME_ZONE='+00:00' */;
 | 
				
			||||||
 | 
					/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
 | 
				
			||||||
 | 
					/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
 | 
				
			||||||
 | 
					/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
 | 
				
			||||||
 | 
					/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `comments`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `comments`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `comments` (
 | 
				
			||||||
 | 
					  `id` int(11) NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `domain_id` int(11) NOT NULL,
 | 
				
			||||||
 | 
					  `name` varchar(255) NOT NULL,
 | 
				
			||||||
 | 
					  `type` varchar(10) NOT NULL,
 | 
				
			||||||
 | 
					  `modified_at` int(11) NOT NULL,
 | 
				
			||||||
 | 
					  `account` varchar(40) CHARACTER SET utf8mb3 DEFAULT NULL,
 | 
				
			||||||
 | 
					  `comment` text CHARACTER SET utf8mb3 NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  KEY `comments_name_type_idx` (`name`,`type`),
 | 
				
			||||||
 | 
					  KEY `comments_order_idx` (`domain_id`,`modified_at`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `comments`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `comments` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `comments` DISABLE KEYS */;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `comments` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `cryptokeys`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `cryptokeys`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `cryptokeys` (
 | 
				
			||||||
 | 
					  `id` int(11) NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `domain_id` int(11) NOT NULL,
 | 
				
			||||||
 | 
					  `flags` int(11) NOT NULL,
 | 
				
			||||||
 | 
					  `active` tinyint(1) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `published` tinyint(1) DEFAULT 1,
 | 
				
			||||||
 | 
					  `content` text DEFAULT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  KEY `domainidindex` (`domain_id`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `cryptokeys`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `cryptokeys` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `cryptokeys` DISABLE KEYS */;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `cryptokeys` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `domainmetadata`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `domainmetadata`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `domainmetadata` (
 | 
				
			||||||
 | 
					  `id` int(11) NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `domain_id` int(11) NOT NULL,
 | 
				
			||||||
 | 
					  `kind` varchar(32) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `content` text DEFAULT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  KEY `domainmetadata_idx` (`domain_id`,`kind`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `domainmetadata`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `domainmetadata` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `domainmetadata` DISABLE KEYS */;
 | 
				
			||||||
 | 
					INSERT INTO `domainmetadata` VALUES
 | 
				
			||||||
 | 
					(1,1,'SOA-EDIT-API','DEFAULT');
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `domainmetadata` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `domains`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `domains`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `domains` (
 | 
				
			||||||
 | 
					  `id` int(11) NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `name` varchar(255) NOT NULL,
 | 
				
			||||||
 | 
					  `master` varchar(128) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `last_check` int(11) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `type` varchar(8) NOT NULL,
 | 
				
			||||||
 | 
					  `notified_serial` int(10) unsigned DEFAULT NULL,
 | 
				
			||||||
 | 
					  `account` varchar(40) CHARACTER SET utf8mb3 DEFAULT NULL,
 | 
				
			||||||
 | 
					  `options` varchar(64000) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `catalog` varchar(255) DEFAULT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  UNIQUE KEY `name_index` (`name`),
 | 
				
			||||||
 | 
					  KEY `catalog_idx` (`catalog`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `domains`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `domains` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `domains` DISABLE KEYS */;
 | 
				
			||||||
 | 
					INSERT INTO `domains` VALUES
 | 
				
			||||||
 | 
					(1,'example.com','',NULL,'NATIVE',NULL,'',NULL,NULL);
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `domains` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `records`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `records`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `records` (
 | 
				
			||||||
 | 
					  `id` bigint(20) NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `domain_id` int(11) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `name` varchar(255) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `type` varchar(10) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `content` varchar(64000) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `ttl` int(11) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `prio` int(11) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `disabled` tinyint(1) DEFAULT 0,
 | 
				
			||||||
 | 
					  `ordername` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
 | 
				
			||||||
 | 
					  `auth` tinyint(1) DEFAULT 1,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  KEY `nametype_index` (`name`,`type`),
 | 
				
			||||||
 | 
					  KEY `domain_id` (`domain_id`),
 | 
				
			||||||
 | 
					  KEY `ordername` (`ordername`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `records`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `records` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `records` DISABLE KEYS */;
 | 
				
			||||||
 | 
					INSERT INTO `records` VALUES
 | 
				
			||||||
 | 
					(1,1,'example.com','NS','ns1.pdns',1500,0,0,NULL,1),
 | 
				
			||||||
 | 
					(2,1,'example.com','NS','ns2.pdns',1500,0,0,NULL,1),
 | 
				
			||||||
 | 
					(3,1,'example.com','SOA','a.misconfigured.dns.server.invalid hostmaster.example.com 2023030501 10800 3600 604800 3600',1500,0,0,NULL,1);
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `records` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `supermasters`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `supermasters`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `supermasters` (
 | 
				
			||||||
 | 
					  `ip` varchar(64) NOT NULL,
 | 
				
			||||||
 | 
					  `nameserver` varchar(255) NOT NULL,
 | 
				
			||||||
 | 
					  `account` varchar(40) CHARACTER SET utf8mb3 NOT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`ip`,`nameserver`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `supermasters`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `supermasters` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `supermasters` DISABLE KEYS */;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `supermasters` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Table structure for table `tsigkeys`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `tsigkeys`;
 | 
				
			||||||
 | 
					/*!40101 SET @saved_cs_client     = @@character_set_client */;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = utf8 */;
 | 
				
			||||||
 | 
					CREATE TABLE `tsigkeys` (
 | 
				
			||||||
 | 
					  `id` int(11) NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
 | 
					  `name` varchar(255) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `algorithm` varchar(50) DEFAULT NULL,
 | 
				
			||||||
 | 
					  `secret` varchar(255) DEFAULT NULL,
 | 
				
			||||||
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
 | 
					  UNIQUE KEY `namealgoindex` (`name`,`algorithm`)
 | 
				
			||||||
 | 
					) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 | 
				
			||||||
 | 
					/*!40101 SET character_set_client = @saved_cs_client */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					-- Dumping data for table `tsigkeys`
 | 
				
			||||||
 | 
					--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOCK TABLES `tsigkeys` WRITE;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `tsigkeys` DISABLE KEYS */;
 | 
				
			||||||
 | 
					/*!40000 ALTER TABLE `tsigkeys` ENABLE KEYS */;
 | 
				
			||||||
 | 
					UNLOCK TABLES;
 | 
				
			||||||
 | 
					/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 | 
				
			||||||
 | 
					/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
 | 
				
			||||||
 | 
					/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
 | 
				
			||||||
 | 
					/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 | 
				
			||||||
 | 
					/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
 | 
				
			||||||
 | 
					/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 | 
				
			||||||
 | 
					/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 | 
				
			||||||
							
								
								
									
										12
									
								
								docker/dev/pebble-config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
						"pebble": {
 | 
				
			||||||
 | 
							"listenAddress": "0.0.0.0:443",
 | 
				
			||||||
 | 
							"managementListenAddress": "0.0.0.0:15000",
 | 
				
			||||||
 | 
							"certificate": "test/certs/localhost/cert.pem",
 | 
				
			||||||
 | 
							"privateKey": "test/certs/localhost/key.pem",
 | 
				
			||||||
 | 
							"httpPort": 80,
 | 
				
			||||||
 | 
							"tlsPort": 443,
 | 
				
			||||||
 | 
							"ocspResponderURL": "",
 | 
				
			||||||
 | 
							"externalAccountBindingRequired": false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								docker/docker-compose.ci.mysql.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fullstack:
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      DB_MYSQL_HOST: 'db-mysql'
 | 
				
			||||||
 | 
					      DB_MYSQL_PORT: '3306'
 | 
				
			||||||
 | 
					      DB_MYSQL_USER: 'npm'
 | 
				
			||||||
 | 
					      DB_MYSQL_PASSWORD: 'npmpass'
 | 
				
			||||||
 | 
					      DB_MYSQL_NAME: 'npm'
 | 
				
			||||||
 | 
					    depends_on:
 | 
				
			||||||
 | 
					      - db-mysql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  db-mysql:
 | 
				
			||||||
 | 
					    image: jc21/mariadb-aria
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      MYSQL_ROOT_PASSWORD: 'npm'
 | 
				
			||||||
 | 
					      MYSQL_DATABASE: 'npm'
 | 
				
			||||||
 | 
					      MYSQL_USER: 'npm'
 | 
				
			||||||
 | 
					      MYSQL_PASSWORD: 'npmpass'
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - mysql_vol:/var/lib/mysql
 | 
				
			||||||
 | 
					    networks:
 | 
				
			||||||
 | 
					      - fulltest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					volumes:
 | 
				
			||||||
 | 
					  mysql_vol:
 | 
				
			||||||
							
								
								
									
										9
									
								
								docker/docker-compose.ci.sqlite.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fullstack:
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      DB_SQLITE_FILE: '/data/mydb.sqlite'
 | 
				
			||||||
 | 
					      PUID: 1000
 | 
				
			||||||
 | 
					      PGID: 1000
 | 
				
			||||||
 | 
					      DISABLE_IPV6: 'true'
 | 
				
			||||||
@@ -1,91 +1,110 @@
 | 
				
			|||||||
# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
 | 
					# WARNING: This is a CI docker-compose file used for building
 | 
				
			||||||
version: '3.8'
 | 
					# and testing of the entire app, it should not be used for production.
 | 
				
			||||||
 | 
					# This is a base compose file, it should be extended with a
 | 
				
			||||||
 | 
					# docker-compose.ci.*.yml file
 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fullstack-mysql:
 | 
					  fullstack:
 | 
				
			||||||
    image: "${IMAGE}:ci-${BUILD_NUMBER}"
 | 
					    image: "${IMAGE}:${BRANCH_LOWER}-ci-${BUILD_NUMBER}"
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      DEBUG: 'true'
 | 
					      DEBUG: 'true'
 | 
				
			||||||
      LE_STAGING: 'true'
 | 
					 | 
				
			||||||
      FORCE_COLOR: 1
 | 
					      FORCE_COLOR: 1
 | 
				
			||||||
      DB_MYSQL_HOST: 'db'
 | 
					 | 
				
			||||||
      DB_MYSQL_PORT: '3306'
 | 
					 | 
				
			||||||
      DB_MYSQL_USER: 'npm'
 | 
					 | 
				
			||||||
      DB_MYSQL_PASSWORD: 'npm'
 | 
					 | 
				
			||||||
      DB_MYSQL_NAME: 'npm'
 | 
					 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - npm_data_mysql:/data
 | 
					      - 'npm_data_ci:/data'
 | 
				
			||||||
      - npm_le_mysql:/etc/letsencrypt
 | 
					      - 'npm_le_ci:/etc/letsencrypt'
 | 
				
			||||||
    expose:
 | 
					      - './dev/letsencrypt.ini:/etc/letsencrypt.ini:ro'
 | 
				
			||||||
      - 81
 | 
					      - './dev/resolv.conf:/etc/resolv.conf:ro'
 | 
				
			||||||
      - 80
 | 
					      - '/etc/localtime:/etc/localtime:ro'
 | 
				
			||||||
      - 443
 | 
					    healthcheck:
 | 
				
			||||||
 | 
					      test: ["CMD", "/usr/bin/check-health"]
 | 
				
			||||||
 | 
					      interval: 10s
 | 
				
			||||||
 | 
					      timeout: 3s
 | 
				
			||||||
 | 
					    networks:
 | 
				
			||||||
 | 
					      fulltest:
 | 
				
			||||||
 | 
					        aliases:
 | 
				
			||||||
 | 
					          - website1.example.com
 | 
				
			||||||
 | 
					          - website2.example.com
 | 
				
			||||||
 | 
					          - website3.example.com
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  stepca:
 | 
				
			||||||
 | 
					    image: jc21/testca
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - './dev/resolv.conf:/etc/resolv.conf:ro'
 | 
				
			||||||
 | 
					      - '/etc/localtime:/etc/localtime:ro'
 | 
				
			||||||
 | 
					    networks:
 | 
				
			||||||
 | 
					      fulltest:
 | 
				
			||||||
 | 
					        aliases:
 | 
				
			||||||
 | 
					          - ca.internal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pdns:
 | 
				
			||||||
 | 
					    image: pschiffe/pdns-mysql
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - '/etc/localtime:/etc/localtime:ro'
 | 
				
			||||||
 | 
					    environment:
 | 
				
			||||||
 | 
					      PDNS_master: 'yes'
 | 
				
			||||||
 | 
					      PDNS_api: 'yes'
 | 
				
			||||||
 | 
					      PDNS_api_key: 'npm'
 | 
				
			||||||
 | 
					      PDNS_webserver: 'yes'
 | 
				
			||||||
 | 
					      PDNS_webserver_address: '0.0.0.0'
 | 
				
			||||||
 | 
					      PDNS_webserver_password: 'npm'
 | 
				
			||||||
 | 
					      PDNS_webserver-allow-from: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
 | 
				
			||||||
 | 
					      PDNS_version_string: 'anonymous'
 | 
				
			||||||
 | 
					      PDNS_default_ttl: 1500
 | 
				
			||||||
 | 
					      PDNS_allow_axfr_ips: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
 | 
				
			||||||
 | 
					      PDNS_gmysql_host: pdns-db
 | 
				
			||||||
 | 
					      PDNS_gmysql_port: 3306
 | 
				
			||||||
 | 
					      PDNS_gmysql_user: pdns
 | 
				
			||||||
 | 
					      PDNS_gmysql_password: pdns
 | 
				
			||||||
 | 
					      PDNS_gmysql_dbname: pdns
 | 
				
			||||||
    depends_on:
 | 
					    depends_on:
 | 
				
			||||||
      - db
 | 
					      - pdns-db
 | 
				
			||||||
    healthcheck:
 | 
					    networks:
 | 
				
			||||||
      test: ["CMD", "/usr/bin/check-health"]
 | 
					      fulltest:
 | 
				
			||||||
      interval: 10s
 | 
					        aliases:
 | 
				
			||||||
      timeout: 3s
 | 
					          - ns1.pdns
 | 
				
			||||||
 | 
					          - ns2.pdns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fullstack-sqlite:
 | 
					  pdns-db:
 | 
				
			||||||
    image: "${IMAGE}:ci-${BUILD_NUMBER}"
 | 
					    image: mariadb
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      DEBUG: 'true'
 | 
					      MYSQL_ROOT_PASSWORD: 'pdns'
 | 
				
			||||||
      LE_STAGING: 'true'
 | 
					      MYSQL_DATABASE: 'pdns'
 | 
				
			||||||
      FORCE_COLOR: 1
 | 
					      MYSQL_USER: 'pdns'
 | 
				
			||||||
      DB_SQLITE_FILE: '/data/mydb.sqlite'
 | 
					      MYSQL_PASSWORD: 'pdns'
 | 
				
			||||||
      PUID: 1000
 | 
					 | 
				
			||||||
      PGID: 1000
 | 
					 | 
				
			||||||
      DISABLE_IPV6: 'true'
 | 
					 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - npm_data_sqlite:/data
 | 
					      - 'pdns_mysql_vol:/var/lib/mysql'
 | 
				
			||||||
      - npm_le_sqlite:/etc/letsencrypt
 | 
					      - '/etc/localtime:/etc/localtime:ro'
 | 
				
			||||||
    expose:
 | 
					      - './dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro'
 | 
				
			||||||
      - 81
 | 
					    networks:
 | 
				
			||||||
      - 80
 | 
					      - fulltest
 | 
				
			||||||
      - 443
 | 
					 | 
				
			||||||
    healthcheck:
 | 
					 | 
				
			||||||
      test: ["CMD", "/usr/bin/check-health"]
 | 
					 | 
				
			||||||
      interval: 10s
 | 
					 | 
				
			||||||
      timeout: 3s
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  db:
 | 
					  dnsrouter:
 | 
				
			||||||
    image: jc21/mariadb-aria
 | 
					    image: jc21/dnsrouter
 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      MYSQL_ROOT_PASSWORD: 'npm'
 | 
					 | 
				
			||||||
      MYSQL_DATABASE: 'npm'
 | 
					 | 
				
			||||||
      MYSQL_USER: 'npm'
 | 
					 | 
				
			||||||
      MYSQL_PASSWORD: 'npm'
 | 
					 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - mysql_data:/var/lib/mysql
 | 
					      - ./dev/dnsrouter-config.json.tmp:/dnsrouter-config.json:ro
 | 
				
			||||||
 | 
					    networks:
 | 
				
			||||||
 | 
					      - fulltest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cypress-mysql:
 | 
					  cypress:
 | 
				
			||||||
    image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
 | 
					    image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
 | 
				
			||||||
    build:
 | 
					    build:
 | 
				
			||||||
      context: ../test/
 | 
					      context: ../
 | 
				
			||||||
      dockerfile: cypress/Dockerfile
 | 
					      dockerfile: test/cypress/Dockerfile
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      CYPRESS_baseUrl: 'http://fullstack-mysql:81'
 | 
					      CYPRESS_baseUrl: 'http://fullstack:81'
 | 
				
			||||||
    volumes:
 | 
					    volumes:
 | 
				
			||||||
      - cypress_logs_mysql:/results
 | 
					      - 'cypress_logs:/results'
 | 
				
			||||||
    command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
 | 
					      - './dev/resolv.conf:/etc/resolv.conf:ro'
 | 
				
			||||||
 | 
					    command: cypress run --browser chrome --config-file=cypress/config/ci.js
 | 
				
			||||||
  cypress-sqlite:
 | 
					    networks:
 | 
				
			||||||
    image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
 | 
					      - fulltest
 | 
				
			||||||
    build:
 | 
					 | 
				
			||||||
      context: ../test/
 | 
					 | 
				
			||||||
      dockerfile: cypress/Dockerfile
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      CYPRESS_baseUrl: "http://fullstack-sqlite:81"
 | 
					 | 
				
			||||||
    volumes:
 | 
					 | 
				
			||||||
      - cypress_logs_sqlite:/results
 | 
					 | 
				
			||||||
    command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
volumes:
 | 
					volumes:
 | 
				
			||||||
  cypress_logs_mysql:
 | 
					  cypress_logs:
 | 
				
			||||||
  cypress_logs_sqlite:
 | 
					  npm_data_ci:
 | 
				
			||||||
  npm_data_mysql:
 | 
					  npm_le_ci:
 | 
				
			||||||
  npm_data_sqlite:
 | 
					  pdns_mysql_vol:
 | 
				
			||||||
  npm_le_sqlite:
 | 
					
 | 
				
			||||||
  npm_le_mysql:
 | 
					networks:
 | 
				
			||||||
  mysql_data:
 | 
					  fulltest:
 | 
				
			||||||
 | 
					    name: "npm-${BRANCH_LOWER}-ci-${BUILD_NUMBER}"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
 | 
					# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
 | 
				
			||||||
version: '3.8'
 | 
					 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  npm:
 | 
					  npm:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								docker/rootfs/etc/nginx/conf.d/include/log.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					log_format proxy '[$time_local] $upstream_cache_status $upstream_status $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] [Sent-to $server] "$http_user_agent" "$http_referer"';
 | 
				
			||||||
 | 
					log_format standard '[$time_local] $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] "$http_user_agent" "$http_referer"';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					access_log /data/logs/fallback_access.log proxy;
 | 
				
			||||||
@@ -43,10 +43,8 @@ http {
 | 
				
			|||||||
	proxy_cache_path              /var/lib/nginx/cache/public  levels=1:2 keys_zone=public-cache:30m max_size=192m;
 | 
						proxy_cache_path              /var/lib/nginx/cache/public  levels=1:2 keys_zone=public-cache:30m max_size=192m;
 | 
				
			||||||
	proxy_cache_path              /var/lib/nginx/cache/private levels=1:2 keys_zone=private-cache:5m max_size=1024m;
 | 
						proxy_cache_path              /var/lib/nginx/cache/private levels=1:2 keys_zone=private-cache:5m max_size=1024m;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log_format proxy '[$time_local] $upstream_cache_status $upstream_status $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] [Sent-to $server] "$http_user_agent" "$http_referer"';
 | 
						# Log format and fallback log file
 | 
				
			||||||
	log_format standard '[$time_local] $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] "$http_user_agent" "$http_referer"';
 | 
						include /etc/nginx/conf.d/include/log.conf;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	access_log /data/logs/fallback_access.log proxy;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	# Dynamically generated resolvers file
 | 
						# Dynamically generated resolvers file
 | 
				
			||||||
	include /etc/nginx/conf.d/include/resolvers.conf;
 | 
						include /etc/nginx/conf.d/include/resolvers.conf;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,8 +1,9 @@
 | 
				
			|||||||
.vuepress/dist
 | 
					dist
 | 
				
			||||||
node_modules
 | 
					node_modules
 | 
				
			||||||
ts
 | 
					ts
 | 
				
			||||||
.temp
 | 
					.temp
 | 
				
			||||||
.cache
 | 
					.cache
 | 
				
			||||||
 | 
					.vitepress/cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.yarn/*
 | 
					.yarn/*
 | 
				
			||||||
!.yarn/releases
 | 
					!.yarn/releases
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								docs/.vitepress/config.mts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					import { defineConfig, type DefaultTheme } from 'vitepress';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// https://vitepress.dev/reference/site-config
 | 
				
			||||||
 | 
					export default defineConfig({
 | 
				
			||||||
 | 
						title: "Nginx Proxy Manager",
 | 
				
			||||||
 | 
						description: "Expose your services easily and securely",
 | 
				
			||||||
 | 
						head: [
 | 
				
			||||||
 | 
							["link", { rel: "icon", href: "/icon.png" }],
 | 
				
			||||||
 | 
							["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }],
 | 
				
			||||||
 | 
							["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
 | 
				
			||||||
 | 
							["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
 | 
				
			||||||
 | 
							["meta", { property: "og:type", content: "website" }],
 | 
				
			||||||
 | 
							["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
 | 
				
			||||||
 | 
							["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
 | 
				
			||||||
 | 
							["meta", { name: "twitter:card", content: "summary"}],
 | 
				
			||||||
 | 
							["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
 | 
				
			||||||
 | 
							["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
 | 
				
			||||||
 | 
							["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
 | 
				
			||||||
 | 
							["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
 | 
				
			||||||
 | 
							// GA
 | 
				
			||||||
 | 
							['script', { async: 'true', src: 'https://www.googletagmanager.com/gtag/js?id=G-TXT8F5WY5B'}],
 | 
				
			||||||
 | 
							['script', {}, "window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-TXT8F5WY5B');"],
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						sitemap: {
 | 
				
			||||||
 | 
							hostname: 'https://nginxproxymanager.com'
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						metaChunk: true,
 | 
				
			||||||
 | 
						srcDir: './src',
 | 
				
			||||||
 | 
						outDir: './dist',
 | 
				
			||||||
 | 
						themeConfig: {
 | 
				
			||||||
 | 
							// https://vitepress.dev/reference/default-theme-config
 | 
				
			||||||
 | 
							logo: { src: '/logo.svg', width: 24, height: 24 },
 | 
				
			||||||
 | 
							nav: [
 | 
				
			||||||
 | 
								{ text: 'Setup', link: '/setup/' },
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							sidebar: [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									items: [
 | 
				
			||||||
 | 
										// { text: 'Home', link: '/' },
 | 
				
			||||||
 | 
										{ text: 'Guide', link: '/guide/' },
 | 
				
			||||||
 | 
										{ text: 'Screenshots', link: '/screenshots/' },
 | 
				
			||||||
 | 
										{ text: 'Setup Instructions', link: '/setup/' },
 | 
				
			||||||
 | 
										{ text: 'Advanced Configuration', link: '/advanced-config/' },
 | 
				
			||||||
 | 
										{ text: 'Upgrading', link: '/upgrading/' },
 | 
				
			||||||
 | 
										{ text: 'Frequently Asked Questions', link: '/faq/' },
 | 
				
			||||||
 | 
										{ text: 'Third Party', link: '/third-party/' },
 | 
				
			||||||
 | 
									]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							socialLinks: [
 | 
				
			||||||
 | 
								{ icon: 'github', link: 'https://github.com/NginxProxyManager/nginx-proxy-manager' }
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							search: {
 | 
				
			||||||
 | 
								provider: 'local'
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							footer: {
 | 
				
			||||||
 | 
								message: 'Released under the MIT License.',
 | 
				
			||||||
 | 
								copyright: 'Copyright © 2016-present jc21.com'
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										27
									
								
								docs/.vitepress/theme/custom.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					:root {
 | 
				
			||||||
 | 
						--vp-home-hero-name-color: transparent;
 | 
				
			||||||
 | 
						--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #f15833 30%, #FAA42F);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						--vp-home-hero-image-background-image: linear-gradient(-45deg, #aaaaaa 50%, #777777 50%);
 | 
				
			||||||
 | 
						--vp-home-hero-image-filter: blur(44px);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						--vp-c-brand-1: #f15833;
 | 
				
			||||||
 | 
						--vp-c-brand-2: #FAA42F;
 | 
				
			||||||
 | 
						--vp-c-brand-3: #f15833;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @media (min-width: 640px) {
 | 
				
			||||||
 | 
						:root {
 | 
				
			||||||
 | 
							--vp-home-hero-image-filter: blur(56px);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @media (min-width: 960px) {
 | 
				
			||||||
 | 
						:root {
 | 
				
			||||||
 | 
							--vp-home-hero-image-filter: blur(68px);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.inline-img img {
 | 
				
			||||||
 | 
						display: inline;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								docs/.vitepress/theme/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					import DefaultTheme from 'vitepress/theme'
 | 
				
			||||||
 | 
					import './custom.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default DefaultTheme
 | 
				
			||||||
@@ -1,120 +0,0 @@
 | 
				
			|||||||
import { defineUserConfig } from 'vuepress';
 | 
					 | 
				
			||||||
import { defaultTheme } from 'vuepress'
 | 
					 | 
				
			||||||
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics';
 | 
					 | 
				
			||||||
import { searchPlugin } from '@vuepress/plugin-search'
 | 
					 | 
				
			||||||
import { sitemapPlugin } from 'vuepress-plugin-sitemap2';
 | 
					 | 
				
			||||||
import zoomingPlugin from 'vuepress-plugin-zooming';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default defineUserConfig({
 | 
					 | 
				
			||||||
  locales: {
 | 
					 | 
				
			||||||
    "/": {
 | 
					 | 
				
			||||||
      lang: "en-US",
 | 
					 | 
				
			||||||
      title: "Nginx Proxy Manager",
 | 
					 | 
				
			||||||
      description: "Expose your services easily and securely",
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  head: [
 | 
					 | 
				
			||||||
    ["link", { rel: "icon", href: "/icon.png" }],
 | 
					 | 
				
			||||||
    ["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }],
 | 
					 | 
				
			||||||
    ["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
 | 
					 | 
				
			||||||
    ["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
 | 
					 | 
				
			||||||
    ["meta", { property: "og:type", content: "website" }],
 | 
					 | 
				
			||||||
    ["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
 | 
					 | 
				
			||||||
    ["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
 | 
					 | 
				
			||||||
    ["meta", { name: "twitter:card", content: "summary"}],
 | 
					 | 
				
			||||||
    ["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
 | 
					 | 
				
			||||||
    ["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
 | 
					 | 
				
			||||||
    ["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
 | 
					 | 
				
			||||||
    ["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  theme: defaultTheme({
 | 
					 | 
				
			||||||
    logo: '/icon.png',
 | 
					 | 
				
			||||||
    repo: "jc21/nginx-proxy-manager",
 | 
					 | 
				
			||||||
    docsRepo: 'https://github.com/jc21/nginx-proxy-manager',
 | 
					 | 
				
			||||||
    docsBranch: 'develop',
 | 
					 | 
				
			||||||
    docsDir: 'docs',
 | 
					 | 
				
			||||||
    editLinkPattern: ':repo/edit/:branch/:path',
 | 
					 | 
				
			||||||
    locales: {
 | 
					 | 
				
			||||||
      '/': {
 | 
					 | 
				
			||||||
        label: 'English',
 | 
					 | 
				
			||||||
        selectLanguageText: 'Languages',
 | 
					 | 
				
			||||||
        selectLanguageName: 'English',
 | 
					 | 
				
			||||||
        editLinkText: 'Edit this page on GitHub',
 | 
					 | 
				
			||||||
        navbar: [
 | 
					 | 
				
			||||||
          { text: 'Setup', link: '/setup/' }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        sidebar: {
 | 
					 | 
				
			||||||
          '/': [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              text: 'Home',
 | 
					 | 
				
			||||||
              link: '/'
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            { 
 | 
					 | 
				
			||||||
              text: 'Guide',
 | 
					 | 
				
			||||||
              link: '/guide/',
 | 
					 | 
				
			||||||
              collapsible: true,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              text: 'Screenshots',
 | 
					 | 
				
			||||||
              link:  '/screenshots/',
 | 
					 | 
				
			||||||
              collapsible: true,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              text: 'Setup Instructions',
 | 
					 | 
				
			||||||
              link: '/setup/',
 | 
					 | 
				
			||||||
              collapsible: true,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              text: 'Advanced Configuration',
 | 
					 | 
				
			||||||
              link: '/advanced-config/',
 | 
					 | 
				
			||||||
              collapsible: true,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              text: 'Upgrading',
 | 
					 | 
				
			||||||
              link: '/upgrading/',
 | 
					 | 
				
			||||||
              collapsible: true,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              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',
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    }),
 | 
					 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 57 KiB  | 
@@ -1,258 +0,0 @@
 | 
				
			|||||||
: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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										893
									
								
								docs/.yarn/releases/yarn-4.0.2.cjs
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,3 +0,0 @@
 | 
				
			|||||||
nodeLinker: node-modules
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
yarnPath: .yarn/releases/yarn-4.0.2.cjs
 | 
					 | 
				
			||||||
@@ -1,41 +0,0 @@
 | 
				
			|||||||
---
 | 
					 | 
				
			||||||
home: true
 | 
					 | 
				
			||||||
heroImage: /logo.png
 | 
					 | 
				
			||||||
actions:
 | 
					 | 
				
			||||||
  - text: Get Started
 | 
					 | 
				
			||||||
    link: /guide/
 | 
					 | 
				
			||||||
    type: primary
 | 
					 | 
				
			||||||
footer: MIT Licensed | Copyright © 2016-present jc21.com
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<div class="features">
 | 
					 | 
				
			||||||
  <div class="feature">
 | 
					 | 
				
			||||||
    <h2>Get Connected</h2>
 | 
					 | 
				
			||||||
    <p>
 | 
					 | 
				
			||||||
      Expose web services on your network ·
 | 
					 | 
				
			||||||
      Free SSL with Let's Encrypt  ·
 | 
					 | 
				
			||||||
      Designed with security in mind  ·
 | 
					 | 
				
			||||||
      Perfect for home networks
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="feature">
 | 
					 | 
				
			||||||
    <h2>Proxy Hosts</h2>
 | 
					 | 
				
			||||||
    <p>Expose your private network Web services and get connected anywhere.</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="feature">
 | 
					 | 
				
			||||||
    <h2>Beautiful UI</h2>
 | 
					 | 
				
			||||||
    <p>Based on Tabler, the interface is a pleasure to use. Configuring a server has never been so fun.</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="feature">
 | 
					 | 
				
			||||||
    <h2>Free SSL</h2>
 | 
					 | 
				
			||||||
    <p>Built in Let’s Encrypt support allows you to secure your Web services at no cost to you. The certificates even renew themselves!</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="feature">
 | 
					 | 
				
			||||||
    <h2>Docker FTW</h2>
 | 
					 | 
				
			||||||
    <p>Built as a Docker Image, Nginx Proxy Manager only requires a database.</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
  <div class="feature">
 | 
					 | 
				
			||||||
    <h2>Multiple Users</h2>
 | 
					 | 
				
			||||||
    <p>Configure other users to either view or manage their own hosts. Full access permissions are available.</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
../../README.md
 | 
					 | 
				
			||||||
@@ -1,23 +1,11 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "docs",
 | 
					 | 
				
			||||||
  "version": "1.0.0",
 | 
					 | 
				
			||||||
  "description": "",
 | 
					 | 
				
			||||||
  "main": "index.js",
 | 
					 | 
				
			||||||
  "devDependencies": {
 | 
					 | 
				
			||||||
    "vuepress": "^2.0.0-rc.0"
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "vuepress dev",
 | 
					    "dev": "vitepress dev --host",
 | 
				
			||||||
    "build": "vuepress build"
 | 
					    "build": "vitepress build",
 | 
				
			||||||
 | 
					    "preview": "vitepress preview"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "author": "",
 | 
					  "devDependencies": {
 | 
				
			||||||
  "license": "ISC",
 | 
					    "vitepress": "^1.1.4"
 | 
				
			||||||
  "packageManager": "yarn@4.0.2",
 | 
					  },
 | 
				
			||||||
  "dependencies": {
 | 
					  "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"
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
# Screenshots
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/login.png" alt="Login" title="Login" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/dashboard.png" alt="Dashboard" title="Dashboard" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts.png" alt="Proxy Hosts" title="Proxy Hosts" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts-add.png" alt="Add Proxy Host" title="Add Proxy Host" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/redirection-hosts.png" alt="Redirection Hosts" title="Redirection Hosts" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/dead-hosts.png" alt="404 Hosts" title="404 Hosts" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/permissions.png" alt="User Permissions" title="User Permissions" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/certificates.png" alt="Certificates" title="Certificates" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/audit-log.png" alt="Audit Log" title="Audit Log" width="200"/>
 | 
					 | 
				
			||||||
<img class="no-medium-zoom zooming" src="/screenshots/custom-settings.png" alt="Custom Settings" title="Custom Settings" width="200"/>
 | 
					 | 
				
			||||||
@@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Advanced Configuration
 | 
					# Advanced Configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Running processes as a user/group
 | 
					## Running processes as a user/group
 | 
				
			||||||
@@ -1,26 +1,26 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# FAQ
 | 
					# FAQ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Do I have to use Docker?
 | 
					## Do I have to use Docker?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Yes, that's how this project is packaged.
 | 
					Yes, that's how this project is packaged.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This makes it easier to support the project when I have control over the version of Nginx and NodeJS
 | 
					This makes it easier to support the project when we have control over the version of Nginx other packages
 | 
				
			||||||
being used. In future this could change if the backend was no longer using NodeJS and it's long list
 | 
					use by the project.
 | 
				
			||||||
of dependencies.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Can I run it on a Raspberry Pi?
 | 
					## Can I run it on a Raspberry Pi?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Yes! The docker image is multi-arch and is built for a variety of architectures. If yours is
 | 
					Yes! The docker image is multi-arch and is built for a variety of architectures. If yours is
 | 
				
			||||||
[not listed](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags) please open a
 | 
					[not listed](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags) please open a
 | 
				
			||||||
[GitHub issue](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
 | 
					[GitHub issue](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## I can't get my service to proxy properly?
 | 
					## I can't get my service to proxy properly?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Your best bet is to ask the [Reddit community for support](https://www.reddit.com/r/nginxproxymanager/). There's safety in numbers.
 | 
					Your best bet is to ask the [Reddit community for support](https://www.reddit.com/r/nginxproxymanager/). There's safety in numbers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Gitter is best left for anyone contributing to the project to ask for help about internals, code reviews etc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## When adding username and password access control to a proxy host, I can no longer login into the app.
 | 
					## When adding username and password access control to a proxy host, I can no longer login into the app.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Having an Access Control List (ACL) with username and password requires the browser to always send this username and password in the `Authorization` header on each request. If your proxied app also requires authentication (like Nginx Proxy Manager itself), most likely the app will also use the `Authorization` header to transmit this information, as this is the standardized header meant for this kind of information. However having multiples of the same headers is not allowed in the [internet standard](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2) and almost all apps do not support multiple values in the `Authorization` header. Hence one of the two logins will be broken. This can only be fixed by either removing one of the logins or by changing the app to use other non-standard headers for authorization.
 | 
					Having an Access Control List (ACL) with username and password requires the browser to always send this username and password in the `Authorization` header on each request. If your proxied app also requires authentication (like Nginx Proxy Manager itself), most likely the app will also use the `Authorization` header to transmit this information, as this is the standardized header meant for this kind of information. However having multiples of the same headers is not allowed in the [internet standard](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2) and almost all apps do not support multiple values in the `Authorization` header. Hence one of the two logins will be broken. This can only be fixed by either removing one of the logins or by changing the app to use other non-standard headers for authorization.
 | 
				
			||||||
							
								
								
									
										126
									
								
								docs/src/guide/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,126 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Guide
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::: raw
 | 
				
			||||||
 | 
					<p align="center">
 | 
				
			||||||
 | 
						<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager" style="display:inline;margin-right:5px;">
 | 
				
			||||||
 | 
							<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge" style="display:inline;">
 | 
				
			||||||
 | 
						</a>
 | 
				
			||||||
 | 
						<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager" style="display:inline;margin-right:5px;">
 | 
				
			||||||
 | 
							<img src="https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg?style=for-the-badge" style="display:inline;">
 | 
				
			||||||
 | 
						</a>
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
 | 
					:::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This project comes as a pre-built docker image that enables you to easily forward to your websites
 | 
				
			||||||
 | 
					running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Quick Setup](#quick-setup)
 | 
				
			||||||
 | 
					- [Full Setup](/setup/)
 | 
				
			||||||
 | 
					- [Screenshots](/screenshots/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Project Goal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::: raw
 | 
				
			||||||
 | 
					<a href="https://www.buymeacoffee.com/jc21" target="_blank"><img src="http://public.jc21.com/github/by-me-a-coffee.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>
 | 
				
			||||||
 | 
					:::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Beautiful and Secure Admin Interface based on [Tabler](https://tabler.github.io/)
 | 
				
			||||||
 | 
					- Easily create forwarding domains, redirections, streams and 404 hosts without knowing anything about Nginx
 | 
				
			||||||
 | 
					- Free SSL using Let's Encrypt or provide your own custom SSL certificates
 | 
				
			||||||
 | 
					- Access Lists and basic HTTP Authentication for your hosts
 | 
				
			||||||
 | 
					- Advanced Nginx configuration available for super users
 | 
				
			||||||
 | 
					- User management, permissions and audit log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Hosting your home network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I won't go in to too much detail here but here are the basics for someone new to this self-hosted world.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Your home router will have a Port Forwarding section somewhere. Log in and find it
 | 
				
			||||||
 | 
					2. Add port forwarding for port 80 and 443 to the server hosting this project
 | 
				
			||||||
 | 
					3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS or [Amazon Route53](https://github.com/jc21/route53-ddns)
 | 
				
			||||||
 | 
					4. Use the Nginx Proxy Manager as your gateway to forward to your other web based services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Quick Setup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. Install Docker and Docker-Compose
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Docker Install documentation](https://docs.docker.com/get-docker/)
 | 
				
			||||||
 | 
					- [Docker-Compose Install documentation](https://docs.docker.com/compose/install/)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2. Create a docker-compose.yml file similar to this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```yml
 | 
				
			||||||
 | 
					version: '3.8'
 | 
				
			||||||
 | 
					services:
 | 
				
			||||||
 | 
					  app:
 | 
				
			||||||
 | 
					    image: 'jc21/nginx-proxy-manager:latest'
 | 
				
			||||||
 | 
					    restart: unless-stopped
 | 
				
			||||||
 | 
					    ports:
 | 
				
			||||||
 | 
					      - '80:80'
 | 
				
			||||||
 | 
					      - '81:81'
 | 
				
			||||||
 | 
					      - '443:443'
 | 
				
			||||||
 | 
					    volumes:
 | 
				
			||||||
 | 
					      - ./data:/data
 | 
				
			||||||
 | 
					      - ./letsencrypt:/etc/letsencrypt
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is the bare minimum configuration required. See the [documentation](https://nginxproxymanager.com/setup/) for more.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					3. Bring up your stack by running
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					docker-compose up -d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If using docker-compose-plugin
 | 
				
			||||||
 | 
					docker compose up -d
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					4. Log in to the Admin UI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When your docker container is running, connect to it on port `81` for the admin interface.
 | 
				
			||||||
 | 
					Sometimes this can take a little bit because of the entropy of keys.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[http://127.0.0.1:81](http://127.0.0.1:81)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Default Admin User:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					Email:    admin@example.com
 | 
				
			||||||
 | 
					Password: changeme
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Immediately after logging in with this default user you will be asked to modify your details and change your password.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Contributing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All are welcome to create pull requests for this project, against the `develop` branch. Official releases are created from the `master` branch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Getting Support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
 | 
				
			||||||
 | 
					2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
 | 
				
			||||||
 | 
					3. [Reddit](https://reddit.com/r/nginxproxymanager)
 | 
				
			||||||
							
								
								
									
										32
									
								
								docs/src/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					# https://vitepress.dev/reference/default-theme-home-page
 | 
				
			||||||
 | 
					layout: home
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hero:
 | 
				
			||||||
 | 
					  name: "Nginx Proxy Manager"
 | 
				
			||||||
 | 
					  tagline: Expose your services easily and securely
 | 
				
			||||||
 | 
					  image:
 | 
				
			||||||
 | 
					    src: /logo.svg
 | 
				
			||||||
 | 
					    alt: NPM Logo
 | 
				
			||||||
 | 
					  actions:
 | 
				
			||||||
 | 
					    - theme: brand
 | 
				
			||||||
 | 
					      text: Get Started
 | 
				
			||||||
 | 
					      link: /guide/
 | 
				
			||||||
 | 
					    - theme: alt
 | 
				
			||||||
 | 
					      text: GitHub
 | 
				
			||||||
 | 
					      link: https://github.com/NginxProxyManager/nginx-proxy-manager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					features:
 | 
				
			||||||
 | 
					  - title: Get Connected
 | 
				
			||||||
 | 
					    details: Expose web services on your network · Free SSL with Let's Encrypt  · Designed with security in mind  · Perfect for home networks
 | 
				
			||||||
 | 
					  - title: Proxy Hosts
 | 
				
			||||||
 | 
					    details: Expose your private network Web services and get connected anywhere.
 | 
				
			||||||
 | 
					  - title: Beautiful UI
 | 
				
			||||||
 | 
					    details: Based on Tabler, the interface is a pleasure to use. Configuring a server has never been so fun.
 | 
				
			||||||
 | 
					  - title: Free SSL
 | 
				
			||||||
 | 
					    details: Built in Let’s Encrypt support allows you to secure your Web services at no cost to you. The certificates even renew themselves!
 | 
				
			||||||
 | 
					  - title: Docker FTW
 | 
				
			||||||
 | 
					    details: Built as a Docker Image, Nginx Proxy Manager only requires a database.
 | 
				
			||||||
 | 
					  - title: Multiple Users
 | 
				
			||||||
 | 
					    details: Configure other users to either view or manage their own hosts. Full access permissions are available.
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB  | 
| 
		 Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB  | 
| 
		 Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB  | 
| 
		 Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB  | 
| 
		 Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB  | 
| 
		 Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB  | 
| 
		 Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB  | 
| 
		 Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB  | 
| 
		 Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB  | 
| 
		 Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB  | 
| 
		 Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 207 KiB  | 
| 
		 Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 181 KiB  | 
| 
		 Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB  | 
							
								
								
									
										20
									
								
								docs/src/screenshots/index.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Screenshots
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::: raw
 | 
				
			||||||
 | 
					<div class="inline-img">
 | 
				
			||||||
 | 
						<a href="/screenshots/login.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/login.png" alt="Login" title="Login" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/dashboard.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/dashboard.png" alt="Dashboard" title="Dashboard" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/proxy-hosts.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts.png" alt="Proxy Hosts" title="Proxy Hosts" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/proxy-hosts-add.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts-add.png" alt="Add Proxy Host" title="Add Proxy Host" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/redirection-hosts.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/redirection-hosts.png" alt="Redirection Hosts" title="Redirection Hosts" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/dead-hosts.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/dead-hosts.png" alt="404 Hosts" title="404 Hosts" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/permissions.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/permissions.png" alt="User Permissions" title="User Permissions" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/certificates.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/certificates.png" alt="Certificates" title="Certificates" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/audit-log.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/audit-log.png" alt="Audit Log" title="Audit Log" width="200"/></a>
 | 
				
			||||||
 | 
						<a href="/screenshots/custom-settings.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/custom-settings.png" alt="Custom Settings" title="Custom Settings" width="200"/></a>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					:::
 | 
				
			||||||
@@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Full Setup Instructions
 | 
					# Full Setup Instructions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Running the App
 | 
					## Running the App
 | 
				
			||||||
@@ -1,3 +1,7 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Third Party
 | 
					# Third Party
 | 
				
			||||||
 | 
					
 | 
				
			||||||
As this software gains popularity it's common to see it integrated with other platforms. Please be aware that unless specifically mentioned in the documentation of those
 | 
					As this software gains popularity it's common to see it integrated with other platforms. Please be aware that unless specifically mentioned in the documentation of those
 | 
				
			||||||
@@ -12,5 +16,4 @@ Known integrations:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you would like your integration of NPM listed, please open a
 | 
					If you would like your integration of NPM listed, please open a
 | 
				
			||||||
[Github issue](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)
 | 
					[Github issue](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)
 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -1,8 +1,12 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					outline: deep
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Upgrading
 | 
					# Upgrading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
docker-compose pull
 | 
					docker compose pull
 | 
				
			||||||
docker-compose up -d
 | 
					docker compose up -d
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This project will automatically update any databases or other requirements so you don't have to follow
 | 
					This project will automatically update any databases or other requirements so you don't have to follow
 | 
				
			||||||
							
								
								
									
										4120
									
								
								docs/yarn.lock
									
									
									
									
									
								
							
							
						
						@@ -35,7 +35,7 @@
 | 
				
			|||||||
		"name": "Cloudflare",
 | 
							"name": "Cloudflare",
 | 
				
			||||||
		"package_name": "certbot-dns-cloudflare",
 | 
							"package_name": "certbot-dns-cloudflare",
 | 
				
			||||||
		"version": "=={{certbot-version}}",
 | 
							"version": "=={{certbot-version}}",
 | 
				
			||||||
		"dependencies": "cloudflare acme=={{certbot-version}}",
 | 
							"dependencies": "cloudflare==2.19.* acme=={{certbot-version}}",
 | 
				
			||||||
		"credentials": "# Cloudflare API token\ndns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567",
 | 
							"credentials": "# Cloudflare API token\ndns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567",
 | 
				
			||||||
		"full_plugin_name": "dns-cloudflare"
 | 
							"full_plugin_name": "dns-cloudflare"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
@@ -239,6 +239,14 @@
 | 
				
			|||||||
		"credentials": "dns_hetzner_api_token = 0123456789abcdef0123456789abcdef",
 | 
							"credentials": "dns_hetzner_api_token = 0123456789abcdef0123456789abcdef",
 | 
				
			||||||
		"full_plugin_name": "dns-hetzner"
 | 
							"full_plugin_name": "dns-hetzner"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						"hover": {
 | 
				
			||||||
 | 
							"name": "Hover",
 | 
				
			||||||
 | 
							"package_name": "certbot-dns-hover",
 | 
				
			||||||
 | 
							"version": "~=1.2.1",
 | 
				
			||||||
 | 
							"dependencies": "",
 | 
				
			||||||
 | 
							"credentials": "dns_hover_hoverurl = https://www.hover.com\ndns_hover_username = hover-admin-username\ndns_hover_password = hover-admin-password\ndns_hover_totpsecret = 2fa-totp-secret",
 | 
				
			||||||
 | 
							"full_plugin_name": "dns-hover"
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	"infomaniak": {
 | 
						"infomaniak": {
 | 
				
			||||||
		"name": "Infomaniak",
 | 
							"name": "Infomaniak",
 | 
				
			||||||
		"package_name": "certbot-dns-infomaniak",
 | 
							"package_name": "certbot-dns-infomaniak",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ if hash docker 2>/dev/null; then
 | 
				
			|||||||
		-e NODE_OPTIONS=--openssl-legacy-provider \
 | 
							-e NODE_OPTIONS=--openssl-legacy-provider \
 | 
				
			||||||
		-v "$(pwd)/frontend:/app/frontend" \
 | 
							-v "$(pwd)/frontend:/app/frontend" \
 | 
				
			||||||
		-v "$(pwd)/global:/app/global" \
 | 
							-v "$(pwd)/global:/app/global" \
 | 
				
			||||||
		-w /app/frontend "$DOCKER_IMAGE" \
 | 
							-w /app/frontend "${DOCKER_IMAGE}" \
 | 
				
			||||||
		sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
 | 
							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}"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										89
									
								
								scripts/ci/fulltest-cypress
									
									
									
									
									
										Executable file
									
								
							
							
						
						@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					STACK="${1:-sqlite}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
				
			||||||
 | 
					# remember this is running in "ci" folder..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Some defaults for running this script outside of CI
 | 
				
			||||||
 | 
					export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-npm_local_fulltest}"
 | 
				
			||||||
 | 
					export IMAGE="${IMAGE:-nginx-proxy-manager}"
 | 
				
			||||||
 | 
					export BRANCH_LOWER="${BRANCH_LOWER:-unknown}"
 | 
				
			||||||
 | 
					export BUILD_NUMBER="${BUILD_NUMBER:-0000}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "${COMPOSE_FILE:-}" = "" ]; then
 | 
				
			||||||
 | 
						export COMPOSE_FILE="docker/docker-compose.ci.yml:docker/docker-compose.ci.${STACK}.yml"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Colors
 | 
				
			||||||
 | 
					BLUE='\E[1;34m'
 | 
				
			||||||
 | 
					RED='\E[1;31m'
 | 
				
			||||||
 | 
					CYAN='\E[1;36m'
 | 
				
			||||||
 | 
					GREEN='\E[1;32m'
 | 
				
			||||||
 | 
					RESET='\E[0m'
 | 
				
			||||||
 | 
					YELLOW='\E[1;33m'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export BLUE CYAN GREEN RESET YELLOW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo -e "${BLUE}❯ ${CYAN}Starting fullstack cypress testing ...${RESET}"
 | 
				
			||||||
 | 
					echo -e "${BLUE}❯ $(docker-compose config)${RESET}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# $1: container_name
 | 
				
			||||||
 | 
					get_container_ip () {
 | 
				
			||||||
 | 
						local container_name=$1
 | 
				
			||||||
 | 
						local container
 | 
				
			||||||
 | 
						local ip
 | 
				
			||||||
 | 
						container=$(docker-compose ps --all -q "${container_name}" | tail -n1)
 | 
				
			||||||
 | 
						ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container")
 | 
				
			||||||
 | 
						echo "$ip"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Bring up a stack, in steps so we can inject IPs everywhere
 | 
				
			||||||
 | 
					docker-compose up -d pdns pdns-db
 | 
				
			||||||
 | 
					PDNS_IP=$(get_container_ip "pdns")
 | 
				
			||||||
 | 
					echo -e "${BLUE}❯ ${YELLOW}PDNS IP is ${PDNS_IP}${RESET}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# adjust the dnsrouter config
 | 
				
			||||||
 | 
					LOCAL_DNSROUTER_CONFIG="$DIR/../../docker/dev/dnsrouter-config.json"
 | 
				
			||||||
 | 
					rm -rf "$LOCAL_DNSROUTER_CONFIG.tmp"
 | 
				
			||||||
 | 
					# IMPORTANT: changes to dnsrouter-config.json will affect this line:
 | 
				
			||||||
 | 
					jq --arg a "$PDNS_IP" '.servers[0].upstreams[1].upstream = $a' "$LOCAL_DNSROUTER_CONFIG" > "$LOCAL_DNSROUTER_CONFIG.tmp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					docker-compose up -d dnsrouter
 | 
				
			||||||
 | 
					DNSROUTER_IP=$(get_container_ip "dnsrouter")
 | 
				
			||||||
 | 
					echo -e "${BLUE}❯ ${YELLOW}DNS Router IP is ${DNSROUTER_IP}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "${DNSROUTER_IP:-}" = "" ]; then
 | 
				
			||||||
 | 
						echo -e "${RED}❯ ERROR: DNS Router IP is not set${RESET}"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# mount the resolver
 | 
				
			||||||
 | 
					LOCAL_RESOLVE="$DIR/../../docker/dev/resolv.conf"
 | 
				
			||||||
 | 
					rm -rf "${LOCAL_RESOLVE}"
 | 
				
			||||||
 | 
					printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bring up all remaining containers, except cypress!
 | 
				
			||||||
 | 
					docker-compose up -d --remove-orphans stepca
 | 
				
			||||||
 | 
					docker-compose pull db-mysql || true # ok to fail
 | 
				
			||||||
 | 
					docker-compose up -d --remove-orphans --pull=never fullstack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# wait for main container to be healthy
 | 
				
			||||||
 | 
					bash "$DIR/../wait-healthy" "$(docker-compose ps --all -q fullstack)" 120
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Run tests
 | 
				
			||||||
 | 
					rm -rf "$DIR/../../test/results"
 | 
				
			||||||
 | 
					docker-compose up --build cypress
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Get results
 | 
				
			||||||
 | 
					docker cp -L "$(docker-compose ps --all -q cypress):/test/results" "$DIR/../../test/"
 | 
				
			||||||
 | 
					docker cp -L "$(docker-compose ps --all -q fullstack):/data/logs" "$DIR/../../test/results/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$2" = "cleanup" ]; then
 | 
				
			||||||
 | 
						echo -e "${BLUE}❯ ${CYAN}Cleaning up containers ...${RESET}"
 | 
				
			||||||
 | 
						docker-compose down --remove-orphans --volumes -t 30
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo -e "${BLUE}❯ ${GREEN}Fullstack cypress testing complete${RESET}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3,8 +3,8 @@
 | 
				
			|||||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
					DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
				
			||||||
. "$DIR/../.common.sh"
 | 
					. "$DIR/../.common.sh"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
 | 
					TESTING_IMAGE=nginxproxymanager/nginx-full:certbot-node
 | 
				
			||||||
docker pull "${DOCKER_IMAGE}"
 | 
					docker pull "${TESTING_IMAGE}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Test
 | 
					# Test
 | 
				
			||||||
echo -e "${BLUE}❯ ${CYAN}Testing backend ...${RESET}"
 | 
					echo -e "${BLUE}❯ ${CYAN}Testing backend ...${RESET}"
 | 
				
			||||||
@@ -12,20 +12,20 @@ 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}" \
 | 
						"${TESTING_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}"
 | 
					echo -e "${BLUE}❯ ${GREEN}Testing Complete${RESET}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Build
 | 
					# Build
 | 
				
			||||||
echo -e "${BLUE}❯ ${CYAN}Building ...${RESET}"
 | 
					echo -e "${BLUE}❯ ${CYAN}Building ...${RESET}"
 | 
				
			||||||
docker build --pull --no-cache --compress \
 | 
					docker build --pull --no-cache --compress \
 | 
				
			||||||
	-t "${IMAGE}:ci-${BUILD_NUMBER}" \
 | 
						-t "${IMAGE:-nginx-proxy-manager}:${BRANCH_LOWER:-unknown}-ci-${BUILD_NUMBER:-0000}" \
 | 
				
			||||||
	-f docker/Dockerfile \
 | 
						-f docker/Dockerfile \
 | 
				
			||||||
	--progress=plain \
 | 
						--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:-unknown}" \
 | 
				
			||||||
	--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \
 | 
						--build-arg BUILD_COMMIT="${BUILD_COMMIT:-unknown}" \
 | 
				
			||||||
	--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}"
 | 
					echo -e "${BLUE}❯ ${GREEN}Building Complete${RESET}"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,9 +23,8 @@ until [ "${HEALTHY}" = "healthy" ]; do
 | 
				
			|||||||
	((LOOPCOUNT++))
 | 
						((LOOPCOUNT++))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if [ "$LOOPCOUNT" == "$LIMIT" ]; then
 | 
						if [ "$LOOPCOUNT" == "$LIMIT" ]; then
 | 
				
			||||||
		echo ""
 | 
					 | 
				
			||||||
		echo ""
 | 
					 | 
				
			||||||
		echo -e "${BLUE}❯ ${RED}Timed out waiting for healthy${RESET}"
 | 
							echo -e "${BLUE}❯ ${RED}Timed out waiting for healthy${RESET}"
 | 
				
			||||||
 | 
							docker logs --tail 50 "$SERVICE"
 | 
				
			||||||
		exit 1
 | 
							exit 1
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
node_modules
 | 
					 | 
				
			||||||
							
								
								
									
										6
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@@ -1,4 +1,2 @@
 | 
				
			|||||||
.vscode
 | 
					results/*
 | 
				
			||||||
node_modules
 | 
					cypress/results/*
 | 
				
			||||||
results
 | 
					 | 
				
			||||||
cypress/videos
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,12 @@
 | 
				
			|||||||
FROM cypress/included:9.4.1
 | 
					FROM cypress/included:13.9.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY --chown=1000 ./ /test
 | 
					COPY --chown=1000 ./test /test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# mkcert
 | 
					# Disable Cypress CLI colors
 | 
				
			||||||
ENV MKCERT=1.4.2
 | 
					ENV FORCE_COLOR=0
 | 
				
			||||||
RUN wget -O /usr/bin/mkcert "https://github.com/FiloSottile/mkcert/releases/download/v${MKCERT}/mkcert-v${MKCERT}-linux-amd64" \
 | 
					ENV NO_COLOR=1
 | 
				
			||||||
	&& chmod +x /usr/bin/mkcert
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /test
 | 
					WORKDIR /test
 | 
				
			||||||
RUN yarn install
 | 
					RUN yarn install && yarn cache clean
 | 
				
			||||||
ENTRYPOINT []
 | 
					ENTRYPOINT []
 | 
				
			||||||
CMD ["cypress", "run"]
 | 
					CMD ["cypress", "run"]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								test/cypress/config/ci.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					const { defineConfig } = require('cypress');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = defineConfig({
 | 
				
			||||||
 | 
						requestTimeout: 30000,
 | 
				
			||||||
 | 
						defaultCommandTimeout: 20000,
 | 
				
			||||||
 | 
						reporter: 'cypress-multi-reporters',
 | 
				
			||||||
 | 
						reporterOptions: {
 | 
				
			||||||
 | 
							configFile: 'multi-reporter.json'
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						video: true,
 | 
				
			||||||
 | 
						videosFolder: 'results/videos',
 | 
				
			||||||
 | 
						screenshotsFolder: 'results/screenshots',
 | 
				
			||||||
 | 
						e2e: {
 | 
				
			||||||
 | 
							setupNodeEvents(on, config) {
 | 
				
			||||||
 | 
								return require("../plugins/index.js")(on, config);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							env: {
 | 
				
			||||||
 | 
								swaggerBase: '{{baseUrl}}/api/schema',
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							baseUrl: 'http://localhost:1234',
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
	"requestTimeout": 30000,
 | 
					 | 
				
			||||||
	"defaultCommandTimeout": 20000,
 | 
					 | 
				
			||||||
	"reporter": "cypress-multi-reporters",
 | 
					 | 
				
			||||||
	"reporterOptions": {
 | 
					 | 
				
			||||||
		"configFile": "multi-reporter.json"
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"videosFolder": "results/videos",
 | 
					 | 
				
			||||||
	"screenshotsFolder": "results/screenshots",
 | 
					 | 
				
			||||||
	"env": {
 | 
					 | 
				
			||||||
		"swaggerBase": "{{baseUrl}}/api/schema",
 | 
					 | 
				
			||||||
		"RETRIES": 4
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								test/cypress/config/dev.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					const { defineConfig } = require('cypress');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = defineConfig({
 | 
				
			||||||
 | 
						requestTimeout: 30000,
 | 
				
			||||||
 | 
						defaultCommandTimeout: 20000,
 | 
				
			||||||
 | 
						reporter: 'cypress-multi-reporters',
 | 
				
			||||||
 | 
						reporterOptions: {
 | 
				
			||||||
 | 
							configFile: 'multi-reporter.json'
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						video: false,
 | 
				
			||||||
 | 
						videosFolder: 'results/videos',
 | 
				
			||||||
 | 
						screenshotsFolder: 'results/screenshots',
 | 
				
			||||||
 | 
						e2e: {
 | 
				
			||||||
 | 
							setupNodeEvents(on, config) {
 | 
				
			||||||
 | 
								return require("../plugins/index.js")(on, config);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							env: {
 | 
				
			||||||
 | 
								swaggerBase: '{{baseUrl}}/api/schema',
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							baseUrl: 'http://localhost:1234',
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
	"requestTimeout": 30000,
 | 
					 | 
				
			||||||
	"defaultCommandTimeout": 20000,
 | 
					 | 
				
			||||||
	"reporter": "cypress-multi-reporters",
 | 
					 | 
				
			||||||
	"reporterOptions": {
 | 
					 | 
				
			||||||
		"configFile": "multi-reporter.json"
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	"videos": false,
 | 
					 | 
				
			||||||
	"screenshotsFolder": "results/screenshots",
 | 
					 | 
				
			||||||
	"env": {
 | 
					 | 
				
			||||||
		"swaggerBase": "{{baseUrl}}/api/schema",
 | 
					 | 
				
			||||||
		"RETRIES": 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "name": "Using fixtures to represent data",
 | 
					 | 
				
			||||||
  "email": "hello@cypress.io",
 | 
					 | 
				
			||||||
  "body": "Fixtures are a great way to mock data for responses to routes"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,8 +1,12 @@
 | 
				
			|||||||
const _     = require('lodash');
 | 
					const _ = require("lodash");
 | 
				
			||||||
const chalk = require('chalk');
 | 
					const chalk = require("chalk");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = function () {
 | 
					module.exports = function() {
 | 
				
			||||||
	var arr = _.values(arguments);
 | 
						var arr = _.values(arguments);
 | 
				
			||||||
	arr.unshift(chalk.blue.bold('[') + chalk.yellow.bold('Backend API') + chalk.blue.bold(']'));
 | 
						arr.unshift(
 | 
				
			||||||
 | 
							chalk.blue.bold("[") +
 | 
				
			||||||
 | 
								chalk.yellow.bold("Backend API") +
 | 
				
			||||||
 | 
								chalk.blue.bold("]"),
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
	console.log.apply(null, arr);
 | 
						console.log.apply(null, arr);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,20 +9,32 @@
 | 
				
			|||||||
// ***********************************************
 | 
					// ***********************************************
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'cypress-wait-until';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cypress.Commands.add('randomString', (length) => {
 | 
				
			||||||
 | 
						var result           = '';
 | 
				
			||||||
 | 
						var characters       = 'ABCDEFGHIJK LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
 | 
				
			||||||
 | 
						var charactersLength = characters.length;
 | 
				
			||||||
 | 
						for (var i = 0; i < length; i++) {
 | 
				
			||||||
 | 
							result += characters.charAt(Math.floor(Math.random() * charactersLength));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Check the swagger schema:
 | 
					 * Check the swagger schema:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {string}  method        API Method in swagger doc, "get", "put", "post", "delete"
 | 
					 * @param {string}  method        API Method in swagger doc, "get", "put", "post", "delete"
 | 
				
			||||||
 * @param {number}  statusCode    API status code in swagger doc
 | 
					 * @param {integer} code          Swagger doc endpoint response code, exactly as defined in swagger doc
 | 
				
			||||||
 * @param {string}  path          Swagger doc endpoint path, exactly as defined in swagger doc
 | 
					 * @param {string}  path          Swagger doc endpoint path, exactly as defined in swagger doc
 | 
				
			||||||
 * @param {*}       data          The API response data to check against the swagger schema
 | 
					 * @param {*}       data          The API response data to check against the swagger schema
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
Cypress.Commands.add('validateSwaggerSchema', (method, statusCode, path, data) => {
 | 
					Cypress.Commands.add('validateSwaggerSchema', (method, code, path, data) => {
 | 
				
			||||||
	cy.task('validateSwaggerSchema', {
 | 
						cy.task('validateSwaggerSchema', {
 | 
				
			||||||
		file:           Cypress.env('swaggerBase'),
 | 
							file:           Cypress.env('swaggerBase'),
 | 
				
			||||||
		endpoint:       path,
 | 
							endpoint:       path,
 | 
				
			||||||
		method:         method,
 | 
							method:         method,
 | 
				
			||||||
		statusCode:     statusCode,
 | 
							statusCode:     code,
 | 
				
			||||||
		responseSchema: data,
 | 
							responseSchema: data,
 | 
				
			||||||
		verbose:        true
 | 
							verbose:        true
 | 
				
			||||||
	}).should('equal', null);
 | 
						}).should('equal', null);
 | 
				
			||||||
@@ -40,3 +52,19 @@ Cypress.Commands.add('getToken', () => {
 | 
				
			|||||||
		cy.wrap(res.token);
 | 
							cy.wrap(res.token);
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: copied from v3, is this usable?
 | 
				
			||||||
 | 
					Cypress.Commands.add('waitForCertificateStatus', (token, certID, expected, timeout = 60) => {
 | 
				
			||||||
 | 
						cy.log(`Waiting for certificate (${certID}) status (${expected}) timeout (${timeout})`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cy.waitUntil(() => cy.task('backendApiGet', {
 | 
				
			||||||
 | 
							token: token,
 | 
				
			||||||
 | 
							path:  `/api/certificates/${certID}`
 | 
				
			||||||
 | 
						}).then((data) => {
 | 
				
			||||||
 | 
							return data.result.status === expected;
 | 
				
			||||||
 | 
						}), {
 | 
				
			||||||
 | 
							errorMsg: 'Waiting for certificate status failed',
 | 
				
			||||||
 | 
							timeout:  timeout * 1000,
 | 
				
			||||||
 | 
							interval: 5000
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,3 @@
 | 
				
			|||||||
require('cypress-plugin-retries');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import './commands';
 | 
					import './commands';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cypress.on('uncaught:exception', (/*err, runnable*/) => {
 | 
					Cypress.on('uncaught:exception', (/*err, runnable*/) => {
 | 
				
			||||||
@@ -4,19 +4,19 @@
 | 
				
			|||||||
	"description": "",
 | 
						"description": "",
 | 
				
			||||||
	"main": "index.js",
 | 
						"main": "index.js",
 | 
				
			||||||
	"dependencies": {
 | 
						"dependencies": {
 | 
				
			||||||
		"@jc21/cypress-swagger-validation": "^0.0.9",
 | 
							"@jc21/cypress-swagger-validation": "^0.2.6",
 | 
				
			||||||
		"@jc21/restler": "^3.4.0",
 | 
							"@jc21/restler": "^3.4.0",
 | 
				
			||||||
		"chalk": "^4.1.0",
 | 
							"chalk": "^4.1.0",
 | 
				
			||||||
		"cypress": "^9.4.1",
 | 
							"cypress": "^13.9.0",
 | 
				
			||||||
		"cypress-multi-reporters": "^1.4.0",
 | 
							"cypress-multi-reporters": "^1.6.4",
 | 
				
			||||||
		"cypress-plugin-retries": "^1.5.2",
 | 
							"cypress-wait-until": "^3.0.1",
 | 
				
			||||||
		"eslint": "^7.6.0",
 | 
							"eslint": "^9.3.0",
 | 
				
			||||||
		"eslint-plugin-align-assignments": "^1.1.2",
 | 
							"eslint-plugin-align-assignments": "^1.1.2",
 | 
				
			||||||
		"eslint-plugin-chai-friendly": "^0.6.0",
 | 
							"eslint-plugin-chai-friendly": "^0.7.4",
 | 
				
			||||||
		"eslint-plugin-cypress": "^2.11.1",
 | 
							"eslint-plugin-cypress": "^3.2.0",
 | 
				
			||||||
		"lodash": "^4.17.19",
 | 
							"lodash": "^4.17.21",
 | 
				
			||||||
		"mocha": "^8.1.1",
 | 
							"mocha": "^10.4.0",
 | 
				
			||||||
		"mocha-junit-reporter": "^2.0.0"
 | 
							"mocha-junit-reporter": "^2.2.1"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"scripts": {
 | 
						"scripts": {
 | 
				
			||||||
		"cypress": "cypress open --config-file=cypress/config/dev.json --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}",
 | 
							"cypress": "cypress open --config-file=cypress/config/dev.json --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}",
 | 
				
			||||||
 
 | 
				
			|||||||