Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
418899d425 | |||
e7379e3683 | |||
29bebcc73e | |||
26064b20b8 | |||
3dc9b20543 | |||
444dbd5160 | |||
c2f99e253c | |||
5c7fb7b698 | |||
733d7d9583 | |||
6d2f532806 | |||
f76c9226c8 | |||
ecbc41b622 | |||
4f60d3e7df | |||
7d86fd223e | |||
e3ed216a70 | |||
2a3d792591 | |||
4d754275ab | |||
44e5f0957c | |||
83ef426b93 | |||
8b8f5fac69 | |||
424ccce43c | |||
ad41cc985d | |||
981d5a199f | |||
48f2bb4cd8 | |||
aa270925e9 | |||
3836f7c40a | |||
9fcd32c2ca | |||
2657bcf30c | |||
86ad7d6238 | |||
c97e6ada5b | |||
cd40ca7f0a | |||
e2ac3b4880 | |||
7f8b185e48 | |||
e923db7e94 | |||
e53d9fa3eb | |||
411734f392 | |||
a457a40359 | |||
caa183c8de | |||
0ea5014edb | |||
046cb0b76e | |||
9fd480cf77 | |||
0f94e68dca | |||
c15edf318d | |||
a73cbc7116 | |||
f9876326c9 | |||
7d5ca84501 | |||
0335370cfb | |||
9b852f01e3 | |||
20fd185652 | |||
ad41986bd5 | |||
c826ed8c1f | |||
eaebc48f66 | |||
eb391959aa | |||
dba4340548 | |||
0b8a49469f | |||
b16a68052f | |||
83686c4535 | |||
efa1424cad | |||
4fe26ec4c0 |
@ -29,4 +29,11 @@ ADD knexfile.js /app/knexfile.js
|
|||||||
VOLUME [ "/data", "/etc/letsencrypt" ]
|
VOLUME [ "/data", "/etc/letsencrypt" ]
|
||||||
CMD [ "/init" ]
|
CMD [ "/init" ]
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 81
|
||||||
|
EXPOSE 443
|
||||||
|
EXPOSE 9876
|
||||||
|
|
||||||
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://localhost:9876/health || exit 1
|
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://localhost:9876/health || exit 1
|
||||||
|
|
||||||
|
38
Dockerfile.arm64
Normal file
38
Dockerfile.arm64
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
FROM jc21/nginx-proxy-manager-base:arm64
|
||||||
|
|
||||||
|
MAINTAINER Jamie Curnow <jc@jc21.com>
|
||||||
|
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||||
|
|
||||||
|
ENV SUPPRESS_NO_CONFIG_WARNING=1
|
||||||
|
ENV S6_FIX_ATTRS_HIDDEN=1
|
||||||
|
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf
|
||||||
|
|
||||||
|
# Nginx, Node and required packages should already be installed from the base image
|
||||||
|
|
||||||
|
# root filesystem
|
||||||
|
COPY rootfs /
|
||||||
|
|
||||||
|
# s6 overlay
|
||||||
|
RUN curl -L -o /tmp/s6-overlay-aarch64.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v1.21.8.0/s6-overlay-aarch64.tar.gz" \
|
||||||
|
&& tar xzf /tmp/s6-overlay-aarch64.tar.gz -C /
|
||||||
|
|
||||||
|
# App
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
ADD dist /app/dist
|
||||||
|
ADD node_modules /app/node_modules
|
||||||
|
ADD src/backend /app/src/backend
|
||||||
|
ADD package.json /app/package.json
|
||||||
|
ADD knexfile.js /app/knexfile.js
|
||||||
|
|
||||||
|
# Volumes
|
||||||
|
VOLUME [ "/data", "/etc/letsencrypt" ]
|
||||||
|
CMD [ "/init" ]
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 81
|
||||||
|
EXPOSE 443
|
||||||
|
EXPOSE 9876
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://localhost:9876/health || exit 1
|
@ -29,4 +29,10 @@ ADD knexfile.js /app/knexfile.js
|
|||||||
VOLUME [ "/data", "/etc/letsencrypt" ]
|
VOLUME [ "/data", "/etc/letsencrypt" ]
|
||||||
CMD [ "/init" ]
|
CMD [ "/init" ]
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 81
|
||||||
|
EXPOSE 443
|
||||||
|
EXPOSE 9876
|
||||||
|
|
||||||
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://localhost:9876/health || exit 1
|
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://localhost:9876/health || exit 1
|
||||||
|
38
Dockerfile.armv6
Normal file
38
Dockerfile.armv6
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
FROM jc21/nginx-proxy-manager-base:armv6
|
||||||
|
|
||||||
|
MAINTAINER Jamie Curnow <jc@jc21.com>
|
||||||
|
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||||
|
|
||||||
|
ENV SUPPRESS_NO_CONFIG_WARNING=1
|
||||||
|
ENV S6_FIX_ATTRS_HIDDEN=1
|
||||||
|
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf
|
||||||
|
|
||||||
|
# Nginx, Node and required packages should already be installed from the base image
|
||||||
|
|
||||||
|
# root filesystem
|
||||||
|
COPY rootfs /
|
||||||
|
|
||||||
|
# s6 overlay
|
||||||
|
RUN curl -L -o /tmp/s6-overlay-arm.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v1.21.8.0/s6-overlay-arm.tar.gz" \
|
||||||
|
&& tar xzf /tmp/s6-overlay-arm.tar.gz -C /
|
||||||
|
|
||||||
|
# App
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
ADD dist /app/dist
|
||||||
|
ADD node_modules /app/node_modules
|
||||||
|
ADD src/backend /app/src/backend
|
||||||
|
ADD package.json /app/package.json
|
||||||
|
ADD knexfile.js /app/knexfile.js
|
||||||
|
|
||||||
|
# Volumes
|
||||||
|
VOLUME [ "/data", "/etc/letsencrypt" ]
|
||||||
|
CMD [ "/init" ]
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
EXPOSE 80
|
||||||
|
EXPOSE 81
|
||||||
|
EXPOSE 443
|
||||||
|
EXPOSE 9876
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=15s --timeout=3s CMD curl -f http://localhost:9876/health || exit 1
|
221
Jenkinsfile
vendored
221
Jenkinsfile
vendored
@ -5,20 +5,82 @@ pipeline {
|
|||||||
}
|
}
|
||||||
agent any
|
agent any
|
||||||
environment {
|
environment {
|
||||||
IMAGE_NAME = "nginx-proxy-manager"
|
IMAGE = "nginx-proxy-manager"
|
||||||
BASE_IMAGE_NAME = "jc21/nginx-proxy-manager-base:v2"
|
BASE_IMAGE = "jc21/nginx-proxy-manager-base"
|
||||||
TEMP_IMAGE_NAME = "nginx-proxy-manager-build_${BUILD_NUMBER}"
|
TEMP_IMAGE = "nginx-proxy-manager-build_${BUILD_NUMBER}"
|
||||||
TEMP_IMAGE_NAME_ARM = "nginx-proxy-manager-arm-build_${BUILD_NUMBER}"
|
TEMP_IMAGE_ARM = "nginx-proxy-manager-arm-build_${BUILD_NUMBER}"
|
||||||
TAG_VERSION = getPackageVersion()
|
TEMP_IMAGE_ARM64 = "nginx-proxy-manager-arm64-build_${BUILD_NUMBER}"
|
||||||
MAJOR_VERSION = "2"
|
TAG_VERSION = getPackageVersion()
|
||||||
|
MAJOR_VERSION = "2"
|
||||||
|
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase()}"
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Prepare') {
|
stage('Build PR') {
|
||||||
|
when {
|
||||||
|
changeRequest()
|
||||||
|
}
|
||||||
steps {
|
steps {
|
||||||
sh 'docker pull $DOCKER_CI_TOOLS'
|
ansiColor('xterm') {
|
||||||
|
// Codebase
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} yarn install'
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} npm run-script build'
|
||||||
|
sh 'rm -rf node_modules'
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} yarn install --prod'
|
||||||
|
sh 'docker run --rm -v $(pwd):/data ${DOCKER_CI_TOOLS} node-prune'
|
||||||
|
|
||||||
|
// Docker Build
|
||||||
|
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE} .'
|
||||||
|
|
||||||
|
// Dockerhub
|
||||||
|
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}'
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||||
|
sh 'docker push docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}'
|
||||||
|
}
|
||||||
|
|
||||||
|
sh 'docker rmi ${TEMP_IMAGE}'
|
||||||
|
|
||||||
|
script {
|
||||||
|
def comment = pullRequest.comment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Build') {
|
stage('Build Develop') {
|
||||||
|
when {
|
||||||
|
branch 'develop'
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
ansiColor('xterm') {
|
||||||
|
// Codebase
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} yarn install'
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} npm run-script build'
|
||||||
|
sh 'rm -rf node_modules'
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} yarn install --prod'
|
||||||
|
sh 'docker run --rm -v $(pwd):/data ${DOCKER_CI_TOOLS} node-prune'
|
||||||
|
|
||||||
|
// Docker Build
|
||||||
|
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE} .'
|
||||||
|
|
||||||
|
// Dockerhub
|
||||||
|
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:develop'
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||||
|
sh 'docker push docker.io/jc21/${IMAGE}:develop'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Registry
|
||||||
|
sh 'docker tag ${TEMP_IMAGE} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:develop'
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-private-registry', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}' ${DOCKER_PRIVATE_REGISTRY}"
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:develop'
|
||||||
|
}
|
||||||
|
|
||||||
|
sh 'docker rmi ${TEMP_IMAGE}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build Master') {
|
||||||
parallel {
|
parallel {
|
||||||
stage('x86_64') {
|
stage('x86_64') {
|
||||||
when {
|
when {
|
||||||
@ -27,36 +89,40 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
ansiColor('xterm') {
|
ansiColor('xterm') {
|
||||||
// Codebase
|
// Codebase
|
||||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME yarn --registry=$NPM_REGISTRY install'
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} yarn install'
|
||||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME npm run-script build'
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} npm run-script build'
|
||||||
sh 'rm -rf node_modules'
|
sh 'rm -rf node_modules'
|
||||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME yarn --registry=$NPM_REGISTRY install --prod'
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE} yarn install --prod'
|
||||||
sh 'docker run --rm -v $(pwd):/data $DOCKER_CI_TOOLS node-prune'
|
sh 'docker run --rm -v $(pwd):/data ${DOCKER_CI_TOOLS} node-prune'
|
||||||
|
|
||||||
// Docker Build
|
// Docker Build
|
||||||
sh 'docker build --pull --no-cache --squash --compress -t $TEMP_IMAGE_NAME .'
|
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE} .'
|
||||||
|
|
||||||
// Private Registry
|
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$TAG_VERSION'
|
|
||||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$TAG_VERSION'
|
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION'
|
|
||||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION'
|
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest'
|
|
||||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest'
|
|
||||||
|
|
||||||
// Dockerhub
|
// Dockerhub
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:$TAG_VERSION'
|
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:${TAG_VERSION}'
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:$MAJOR_VERSION'
|
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:${MAJOR_VERSION}'
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:latest'
|
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:latest'
|
||||||
|
|
||||||
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
sh "docker login -u '${duser}' -p '$dpass'"
|
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:$TAG_VERSION'
|
sh 'docker push docker.io/jc21/${IMAGE}:${TAG_VERSION}'
|
||||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:$MAJOR_VERSION'
|
sh 'docker push docker.io/jc21/${IMAGE}:${MAJOR_VERSION}'
|
||||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:latest'
|
sh 'docker push docker.io/jc21/${IMAGE}:latest'
|
||||||
}
|
}
|
||||||
|
|
||||||
sh 'docker rmi $TEMP_IMAGE_NAME'
|
// Private Registry
|
||||||
|
sh 'docker tag ${TEMP_IMAGE} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${TAG_VERSION}'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${MAJOR_VERSION}'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:latest'
|
||||||
|
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-private-registry', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}' ${DOCKER_PRIVATE_REGISTRY}"
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${TAG_VERSION}'
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${MAJOR_VERSION}'
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:latest'
|
||||||
|
}
|
||||||
|
|
||||||
|
sh 'docker rmi ${TEMP_IMAGE}'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,35 +136,88 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
ansiColor('xterm') {
|
ansiColor('xterm') {
|
||||||
// Codebase
|
// Codebase
|
||||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME-armhf yarn --registry=$NPM_REGISTRY install'
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:armhf yarn install'
|
||||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME-armhf npm run-script build'
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:armhf npm run-script build'
|
||||||
sh 'rm -rf node_modules'
|
sh 'rm -rf node_modules'
|
||||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME-armhf yarn --registry=$NPM_REGISTRY install --prod'
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:armhf yarn install --prod'
|
||||||
|
|
||||||
// Docker Build
|
// Docker Build
|
||||||
sh 'docker build --pull --no-cache --squash --compress -t $TEMP_IMAGE_NAME_ARM -f Dockerfile.armhf .'
|
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE_ARM} -f Dockerfile.armhf .'
|
||||||
|
|
||||||
// Private Registry
|
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$TAG_VERSION-armhf'
|
|
||||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$TAG_VERSION-armhf'
|
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION-armhf'
|
|
||||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION-armhf'
|
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest-armhf'
|
|
||||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest-armhf'
|
|
||||||
|
|
||||||
// Dockerhub
|
// Dockerhub
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM docker.io/jc21/$IMAGE_NAME:$TAG_VERSION-armhf'
|
sh 'docker tag ${TEMP_IMAGE_ARM} docker.io/jc21/${IMAGE}:${TAG_VERSION}-armhf'
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM docker.io/jc21/$IMAGE_NAME:$MAJOR_VERSION-armhf'
|
sh 'docker tag ${TEMP_IMAGE_ARM} docker.io/jc21/${IMAGE}:${MAJOR_VERSION}-armhf'
|
||||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM docker.io/jc21/$IMAGE_NAME:latest-armhf'
|
sh 'docker tag ${TEMP_IMAGE_ARM} docker.io/jc21/${IMAGE}:latest-armhf'
|
||||||
|
|
||||||
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
sh "docker login -u '${duser}' -p '$dpass'"
|
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:$TAG_VERSION-armhf'
|
sh 'docker push docker.io/jc21/${IMAGE}:${TAG_VERSION}-armhf'
|
||||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:$MAJOR_VERSION-armhf'
|
sh 'docker push docker.io/jc21/${IMAGE}:${MAJOR_VERSION}-armhf'
|
||||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:latest-armhf'
|
sh 'docker push docker.io/jc21/${IMAGE}:latest-armhf'
|
||||||
}
|
}
|
||||||
|
|
||||||
sh 'docker rmi $TEMP_IMAGE_NAME_ARM'
|
// Private Registry
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${TAG_VERSION}-armhf'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${MAJOR_VERSION}-armhf'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:latest-armhf'
|
||||||
|
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-private-registry', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}' ${DOCKER_PRIVATE_REGISTRY}"
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${TAG_VERSION}-armhf'
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${MAJOR_VERSION}-armhf'
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:latest-armhf'
|
||||||
|
}
|
||||||
|
|
||||||
|
sh 'docker rmi ${TEMP_IMAGE_ARM}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('arm64') {
|
||||||
|
when {
|
||||||
|
branch 'master'
|
||||||
|
}
|
||||||
|
agent {
|
||||||
|
label 'arm64'
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
ansiColor('xterm') {
|
||||||
|
// Codebase
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:arm64 yarn install'
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:arm64 npm run-script build'
|
||||||
|
sh 'sudo rm -rf node_modules'
|
||||||
|
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:arm64 yarn install --prod'
|
||||||
|
|
||||||
|
// Docker Build
|
||||||
|
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE_ARM64} -f Dockerfile.arm64 .'
|
||||||
|
|
||||||
|
// Dockerhub
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM64} docker.io/jc21/${IMAGE}:${TAG_VERSION}-arm64'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM64} docker.io/jc21/${IMAGE}:${MAJOR_VERSION}-arm64'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM64} docker.io/jc21/${IMAGE}:latest-arm64'
|
||||||
|
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||||
|
sh 'docker push docker.io/jc21/${IMAGE}:${TAG_VERSION}-arm64'
|
||||||
|
sh 'docker push docker.io/jc21/${IMAGE}:${MAJOR_VERSION}-arm64'
|
||||||
|
sh 'docker push docker.io/jc21/${IMAGE}:latest-arm64'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Registry
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM64} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${TAG_VERSION}-arm64'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM64} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${MAJOR_VERSION}-arm64'
|
||||||
|
sh 'docker tag ${TEMP_IMAGE_ARM64} ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:latest-arm64'
|
||||||
|
|
||||||
|
withCredentials([usernamePassword(credentialsId: 'jc21-private-registry', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
|
sh "docker login -u '${duser}' -p '${dpass}' ${DOCKER_PRIVATE_REGISTRY}"
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${TAG_VERSION}-arm64'
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:${MAJOR_VERSION}-arm64'
|
||||||
|
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:latest-arm64'
|
||||||
|
}
|
||||||
|
|
||||||
|
sh 'docker rmi ${TEMP_IMAGE_ARM64}'
|
||||||
|
|
||||||
|
// Hack to clean up ec2 instance for next build
|
||||||
|
sh 'sudo chown -R ec2-user:ec2-user *'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,7 +237,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def getPackageVersion() {
|
def getPackageVersion() {
|
||||||
ver = sh(script: 'docker run --rm -v $(pwd):/data $DOCKER_CI_TOOLS bash -c "cat /data/package.json|jq -r \'.version\'"', returnStdout: true)
|
ver = sh(script: 'docker run --rm -v $(pwd):/data ${DOCKER_CI_TOOLS} bash -c "cat /data/package.json|jq -r \'.version\'"', returnStdout: true)
|
||||||
return ver.trim()
|
return ver.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
README.md
16
README.md
@ -2,20 +2,22 @@
|
|||||||
|
|
||||||
# Nginx Proxy Manager
|
# Nginx Proxy Manager
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||||
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
**WARNING: Version 2 a complete rewrite!** If you are using the `latest` docker tag and update to version 2
|
|
||||||
without preparation, horrible things might happen. Refer to the [Importing Documentation](doc/IMPORTING.md).
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
|
## Project Goal
|
||||||
|
|
||||||
|
I created this project to fill a personal need to provide users with a 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.
|
||||||
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Beautiful and Secure Admin Interface based on [Tabler](https://tabler.github.io/)
|
- Beautiful and Secure Admin Interface based on [Tabler](https://tabler.github.io/)
|
||||||
|
17
TODO.md
17
TODO.md
@ -1,17 +0,0 @@
|
|||||||
# TODO
|
|
||||||
|
|
||||||
- Dashboard stats are caching instead of querying
|
|
||||||
|
|
||||||
Next version:
|
|
||||||
|
|
||||||
- UI Log tail
|
|
||||||
- Enable/Disable a config
|
|
||||||
|
|
||||||
Testing:
|
|
||||||
|
|
||||||
- Access Levels
|
|
||||||
- Adding a proxy host without access to read certs or access lists
|
|
||||||
- Visibility
|
|
||||||
- Forwarding
|
|
||||||
- Cert renewals
|
|
||||||
- Custom certs
|
|
26
bin/migrate_create
Executable file
26
bin/migrate_create
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ "$1" == "" ]; then
|
||||||
|
echo "Error: migrate name must be specified as first arg"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
# Code path
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
if hash realpath 2>/dev/null; then
|
||||||
|
export CODEBASE=$(realpath $SCRIPT_DIR/..)
|
||||||
|
elif hash grealpath 2>/dev/null; then
|
||||||
|
export CODEBASE=$(grealpath $SCRIPT_DIR/..)
|
||||||
|
else
|
||||||
|
export CODEBASE=$(readlink -e $SCRIPT_DIR/..)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CODEBASE" ]; then
|
||||||
|
echo "Unable to determine absolute codebase directory"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$CODEBASE"
|
||||||
|
|
||||||
|
sudo /usr/local/bin/docker-compose run --rm --no-deps app node node_modules/knex/bin/cli.js migrate:make "$1"
|
||||||
|
exit $?
|
||||||
|
fi
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Nginx Proxy Manager
|
# Nginx Proxy Manager
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
@ -16,6 +16,7 @@ running at home or otherwise, including free SSL, without having to know too muc
|
|||||||
|
|
||||||
* latest 2, 2.x.x ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/master/Dockerfile))
|
* latest 2, 2.x.x ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/master/Dockerfile))
|
||||||
* latest-armhf, 2-armhf, 2.x.x-armhf ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/master/Dockerfile.armhf))
|
* latest-armhf, 2-armhf, 2.x.x-armhf ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/master/Dockerfile.armhf))
|
||||||
|
* latest-arm64, 2-arm64, 2.x.x-arm64 ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/master/Dockerfile.arm64))
|
||||||
* 1, 1.x.x ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/1.1.2/Dockerfile))
|
* 1, 1.x.x ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/1.1.2/Dockerfile))
|
||||||
* 1-armhf, 1.x.x-armhf ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/1.1.2/Dockerfile.armhf))
|
* 1-armhf, 1.x.x-armhf ([Dockerfile](https://github.com/jc21/nginx-proxy-manager/blob/1.1.2/Dockerfile.armhf))
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ It's easy to use another docker container for your database also and link it as
|
|||||||
version: "3"
|
version: "3"
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: jc21/nginx-proxy-manager:2
|
image: jc21/nginx-proxy-manager:latest
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
@ -57,7 +57,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
db:
|
db:
|
||||||
image: mariadb
|
image: jc21/mariadb-aria
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: "password123"
|
MYSQL_ROOT_PASSWORD: "password123"
|
||||||
@ -77,7 +77,7 @@ Via `docker-compose`:
|
|||||||
version: "3"
|
version: "3"
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: jc21/nginx-proxy-manager:2
|
image: jc21/nginx-proxy-manager:latest
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
@ -100,15 +100,17 @@ docker run -d \
|
|||||||
-v /path/to/config.json:/app/config/production.json \
|
-v /path/to/config.json:/app/config/production.json \
|
||||||
-v /path/to/data:/data \
|
-v /path/to/data:/data \
|
||||||
-v /path/to/letsencrypt:/etc/letsencrypt \
|
-v /path/to/letsencrypt:/etc/letsencrypt \
|
||||||
jc21/nginx-proxy-manager:2
|
jc21/nginx-proxy-manager:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Running on Raspberry PI / `armhf`
|
### Running on Raspberry PI / `armhf`
|
||||||
|
|
||||||
I have created a `armhf` docker container just for you. There may be issues with it,
|
I have created `armhf` and `arm64` docker containers just for you. There may be issues with it,
|
||||||
if you have issues please report them here.
|
if you have issues please report them here.
|
||||||
|
|
||||||
|
Note: Rpi v2 and below won't work with these images.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
--name nginx-proxy-manager-app \
|
--name nginx-proxy-manager-app \
|
||||||
@ -118,7 +120,7 @@ docker run -d \
|
|||||||
-v /path/to/config.json:/app/config/production.json \
|
-v /path/to/config.json:/app/config/production.json \
|
||||||
-v /path/to/data:/data \
|
-v /path/to/data:/data \
|
||||||
-v /path/to/letsencrypt:/etc/letsencrypt \
|
-v /path/to/letsencrypt:/etc/letsencrypt \
|
||||||
jc21/nginx-proxy-manager:2-armhf
|
jc21/nginx-proxy-manager:latest-armhf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ services:
|
|||||||
# if you want pretty colors in your docker logs:
|
# if you want pretty colors in your docker logs:
|
||||||
- FORCE_COLOR=1
|
- FORCE_COLOR=1
|
||||||
db:
|
db:
|
||||||
image: mariadb
|
image: jc21/mariadb-aria
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: "password123"
|
MYSQL_ROOT_PASSWORD: "password123"
|
||||||
|
@ -11,6 +11,7 @@ services:
|
|||||||
- NODE_ENV=development
|
- NODE_ENV=development
|
||||||
- FORCE_COLOR=1
|
- FORCE_COLOR=1
|
||||||
volumes:
|
volumes:
|
||||||
|
- ./data:/data
|
||||||
- ./data/letsencrypt:/etc/letsencrypt
|
- ./data/letsencrypt:/etc/letsencrypt
|
||||||
- .:/app
|
- .:/app
|
||||||
- ./rootfs/etc/nginx:/etc/nginx
|
- ./rootfs/etc/nginx:/etc/nginx
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nginx-proxy-manager",
|
"name": "nginx-proxy-manager",
|
||||||
"version": "2.0.2",
|
"version": "2.0.10",
|
||||||
"description": "A beautiful interface for creating Nginx endpoints",
|
"description": "A beautiful interface for creating Nginx endpoints",
|
||||||
"main": "src/backend/index.js",
|
"main": "src/backend/index.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -30,8 +30,8 @@
|
|||||||
"style-loader": "^0.22.1",
|
"style-loader": "^0.22.1",
|
||||||
"tabler-ui": "git+https://github.com/tabler/tabler.git",
|
"tabler-ui": "git+https://github.com/tabler/tabler.git",
|
||||||
"underscore": "^1.8.3",
|
"underscore": "^1.8.3",
|
||||||
"webpack": "^4.12.0",
|
"webpack": "^4.25.1",
|
||||||
"webpack-cli": "^3.0.8",
|
"webpack-cli": "^3.1.2",
|
||||||
"webpack-visualizer-plugin": "^0.1.11"
|
"webpack-visualizer-plugin": "^0.1.11"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -8,8 +8,9 @@ server {
|
|||||||
|
|
||||||
include conf.d/include/block-exploits.conf;
|
include conf.d/include/block-exploits.conf;
|
||||||
|
|
||||||
set $server 127.0.0.1;
|
set $forward_scheme http;
|
||||||
set $port 81;
|
set $server 127.0.0.1;
|
||||||
|
set $port 81;
|
||||||
|
|
||||||
location /health {
|
location /health {
|
||||||
access_log off;
|
access_log off;
|
||||||
@ -36,3 +37,17 @@ server {
|
|||||||
root /var/www/html;
|
root /var/www/html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Default 443 Host
|
||||||
|
server {
|
||||||
|
listen 443 ssl default;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
access_log /data/logs/default.log proxy;
|
||||||
|
|
||||||
|
ssl_certificate /data/nginx/dummycert.pem;
|
||||||
|
ssl_certificate_key /data/nginx/dummykey.pem;
|
||||||
|
ssl_ciphers aNULL;
|
||||||
|
|
||||||
|
return 444;
|
||||||
|
}
|
||||||
|
2
rootfs/etc/nginx/conf.d/include/ip_ranges.conf
Normal file
2
rootfs/etc/nginx/conf.d/include/ip_ranges.conf
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Intentionally left blank
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
add_header X-Served-By $host;
|
add_header X-Served-By $host;
|
||||||
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-Protocol $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
proxy_pass http://$server:$port;
|
proxy_pass $forward_scheme://$server:$port;
|
||||||
|
1
rootfs/etc/nginx/conf.d/include/resolvers.conf
Normal file
1
rootfs/etc/nginx/conf.d/include/resolvers.conf
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Intentionally blank
|
@ -7,6 +7,3 @@ ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA
|
|||||||
ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AE
|
ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AE
|
||||||
S128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
|
S128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
|
||||||
ssl_prefer_server_ciphers on;
|
ssl_prefer_server_ciphers on;
|
||||||
|
|
||||||
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
|
|
||||||
add_header Strict-Transport-Security max-age=15768000;
|
|
||||||
|
@ -51,6 +51,24 @@ http {
|
|||||||
|
|
||||||
access_log /data/logs/default.log proxy;
|
access_log /data/logs/default.log proxy;
|
||||||
|
|
||||||
|
# Dynamically generated resolvers file
|
||||||
|
include /etc/nginx/conf.d/include/resolvers.conf;
|
||||||
|
|
||||||
|
# Default upstream scheme
|
||||||
|
map $host $forward_scheme {
|
||||||
|
default http;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Real IP Determination
|
||||||
|
# Docker subnet:
|
||||||
|
set_real_ip_from 172.0.0.0/8;
|
||||||
|
# NPM generated CDN ip ranges:
|
||||||
|
include conf.d/include/ip_ranges.conf;
|
||||||
|
# always put the following 2 lines after ip subnets:
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
real_ip_recursive on;
|
||||||
|
|
||||||
|
# Files generated by NPM
|
||||||
include /etc/nginx/conf.d/*.conf;
|
include /etc/nginx/conf.d/*.conf;
|
||||||
include /data/nginx/proxy_host/*.conf;
|
include /data/nginx/proxy_host/*.conf;
|
||||||
include /data/nginx/redirection_host/*.conf;
|
include /data/nginx/redirection_host/*.conf;
|
||||||
@ -59,6 +77,7 @@ http {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream {
|
stream {
|
||||||
|
# Files generated by NPM
|
||||||
include /data/nginx/stream/*.conf;
|
include /data/nginx/stream/*.conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,4 +3,9 @@
|
|||||||
mkdir -p /data/letsencrypt-acme-challenge
|
mkdir -p /data/letsencrypt-acme-challenge
|
||||||
|
|
||||||
cd /app
|
cd /app
|
||||||
node --abort_on_uncaught_exception --max_old_space_size=250 /app/src/backend/index.js
|
|
||||||
|
while :
|
||||||
|
do
|
||||||
|
node --abort_on_uncaught_exception --max_old_space_size=250 /app/src/backend/index.js
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/usr/bin/with-contenv bash
|
||||||
|
|
||||||
|
# Create required folders
|
||||||
mkdir -p /tmp/nginx/body \
|
mkdir -p /tmp/nginx/body \
|
||||||
/var/log/nginx \
|
/var/log/nginx \
|
||||||
/data/nginx \
|
/data/nginx \
|
||||||
@ -12,9 +13,30 @@ mkdir -p /tmp/nginx/body \
|
|||||||
/data/nginx/dead_host \
|
/data/nginx/dead_host \
|
||||||
/data/nginx/temp \
|
/data/nginx/temp \
|
||||||
/var/lib/nginx/cache/public \
|
/var/lib/nginx/cache/public \
|
||||||
/var/lib/nginx/cache/private
|
/var/lib/nginx/cache/private \
|
||||||
|
/var/cache/nginx/proxy_temp
|
||||||
|
|
||||||
touch /var/log/nginx/error.log && chmod 777 /var/log/nginx/error.log
|
touch /var/log/nginx/error.log && chmod 777 /var/log/nginx/error.log && chmod -R 777 /var/cache/nginx
|
||||||
chown root /tmp/nginx
|
chown root /tmp/nginx
|
||||||
|
|
||||||
|
# Dynamically generate resolvers file
|
||||||
|
echo resolver $(awk 'BEGIN{ORS=" "} $1=="nameserver" {print $2}' /etc/resolv.conf) ";" > /etc/nginx/conf.d/include/resolvers.conf
|
||||||
|
|
||||||
|
# Generate dummy self-signed certificate.
|
||||||
|
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]
|
||||||
|
then
|
||||||
|
echo "Generating dummy SSL certificate..."
|
||||||
|
openssl req \
|
||||||
|
-new \
|
||||||
|
-newkey rsa:2048 \
|
||||||
|
-days 3650 \
|
||||||
|
-nodes \
|
||||||
|
-x509 \
|
||||||
|
-subj '/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost' \
|
||||||
|
-keyout /data/nginx/dummykey.pem \
|
||||||
|
-out /data/nginx/dummycert.pem
|
||||||
|
echo "Complete"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run
|
||||||
exec nginx
|
exec nginx
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logger = require('./logger').import;
|
const logger = require('./logger').import;
|
||||||
const utils = require('./lib/utils');
|
const utils = require('./lib/utils');
|
||||||
const batchflow = require('batchflow');
|
const batchflow = require('batchflow');
|
||||||
|
const debug_mode = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
const internalProxyHost = require('./internal/proxy-host');
|
const internalProxyHost = require('./internal/proxy-host');
|
||||||
const internalRedirectionHost = require('./internal/redirection-host');
|
const internalRedirectionHost = require('./internal/redirection-host');
|
||||||
@ -353,7 +354,7 @@ module.exports = function () {
|
|||||||
.insertAndFetch({
|
.insertAndFetch({
|
||||||
owner_user_id: 1,
|
owner_user_id: 1,
|
||||||
domain_names: [host.hostname],
|
domain_names: [host.hostname],
|
||||||
forward_ip: host.forward_server,
|
forward_host: host.forward_server,
|
||||||
forward_port: host.forward_port,
|
forward_port: host.forward_port,
|
||||||
access_list_id: access_list_id,
|
access_list_id: access_list_id,
|
||||||
certificate_id: certificate_id,
|
certificate_id: certificate_id,
|
||||||
@ -534,6 +535,10 @@ module.exports = function () {
|
|||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (debug_mode) {
|
||||||
|
logger.debug('Importer skipped');
|
||||||
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -11,6 +11,7 @@ function appStart () {
|
|||||||
const app = require('./app');
|
const app = require('./app');
|
||||||
const apiValidator = require('./lib/validator/api');
|
const apiValidator = require('./lib/validator/api');
|
||||||
const internalCertificate = require('./internal/certificate');
|
const internalCertificate = require('./internal/certificate');
|
||||||
|
const internalIpRanges = require('./internal/ip_ranges');
|
||||||
|
|
||||||
return migrate.latest()
|
return migrate.latest()
|
||||||
.then(setup)
|
.then(setup)
|
||||||
@ -18,9 +19,11 @@ function appStart () {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
return apiValidator.loadSchemas;
|
return apiValidator.loadSchemas;
|
||||||
})
|
})
|
||||||
|
.then(internalIpRanges.fetch)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
||||||
internalCertificate.initTimer();
|
internalCertificate.initTimer();
|
||||||
|
internalIpRanges.initTimer();
|
||||||
|
|
||||||
const server = app.listen(81, () => {
|
const server = app.listen(81, () => {
|
||||||
logger.info('PID ' + process.pid + ' listening on port 81 ...');
|
logger.info('PID ' + process.pid + ' listening on port 81 ...');
|
||||||
|
@ -47,6 +47,7 @@ const internalDeadHost = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point the domains should have been checked
|
// At this point the domains should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
|
data = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
@ -89,11 +90,11 @@ const internalDeadHost = {
|
|||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'dead-host',
|
object_type: 'dead-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
@ -103,7 +104,7 @@ const internalDeadHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
@ -144,9 +145,9 @@ const internalDeadHost = {
|
|||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate.createQuickCertificate(access, {
|
||||||
domain_names: data.domain_names || row.domain_names,
|
domain_names: data.domain_names || row.domain_names,
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
meta: _.assign({}, row.meta, data.meta)
|
||||||
})
|
})
|
||||||
.then(cert => {
|
.then(cert => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
data.certificate_id = cert.id;
|
||||||
@ -162,7 +163,9 @@ const internalDeadHost = {
|
|||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
data = _.assign({}, {
|
||||||
domain_names: row.domain_names
|
domain_names: row.domain_names
|
||||||
},data);
|
}, data);
|
||||||
|
|
||||||
|
data = internalHost.cleanSslHstsData(data, row);
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
@ -171,11 +174,11 @@ const internalDeadHost = {
|
|||||||
.then(saved_row => {
|
.then(saved_row => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'dead-host',
|
object_type: 'dead-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
});
|
});
|
||||||
@ -183,15 +186,15 @@ const internalDeadHost = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {
|
return internalDeadHost.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'certificate']
|
expand: ['owner', 'certificate']
|
||||||
})
|
})
|
||||||
.then(row => {
|
.then(row => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(deadHostModel, 'dead_host', row)
|
return internalNginx.configure(deadHostModel, 'dead_host', row)
|
||||||
.then(new_meta => {
|
.then(new_meta => {
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -201,7 +204,7 @@ const internalDeadHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {Array} [data.expand]
|
* @param {Array} [data.expand]
|
||||||
* @param {Array} [data.omit]
|
* @param {Array} [data.omit]
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
@ -248,7 +251,7 @@ const internalDeadHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {String} [data.reason]
|
* @param {String} [data.reason]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -290,6 +293,104 @@ const internalDeadHost = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: (access, data) => {
|
||||||
|
return access.can('dead_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalDeadHost.get(access, {
|
||||||
|
id: data.id,
|
||||||
|
expand: ['certificate', 'owner']
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 1;
|
||||||
|
|
||||||
|
return deadHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 1
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Configure nginx
|
||||||
|
return internalNginx.configure(deadHostModel, 'dead_host', row);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'enabled',
|
||||||
|
object_type: 'dead-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: (access, data) => {
|
||||||
|
return access.can('dead_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalDeadHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (!row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 0;
|
||||||
|
|
||||||
|
return deadHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 0
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Delete Nginx Config
|
||||||
|
return internalNginx.deleteConfig('dead_host', row)
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'disabled',
|
||||||
|
object_type: 'dead-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All Hosts
|
* All Hosts
|
||||||
*
|
*
|
||||||
@ -338,7 +439,7 @@ const internalDeadHost = {
|
|||||||
/**
|
/**
|
||||||
* Report use
|
* Report use
|
||||||
*
|
*
|
||||||
* @param {Integer} user_id
|
* @param {Number} user_id
|
||||||
* @param {String} visibility
|
* @param {String} visibility
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -1,11 +1,40 @@
|
|||||||
'use strict';
|
const _ = require('lodash');
|
||||||
|
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
const redirectionHostModel = require('../models/redirection_host');
|
const redirectionHostModel = require('../models/redirection_host');
|
||||||
const deadHostModel = require('../models/dead_host');
|
const deadHostModel = require('../models/dead_host');
|
||||||
|
|
||||||
const internalHost = {
|
const internalHost = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure that the ssl_* and hsts_* fields play nicely together.
|
||||||
|
* ie: if there is no cert, then force_ssl is off.
|
||||||
|
* if force_ssl is off, then hsts_enabled is definitely off.
|
||||||
|
*
|
||||||
|
* @param {object} data
|
||||||
|
* @param {object} [existing_data]
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
cleanSslHstsData: function (data, existing_data) {
|
||||||
|
existing_data = existing_data === undefined ? {} : existing_data;
|
||||||
|
|
||||||
|
let combined_data = _.assign({}, existing_data, data);
|
||||||
|
|
||||||
|
if (!combined_data.certificate_id) {
|
||||||
|
combined_data.ssl_forced = false;
|
||||||
|
combined_data.http2_support = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!combined_data.ssl_forced) {
|
||||||
|
combined_data.hsts_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!combined_data.hsts_enabled) {
|
||||||
|
combined_data.hsts_subdomains = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return combined_data;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* used by the getAll functions of hosts, this removes the certificate meta if present
|
* used by the getAll functions of hosts, this removes the certificate meta if present
|
||||||
*
|
*
|
||||||
|
150
src/backend/internal/ip_ranges.js
Normal file
150
src/backend/internal/ip_ranges.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const https = require('https');
|
||||||
|
const fs = require('fs');
|
||||||
|
const _ = require('lodash');
|
||||||
|
const logger = require('../logger').ip_ranges;
|
||||||
|
const error = require('../lib/error');
|
||||||
|
const internalNginx = require('./nginx');
|
||||||
|
const Liquid = require('liquidjs');
|
||||||
|
|
||||||
|
const CLOUDFRONT_URL = 'https://ip-ranges.amazonaws.com/ip-ranges.json';
|
||||||
|
const CLOUDFARE_V4_URL = 'https://www.cloudflare.com/ips-v4';
|
||||||
|
const CLOUDFARE_V6_URL = 'https://www.cloudflare.com/ips-v6';
|
||||||
|
|
||||||
|
const internalIpRanges = {
|
||||||
|
|
||||||
|
interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
|
||||||
|
interval: null,
|
||||||
|
interval_processing: false,
|
||||||
|
iteration_count: 0,
|
||||||
|
|
||||||
|
initTimer: () => {
|
||||||
|
logger.info('IP Ranges Renewal Timer initialized');
|
||||||
|
internalIpRanges.interval = setInterval(internalIpRanges.fetch, internalIpRanges.interval_timeout);
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchUrl: url => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
logger.info('Fetching ' + url);
|
||||||
|
return https.get(url, res => {
|
||||||
|
res.setEncoding('utf8');
|
||||||
|
let raw_data = '';
|
||||||
|
res.on('data', chunk => {
|
||||||
|
raw_data += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on('end', () => {
|
||||||
|
resolve(raw_data);
|
||||||
|
});
|
||||||
|
}).on('error', err => {
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered at startup and then later by a timer, this will fetch the ip ranges from services and apply them to nginx.
|
||||||
|
*/
|
||||||
|
fetch: () => {
|
||||||
|
if (!internalIpRanges.interval_processing) {
|
||||||
|
internalIpRanges.interval_processing = true;
|
||||||
|
logger.info('Fetching IP Ranges from online services...');
|
||||||
|
|
||||||
|
let ip_ranges = [];
|
||||||
|
|
||||||
|
return internalIpRanges.fetchUrl(CLOUDFRONT_URL)
|
||||||
|
.then(cloudfront_data => {
|
||||||
|
let data = JSON.parse(cloudfront_data);
|
||||||
|
|
||||||
|
if (data && typeof data.prefixes !== 'undefined') {
|
||||||
|
data.prefixes.map(item => {
|
||||||
|
if (item.service === 'CLOUDFRONT') {
|
||||||
|
ip_ranges.push(item.ip_prefix);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data && typeof data.ipv6_prefixes !== 'undefined') {
|
||||||
|
data.ipv6_prefixes.map(item => {
|
||||||
|
if (item.service === 'CLOUDFRONT') {
|
||||||
|
ip_ranges.push(item.ipv6_prefix);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return internalIpRanges.fetchUrl(CLOUDFARE_V4_URL);
|
||||||
|
})
|
||||||
|
.then(cloudfare_data => {
|
||||||
|
let items = cloudfare_data.split('\n');
|
||||||
|
ip_ranges = [... ip_ranges, ... items];
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return internalIpRanges.fetchUrl(CLOUDFARE_V6_URL);
|
||||||
|
})
|
||||||
|
.then(cloudfare_data => {
|
||||||
|
let items = cloudfare_data.split('\n');
|
||||||
|
ip_ranges = [... ip_ranges, ... items];
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
let clean_ip_ranges = [];
|
||||||
|
ip_ranges.map(range => {
|
||||||
|
if (range) {
|
||||||
|
clean_ip_ranges.push(range);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return internalIpRanges.generateConfig(clean_ip_ranges)
|
||||||
|
.then(() => {
|
||||||
|
if (internalIpRanges.iteration_count) {
|
||||||
|
// Reload nginx
|
||||||
|
return internalNginx.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
internalIpRanges.interval_processing = false;
|
||||||
|
internalIpRanges.iteration_count++;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.error(err.message);
|
||||||
|
internalIpRanges.interval_processing = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} ip_ranges
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
generateConfig: (ip_ranges) => {
|
||||||
|
let renderEngine = Liquid({
|
||||||
|
root: __dirname + '/../templates/'
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let template = null;
|
||||||
|
let filename = '/etc/nginx/conf.d/include/ip_ranges.conf';
|
||||||
|
try {
|
||||||
|
template = fs.readFileSync(__dirname + '/../templates/ip_ranges.conf', {encoding: 'utf8'});
|
||||||
|
} catch (err) {
|
||||||
|
reject(new error.ConfigurationError(err.message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEngine
|
||||||
|
.parseAndRender(template, {ip_ranges: ip_ranges})
|
||||||
|
.then(config_text => {
|
||||||
|
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
logger.warn('Could not write ' + filename + ':', err.message);
|
||||||
|
reject(new error.ConfigurationError(err.message));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = internalIpRanges;
|
@ -1,5 +1,3 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const Liquid = require('liquidjs');
|
const Liquid = require('liquidjs');
|
||||||
@ -92,7 +90,7 @@ const internalNginx = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return combined_meta;
|
return combined_meta;
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,6 +144,7 @@ const internalNginx = {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let filename = internalNginx.getConfigName(host_type, host.id);
|
let filename = internalNginx.getConfigName(host_type, host.id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/' + host_type + '.conf', {encoding: 'utf8'});
|
template = fs.readFileSync(__dirname + '/../templates/' + host_type + '.conf', {encoding: 'utf8'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -153,6 +152,12 @@ const internalNginx = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manipulate the data a bit before sending it to the template
|
||||||
|
host.use_default_location = true;
|
||||||
|
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
|
||||||
|
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
||||||
|
}
|
||||||
|
|
||||||
renderEngine
|
renderEngine
|
||||||
.parseAndRender(template, host)
|
.parseAndRender(template, host)
|
||||||
.then(config_text => {
|
.then(config_text => {
|
||||||
@ -312,6 +317,14 @@ const internalNginx = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} config
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
advancedConfigHasDefaultLocation: function (config) {
|
||||||
|
return !!config.match(/^(?:.*;)?\s*?location\s*?\/\s*?{/im);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
@ -47,6 +45,7 @@ const internalProxyHost = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point the domains should have been checked
|
// At this point the domains should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
|
data = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
@ -90,11 +89,11 @@ const internalProxyHost = {
|
|||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'proxy-host',
|
object_type: 'proxy-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
@ -104,12 +103,12 @@ const internalProxyHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
let create_certificate = data.certificate_id === 'new';
|
||||||
|
console.log('PH UPDATE:', data);
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
delete data.certificate_id;
|
delete data.certificate_id;
|
||||||
}
|
}
|
||||||
@ -145,9 +144,9 @@ const internalProxyHost = {
|
|||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate.createQuickCertificate(access, {
|
||||||
domain_names: data.domain_names || row.domain_names,
|
domain_names: data.domain_names || row.domain_names,
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
meta: _.assign({}, row.meta, data.meta)
|
||||||
})
|
})
|
||||||
.then(cert => {
|
.then(cert => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
data.certificate_id = cert.id;
|
||||||
@ -163,7 +162,9 @@ const internalProxyHost = {
|
|||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
data = _.assign({}, {
|
||||||
domain_names: row.domain_names
|
domain_names: row.domain_names
|
||||||
},data);
|
}, data);
|
||||||
|
|
||||||
|
data = internalHost.cleanSslHstsData(data, row);
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
@ -172,11 +173,11 @@ const internalProxyHost = {
|
|||||||
.then(saved_row => {
|
.then(saved_row => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'proxy-host',
|
object_type: 'proxy-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
});
|
});
|
||||||
@ -184,15 +185,15 @@ const internalProxyHost = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {
|
return internalProxyHost.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'certificate', 'access_list']
|
expand: ['owner', 'certificate', 'access_list']
|
||||||
})
|
})
|
||||||
.then(row => {
|
.then(row => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(proxyHostModel, 'proxy_host', row)
|
return internalNginx.configure(proxyHostModel, 'proxy_host', row)
|
||||||
.then(new_meta => {
|
.then(new_meta => {
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -202,7 +203,7 @@ const internalProxyHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {Array} [data.expand]
|
* @param {Array} [data.expand]
|
||||||
* @param {Array} [data.omit]
|
* @param {Array} [data.omit]
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
@ -249,7 +250,7 @@ const internalProxyHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {String} [data.reason]
|
* @param {String} [data.reason]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -291,6 +292,104 @@ const internalProxyHost = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: (access, data) => {
|
||||||
|
return access.can('proxy_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalProxyHost.get(access, {
|
||||||
|
id: data.id,
|
||||||
|
expand: ['certificate', 'owner', 'access_list']
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 1;
|
||||||
|
|
||||||
|
return proxyHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 1
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Configure nginx
|
||||||
|
return internalNginx.configure(proxyHostModel, 'proxy_host', row);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'enabled',
|
||||||
|
object_type: 'proxy-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: (access, data) => {
|
||||||
|
return access.can('proxy_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalProxyHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (!row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 0;
|
||||||
|
|
||||||
|
return proxyHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 0
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Delete Nginx Config
|
||||||
|
return internalNginx.deleteConfig('proxy_host', row)
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'disabled',
|
||||||
|
object_type: 'proxy-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All Hosts
|
* All Hosts
|
||||||
*
|
*
|
||||||
@ -339,7 +438,7 @@ const internalProxyHost = {
|
|||||||
/**
|
/**
|
||||||
* Report use
|
* Report use
|
||||||
*
|
*
|
||||||
* @param {Integer} user_id
|
* @param {Number} user_id
|
||||||
* @param {String} visibility
|
* @param {String} visibility
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +47,7 @@ const internalRedirectionHost = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point the domains should have been checked
|
// At this point the domains should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
|
data = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
@ -89,11 +90,11 @@ const internalRedirectionHost = {
|
|||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'redirection-host',
|
object_type: 'redirection-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
@ -103,7 +104,7 @@ const internalRedirectionHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
@ -144,9 +145,9 @@ const internalRedirectionHost = {
|
|||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate.createQuickCertificate(access, {
|
||||||
domain_names: data.domain_names || row.domain_names,
|
domain_names: data.domain_names || row.domain_names,
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
meta: _.assign({}, row.meta, data.meta)
|
||||||
})
|
})
|
||||||
.then(cert => {
|
.then(cert => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
data.certificate_id = cert.id;
|
||||||
@ -162,7 +163,9 @@ const internalRedirectionHost = {
|
|||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
data = _.assign({}, {
|
||||||
domain_names: row.domain_names
|
domain_names: row.domain_names
|
||||||
},data);
|
}, data);
|
||||||
|
|
||||||
|
data = internalHost.cleanSslHstsData(data, row);
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
@ -171,11 +174,11 @@ const internalRedirectionHost = {
|
|||||||
.then(saved_row => {
|
.then(saved_row => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'redirection-host',
|
object_type: 'redirection-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
});
|
});
|
||||||
@ -183,15 +186,15 @@ const internalRedirectionHost = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {
|
return internalRedirectionHost.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'certificate']
|
expand: ['owner', 'certificate']
|
||||||
})
|
})
|
||||||
.then(row => {
|
.then(row => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(redirectionHostModel, 'redirection_host', row)
|
return internalNginx.configure(redirectionHostModel, 'redirection_host', row)
|
||||||
.then(new_meta => {
|
.then(new_meta => {
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -201,7 +204,7 @@ const internalRedirectionHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {Array} [data.expand]
|
* @param {Array} [data.expand]
|
||||||
* @param {Array} [data.omit]
|
* @param {Array} [data.omit]
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
@ -248,7 +251,7 @@ const internalRedirectionHost = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {String} [data.reason]
|
* @param {String} [data.reason]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -290,6 +293,104 @@ const internalRedirectionHost = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: (access, data) => {
|
||||||
|
return access.can('redirection_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalRedirectionHost.get(access, {
|
||||||
|
id: data.id,
|
||||||
|
expand: ['certificate', 'owner']
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 1;
|
||||||
|
|
||||||
|
return redirectionHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 1
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Configure nginx
|
||||||
|
return internalNginx.configure(redirectionHostModel, 'redirection_host', row);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'enabled',
|
||||||
|
object_type: 'redirection-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: (access, data) => {
|
||||||
|
return access.can('redirection_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalRedirectionHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (!row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 0;
|
||||||
|
|
||||||
|
return redirectionHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 0
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Delete Nginx Config
|
||||||
|
return internalNginx.deleteConfig('redirection_host', row)
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'disabled',
|
||||||
|
object_type: 'redirection-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All Hosts
|
* All Hosts
|
||||||
*
|
*
|
||||||
@ -338,7 +439,7 @@ const internalRedirectionHost = {
|
|||||||
/**
|
/**
|
||||||
* Report use
|
* Report use
|
||||||
*
|
*
|
||||||
* @param {Integer} user_id
|
* @param {Number} user_id
|
||||||
* @param {String} visibility
|
* @param {String} visibility
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,7 @@ const internalStream = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
@ -75,6 +75,12 @@ const internalStream = {
|
|||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.omit(omissions())
|
||||||
.patchAndFetchById(row.id, data)
|
.patchAndFetchById(row.id, data)
|
||||||
|
.then(saved_row => {
|
||||||
|
return internalNginx.configure(streamModel, 'stream', saved_row)
|
||||||
|
.then(() => {
|
||||||
|
return internalStream.get(access, {id: row.id, expand: ['owner']});
|
||||||
|
});
|
||||||
|
})
|
||||||
.then(saved_row => {
|
.then(saved_row => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
@ -93,7 +99,7 @@ const internalStream = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {Array} [data.expand]
|
* @param {Array} [data.expand]
|
||||||
* @param {Array} [data.omit]
|
* @param {Array} [data.omit]
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
@ -139,7 +145,7 @@ const internalStream = {
|
|||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @param {String} [data.reason]
|
* @param {String} [data.reason]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -181,6 +187,104 @@ const internalStream = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: (access, data) => {
|
||||||
|
return access.can('streams:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalStream.get(access, {
|
||||||
|
id: data.id,
|
||||||
|
expand: ['owner']
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 1;
|
||||||
|
|
||||||
|
return streamModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 1
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Configure nginx
|
||||||
|
return internalNginx.configure(streamModel, 'stream', row);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'enabled',
|
||||||
|
object_type: 'stream',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: (access, data) => {
|
||||||
|
return access.can('streams:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalStream.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then(row => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (!row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 0;
|
||||||
|
|
||||||
|
return streamModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 0
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Delete Nginx Config
|
||||||
|
return internalNginx.deleteConfig('stream', row)
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'disabled',
|
||||||
|
object_type: 'stream-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All Streams
|
* All Streams
|
||||||
*
|
*
|
||||||
@ -222,7 +326,7 @@ const internalStream = {
|
|||||||
/**
|
/**
|
||||||
* Report use
|
* Report use
|
||||||
*
|
*
|
||||||
* @param {Integer} user_id
|
* @param {Number} user_id
|
||||||
* @param {String} visibility
|
* @param {String} visibility
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
const {Signale} = require('signale');
|
const {Signale} = require('signale');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
global: new Signale({scope: 'Global '}),
|
global: new Signale({scope: 'Global '}),
|
||||||
migrate: new Signale({scope: 'Migrate '}),
|
migrate: new Signale({scope: 'Migrate '}),
|
||||||
express: new Signale({scope: 'Express '}),
|
express: new Signale({scope: 'Express '}),
|
||||||
access: new Signale({scope: 'Access '}),
|
access: new Signale({scope: 'Access '}),
|
||||||
nginx: new Signale({scope: 'Nginx '}),
|
nginx: new Signale({scope: 'Nginx '}),
|
||||||
ssl: new Signale({scope: 'SSL '}),
|
ssl: new Signale({scope: 'SSL '}),
|
||||||
import: new Signale({scope: 'Importer'}),
|
import: new Signale({scope: 'Importer '}),
|
||||||
|
setup: new Signale({scope: 'Setup '}),
|
||||||
|
ip_ranges: new Signale({scope: 'IP Ranges'})
|
||||||
};
|
};
|
||||||
|
37
src/backend/migrations/20180929054513_websockets.js
Normal file
37
src/backend/migrations/20180929054513_websockets.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const migrate_name = 'websockets';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.integer('allow_websocket_upgrade').notNull().unsigned().defaultTo(0);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex, Promise) {
|
||||||
|
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||||
|
return Promise.resolve(true);
|
||||||
|
};
|
36
src/backend/migrations/20181019052346_forward_host.js
Normal file
36
src/backend/migrations/20181019052346_forward_host.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const migrate_name = 'forward_host';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.renameColumn('forward_ip', 'forward_host');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex, Promise) {
|
||||||
|
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||||
|
return Promise.resolve(true);
|
||||||
|
};
|
51
src/backend/migrations/20181113041458_http2_support.js
Normal file
51
src/backend/migrations/20181113041458_http2_support.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const migrate_name = 'http2_support';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('redirection_host', function (redirection_host) {
|
||||||
|
redirection_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('dead_host', function (dead_host) {
|
||||||
|
dead_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] dead_host Table altered');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex, Promise) {
|
||||||
|
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||||
|
return Promise.resolve(true);
|
||||||
|
};
|
||||||
|
|
36
src/backend/migrations/20181213013211_forward_scheme.js
Normal file
36
src/backend/migrations/20181213013211_forward_scheme.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const migrate_name = 'forward_scheme';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.string('forward_scheme').notNull().defaultTo('http');
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex, Promise) {
|
||||||
|
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||||
|
return Promise.resolve(true);
|
||||||
|
};
|
57
src/backend/migrations/20190104035154_disabled.js
Normal file
57
src/backend/migrations/20190104035154_disabled.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const migrate_name = 'disabled';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('redirection_host', function (redirection_host) {
|
||||||
|
redirection_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('dead_host', function (dead_host) {
|
||||||
|
dead_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] dead_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('stream', function (stream) {
|
||||||
|
stream.integer('enabled').notNull().unsigned().defaultTo(1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] stream Table altered');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex, Promise) {
|
||||||
|
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||||
|
return Promise.resolve(true);
|
||||||
|
};
|
53
src/backend/migrations/20190218060101_hsts.js
Normal file
53
src/backend/migrations/20190218060101_hsts.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const migrate_name = 'hsts';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||||
|
proxy_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||||
|
proxy_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('redirection_host', function (redirection_host) {
|
||||||
|
redirection_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||||
|
redirection_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
||||||
|
|
||||||
|
return knex.schema.table('dead_host', function (dead_host) {
|
||||||
|
dead_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||||
|
dead_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info('[' + migrate_name + '] dead_host Table altered');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex, Promise) {
|
||||||
|
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
||||||
|
return Promise.resolve(true);
|
||||||
|
};
|
@ -20,7 +20,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/access-lists
|
* GET /api/nginx/access-lists
|
||||||
@ -79,7 +79,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/access-lists/123
|
* GET /api/nginx/access-lists/123
|
||||||
|
@ -20,7 +20,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/certificates
|
* GET /api/nginx/certificates
|
||||||
@ -79,7 +79,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/certificates/123
|
* GET /api/nginx/certificates/123
|
||||||
@ -157,7 +157,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/nginx/certificates/123/upload
|
* POST /api/nginx/certificates/123/upload
|
||||||
@ -191,7 +191,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/nginx/certificates/validate
|
* POST /api/nginx/certificates/validate
|
||||||
|
@ -20,7 +20,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/dead-hosts
|
* GET /api/nginx/dead-hosts
|
||||||
@ -79,7 +79,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/dead-hosts/123
|
* GET /api/nginx/dead-hosts/123
|
||||||
@ -147,4 +147,52 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable dead-host
|
||||||
|
*
|
||||||
|
* /api/nginx/dead-hosts/123/enable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/enable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/dead-hosts/123/enable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalDeadHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable dead-host
|
||||||
|
*
|
||||||
|
* /api/nginx/dead-hosts/123/disable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/disable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/dead-hosts/123/disable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalDeadHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -20,7 +20,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/proxy-hosts
|
* GET /api/nginx/proxy-hosts
|
||||||
@ -79,7 +79,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/proxy-hosts/123
|
* GET /api/nginx/proxy-hosts/123
|
||||||
@ -147,4 +147,52 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable proxy-host
|
||||||
|
*
|
||||||
|
* /api/nginx/proxy-hosts/123/enable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/enable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/proxy-hosts/123/enable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalProxyHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable proxy-host
|
||||||
|
*
|
||||||
|
* /api/nginx/proxy-hosts/123/disable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/disable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/proxy-hosts/123/disable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalProxyHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -20,7 +20,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/redirection-hosts
|
* GET /api/nginx/redirection-hosts
|
||||||
@ -79,7 +79,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/nginx/redirection-hosts/123
|
* GET /api/nginx/redirection-hosts/123
|
||||||
@ -147,4 +147,52 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable redirection-host
|
||||||
|
*
|
||||||
|
* /api/nginx/redirection-hosts/123/enable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/enable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/redirection-hosts/123/enable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalRedirectionHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable redirection-host
|
||||||
|
*
|
||||||
|
* /api/nginx/redirection-hosts/123/disable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/disable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/redirection-hosts/123/disable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalRedirectionHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -147,4 +147,52 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable stream
|
||||||
|
*
|
||||||
|
* /api/nginx/streams/123/enable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/enable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/streams/123/enable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalStream.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable stream
|
||||||
|
*
|
||||||
|
* /api/nginx/streams/123/disable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/disable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/streams/123/disable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalStream.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then(result => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -21,7 +21,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/users
|
* GET /api/users
|
||||||
@ -80,7 +80,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
.all(userIdFromMe)
|
.all(userIdFromMe)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,7 +160,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
.all(userIdFromMe)
|
.all(userIdFromMe)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,7 +191,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
.all(userIdFromMe)
|
.all(userIdFromMe)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,7 +222,7 @@ router
|
|||||||
.options((req, res) => {
|
.options((req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/users/123/login
|
* POST /api/users/123/login
|
||||||
|
@ -172,6 +172,11 @@
|
|||||||
"pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$"
|
"pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"description": "Is Enabled",
|
||||||
|
"example": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"ssl_enabled": {
|
"ssl_enabled": {
|
||||||
"description": "Is SSL Enabled",
|
"description": "Is SSL Enabled",
|
||||||
"example": true,
|
"example": true,
|
||||||
@ -182,10 +187,25 @@
|
|||||||
"example": false,
|
"example": false,
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"description": "Is HSTS Enabled",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"description": "Is HSTS applicable to all subdomains",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"ssl_provider": {
|
"ssl_provider": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^(letsencrypt|other)$"
|
"pattern": "^(letsencrypt|other)$"
|
||||||
},
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"description": "HTTP2 Protocol Support",
|
||||||
|
"example": false,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"description": "Should we block common exploits",
|
"description": "Should we block common exploits",
|
||||||
"example": true,
|
"example": true,
|
||||||
|
@ -24,9 +24,21 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "../definitions.json#/definitions/ssl_forced"
|
"$ref": "../definitions.json#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "../definitions.json#/definitions/hsts_subdomains"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "../definitions.json#/definitions/http2_support"
|
||||||
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
@ -50,9 +62,21 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_subdomains"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -101,6 +125,15 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
@ -138,6 +171,15 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
@ -165,6 +207,34 @@
|
|||||||
"targetSchema": {
|
"targetSchema": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Enable",
|
||||||
|
"description": "Enables a existing 404 Host",
|
||||||
|
"href": "/nginx/dead-hosts/{definitions.identity.example}/enable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Disable",
|
||||||
|
"description": "Disables a existing 404 Host",
|
||||||
|
"href": "/nginx/dead-hosts/{definitions.identity.example}/disable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,14 @@
|
|||||||
"domain_names": {
|
"domain_names": {
|
||||||
"$ref": "../definitions.json#/definitions/domain_names"
|
"$ref": "../definitions.json#/definitions/domain_names"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forward_scheme": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "ipv4"
|
"enum": ["http", "https"]
|
||||||
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 50
|
||||||
},
|
},
|
||||||
"forward_port": {
|
"forward_port": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@ -33,18 +38,35 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "../definitions.json#/definitions/ssl_forced"
|
"$ref": "../definitions.json#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "../definitions.json#/definitions/hsts_subdomains"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "../definitions.json#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "../definitions.json#/definitions/block_exploits"
|
"$ref": "../definitions.json#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
"caching_enabled": {
|
"caching_enabled": {
|
||||||
"$ref": "../definitions.json#/definitions/caching_enabled"
|
"$ref": "../definitions.json#/definitions/caching_enabled"
|
||||||
},
|
},
|
||||||
|
"allow_websocket_upgrade": {
|
||||||
|
"description": "Allow Websocket Upgrade for all paths",
|
||||||
|
"example": true,
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "../definitions.json#/definitions/access_list_id"
|
"$ref": "../definitions.json#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
@ -62,8 +84,11 @@
|
|||||||
"domain_names": {
|
"domain_names": {
|
||||||
"$ref": "#/definitions/domain_names"
|
"$ref": "#/definitions/domain_names"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forward_scheme": {
|
||||||
"$ref": "#/definitions/forward_ip"
|
"$ref": "#/definitions/forward_scheme"
|
||||||
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"$ref": "#/definitions/forward_host"
|
||||||
},
|
},
|
||||||
"forward_port": {
|
"forward_port": {
|
||||||
"$ref": "#/definitions/forward_port"
|
"$ref": "#/definitions/forward_port"
|
||||||
@ -74,18 +99,33 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_subdomains"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "#/definitions/block_exploits"
|
"$ref": "#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
"caching_enabled": {
|
"caching_enabled": {
|
||||||
"$ref": "#/definitions/caching_enabled"
|
"$ref": "#/definitions/caching_enabled"
|
||||||
},
|
},
|
||||||
|
"allow_websocket_upgrade": {
|
||||||
|
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "#/definitions/access_list_id"
|
"$ref": "#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -123,15 +163,19 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": [
|
||||||
"domain_names",
|
"domain_names",
|
||||||
"forward_ip",
|
"forward_scheme",
|
||||||
|
"forward_host",
|
||||||
"forward_port"
|
"forward_port"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"domain_names": {
|
"domain_names": {
|
||||||
"$ref": "#/definitions/domain_names"
|
"$ref": "#/definitions/domain_names"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forward_scheme": {
|
||||||
"$ref": "#/definitions/forward_ip"
|
"$ref": "#/definitions/forward_scheme"
|
||||||
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"$ref": "#/definitions/forward_host"
|
||||||
},
|
},
|
||||||
"forward_port": {
|
"forward_port": {
|
||||||
"$ref": "#/definitions/forward_port"
|
"$ref": "#/definitions/forward_port"
|
||||||
@ -142,18 +186,33 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "#/definitions/block_exploits"
|
"$ref": "#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
"caching_enabled": {
|
"caching_enabled": {
|
||||||
"$ref": "#/definitions/caching_enabled"
|
"$ref": "#/definitions/caching_enabled"
|
||||||
},
|
},
|
||||||
|
"allow_websocket_upgrade": {
|
||||||
|
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "#/definitions/access_list_id"
|
"$ref": "#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -182,8 +241,11 @@
|
|||||||
"domain_names": {
|
"domain_names": {
|
||||||
"$ref": "#/definitions/domain_names"
|
"$ref": "#/definitions/domain_names"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forward_scheme": {
|
||||||
"$ref": "#/definitions/forward_ip"
|
"$ref": "#/definitions/forward_scheme"
|
||||||
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"$ref": "#/definitions/forward_host"
|
||||||
},
|
},
|
||||||
"forward_port": {
|
"forward_port": {
|
||||||
"$ref": "#/definitions/forward_port"
|
"$ref": "#/definitions/forward_port"
|
||||||
@ -194,18 +256,33 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "#/definitions/block_exploits"
|
"$ref": "#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
"caching_enabled": {
|
"caching_enabled": {
|
||||||
"$ref": "#/definitions/caching_enabled"
|
"$ref": "#/definitions/caching_enabled"
|
||||||
},
|
},
|
||||||
|
"allow_websocket_upgrade": {
|
||||||
|
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||||
|
},
|
||||||
"access_list_id": {
|
"access_list_id": {
|
||||||
"$ref": "#/definitions/access_list_id"
|
"$ref": "#/definitions/access_list_id"
|
||||||
},
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -230,6 +307,34 @@
|
|||||||
"targetSchema": {
|
"targetSchema": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Enable",
|
||||||
|
"description": "Enables a existing Proxy Host",
|
||||||
|
"href": "/nginx/proxy-hosts/{definitions.identity.example}/enable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Disable",
|
||||||
|
"description": "Disables a existing Proxy Host",
|
||||||
|
"href": "/nginx/proxy-hosts/{definitions.identity.example}/disable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,24 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "../definitions.json#/definitions/ssl_forced"
|
"$ref": "../definitions.json#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "../definitions.json#/definitions/hsts_subdomains"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "../definitions.json#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "../definitions.json#/definitions/block_exploits"
|
"$ref": "../definitions.json#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
@ -67,12 +79,24 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_subdomains"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "#/definitions/block_exploits"
|
"$ref": "#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
"advanced_config": {
|
"advanced_config": {
|
||||||
"$ref": "#/definitions/advanced_config"
|
"$ref": "#/definitions/advanced_config"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -128,6 +152,15 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "#/definitions/block_exploits"
|
"$ref": "#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
@ -174,6 +207,15 @@
|
|||||||
"ssl_forced": {
|
"ssl_forced": {
|
||||||
"$ref": "#/definitions/ssl_forced"
|
"$ref": "#/definitions/ssl_forced"
|
||||||
},
|
},
|
||||||
|
"hsts_enabled": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"hsts_subdomains": {
|
||||||
|
"$ref": "#/definitions/hsts_enabled"
|
||||||
|
},
|
||||||
|
"http2_support": {
|
||||||
|
"$ref": "#/definitions/http2_support"
|
||||||
|
},
|
||||||
"block_exploits": {
|
"block_exploits": {
|
||||||
"$ref": "#/definitions/block_exploits"
|
"$ref": "#/definitions/block_exploits"
|
||||||
},
|
},
|
||||||
@ -204,6 +246,34 @@
|
|||||||
"targetSchema": {
|
"targetSchema": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Enable",
|
||||||
|
"description": "Enables a existing Redirection Host",
|
||||||
|
"href": "/nginx/redirection-hosts/{definitions.identity.example}/enable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Disable",
|
||||||
|
"description": "Disables a existing Redirection Host",
|
||||||
|
"href": "/nginx/redirection-hosts/{definitions.identity.example}/disable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@
|
|||||||
"udp_forwarding": {
|
"udp_forwarding": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"type": "object"
|
"type": "object"
|
||||||
}
|
}
|
||||||
@ -64,6 +67,9 @@
|
|||||||
"udp_forwarding": {
|
"udp_forwarding": {
|
||||||
"$ref": "#/definitions/udp_forwarding"
|
"$ref": "#/definitions/udp_forwarding"
|
||||||
},
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"$ref": "#/definitions/meta"
|
"$ref": "#/definitions/meta"
|
||||||
}
|
}
|
||||||
@ -184,6 +190,34 @@
|
|||||||
"targetSchema": {
|
"targetSchema": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Enable",
|
||||||
|
"description": "Enables a existing Stream",
|
||||||
|
"href": "/nginx/streams/{definitions.identity.example}/enable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Disable",
|
||||||
|
"description": "Disables a existing Stream",
|
||||||
|
"href": "/nginx/streams/{definitions.identity.example}/disable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const NodeRSA = require('node-rsa');
|
const NodeRSA = require('node-rsa');
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
const logger = require('./logger').global;
|
const logger = require('./logger').setup;
|
||||||
const userModel = require('./models/user');
|
const userModel = require('./models/user');
|
||||||
const userPermissionModel = require('./models/user_permission');
|
const userPermissionModel = require('./models/user_permission');
|
||||||
const authModel = require('./models/auth');
|
const authModel = require('./models/auth');
|
||||||
|
const debug_mode = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -22,6 +23,9 @@ module.exports = function () {
|
|||||||
config_data = require(filename);
|
config_data = require(filename);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// do nothing
|
// do nothing
|
||||||
|
if (debug_mode) {
|
||||||
|
logger.debug(filename + ' config file could not be required');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now create the keys and save them in the config.
|
// Now create the keys and save them in the config.
|
||||||
@ -40,12 +44,18 @@ module.exports = function () {
|
|||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
logger.info('Wrote JWT key pair to config file: ' + filename);
|
logger.info('Wrote JWT key pair to config file: ' + filename);
|
||||||
config.util.loadFileConfigs();
|
|
||||||
resolve();
|
logger.warn('Restarting interface to apply new configuration');
|
||||||
|
process.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// JWT key pair exists
|
// JWT key pair exists
|
||||||
|
if (debug_mode) {
|
||||||
|
logger.debug('JWT Keypair already exists');
|
||||||
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -54,49 +64,54 @@ module.exports = function () {
|
|||||||
.query()
|
.query()
|
||||||
.select(userModel.raw('COUNT(`id`) as `count`'))
|
.select(userModel.raw('COUNT(`id`) as `count`'))
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.first('count')
|
.first();
|
||||||
.then(row => {
|
})
|
||||||
if (!row.count) {
|
.then(row => {
|
||||||
// Create a new user and set password
|
if (!row.count) {
|
||||||
logger.info('Creating a new user: admin@example.com with password: changeme');
|
// Create a new user and set password
|
||||||
|
logger.info('Creating a new user: admin@example.com with password: changeme');
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
is_deleted: 0,
|
is_deleted: 0,
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
name: 'Administrator',
|
name: 'Administrator',
|
||||||
nickname: 'Admin',
|
nickname: 'Admin',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
roles: ['admin']
|
roles: ['admin']
|
||||||
};
|
};
|
||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
|
.query()
|
||||||
|
.insertAndFetch(data)
|
||||||
|
.then(user => {
|
||||||
|
return authModel
|
||||||
.query()
|
.query()
|
||||||
.insertAndFetch(data)
|
.insert({
|
||||||
.then(user => {
|
user_id: user.id,
|
||||||
return authModel
|
type: 'password',
|
||||||
|
secret: 'changeme',
|
||||||
|
meta: {}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return userPermissionModel
|
||||||
.query()
|
.query()
|
||||||
.insert({
|
.insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
type: 'password',
|
visibility: 'all',
|
||||||
secret: 'changeme',
|
proxy_hosts: 'manage',
|
||||||
meta: {}
|
redirection_hosts: 'manage',
|
||||||
})
|
dead_hosts: 'manage',
|
||||||
.then(() => {
|
streams: 'manage',
|
||||||
return userPermissionModel
|
access_lists: 'manage',
|
||||||
.query()
|
certificates: 'manage'
|
||||||
.insert({
|
|
||||||
user_id: user.id,
|
|
||||||
visibility: 'all',
|
|
||||||
proxy_hosts: 'manage',
|
|
||||||
redirection_hosts: 'manage',
|
|
||||||
dead_hosts: 'manage',
|
|
||||||
streams: 'manage',
|
|
||||||
access_lists: 'manage',
|
|
||||||
certificates: 'manage'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
})
|
||||||
});
|
.then(() => {
|
||||||
|
logger.info('Initial setup completed');
|
||||||
|
});
|
||||||
|
} else if (debug_mode) {
|
||||||
|
logger.debug('Admin user setup not required');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
8
src/backend/templates/_hsts.conf
Normal file
8
src/backend/templates/_hsts.conf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{% if certificate and certificate_id > 0 -%}
|
||||||
|
{% if ssl_forced == 1 or ssl_forced == true %}
|
||||||
|
{% if hsts_enabled == 1 or hsts_enabled == true %}
|
||||||
|
# HSTS (ngx_http_headers_module is required) (31536000 seconds = 1 year)
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload" always;
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
@ -1,5 +1,5 @@
|
|||||||
listen 80;
|
listen 80;
|
||||||
{% if certificate -%}
|
{% if certificate -%}
|
||||||
listen 443 ssl;
|
listen 443 ssl{% if http2_support %} http2{% endif %};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
server_name {{ domain_names | join: " " }};
|
server_name {{ domain_names | join: " " }};
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
{% include "_header_comment.conf" %}
|
{% include "_header_comment.conf" %}
|
||||||
|
|
||||||
|
{% if enabled %}
|
||||||
server {
|
server {
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
access_log /data/logs/dead_host-{{ id }}.log standard;
|
access_log /data/logs/dead_host-{{ id }}.log standard;
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
|
|
||||||
return 404;
|
{% if use_default_location %}
|
||||||
|
location / {
|
||||||
|
{% include "_forced_ssl.conf" %}
|
||||||
|
{% include "_hsts.conf" %}
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
{% endif %}
|
||||||
|
3
src/backend/templates/ip_ranges.conf
Normal file
3
src/backend/templates/ip_ranges.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{% for range in ip_ranges %}
|
||||||
|
set_real_ip_from {{ range }};
|
||||||
|
{% endfor %}
|
@ -1,18 +1,22 @@
|
|||||||
{% include "_header_comment.conf" %}
|
{% include "_header_comment.conf" %}
|
||||||
|
|
||||||
|
{% if enabled %}
|
||||||
server {
|
server {
|
||||||
set $server {{ forward_ip }};
|
set $forward_scheme {{ forward_scheme }};
|
||||||
set $port {{ forward_port }};
|
set $server "{{ forward_host }}";
|
||||||
|
set $port {{ forward_port }};
|
||||||
|
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
{% include "_assets.conf" %}
|
{% include "_assets.conf" %}
|
||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
access_log /data/logs/proxy_host-{{ id }}.log proxy;
|
access_log /data/logs/proxy_host-{{ id }}.log proxy;
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
|
|
||||||
|
{% if use_default_location %}
|
||||||
location / {
|
location / {
|
||||||
{%- if access_list_id > 0 -%}
|
{%- if access_list_id > 0 -%}
|
||||||
# Access List
|
# Access List
|
||||||
@ -21,8 +25,18 @@ server {
|
|||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
|
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
# Proxy!
|
# Proxy!
|
||||||
include conf.d/include/proxy.conf;
|
include conf.d/include/proxy.conf;
|
||||||
}
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
{% endif %}
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
{% include "_header_comment.conf" %}
|
{% include "_header_comment.conf" %}
|
||||||
|
|
||||||
|
{% if enabled %}
|
||||||
server {
|
server {
|
||||||
{% include "_listen.conf" %}
|
{% include "_listen.conf" %}
|
||||||
{% include "_certificates.conf" %}
|
{% include "_certificates.conf" %}
|
||||||
{% include "_assets.conf" %}
|
{% include "_assets.conf" %}
|
||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
access_log /data/logs/redirection_host-{{ id }}.log standard;
|
access_log /data/logs/redirection_host-{{ id }}.log standard;
|
||||||
|
|
||||||
{{ advanced_config }}
|
{{ advanced_config }}
|
||||||
|
|
||||||
# TODO: Preserve Path Option
|
{% if use_default_location %}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
{% if preserve_path == 1 or preserve_path == true %}
|
{% if preserve_path == 1 or preserve_path == true %}
|
||||||
return 301 $scheme://{{ forward_domain_name }}$request_uri;
|
return 301 $scheme://{{ forward_domain_name }}$request_uri;
|
||||||
@ -21,4 +23,7 @@ server {
|
|||||||
return 301 $scheme://{{ forward_domain_name }};
|
return 301 $scheme://{{ forward_domain_name }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
}
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
{% endif %}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
|
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
{% if enabled %}
|
||||||
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
||||||
server {
|
server {
|
||||||
listen {{ incoming_port }};
|
listen {{ incoming_port }};
|
||||||
@ -14,3 +15,4 @@ server {
|
|||||||
proxy_pass {{ forward_ip }}:{{ forwarding_port }};
|
proxy_pass {{ forward_ip }}:{{ forwarding_port }};
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
@ -5,5 +5,5 @@
|
|||||||
<span class="loader"></span>
|
<span class="loader"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/main.js?v=<%= version %>"></script>
|
<script type="text/javascript" src="/js/main.bundle.js?v=<%= version %>"></script>
|
||||||
<%- include partials/footer.ejs %>
|
<%- include partials/footer.ejs %>
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
<span class="loader"></span>
|
<span class="loader"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="/js/login.js?v=<%= version %>"></script>
|
<script type="text/javascript" src="/js/login.bundle.js?v=<%= version %>"></script>
|
||||||
<%- include partials/footer.ejs %>
|
<%- include partials/footer.ejs %>
|
||||||
|
@ -7,7 +7,7 @@ const Tokens = require('./tokens');
|
|||||||
/**
|
/**
|
||||||
* @param {String} message
|
* @param {String} message
|
||||||
* @param {*} debug
|
* @param {*} debug
|
||||||
* @param {Integer} code
|
* @param {Number} code
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
const ApiError = function (message, debug, code) {
|
const ApiError = function (message, debug, code) {
|
||||||
@ -129,7 +129,7 @@ function getAllObjects (path, expand, query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} path
|
* @param {String} path
|
||||||
* @param {FormData} form_data
|
* @param {FormData} form_data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -241,7 +241,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -251,7 +251,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
@ -260,7 +260,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @param {Object} auth
|
* @param {Object} auth
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -269,7 +269,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
loginAs: function (id) {
|
loginAs: function (id) {
|
||||||
@ -278,7 +278,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @param {Object} perms
|
* @param {Object} perms
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -308,7 +308,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -318,11 +318,35 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
return fetch('delete', 'nginx/proxy-hosts/' + id);
|
return fetch('delete', 'nginx/proxy-hosts/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
get: function (id) {
|
||||||
|
return fetch('get', 'nginx/proxy-hosts/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: function (id) {
|
||||||
|
return fetch('post', 'nginx/proxy-hosts/' + id + '/enable');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: function (id) {
|
||||||
|
return fetch('post', 'nginx/proxy-hosts/' + id + '/disable');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -345,7 +369,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -355,7 +379,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
@ -363,12 +387,36 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
get: function (id) {
|
||||||
|
return fetch('get', 'nginx/redirection-hosts/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
* @param {FormData} form_data
|
* @param {FormData} form_data
|
||||||
* @params {Promise}
|
* @params {Promise}
|
||||||
*/
|
*/
|
||||||
setCerts: function (id, form_data) {
|
setCerts: function (id, form_data) {
|
||||||
return FileUpload('nginx/redirection-hosts/' + id + '/certificates', form_data);
|
return FileUpload('nginx/redirection-hosts/' + id + '/certificates', form_data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: function (id) {
|
||||||
|
return fetch('post', 'nginx/redirection-hosts/' + id + '/enable');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: function (id) {
|
||||||
|
return fetch('post', 'nginx/redirection-hosts/' + id + '/disable');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -391,7 +439,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -401,11 +449,35 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
return fetch('delete', 'nginx/streams/' + id);
|
return fetch('delete', 'nginx/streams/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
get: function (id) {
|
||||||
|
return fetch('get', 'nginx/streams/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: function (id) {
|
||||||
|
return fetch('post', 'nginx/streams/' + id + '/enable');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: function (id) {
|
||||||
|
return fetch('post', 'nginx/streams/' + id + '/disable');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -428,7 +500,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -438,7 +510,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
@ -446,12 +518,36 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
get: function (id) {
|
||||||
|
return fetch('get', 'nginx/dead-hosts/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
* @param {FormData} form_data
|
* @param {FormData} form_data
|
||||||
* @params {Promise}
|
* @params {Promise}
|
||||||
*/
|
*/
|
||||||
setCerts: function (id, form_data) {
|
setCerts: function (id, form_data) {
|
||||||
return FileUpload('nginx/dead-hosts/' + id + '/certificates', form_data);
|
return FileUpload('nginx/dead-hosts/' + id + '/certificates', form_data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: function (id) {
|
||||||
|
return fetch('post', 'nginx/dead-hosts/' + id + '/enable');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: function (id) {
|
||||||
|
return fetch('post', 'nginx/dead-hosts/' + id + '/disable');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -474,7 +570,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -484,7 +580,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
@ -511,7 +607,7 @@ module.exports = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {Integer} data.id
|
* @param {Number} data.id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
update: function (data) {
|
update: function (data) {
|
||||||
@ -521,7 +617,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: function (id) {
|
delete: function (id) {
|
||||||
@ -529,7 +625,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Integer} id
|
* @param {Number} id
|
||||||
* @param {FormData} form_data
|
* @param {FormData} form_data
|
||||||
* @params {Promise}
|
* @params {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +12,7 @@ require('selectize');
|
|||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
template: template,
|
template: template,
|
||||||
className: 'modal-dialog',
|
className: 'modal-dialog',
|
||||||
max_file_size: 5120,
|
max_file_size: 102400,
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
form: 'form',
|
form: 'form',
|
||||||
@ -56,7 +56,7 @@ module.exports = Mn.View.extend({
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (this.ui.other_certificate[0].files[0].size > this.max_file_size) {
|
if (this.ui.other_certificate[0].files[0].size > this.max_file_size) {
|
||||||
alert('Certificate file is too large (> 5kb)');
|
alert('Certificate file is too large (> 100kb)');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ssl_files.push({name: 'certificate', file: this.ui.other_certificate[0].files[0]});
|
ssl_files.push({name: 'certificate', file: this.ui.other_certificate[0].files[0]});
|
||||||
@ -67,7 +67,7 @@ module.exports = Mn.View.extend({
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (this.ui.other_certificate_key[0].files[0].size > this.max_file_size) {
|
if (this.ui.other_certificate_key[0].files[0].size > this.max_file_size) {
|
||||||
alert('Certificate key file is too large (> 5kb)');
|
alert('Certificate key file is too large (> 100kb)');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ssl_files.push({name: 'certificate_key', file: this.ui.other_certificate_key[0].files[0]});
|
ssl_files.push({name: 'certificate_key', file: this.ui.other_certificate_key[0].files[0]});
|
||||||
@ -75,7 +75,7 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
if (this.ui.other_intermediate_certificate[0].files.length && this.ui.other_intermediate_certificate[0].files[0].size) {
|
if (this.ui.other_intermediate_certificate[0].files.length && this.ui.other_intermediate_certificate[0].files[0].size) {
|
||||||
if (this.ui.other_intermediate_certificate[0].files[0].size > this.max_file_size) {
|
if (this.ui.other_intermediate_certificate[0].files[0].size > this.max_file_size) {
|
||||||
alert('Intermediate Certificate file is too large (> 5kb)');
|
alert('Intermediate Certificate file is too large (> 100kb)');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ssl_files.push({name: 'intermediate_certificate', file: this.ui.other_intermediate_certificate[0].files[0]});
|
ssl_files.push({name: 'intermediate_certificate', file: this.ui.other_intermediate_certificate[0].files[0]});
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-6 col-md-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="custom-switch">
|
<label class="custom-switch">
|
||||||
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
||||||
@ -45,6 +45,33 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="http2_support" value="1"<%- http2_support ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'http2-support') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="hsts_subdomains" value="1"<%- hsts_subdomains ? ' checked' : '' %><%- certificate_id && ssl_forced && hsts_enabled ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-subdomains') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Lets encrypt -->
|
<!-- Lets encrypt -->
|
||||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||||
|
@ -22,6 +22,9 @@ module.exports = Mn.View.extend({
|
|||||||
save: 'button.save',
|
save: 'button.save',
|
||||||
certificate_select: 'select[name="certificate_id"]',
|
certificate_select: 'select[name="certificate_id"]',
|
||||||
ssl_forced: 'input[name="ssl_forced"]',
|
ssl_forced: 'input[name="ssl_forced"]',
|
||||||
|
hsts_enabled: 'input[name="hsts_enabled"]',
|
||||||
|
hsts_subdomains: 'input[name="hsts_subdomains"]',
|
||||||
|
http2_support: 'input[name="http2_support"]',
|
||||||
letsencrypt: '.letsencrypt'
|
letsencrypt: '.letsencrypt'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -35,7 +38,44 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||||
this.ui.ssl_forced.prop('disabled', !enabled).parents('.form-group').css('opacity', enabled ? 1 : 0.5);
|
|
||||||
|
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||||
|
inputs
|
||||||
|
.prop('disabled', !enabled)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', enabled ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
inputs.prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change @ui.ssl_forced': function () {
|
||||||
|
let checked = this.ui.ssl_forced.prop('checked');
|
||||||
|
this.ui.hsts_enabled
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
this.ui.hsts_enabled.prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.hsts_enabled.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change @ui.hsts_enabled': function () {
|
||||||
|
let checked = this.ui.hsts_enabled.prop('checked');
|
||||||
|
this.ui.hsts_subdomains
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
this.ui.hsts_subdomains.prop('checked', false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'click @ui.save': function (e) {
|
'click @ui.save': function (e) {
|
||||||
@ -50,9 +90,10 @@ module.exports = Mn.View.extend({
|
|||||||
let data = this.ui.form.serializeJSON();
|
let data = this.ui.form.serializeJSON();
|
||||||
|
|
||||||
// Manipulate
|
// Manipulate
|
||||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
data.hsts_enabled = !!data.hsts_enabled;
|
||||||
data.ssl_forced = true;
|
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||||
}
|
data.http2_support = !!data.http2_support;
|
||||||
|
data.ssl_forced = !!data.ssl_forced;
|
||||||
|
|
||||||
if (typeof data.domain_names === 'string' && data.domain_names) {
|
if (typeof data.domain_names === 'string' && data.domain_names) {
|
||||||
data.domain_names = data.domain_names.split(',');
|
data.domain_names = data.domain_names.split(',');
|
||||||
@ -74,7 +115,7 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
|
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
|
||||||
} else {
|
} else {
|
||||||
data.certificate_id = parseInt(data.certificate_id, 0);
|
data.certificate_id = parseInt(data.certificate_id, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
let method = App.Api.Nginx.DeadHosts.create;
|
let method = App.Api.Nginx.DeadHosts.create;
|
||||||
|
@ -6,9 +6,15 @@
|
|||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
<% domain_names.map(function(host) {
|
<% domain_names.map(function(host) {
|
||||||
%>
|
if (host.indexOf('*') === -1) {
|
||||||
<span class="tag"><%- host %></span>
|
%>
|
||||||
<%
|
<span class="tag host-link hover-red" rel="http<%- certificate_id ? 's' : '' %>://<%- host %>"><%- host %></span>
|
||||||
|
<%
|
||||||
|
} else {
|
||||||
|
%>
|
||||||
|
<span class="tag"><%- host %></span>
|
||||||
|
<%
|
||||||
|
}
|
||||||
});
|
});
|
||||||
%>
|
%>
|
||||||
</div>
|
</div>
|
||||||
@ -22,7 +28,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<%
|
<%
|
||||||
var o = isOnline();
|
var o = isOnline();
|
||||||
if (o === true) { %>
|
if (!enabled) { %>
|
||||||
|
<span class="status-icon bg-warning"></span> <%- i18n('str', 'disabled') %>
|
||||||
|
<% } else if (o === true) { %>
|
||||||
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
||||||
<% } else if (o === false) { %>
|
<% } else if (o === false) { %>
|
||||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||||
@ -36,7 +44,7 @@
|
|||||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
||||||
<!--<a href="#" class="logs dropdown-item"><i class="dropdown-icon fe fe-book"></i> <%- i18n('str', 'logs') %></a>-->
|
<a href="#" class="able dropdown-item"><i class="dropdown-icon fe fe-power"></i> <%- i18n('str', enabled ? 'disable' : 'enable') %></a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,11 +9,25 @@ module.exports = Mn.View.extend({
|
|||||||
tagName: 'tr',
|
tagName: 'tr',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
edit: 'a.edit',
|
able: 'a.able',
|
||||||
delete: 'a.delete'
|
edit: 'a.edit',
|
||||||
|
delete: 'a.delete',
|
||||||
|
host_link: '.host-link'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
'click @ui.able': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let id = this.model.get('id');
|
||||||
|
App.Api.Nginx.DeadHosts[this.model.get('enabled') ? 'disable' : 'enable'](id)
|
||||||
|
.then(() => {
|
||||||
|
return App.Api.Nginx.DeadHosts.get(id)
|
||||||
|
.then(row => {
|
||||||
|
this.model.set(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
'click @ui.edit': function (e) {
|
'click @ui.edit': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxDeadForm(this.model);
|
App.Controller.showNginxDeadForm(this.model);
|
||||||
@ -22,6 +36,12 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.delete': function (e) {
|
'click @ui.delete': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxDeadDeleteConfirm(this.model);
|
App.Controller.showNginxDeadDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.host_link': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
||||||
|
win.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -20,10 +20,19 @@
|
|||||||
<input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>" required>
|
<input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-8 col-md-8">
|
<div class="col-sm-3 col-md-3">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label"><%- i18n('proxy-hosts', 'forward-ip') %><span class="form-required">*</span></label>
|
<label class="form-label"><%- i18n('proxy-hosts', 'forward-scheme') %><span class="form-required">*</span></label>
|
||||||
<input type="text" name="forward_ip" class="form-control text-monospace" placeholder="000.000.000.000" value="<%- forward_ip %>" autocomplete="off" maxlength="15" required>
|
<select name="forward_scheme" class="form-control custom-select" placeholder="http">
|
||||||
|
<option value="http" <%- forward_scheme === 'http' ? 'selected' : '' %>>http</option>
|
||||||
|
<option value="https" <%- forward_scheme === 'https' ? 'selected' : '' %>>https</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-5 col-md-5">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('proxy-hosts', 'forward-host') %><span class="form-required">*</span></label>
|
||||||
|
<input type="text" name="forward_host" class="form-control text-monospace" placeholder="" value="<%- forward_host %>" autocomplete="off" maxlength="50" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 col-md-4">
|
<div class="col-sm-4 col-md-4">
|
||||||
@ -50,6 +59,16 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="allow_websocket_upgrade" value="1"<%- allow_websocket_upgrade ? ' checked' : '' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'allow-websocket-upgrade') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label"><%- i18n('proxy-hosts', 'access-list') %></label>
|
<label class="form-label"><%- i18n('proxy-hosts', 'access-list') %></label>
|
||||||
@ -73,7 +92,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-6 col-md-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="custom-switch">
|
<label class="custom-switch">
|
||||||
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
||||||
@ -82,6 +101,33 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="http2_support" value="1"<%- http2_support ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'http2-support') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="hsts_subdomains" value="1"<%- hsts_subdomains ? ' checked' : '' %><%- certificate_id && ssl_forced && hsts_enabled ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-subdomains') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Lets encrypt -->
|
<!-- Lets encrypt -->
|
||||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||||
@ -106,6 +152,12 @@
|
|||||||
<div role="tabpanel" class="tab-pane" id="advanced">
|
<div role="tabpanel" class="tab-pane" id="advanced">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
<p>Nginx variables available to you are:</p>
|
||||||
|
<ul class="text-monospace">
|
||||||
|
<li>$server # Host/IP</li>
|
||||||
|
<li>$port # Port Number</li>
|
||||||
|
<li>$forward_scheme # http or https</li>
|
||||||
|
</ul>
|
||||||
<div class="form-group mb-0">
|
<div class="form-group mb-0">
|
||||||
<label class="form-label"><%- i18n('all-hosts', 'advanced-config') %></label>
|
<label class="form-label"><%- i18n('all-hosts', 'advanced-config') %></label>
|
||||||
<textarea name="advanced_config" rows="8" class="form-control text-monospace" placeholder="# <%- i18n('all-hosts', 'advanced-warning') %>"><%- advanced_config %></textarea>
|
<textarea name="advanced_config" rows="8" class="form-control text-monospace" placeholder="# <%- i18n('all-hosts', 'advanced-warning') %>"><%- advanced_config %></textarea>
|
||||||
|
@ -9,7 +9,6 @@ const accessListItemTemplate = require('./access-list-item.ejs');
|
|||||||
const Helpers = require('../../../lib/helpers');
|
const Helpers = require('../../../lib/helpers');
|
||||||
|
|
||||||
require('jquery-serializejson');
|
require('jquery-serializejson');
|
||||||
require('jquery-mask-plugin');
|
|
||||||
require('selectize');
|
require('selectize');
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
@ -19,13 +18,17 @@ module.exports = Mn.View.extend({
|
|||||||
ui: {
|
ui: {
|
||||||
form: 'form',
|
form: 'form',
|
||||||
domain_names: 'input[name="domain_names"]',
|
domain_names: 'input[name="domain_names"]',
|
||||||
forward_ip: 'input[name="forward_ip"]',
|
forward_host: 'input[name="forward_host"]',
|
||||||
buttons: '.modal-footer button',
|
buttons: '.modal-footer button',
|
||||||
cancel: 'button.cancel',
|
cancel: 'button.cancel',
|
||||||
save: 'button.save',
|
save: 'button.save',
|
||||||
certificate_select: 'select[name="certificate_id"]',
|
certificate_select: 'select[name="certificate_id"]',
|
||||||
access_list_select: 'select[name="access_list_id"]',
|
access_list_select: 'select[name="access_list_id"]',
|
||||||
ssl_forced: 'input[name="ssl_forced"]',
|
ssl_forced: 'input[name="ssl_forced"]',
|
||||||
|
hsts_enabled: 'input[name="hsts_enabled"]',
|
||||||
|
hsts_subdomains: 'input[name="hsts_subdomains"]',
|
||||||
|
http2_support: 'input[name="http2_support"]',
|
||||||
|
forward_scheme: 'select[name="forward_scheme"]',
|
||||||
letsencrypt: '.letsencrypt'
|
letsencrypt: '.letsencrypt'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -39,7 +42,44 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||||
this.ui.ssl_forced.prop('disabled', !enabled).parents('.form-group').css('opacity', enabled ? 1 : 0.5);
|
|
||||||
|
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||||
|
inputs
|
||||||
|
.prop('disabled', !enabled)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', enabled ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
inputs.prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change @ui.ssl_forced': function () {
|
||||||
|
let checked = this.ui.ssl_forced.prop('checked');
|
||||||
|
this.ui.hsts_enabled
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
this.ui.hsts_enabled.prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.hsts_enabled.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change @ui.hsts_enabled': function () {
|
||||||
|
let checked = this.ui.hsts_enabled.prop('checked');
|
||||||
|
this.ui.hsts_subdomains
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
this.ui.hsts_subdomains.prop('checked', false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'click @ui.save': function (e) {
|
'click @ui.save': function (e) {
|
||||||
@ -54,13 +94,14 @@ module.exports = Mn.View.extend({
|
|||||||
let data = this.ui.form.serializeJSON();
|
let data = this.ui.form.serializeJSON();
|
||||||
|
|
||||||
// Manipulate
|
// Manipulate
|
||||||
data.forward_port = parseInt(data.forward_port, 10);
|
data.forward_port = parseInt(data.forward_port, 10);
|
||||||
data.block_exploits = !!data.block_exploits;
|
data.block_exploits = !!data.block_exploits;
|
||||||
data.caching_enabled = !!data.caching_enabled;
|
data.caching_enabled = !!data.caching_enabled;
|
||||||
|
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
|
||||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
data.http2_support = !!data.http2_support;
|
||||||
data.ssl_forced = true;
|
data.hsts_enabled = !!data.hsts_enabled;
|
||||||
}
|
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||||
|
data.ssl_forced = !!data.ssl_forced;
|
||||||
|
|
||||||
if (typeof data.domain_names === 'string' && data.domain_names) {
|
if (typeof data.domain_names === 'string' && data.domain_names) {
|
||||||
data.domain_names = data.domain_names.split(',');
|
data.domain_names = data.domain_names.split(',');
|
||||||
@ -82,7 +123,7 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
|
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
|
||||||
} else {
|
} else {
|
||||||
data.certificate_id = parseInt(data.certificate_id, 0);
|
data.certificate_id = parseInt(data.certificate_id, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
let method = App.Api.Nginx.ProxyHosts.create;
|
let method = App.Api.Nginx.ProxyHosts.create;
|
||||||
@ -122,11 +163,8 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
// IP Address
|
this.ui.ssl_forced.trigger('change');
|
||||||
this.ui.forward_ip.mask('099.099.099.099', {
|
this.ui.hsts_enabled.trigger('change');
|
||||||
clearIfNotMatch: true,
|
|
||||||
placeholder: '000.000.000.000'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Domain names
|
// Domain names
|
||||||
this.ui.domain_names.selectize({
|
this.ui.domain_names.selectize({
|
||||||
@ -143,7 +181,6 @@ module.exports = Mn.View.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Access Lists
|
// Access Lists
|
||||||
this.ui.letsencrypt.hide();
|
|
||||||
this.ui.access_list_select.selectize({
|
this.ui.access_list_select.selectize({
|
||||||
valueField: 'id',
|
valueField: 'id',
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
|
@ -6,9 +6,15 @@
|
|||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
<% domain_names.map(function(host) {
|
<% domain_names.map(function(host) {
|
||||||
%>
|
if (host.indexOf('*') === -1) {
|
||||||
<span class="tag"><%- host %></span>
|
%>
|
||||||
<%
|
<span class="tag host-link hover-green" rel="http<%- certificate_id ? 's' : '' %>://<%- host %>"><%- host %></span>
|
||||||
|
<%
|
||||||
|
} else {
|
||||||
|
%>
|
||||||
|
<span class="tag"><%- host %></span>
|
||||||
|
<%
|
||||||
|
}
|
||||||
});
|
});
|
||||||
%>
|
%>
|
||||||
</div>
|
</div>
|
||||||
@ -17,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="text-monospace"><%- forward_ip %>:<%- forward_port %></div>
|
<div class="text-monospace"><%- forward_scheme %>://<%- forward_host %>:<%- forward_port %></div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div><%- certificate && certificate_id ? i18n('ssl', certificate.provider) : i18n('ssl', 'none') %></div>
|
<div><%- certificate && certificate_id ? i18n('ssl', certificate.provider) : i18n('ssl', 'none') %></div>
|
||||||
@ -28,7 +34,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<%
|
<%
|
||||||
var o = isOnline();
|
var o = isOnline();
|
||||||
if (o === true) { %>
|
if (!enabled) { %>
|
||||||
|
<span class="status-icon bg-warning"></span> <%- i18n('str', 'disabled') %>
|
||||||
|
<% } else if (o === true) { %>
|
||||||
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
||||||
<% } else if (o === false) { %>
|
<% } else if (o === false) { %>
|
||||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||||
@ -42,7 +50,7 @@
|
|||||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
||||||
<!--<a href="#" class="logs dropdown-item"><i class="dropdown-icon fe fe-book"></i> <%- i18n('str', 'logs') %></a>-->
|
<a href="#" class="able dropdown-item"><i class="dropdown-icon fe fe-power"></i> <%- i18n('str', enabled ? 'disable' : 'enable') %></a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,11 +9,25 @@ module.exports = Mn.View.extend({
|
|||||||
tagName: 'tr',
|
tagName: 'tr',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
edit: 'a.edit',
|
able: 'a.able',
|
||||||
delete: 'a.delete'
|
edit: 'a.edit',
|
||||||
|
delete: 'a.delete',
|
||||||
|
host_link: '.host-link'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
'click @ui.able': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let id = this.model.get('id');
|
||||||
|
App.Api.Nginx.ProxyHosts[this.model.get('enabled') ? 'disable' : 'enable'](id)
|
||||||
|
.then(() => {
|
||||||
|
return App.Api.Nginx.ProxyHosts.get(id)
|
||||||
|
.then(row => {
|
||||||
|
this.model.set(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
'click @ui.edit': function (e) {
|
'click @ui.edit': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxProxyForm(this.model);
|
App.Controller.showNginxProxyForm(this.model);
|
||||||
@ -22,6 +36,12 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.delete': function (e) {
|
'click @ui.delete': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxProxyDeleteConfirm(this.model);
|
App.Controller.showNginxProxyDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.host_link': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
||||||
|
win.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-6 col-md-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="custom-switch">
|
<label class="custom-switch">
|
||||||
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
<input type="checkbox" class="custom-switch-input" name="ssl_forced" value="1"<%- ssl_forced ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
||||||
@ -69,6 +69,33 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="http2_support" value="1"<%- http2_support ? ' checked' : '' %><%- certificate_id ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'http2-support') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="hsts_enabled" value="1"<%- hsts_enabled ? ' checked' : '' %><%- certificate_id && ssl_forced ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-enabled') %> <a href="https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-md-6">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="custom-switch">
|
||||||
|
<input type="checkbox" class="custom-switch-input" name="hsts_subdomains" value="1"<%- hsts_subdomains ? ' checked' : '' %><%- certificate_id && ssl_forced && hsts_enabled ? '' : ' disabled' %>>
|
||||||
|
<span class="custom-switch-indicator"></span>
|
||||||
|
<span class="custom-switch-description"><%- i18n('all-hosts', 'hsts-subdomains') %></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Lets encrypt -->
|
<!-- Lets encrypt -->
|
||||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||||
|
@ -22,6 +22,9 @@ module.exports = Mn.View.extend({
|
|||||||
save: 'button.save',
|
save: 'button.save',
|
||||||
certificate_select: 'select[name="certificate_id"]',
|
certificate_select: 'select[name="certificate_id"]',
|
||||||
ssl_forced: 'input[name="ssl_forced"]',
|
ssl_forced: 'input[name="ssl_forced"]',
|
||||||
|
hsts_enabled: 'input[name="hsts_enabled"]',
|
||||||
|
hsts_subdomains: 'input[name="hsts_subdomains"]',
|
||||||
|
http2_support: 'input[name="http2_support"]',
|
||||||
letsencrypt: '.letsencrypt'
|
letsencrypt: '.letsencrypt'
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -35,7 +38,44 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||||
this.ui.ssl_forced.prop('disabled', !enabled).parents('.form-group').css('opacity', enabled ? 1 : 0.5);
|
|
||||||
|
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||||
|
inputs
|
||||||
|
.prop('disabled', !enabled)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', enabled ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
inputs.prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
inputs.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change @ui.ssl_forced': function () {
|
||||||
|
let checked = this.ui.ssl_forced.prop('checked');
|
||||||
|
this.ui.hsts_enabled
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
this.ui.hsts_enabled.prop('checked', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.hsts_enabled.trigger('change');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change @ui.hsts_enabled': function () {
|
||||||
|
let checked = this.ui.hsts_enabled.prop('checked');
|
||||||
|
this.ui.hsts_subdomains
|
||||||
|
.prop('disabled', !checked)
|
||||||
|
.parents('.form-group')
|
||||||
|
.css('opacity', checked ? 1 : 0.5);
|
||||||
|
|
||||||
|
if (!checked) {
|
||||||
|
this.ui.hsts_subdomains.prop('checked', false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'click @ui.save': function (e) {
|
'click @ui.save': function (e) {
|
||||||
@ -50,12 +90,12 @@ module.exports = Mn.View.extend({
|
|||||||
let data = this.ui.form.serializeJSON();
|
let data = this.ui.form.serializeJSON();
|
||||||
|
|
||||||
// Manipulate
|
// Manipulate
|
||||||
data.block_exploits = !!data.block_exploits;
|
data.block_exploits = !!data.block_exploits;
|
||||||
data.preserve_path = !!data.preserve_path;
|
data.preserve_path = !!data.preserve_path;
|
||||||
|
data.http2_support = !!data.http2_support;
|
||||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
data.hsts_enabled = !!data.hsts_enabled;
|
||||||
data.ssl_forced = true;
|
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||||
}
|
data.ssl_forced = !!data.ssl_forced;
|
||||||
|
|
||||||
if (typeof data.domain_names === 'string' && data.domain_names) {
|
if (typeof data.domain_names === 'string' && data.domain_names) {
|
||||||
data.domain_names = data.domain_names.split(',');
|
data.domain_names = data.domain_names.split(',');
|
||||||
@ -77,7 +117,7 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
|
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree === '1';
|
||||||
} else {
|
} else {
|
||||||
data.certificate_id = parseInt(data.certificate_id, 0);
|
data.certificate_id = parseInt(data.certificate_id, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
let method = App.Api.Nginx.RedirectionHosts.create;
|
let method = App.Api.Nginx.RedirectionHosts.create;
|
||||||
|
@ -6,9 +6,15 @@
|
|||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
<% domain_names.map(function(host) {
|
<% domain_names.map(function(host) {
|
||||||
%>
|
if (host.indexOf('*') === -1) {
|
||||||
<span class="tag"><%- host %></span>
|
%>
|
||||||
<%
|
<span class="tag host-link hover-yellow" rel="http<%- certificate_id ? 's' : '' %>://<%- host %>"><%- host %></span>
|
||||||
|
<%
|
||||||
|
} else {
|
||||||
|
%>
|
||||||
|
<span class="tag"><%- host %></span>
|
||||||
|
<%
|
||||||
|
}
|
||||||
});
|
});
|
||||||
%>
|
%>
|
||||||
</div>
|
</div>
|
||||||
@ -25,7 +31,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<%
|
<%
|
||||||
var o = isOnline();
|
var o = isOnline();
|
||||||
if (o === true) { %>
|
if (!enabled) { %>
|
||||||
|
<span class="status-icon bg-warning"></span> <%- i18n('str', 'disabled') %>
|
||||||
|
<% } else if (o === true) { %>
|
||||||
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
||||||
<% } else if (o === false) { %>
|
<% } else if (o === false) { %>
|
||||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||||
@ -39,7 +47,7 @@
|
|||||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
||||||
<!--<a href="#" class="logs dropdown-item"><i class="dropdown-icon fe fe-book"></i> <%- i18n('str', 'logs') %></a>-->
|
<a href="#" class="able dropdown-item"><i class="dropdown-icon fe fe-power"></i> <%- i18n('str', enabled ? 'disable' : 'enable') %></a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,11 +9,25 @@ module.exports = Mn.View.extend({
|
|||||||
tagName: 'tr',
|
tagName: 'tr',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
edit: 'a.edit',
|
able: 'a.able',
|
||||||
delete: 'a.delete'
|
edit: 'a.edit',
|
||||||
|
delete: 'a.delete',
|
||||||
|
host_link: '.host-link'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
'click @ui.able': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let id = this.model.get('id');
|
||||||
|
App.Api.Nginx.RedirectionHosts[this.model.get('enabled') ? 'disable' : 'enable'](id)
|
||||||
|
.then(() => {
|
||||||
|
return App.Api.Nginx.RedirectionHosts.get(id)
|
||||||
|
.then(row => {
|
||||||
|
this.model.set(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
'click @ui.edit': function (e) {
|
'click @ui.edit': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxRedirectionForm(this.model);
|
App.Controller.showNginxRedirectionForm(this.model);
|
||||||
@ -22,6 +36,12 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.delete': function (e) {
|
'click @ui.delete': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxRedirectionDeleteConfirm(this.model);
|
App.Controller.showNginxRedirectionDeleteConfirm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.host_link': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
||||||
|
win.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -27,7 +27,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<%
|
<%
|
||||||
var o = isOnline();
|
var o = isOnline();
|
||||||
if (o === true) { %>
|
if (!enabled) { %>
|
||||||
|
<span class="status-icon bg-warning"></span> <%- i18n('str', 'disabled') %>
|
||||||
|
<% } else if (o === true) { %>
|
||||||
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
||||||
<% } else if (o === false) { %>
|
<% } else if (o === false) { %>
|
||||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||||
@ -41,6 +43,7 @@
|
|||||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
||||||
|
<a href="#" class="able dropdown-item"><i class="dropdown-icon fe fe-power"></i> <%- i18n('str', enabled ? 'disable' : 'enable') %></a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,11 +9,24 @@ module.exports = Mn.View.extend({
|
|||||||
tagName: 'tr',
|
tagName: 'tr',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
|
able: 'a.able',
|
||||||
edit: 'a.edit',
|
edit: 'a.edit',
|
||||||
delete: 'a.delete'
|
delete: 'a.delete'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
'click @ui.able': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let id = this.model.get('id');
|
||||||
|
App.Api.Nginx.Streams[this.model.get('enabled') ? 'disable' : 'enable'](id)
|
||||||
|
.then(() => {
|
||||||
|
return App.Api.Nginx.Streams.get(id)
|
||||||
|
.then(row => {
|
||||||
|
this.model.set(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
'click @ui.edit': function (e) {
|
'click @ui.edit': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showNginxStreamForm(this.model);
|
App.Controller.showNginxStreamForm(this.model);
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
"enable": "Enable",
|
||||||
|
"disable": "Disable",
|
||||||
"sure": "Yes I'm Sure",
|
"sure": "Yes I'm Sure",
|
||||||
"disabled": "Disabled",
|
"disabled": "Disabled",
|
||||||
"choose-file": "Choose file",
|
"choose-file": "Choose file",
|
||||||
@ -65,6 +67,7 @@
|
|||||||
"details": "Details",
|
"details": "Details",
|
||||||
"enable-ssl": "Enable SSL",
|
"enable-ssl": "Enable SSL",
|
||||||
"force-ssl": "Force SSL",
|
"force-ssl": "Force SSL",
|
||||||
|
"http2-support": "HTTP/2 Support",
|
||||||
"domain-names": "Domain Names",
|
"domain-names": "Domain Names",
|
||||||
"cert-provider": "Certificate Provider",
|
"cert-provider": "Certificate Provider",
|
||||||
"block-exploits": "Block Common Exploits",
|
"block-exploits": "Block Common Exploits",
|
||||||
@ -76,7 +79,9 @@
|
|||||||
"no-ssl": "This host will not use HTTPS",
|
"no-ssl": "This host will not use HTTPS",
|
||||||
"advanced": "Advanced",
|
"advanced": "Advanced",
|
||||||
"advanced-warning": "Enter your custom Nginx configuration here at your own risk!",
|
"advanced-warning": "Enter your custom Nginx configuration here at your own risk!",
|
||||||
"advanced-config": "Custom Nginx Configuration"
|
"advanced-config": "Custom Nginx Configuration",
|
||||||
|
"hsts-enabled": "HSTS Enabled",
|
||||||
|
"hsts-subdomains": "HSTS Subdomains"
|
||||||
},
|
},
|
||||||
"ssl": {
|
"ssl": {
|
||||||
"letsencrypt": "Let's Encrypt",
|
"letsencrypt": "Let's Encrypt",
|
||||||
@ -92,13 +97,16 @@
|
|||||||
"empty": "There are no Proxy Hosts",
|
"empty": "There are no Proxy Hosts",
|
||||||
"add": "Add Proxy Host",
|
"add": "Add Proxy Host",
|
||||||
"form-title": "{id, select, undefined{New} other{Edit}} Proxy Host",
|
"form-title": "{id, select, undefined{New} other{Edit}} Proxy Host",
|
||||||
"forward-ip": "Forward IP",
|
"forward-scheme": "Scheme",
|
||||||
|
"forward-host": "Forward Hostname / IP",
|
||||||
"forward-port": "Forward Port",
|
"forward-port": "Forward Port",
|
||||||
"delete": "Delete Proxy Host",
|
"delete": "Delete Proxy Host",
|
||||||
"delete-confirm": "Are you sure you want to delete the Proxy host for: <strong>{domains}</strong>?",
|
"delete-confirm": "Are you sure you want to delete the Proxy host for: <strong>{domains}</strong>?",
|
||||||
"help-title": "What is a Proxy Host?",
|
"help-title": "What is a Proxy Host?",
|
||||||
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional SSL termination for your service that might not have SSL support built in.\nProxy Hosts are the most common use for the Nginx Proxy Manager.",
|
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional SSL termination for your service that might not have SSL support built in.\nProxy Hosts are the most common use for the Nginx Proxy Manager.",
|
||||||
"access-list": "Access List"
|
"access-list": "Access List",
|
||||||
|
"allow-websocket-upgrade": "Websockets Support",
|
||||||
|
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL"
|
||||||
},
|
},
|
||||||
"redirection-hosts": {
|
"redirection-hosts": {
|
||||||
"title": "Redirection Hosts",
|
"title": "Redirection Hosts",
|
||||||
@ -209,6 +217,8 @@
|
|||||||
"created": "Created {name}",
|
"created": "Created {name}",
|
||||||
"updated": "Updated {name}",
|
"updated": "Updated {name}",
|
||||||
"deleted": "Deleted {name}",
|
"deleted": "Deleted {name}",
|
||||||
|
"enabled": "Enabled {name}",
|
||||||
|
"disabled": "Disabled {name}",
|
||||||
"meta-title": "Details for Event",
|
"meta-title": "Details for Event",
|
||||||
"view-meta": "View Details",
|
"view-meta": "View Details",
|
||||||
"date": "Date"
|
"date": "Date"
|
||||||
|
@ -13,6 +13,10 @@ const model = Backbone.Model.extend({
|
|||||||
domain_names: [],
|
domain_names: [],
|
||||||
certificate_id: 0,
|
certificate_id: 0,
|
||||||
ssl_forced: false,
|
ssl_forced: false,
|
||||||
|
http2_support: false,
|
||||||
|
hsts_enabled: false,
|
||||||
|
hsts_subdomains: false,
|
||||||
|
enabled: true,
|
||||||
meta: {},
|
meta: {},
|
||||||
advanced_config: '',
|
advanced_config: '',
|
||||||
// The following are expansions:
|
// The following are expansions:
|
||||||
|
@ -7,23 +7,29 @@ const model = Backbone.Model.extend({
|
|||||||
|
|
||||||
defaults: function () {
|
defaults: function () {
|
||||||
return {
|
return {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
created_on: null,
|
created_on: null,
|
||||||
modified_on: null,
|
modified_on: null,
|
||||||
domain_names: [],
|
domain_names: [],
|
||||||
forward_ip: '',
|
forward_scheme: 'http',
|
||||||
forward_port: null,
|
forward_host: '',
|
||||||
access_list_id: 0,
|
forward_port: null,
|
||||||
certificate_id: 0,
|
access_list_id: 0,
|
||||||
ssl_forced: false,
|
certificate_id: 0,
|
||||||
caching_enabled: false,
|
ssl_forced: false,
|
||||||
block_exploits: false,
|
hsts_enabled: false,
|
||||||
advanced_config: '',
|
hsts_subdomains: false,
|
||||||
meta: {},
|
caching_enabled: false,
|
||||||
|
allow_websocket_upgrade: false,
|
||||||
|
block_exploits: false,
|
||||||
|
http2_support: false,
|
||||||
|
advanced_config: '',
|
||||||
|
enabled: true,
|
||||||
|
meta: {},
|
||||||
// The following are expansions:
|
// The following are expansions:
|
||||||
owner: null,
|
owner: null,
|
||||||
access_list: null,
|
access_list: null,
|
||||||
certificate: null
|
certificate: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -15,8 +15,12 @@ const model = Backbone.Model.extend({
|
|||||||
preserve_path: true,
|
preserve_path: true,
|
||||||
certificate_id: 0,
|
certificate_id: 0,
|
||||||
ssl_forced: false,
|
ssl_forced: false,
|
||||||
|
hsts_enabled: false,
|
||||||
|
hsts_subdomains: false,
|
||||||
block_exploits: false,
|
block_exploits: false,
|
||||||
|
http2_support: false,
|
||||||
advanced_config: '',
|
advanced_config: '',
|
||||||
|
enabled: true,
|
||||||
meta: {},
|
meta: {},
|
||||||
// The following are expansions:
|
// The following are expansions:
|
||||||
owner: null,
|
owner: null,
|
||||||
|
@ -15,6 +15,7 @@ const model = Backbone.Model.extend({
|
|||||||
forwarding_port: null,
|
forwarding_port: null,
|
||||||
tcp_forwarding: true,
|
tcp_forwarding: true,
|
||||||
udp_forwarding: false,
|
udp_forwarding: false,
|
||||||
|
enabled: true,
|
||||||
meta: {},
|
meta: {},
|
||||||
// The following are expansions:
|
// The following are expansions:
|
||||||
owner: null
|
owner: null
|
||||||
|
@ -3,6 +3,18 @@ $yellow: #f1c40f;
|
|||||||
$blue: #467fcf;
|
$blue: #467fcf;
|
||||||
$pink: #f66d9b;
|
$pink: #f66d9b;
|
||||||
|
|
||||||
|
.tag.hover-green:hover, .tag.hover-green:active, .tag.hover-green:focus {
|
||||||
|
background-color: #5eba00;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.hover-red:hover, .tag.hover-red:active, .tag.hover-red:focus {
|
||||||
|
background-color: #cd201f;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
/* For Card bodies where I don't want padding */
|
/* For Card bodies where I don't want padding */
|
||||||
.card-body.no-padding {
|
.card-body.no-padding {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -28,6 +40,12 @@ $pink: #f66d9b;
|
|||||||
border-color: $teal;
|
border-color: $teal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag.hover-teal:hover, .tag.hover-teal:active, .tag.hover-teal:focus {
|
||||||
|
background-color: $teal;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
/* Yellow Outline Buttons */
|
/* Yellow Outline Buttons */
|
||||||
.btn-outline-yellow {
|
.btn-outline-yellow {
|
||||||
color: $yellow;
|
color: $yellow;
|
||||||
@ -48,6 +66,12 @@ $pink: #f66d9b;
|
|||||||
border-color: $yellow;
|
border-color: $yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag.hover-yellow:hover, .tag.hover-yellow:active, .tag.hover-yellow:focus {
|
||||||
|
background-color: $yellow;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
/* Blue Outline Buttons */
|
/* Blue Outline Buttons */
|
||||||
.btn-outline-blue {
|
.btn-outline-blue {
|
||||||
color: $blue;
|
color: $blue;
|
||||||
@ -68,6 +92,12 @@ $pink: #f66d9b;
|
|||||||
border-color: $blue;
|
border-color: $blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag.hover-blue:hover, .tag.hover-blue:active, .tag.hover-blue:focus {
|
||||||
|
background-color: $blue;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pink Outline Buttons */
|
/* Pink Outline Buttons */
|
||||||
.btn-outline-pink {
|
.btn-outline-pink {
|
||||||
color: $pink;
|
color: $pink;
|
||||||
@ -88,6 +118,11 @@ $pink: #f66d9b;
|
|||||||
border-color: $pink;
|
border-color: $pink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag.hover-pink:hover, .tag.hover-pink:active, .tag.hover-pink:focus {
|
||||||
|
background-color: $pink;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
/* dimmer */
|
/* dimmer */
|
||||||
|
|
||||||
.dimmer .loader {
|
.dimmer .loader {
|
||||||
|
@ -10,9 +10,10 @@ module.exports = {
|
|||||||
login: './src/frontend/js/login.js'
|
login: './src/frontend/js/login.js'
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, 'dist'),
|
path: path.resolve(__dirname, 'dist'),
|
||||||
filename: 'js/[name].js',
|
filename: 'js/[name].bundle.js',
|
||||||
publicPath: '/'
|
chunkFilename: 'js/[name].bundle.[id].js',
|
||||||
|
publicPath: '/'
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@ -108,41 +109,6 @@ module.exports = {
|
|||||||
to: 'images',
|
to: 'images',
|
||||||
toType: 'dir',
|
toType: 'dir',
|
||||||
context: '/app'
|
context: '/app'
|
||||||
}]),
|
}])
|
||||||
new webpack.optimize.LimitChunkCountPlugin({
|
]
|
||||||
maxChunks: 1, // Must be greater than or equal to one
|
|
||||||
minChunkSize: 999999999
|
|
||||||
})
|
|
||||||
],
|
|
||||||
/*
|
|
||||||
optimization: {
|
|
||||||
splitChunks: {
|
|
||||||
chunks (chunk) {
|
|
||||||
// exclude `my-excluded-chunk`
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
minSize: 999999999,
|
|
||||||
minChunks: 1,
|
|
||||||
name: true,
|
|
||||||
cacheGroups: {
|
|
||||||
vendors: {
|
|
||||||
test: /[\\/]node_modules[\\/]/,
|
|
||||||
priority: -10
|
|
||||||
},
|
|
||||||
default: {
|
|
||||||
minChunks: 2,
|
|
||||||
priority: -20,
|
|
||||||
reuseExistingChunk: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
devServer: {
|
|
||||||
contentBase: path.join(__dirname, 'dist'),
|
|
||||||
compress: true,
|
|
||||||
port: 8080,
|
|
||||||
disableHostCheck: true,
|
|
||||||
host: '0.0.0.0'
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user