Compare commits
26 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 |
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
|
@ -1,4 +1,4 @@
|
||||
FROM jc21/nginx-proxy-manager-base:latest-armhf
|
||||
FROM jc21/nginx-proxy-manager-base:armhf
|
||||
|
||||
MAINTAINER Jamie Curnow <jc@jc21.com>
|
||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||
|
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
|
197
Jenkinsfile
vendored
197
Jenkinsfile
vendored
@ -5,17 +5,45 @@ pipeline {
|
||||
}
|
||||
agent any
|
||||
environment {
|
||||
IMAGE_NAME = "nginx-proxy-manager"
|
||||
BASE_IMAGE_NAME = "jc21/nginx-proxy-manager-base:latest"
|
||||
TEMP_IMAGE_NAME = "nginx-proxy-manager-build_${BUILD_NUMBER}"
|
||||
TEMP_IMAGE_NAME_ARM = "nginx-proxy-manager-arm-build_${BUILD_NUMBER}"
|
||||
TAG_VERSION = getPackageVersion()
|
||||
MAJOR_VERSION = "2"
|
||||
IMAGE = "nginx-proxy-manager"
|
||||
BASE_IMAGE = "jc21/nginx-proxy-manager-base"
|
||||
TEMP_IMAGE = "nginx-proxy-manager-build_${BUILD_NUMBER}"
|
||||
TEMP_IMAGE_ARM = "nginx-proxy-manager-arm-build_${BUILD_NUMBER}"
|
||||
TEMP_IMAGE_ARM64 = "nginx-proxy-manager-arm64-build_${BUILD_NUMBER}"
|
||||
TAG_VERSION = getPackageVersion()
|
||||
MAJOR_VERSION = "2"
|
||||
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase()}"
|
||||
}
|
||||
stages {
|
||||
stage('Prepare') {
|
||||
stage('Build PR') {
|
||||
when {
|
||||
changeRequest()
|
||||
}
|
||||
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 Develop') {
|
||||
@ -25,30 +53,30 @@ pipeline {
|
||||
steps {
|
||||
ansiColor('xterm') {
|
||||
// Codebase
|
||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME 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} 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_NAME yarn install --prod'
|
||||
sh 'docker run --rm -v $(pwd):/data $DOCKER_CI_TOOLS node-prune'
|
||||
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_NAME .'
|
||||
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE} .'
|
||||
|
||||
// Dockerhub
|
||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:develop'
|
||||
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_NAME:develop'
|
||||
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:develop'
|
||||
}
|
||||
|
||||
// Private Registry
|
||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:develop'
|
||||
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_NAME:develop'
|
||||
sh "docker login -u '${duser}' -p '${dpass}' ${DOCKER_PRIVATE_REGISTRY}"
|
||||
sh 'docker push ${DOCKER_PRIVATE_REGISTRY}/${IMAGE}:develop'
|
||||
}
|
||||
|
||||
sh 'docker rmi $TEMP_IMAGE_NAME'
|
||||
sh 'docker rmi ${TEMP_IMAGE}'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,40 +89,40 @@ pipeline {
|
||||
steps {
|
||||
ansiColor('xterm') {
|
||||
// Codebase
|
||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME 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} 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_NAME yarn install --prod'
|
||||
sh 'docker run --rm -v $(pwd):/data $DOCKER_CI_TOOLS node-prune'
|
||||
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_NAME .'
|
||||
sh 'docker build --pull --no-cache --squash --compress -t ${TEMP_IMAGE} .'
|
||||
|
||||
// Dockerhub
|
||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:$TAG_VERSION'
|
||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:$MAJOR_VERSION'
|
||||
sh 'docker tag $TEMP_IMAGE_NAME docker.io/jc21/$IMAGE_NAME:latest'
|
||||
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:${TAG_VERSION}'
|
||||
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:${MAJOR_VERSION}'
|
||||
sh 'docker tag ${TEMP_IMAGE} docker.io/jc21/${IMAGE}:latest'
|
||||
|
||||
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||
sh "docker login -u '${duser}' -p '$dpass'"
|
||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:$TAG_VERSION'
|
||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:$MAJOR_VERSION'
|
||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:latest'
|
||||
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:${TAG_VERSION}'
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:${MAJOR_VERSION}'
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:latest'
|
||||
}
|
||||
|
||||
// Private Registry
|
||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$TAG_VERSION'
|
||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION'
|
||||
sh 'docker tag $TEMP_IMAGE_NAME $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest'
|
||||
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_NAME:$TAG_VERSION'
|
||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION'
|
||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest'
|
||||
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_NAME'
|
||||
sh 'docker rmi ${TEMP_IMAGE}'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -108,39 +136,88 @@ pipeline {
|
||||
steps {
|
||||
ansiColor('xterm') {
|
||||
// Codebase
|
||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME-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 yarn install'
|
||||
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:armhf npm run-script build'
|
||||
sh 'rm -rf node_modules'
|
||||
sh 'docker run --rm -v $(pwd):/app -w /app $BASE_IMAGE_NAME-armhf yarn install --prod'
|
||||
sh 'docker run --rm -v $(pwd):/app -w /app ${BASE_IMAGE}:armhf yarn install --prod'
|
||||
|
||||
// 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 .'
|
||||
|
||||
// Dockerhub
|
||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM docker.io/jc21/$IMAGE_NAME:$TAG_VERSION-armhf'
|
||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM docker.io/jc21/$IMAGE_NAME:$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}:${TAG_VERSION}-armhf'
|
||||
sh 'docker tag ${TEMP_IMAGE_ARM} docker.io/jc21/${IMAGE}:${MAJOR_VERSION}-armhf'
|
||||
sh 'docker tag ${TEMP_IMAGE_ARM} docker.io/jc21/${IMAGE}:latest-armhf'
|
||||
|
||||
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||
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_NAME:$MAJOR_VERSION-armhf'
|
||||
sh 'docker push docker.io/jc21/$IMAGE_NAME:latest-armhf'
|
||||
sh "docker login -u '${duser}' -p '${dpass}'"
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:${TAG_VERSION}-armhf'
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:${MAJOR_VERSION}-armhf'
|
||||
sh 'docker push docker.io/jc21/${IMAGE}:latest-armhf'
|
||||
}
|
||||
|
||||
// Private Registry
|
||||
sh 'docker tag $TEMP_IMAGE_NAME_ARM $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 tag $TEMP_IMAGE_NAME_ARM $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest-armhf'
|
||||
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_NAME:$TAG_VERSION-armhf'
|
||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:$MAJOR_VERSION-armhf'
|
||||
sh 'docker push $DOCKER_PRIVATE_REGISTRY/$IMAGE_NAME:latest-armhf'
|
||||
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_NAME_ARM'
|
||||
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 *'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,7 +237,7 @@ pipeline {
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
|
16
README.md
16
README.md
@ -2,20 +2,22 @@
|
||||
|
||||
# Nginx Proxy Manager
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
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.
|
||||
|
||||
----------
|
||||
|
||||
**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
|
||||
|
||||
- Beautiful and Secure Admin Interface based on [Tabler](https://tabler.github.io/)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# 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-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-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"
|
||||
services:
|
||||
app:
|
||||
image: jc21/nginx-proxy-manager:2
|
||||
image: jc21/nginx-proxy-manager:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
@ -77,7 +77,7 @@ Via `docker-compose`:
|
||||
version: "3"
|
||||
services:
|
||||
app:
|
||||
image: jc21/nginx-proxy-manager:2
|
||||
image: jc21/nginx-proxy-manager:latest
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
@ -100,15 +100,17 @@ docker run -d \
|
||||
-v /path/to/config.json:/app/config/production.json \
|
||||
-v /path/to/data:/data \
|
||||
-v /path/to/letsencrypt:/etc/letsencrypt \
|
||||
jc21/nginx-proxy-manager:2
|
||||
jc21/nginx-proxy-manager:latest
|
||||
```
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
Note: Rpi v2 and below won't work with these images.
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name nginx-proxy-manager-app \
|
||||
@ -118,7 +120,7 @@ docker run -d \
|
||||
-v /path/to/config.json:/app/config/production.json \
|
||||
-v /path/to/data:/data \
|
||||
-v /path/to/letsencrypt:/etc/letsencrypt \
|
||||
jc21/nginx-proxy-manager:2-armhf
|
||||
jc21/nginx-proxy-manager:latest-armhf
|
||||
```
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nginx-proxy-manager",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.10",
|
||||
"description": "A beautiful interface for creating Nginx endpoints",
|
||||
"main": "src/backend/index.js",
|
||||
"devDependencies": {
|
||||
|
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
|
||||
|
@ -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
|
||||
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;
|
||||
|
||||
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
|
||||
add_header Strict-Transport-Security max-age=15768000;
|
||||
|
@ -59,6 +59,15 @@ http {
|
||||
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 /data/nginx/proxy_host/*.conf;
|
||||
|
@ -11,6 +11,7 @@ function appStart () {
|
||||
const app = require('./app');
|
||||
const apiValidator = require('./lib/validator/api');
|
||||
const internalCertificate = require('./internal/certificate');
|
||||
const internalIpRanges = require('./internal/ip_ranges');
|
||||
|
||||
return migrate.latest()
|
||||
.then(setup)
|
||||
@ -18,9 +19,11 @@ function appStart () {
|
||||
.then(() => {
|
||||
return apiValidator.loadSchemas;
|
||||
})
|
||||
.then(internalIpRanges.fetch)
|
||||
.then(() => {
|
||||
|
||||
internalCertificate.initTimer();
|
||||
internalIpRanges.initTimer();
|
||||
|
||||
const server = app.listen(81, () => {
|
||||
logger.info('PID ' + process.pid + ' listening on port 81 ...');
|
||||
|
@ -47,6 +47,7 @@ const internalDeadHost = {
|
||||
.then(() => {
|
||||
// At this point the domains should have been checked
|
||||
data.owner_user_id = access.token.getUserId(1);
|
||||
data = internalHost.cleanSslHstsData(data);
|
||||
|
||||
return deadHostModel
|
||||
.query()
|
||||
@ -89,11 +90,11 @@ const internalDeadHost = {
|
||||
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'created',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'created',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return row;
|
||||
});
|
||||
@ -103,7 +104,7 @@ const internalDeadHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @return {Promise}
|
||||
*/
|
||||
update: (access, data) => {
|
||||
@ -144,9 +145,9 @@ const internalDeadHost = {
|
||||
|
||||
if (create_certificate) {
|
||||
return internalCertificate.createQuickCertificate(access, {
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
.then(cert => {
|
||||
// update host with 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.
|
||||
data = _.assign({}, {
|
||||
domain_names: row.domain_names
|
||||
},data);
|
||||
}, data);
|
||||
|
||||
data = internalHost.cleanSslHstsData(data, row);
|
||||
|
||||
return deadHostModel
|
||||
.query()
|
||||
@ -171,11 +174,11 @@ const internalDeadHost = {
|
||||
.then(saved_row => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'updated',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'updated',
|
||||
object_type: 'dead-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return _.omit(saved_row, omissions());
|
||||
});
|
||||
@ -183,15 +186,15 @@ const internalDeadHost = {
|
||||
})
|
||||
.then(() => {
|
||||
return internalDeadHost.get(access, {
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
.then(row => {
|
||||
// Configure nginx
|
||||
return internalNginx.configure(deadHostModel, 'dead_host', row)
|
||||
.then(new_meta => {
|
||||
row.meta = new_meta;
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
return _.omit(row, omissions());
|
||||
});
|
||||
});
|
||||
@ -201,7 +204,7 @@ const internalDeadHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {Array} [data.expand]
|
||||
* @param {Array} [data.omit]
|
||||
* @return {Promise}
|
||||
@ -248,7 +251,7 @@ const internalDeadHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {String} [data.reason]
|
||||
* @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
|
||||
*
|
||||
@ -338,7 +439,7 @@ const internalDeadHost = {
|
||||
/**
|
||||
* Report use
|
||||
*
|
||||
* @param {Integer} user_id
|
||||
* @param {Number} user_id
|
||||
* @param {String} visibility
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
@ -1,11 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const proxyHostModel = require('../models/proxy_host');
|
||||
const redirectionHostModel = require('../models/redirection_host');
|
||||
const deadHostModel = require('../models/dead_host');
|
||||
|
||||
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
|
||||
*
|
||||
|
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 fs = require('fs');
|
||||
const Liquid = require('liquidjs');
|
||||
@ -92,7 +90,7 @@ const internalNginx = {
|
||||
})
|
||||
.then(() => {
|
||||
return combined_meta;
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -146,6 +144,7 @@ const internalNginx = {
|
||||
return new Promise((resolve, reject) => {
|
||||
let template = null;
|
||||
let filename = internalNginx.getConfigName(host_type, host.id);
|
||||
|
||||
try {
|
||||
template = fs.readFileSync(__dirname + '/../templates/' + host_type + '.conf', {encoding: 'utf8'});
|
||||
} catch (err) {
|
||||
@ -153,6 +152,12 @@ const internalNginx = {
|
||||
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
|
||||
.parseAndRender(template, host)
|
||||
.then(config_text => {
|
||||
@ -312,6 +317,14 @@ const internalNginx = {
|
||||
});
|
||||
|
||||
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 error = require('../lib/error');
|
||||
const proxyHostModel = require('../models/proxy_host');
|
||||
@ -47,6 +45,7 @@ const internalProxyHost = {
|
||||
.then(() => {
|
||||
// At this point the domains should have been checked
|
||||
data.owner_user_id = access.token.getUserId(1);
|
||||
data = internalHost.cleanSslHstsData(data);
|
||||
|
||||
return proxyHostModel
|
||||
.query()
|
||||
@ -90,11 +89,11 @@ const internalProxyHost = {
|
||||
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'created',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'created',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return row;
|
||||
});
|
||||
@ -104,12 +103,12 @@ const internalProxyHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @return {Promise}
|
||||
*/
|
||||
update: (access, data) => {
|
||||
let create_certificate = data.certificate_id === 'new';
|
||||
|
||||
console.log('PH UPDATE:', data);
|
||||
if (create_certificate) {
|
||||
delete data.certificate_id;
|
||||
}
|
||||
@ -145,9 +144,9 @@ const internalProxyHost = {
|
||||
|
||||
if (create_certificate) {
|
||||
return internalCertificate.createQuickCertificate(access, {
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
.then(cert => {
|
||||
// update host with cert id
|
||||
data.certificate_id = cert.id;
|
||||
@ -165,6 +164,8 @@ const internalProxyHost = {
|
||||
domain_names: row.domain_names
|
||||
}, data);
|
||||
|
||||
data = internalHost.cleanSslHstsData(data, row);
|
||||
|
||||
return proxyHostModel
|
||||
.query()
|
||||
.where({id: data.id})
|
||||
@ -172,11 +173,11 @@ const internalProxyHost = {
|
||||
.then(saved_row => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'updated',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'updated',
|
||||
object_type: 'proxy-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return _.omit(saved_row, omissions());
|
||||
});
|
||||
@ -184,15 +185,15 @@ const internalProxyHost = {
|
||||
})
|
||||
.then(() => {
|
||||
return internalProxyHost.get(access, {
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate', 'access_list']
|
||||
})
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate', 'access_list']
|
||||
})
|
||||
.then(row => {
|
||||
// Configure nginx
|
||||
return internalNginx.configure(proxyHostModel, 'proxy_host', row)
|
||||
.then(new_meta => {
|
||||
row.meta = new_meta;
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
return _.omit(row, omissions());
|
||||
});
|
||||
});
|
||||
@ -202,7 +203,7 @@ const internalProxyHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {Array} [data.expand]
|
||||
* @param {Array} [data.omit]
|
||||
* @return {Promise}
|
||||
@ -249,7 +250,7 @@ const internalProxyHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {String} [data.reason]
|
||||
* @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
|
||||
*
|
||||
@ -339,7 +438,7 @@ const internalProxyHost = {
|
||||
/**
|
||||
* Report use
|
||||
*
|
||||
* @param {Integer} user_id
|
||||
* @param {Number} user_id
|
||||
* @param {String} visibility
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
@ -47,6 +47,7 @@ const internalRedirectionHost = {
|
||||
.then(() => {
|
||||
// At this point the domains should have been checked
|
||||
data.owner_user_id = access.token.getUserId(1);
|
||||
data = internalHost.cleanSslHstsData(data);
|
||||
|
||||
return redirectionHostModel
|
||||
.query()
|
||||
@ -89,11 +90,11 @@ const internalRedirectionHost = {
|
||||
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'created',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'created',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return row;
|
||||
});
|
||||
@ -103,7 +104,7 @@ const internalRedirectionHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @return {Promise}
|
||||
*/
|
||||
update: (access, data) => {
|
||||
@ -144,9 +145,9 @@ const internalRedirectionHost = {
|
||||
|
||||
if (create_certificate) {
|
||||
return internalCertificate.createQuickCertificate(access, {
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
domain_names: data.domain_names || row.domain_names,
|
||||
meta: _.assign({}, row.meta, data.meta)
|
||||
})
|
||||
.then(cert => {
|
||||
// update host with 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.
|
||||
data = _.assign({}, {
|
||||
domain_names: row.domain_names
|
||||
},data);
|
||||
}, data);
|
||||
|
||||
data = internalHost.cleanSslHstsData(data, row);
|
||||
|
||||
return redirectionHostModel
|
||||
.query()
|
||||
@ -171,11 +174,11 @@ const internalRedirectionHost = {
|
||||
.then(saved_row => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
action: 'updated',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
action: 'updated',
|
||||
object_type: 'redirection-host',
|
||||
object_id: row.id,
|
||||
meta: data
|
||||
})
|
||||
.then(() => {
|
||||
return _.omit(saved_row, omissions());
|
||||
});
|
||||
@ -183,15 +186,15 @@ const internalRedirectionHost = {
|
||||
})
|
||||
.then(() => {
|
||||
return internalRedirectionHost.get(access, {
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
id: data.id,
|
||||
expand: ['owner', 'certificate']
|
||||
})
|
||||
.then(row => {
|
||||
// Configure nginx
|
||||
return internalNginx.configure(redirectionHostModel, 'redirection_host', row)
|
||||
.then(new_meta => {
|
||||
row.meta = new_meta;
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
row = internalHost.cleanRowCertificateMeta(row);
|
||||
return _.omit(row, omissions());
|
||||
});
|
||||
});
|
||||
@ -201,7 +204,7 @@ const internalRedirectionHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {Array} [data.expand]
|
||||
* @param {Array} [data.omit]
|
||||
* @return {Promise}
|
||||
@ -248,7 +251,7 @@ const internalRedirectionHost = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {String} [data.reason]
|
||||
* @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
|
||||
*
|
||||
@ -338,7 +439,7 @@ const internalRedirectionHost = {
|
||||
/**
|
||||
* Report use
|
||||
*
|
||||
* @param {Integer} user_id
|
||||
* @param {Number} user_id
|
||||
* @param {String} visibility
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
@ -56,7 +56,7 @@ const internalStream = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @return {Promise}
|
||||
*/
|
||||
update: (access, data) => {
|
||||
@ -75,6 +75,12 @@ const internalStream = {
|
||||
.query()
|
||||
.omit(omissions())
|
||||
.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 => {
|
||||
// Add to audit log
|
||||
return internalAuditLog.add(access, {
|
||||
@ -93,7 +99,7 @@ const internalStream = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {Array} [data.expand]
|
||||
* @param {Array} [data.omit]
|
||||
* @return {Promise}
|
||||
@ -139,7 +145,7 @@ const internalStream = {
|
||||
/**
|
||||
* @param {Access} access
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @param {String} [data.reason]
|
||||
* @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
|
||||
*
|
||||
@ -222,7 +326,7 @@ const internalStream = {
|
||||
/**
|
||||
* Report use
|
||||
*
|
||||
* @param {Integer} user_id
|
||||
* @param {Number} user_id
|
||||
* @param {String} visibility
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
@ -1,12 +1,13 @@
|
||||
const {Signale} = require('signale');
|
||||
|
||||
module.exports = {
|
||||
global: new Signale({scope: 'Global '}),
|
||||
migrate: new Signale({scope: 'Migrate '}),
|
||||
express: new Signale({scope: 'Express '}),
|
||||
access: new Signale({scope: 'Access '}),
|
||||
nginx: new Signale({scope: 'Nginx '}),
|
||||
ssl: new Signale({scope: 'SSL '}),
|
||||
import: new Signale({scope: 'Importer'}),
|
||||
setup: new Signale({scope: 'Setup '})
|
||||
global: new Signale({scope: 'Global '}),
|
||||
migrate: new Signale({scope: 'Migrate '}),
|
||||
express: new Signale({scope: 'Express '}),
|
||||
access: new Signale({scope: 'Access '}),
|
||||
nginx: new Signale({scope: 'Nginx '}),
|
||||
ssl: new Signale({scope: 'SSL '}),
|
||||
import: new Signale({scope: 'Importer '}),
|
||||
setup: new Signale({scope: 'Setup '}),
|
||||
ip_ranges: new Signale({scope: 'IP Ranges'})
|
||||
};
|
||||
|
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) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/access-lists
|
||||
@ -79,7 +79,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/access-lists/123
|
||||
|
@ -20,7 +20,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/certificates
|
||||
@ -79,7 +79,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/certificates/123
|
||||
@ -157,7 +157,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* POST /api/nginx/certificates/123/upload
|
||||
@ -191,7 +191,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* POST /api/nginx/certificates/validate
|
||||
|
@ -20,7 +20,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/dead-hosts
|
||||
@ -79,7 +79,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/dead-hosts/123
|
||||
@ -147,4 +147,52 @@ router
|
||||
.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;
|
||||
|
@ -20,7 +20,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/proxy-hosts
|
||||
@ -79,7 +79,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/proxy-hosts/123
|
||||
@ -147,4 +147,52 @@ router
|
||||
.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;
|
||||
|
@ -20,7 +20,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/redirection-hosts
|
||||
@ -79,7 +79,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/nginx/redirection-hosts/123
|
||||
@ -147,4 +147,52 @@ router
|
||||
.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;
|
||||
|
@ -147,4 +147,52 @@ router
|
||||
.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;
|
||||
|
@ -21,7 +21,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* GET /api/users
|
||||
@ -80,7 +80,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
.all(userIdFromMe)
|
||||
|
||||
/**
|
||||
@ -160,7 +160,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
.all(userIdFromMe)
|
||||
|
||||
/**
|
||||
@ -191,7 +191,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
.all(userIdFromMe)
|
||||
|
||||
/**
|
||||
@ -222,7 +222,7 @@ router
|
||||
.options((req, res) => {
|
||||
res.sendStatus(204);
|
||||
})
|
||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||
.all(jwtdecode())
|
||||
|
||||
/**
|
||||
* POST /api/users/123/login
|
||||
|
@ -172,6 +172,11 @@
|
||||
"pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$"
|
||||
}
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Is Enabled",
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"ssl_enabled": {
|
||||
"description": "Is SSL Enabled",
|
||||
"example": true,
|
||||
@ -182,6 +187,16 @@
|
||||
"example": false,
|
||||
"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": {
|
||||
"type": "string",
|
||||
"pattern": "^(letsencrypt|other)$"
|
||||
|
@ -24,12 +24,21 @@
|
||||
"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": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "../definitions.json#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"type": "object"
|
||||
}
|
||||
@ -53,12 +62,21 @@
|
||||
"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": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -107,6 +125,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -147,6 +171,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -177,6 +207,34 @@
|
||||
"targetSchema": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -38,6 +38,12 @@
|
||||
"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"
|
||||
},
|
||||
@ -58,6 +64,9 @@
|
||||
"advanced_config": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "../definitions.json#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"type": "object"
|
||||
}
|
||||
@ -90,6 +99,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -108,6 +123,9 @@
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -168,6 +186,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -186,6 +210,9 @@
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -229,6 +256,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -247,6 +280,9 @@
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -271,6 +307,34 @@
|
||||
"targetSchema": {
|
||||
"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,6 +32,12 @@
|
||||
"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"
|
||||
},
|
||||
@ -41,6 +47,9 @@
|
||||
"advanced_config": {
|
||||
"type": "string"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "../definitions.json#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"type": "object"
|
||||
}
|
||||
@ -70,6 +79,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_subdomains"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -79,6 +94,9 @@
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -134,6 +152,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -183,6 +207,12 @@
|
||||
"ssl_forced": {
|
||||
"$ref": "#/definitions/ssl_forced"
|
||||
},
|
||||
"hsts_enabled": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"hsts_subdomains": {
|
||||
"$ref": "#/definitions/hsts_enabled"
|
||||
},
|
||||
"http2_support": {
|
||||
"$ref": "#/definitions/http2_support"
|
||||
},
|
||||
@ -216,6 +246,34 @@
|
||||
"targetSchema": {
|
||||
"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": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "../definitions.json#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"type": "object"
|
||||
}
|
||||
@ -64,6 +67,9 @@
|
||||
"udp_forwarding": {
|
||||
"$ref": "#/definitions/udp_forwarding"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -184,6 +190,34 @@
|
||||
"targetSchema": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
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,12 +1,22 @@
|
||||
{% include "_header_comment.conf" %}
|
||||
|
||||
{% if enabled %}
|
||||
server {
|
||||
{% include "_listen.conf" %}
|
||||
{% include "_certificates.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
access_log /data/logs/dead_host-{{ id }}.log standard;
|
||||
|
||||
{{ 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,5 +1,6 @@
|
||||
{% include "_header_comment.conf" %}
|
||||
|
||||
{% if enabled %}
|
||||
server {
|
||||
set $forward_scheme {{ forward_scheme }};
|
||||
set $server "{{ forward_host }}";
|
||||
@ -9,11 +10,13 @@ server {
|
||||
{% include "_certificates.conf" %}
|
||||
{% include "_assets.conf" %}
|
||||
{% include "_exploits.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
access_log /data/logs/proxy_host-{{ id }}.log proxy;
|
||||
|
||||
{{ advanced_config }}
|
||||
|
||||
{% if use_default_location %}
|
||||
location / {
|
||||
{%- if access_list_id > 0 -%}
|
||||
# Access List
|
||||
@ -22,6 +25,7 @@ server {
|
||||
{%- endif %}
|
||||
|
||||
{% include "_forced_ssl.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
@ -32,4 +36,7 @@ server {
|
||||
# Proxy!
|
||||
include conf.d/include/proxy.conf;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
}
|
||||
{% endif %}
|
||||
|
@ -1,19 +1,21 @@
|
||||
{% include "_header_comment.conf" %}
|
||||
|
||||
{% if enabled %}
|
||||
server {
|
||||
{% include "_listen.conf" %}
|
||||
{% include "_certificates.conf" %}
|
||||
{% include "_assets.conf" %}
|
||||
{% include "_exploits.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
access_log /data/logs/redirection_host-{{ id }}.log standard;
|
||||
|
||||
{{ advanced_config }}
|
||||
|
||||
# TODO: Preserve Path Option
|
||||
|
||||
{% if use_default_location %}
|
||||
location / {
|
||||
{% include "_forced_ssl.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
{% if preserve_path == 1 or preserve_path == true %}
|
||||
return 301 $scheme://{{ forward_domain_name }}$request_uri;
|
||||
@ -21,4 +23,7 @@ server {
|
||||
return 301 $scheme://{{ forward_domain_name }};
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
}
|
||||
{% endif %}
|
||||
|
@ -2,6 +2,7 @@
|
||||
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
|
||||
# ------------------------------------------------------------
|
||||
|
||||
{% if enabled %}
|
||||
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
||||
server {
|
||||
listen {{ incoming_port }};
|
||||
@ -14,3 +15,4 @@ server {
|
||||
proxy_pass {{ forward_ip }}:{{ forwarding_port }};
|
||||
}
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -7,7 +7,7 @@ const Tokens = require('./tokens');
|
||||
/**
|
||||
* @param {String} message
|
||||
* @param {*} debug
|
||||
* @param {Integer} code
|
||||
* @param {Number} code
|
||||
* @constructor
|
||||
*/
|
||||
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
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -241,7 +241,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -251,7 +251,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
delete: function (id) {
|
||||
@ -260,7 +260,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @param {Object} auth
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -269,7 +269,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
loginAs: function (id) {
|
||||
@ -278,7 +278,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @param {Object} perms
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -308,7 +308,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -318,11 +318,35 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
delete: function (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 {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -355,7 +379,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
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
|
||||
* @params {Promise}
|
||||
*/
|
||||
setCerts: function (id, 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 {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -401,11 +449,35 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
delete: function (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 {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -438,7 +510,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
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
|
||||
* @params {Promise}
|
||||
*/
|
||||
setCerts: function (id, 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 {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -484,7 +580,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
delete: function (id) {
|
||||
@ -511,7 +607,7 @@ module.exports = {
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @param {Integer} data.id
|
||||
* @param {Number} data.id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
update: function (data) {
|
||||
@ -521,7 +617,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @returns {Promise}
|
||||
*/
|
||||
delete: function (id) {
|
||||
@ -529,7 +625,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Integer} id
|
||||
* @param {Number} id
|
||||
* @param {FormData} form_data
|
||||
* @params {Promise}
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@ require('selectize');
|
||||
module.exports = Mn.View.extend({
|
||||
template: template,
|
||||
className: 'modal-dialog',
|
||||
max_file_size: 5120,
|
||||
max_file_size: 102400,
|
||||
|
||||
ui: {
|
||||
form: 'form',
|
||||
@ -56,7 +56,7 @@ module.exports = Mn.View.extend({
|
||||
return;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
ssl_files.push({name: 'certificate', file: this.ui.other_certificate[0].files[0]});
|
||||
@ -67,7 +67,7 @@ module.exports = Mn.View.extend({
|
||||
return;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
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[0].size > this.max_file_size) {
|
||||
alert('Intermediate Certificate file is too large (> 5kb)');
|
||||
alert('Intermediate Certificate file is too large (> 100kb)');
|
||||
return;
|
||||
}
|
||||
ssl_files.push({name: 'intermediate_certificate', file: this.ui.other_intermediate_certificate[0].files[0]});
|
||||
|
@ -54,6 +54,24 @@
|
||||
</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 -->
|
||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||
|
@ -22,6 +22,8 @@ module.exports = Mn.View.extend({
|
||||
save: 'button.save',
|
||||
certificate_select: 'select[name="certificate_id"]',
|
||||
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'
|
||||
},
|
||||
@ -36,11 +38,44 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
|
||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||
this.ui.ssl_forced.add(this.ui.http2_support)
|
||||
|
||||
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||
inputs
|
||||
.prop('disabled', !enabled)
|
||||
.parents('.form-group')
|
||||
.css('opacity', enabled ? 1 : 0.5);
|
||||
this.ui.http2_support.prop('disabled', !enabled);
|
||||
|
||||
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) {
|
||||
@ -55,13 +90,10 @@ module.exports = Mn.View.extend({
|
||||
let data = this.ui.form.serializeJSON();
|
||||
|
||||
// Manipulate
|
||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
||||
data.ssl_forced = true;
|
||||
}
|
||||
|
||||
if (typeof data.http2_support !== 'undefined') {
|
||||
data.http2_support = !!data.http2_support;
|
||||
}
|
||||
data.hsts_enabled = !!data.hsts_enabled;
|
||||
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) {
|
||||
data.domain_names = data.domain_names.split(',');
|
||||
|
@ -28,7 +28,9 @@
|
||||
<td>
|
||||
<%
|
||||
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') %>
|
||||
<% } else if (o === false) { %>
|
||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||
@ -42,7 +44,7 @@
|
||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||
<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="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>
|
||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||
</div>
|
||||
|
@ -9,12 +9,25 @@ module.exports = Mn.View.extend({
|
||||
tagName: 'tr',
|
||||
|
||||
ui: {
|
||||
able: 'a.able',
|
||||
edit: 'a.edit',
|
||||
delete: 'a.delete',
|
||||
host_link: '.host-link'
|
||||
},
|
||||
|
||||
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) {
|
||||
e.preventDefault();
|
||||
App.Controller.showNginxDeadForm(this.model);
|
||||
|
@ -110,6 +110,24 @@
|
||||
</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 -->
|
||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||
@ -134,6 +152,12 @@
|
||||
<div role="tabpanel" class="tab-pane" id="advanced">
|
||||
<div class="row">
|
||||
<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">
|
||||
<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>
|
||||
|
@ -25,6 +25,8 @@ module.exports = Mn.View.extend({
|
||||
certificate_select: 'select[name="certificate_id"]',
|
||||
access_list_select: 'select[name="access_list_id"]',
|
||||
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'
|
||||
@ -40,10 +42,44 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
|
||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||
this.ui.ssl_forced.add(this.ui.http2_support)
|
||||
|
||||
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) {
|
||||
@ -58,18 +94,14 @@ module.exports = Mn.View.extend({
|
||||
let data = this.ui.form.serializeJSON();
|
||||
|
||||
// Manipulate
|
||||
data.forward_port = parseInt(data.forward_port, 10);
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
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.ssl_forced = true;
|
||||
}
|
||||
|
||||
if (typeof data.http2_support !== 'undefined') {
|
||||
data.http2_support = !!data.http2_support;
|
||||
}
|
||||
data.forward_port = parseInt(data.forward_port, 10);
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
data.caching_enabled = !!data.caching_enabled;
|
||||
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
|
||||
data.http2_support = !!data.http2_support;
|
||||
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) {
|
||||
data.domain_names = data.domain_names.split(',');
|
||||
@ -131,6 +163,9 @@ module.exports = Mn.View.extend({
|
||||
onRender: function () {
|
||||
let view = this;
|
||||
|
||||
this.ui.ssl_forced.trigger('change');
|
||||
this.ui.hsts_enabled.trigger('change');
|
||||
|
||||
// Domain names
|
||||
this.ui.domain_names.selectize({
|
||||
delimiter: ',',
|
||||
|
@ -34,7 +34,9 @@
|
||||
<td>
|
||||
<%
|
||||
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') %>
|
||||
<% } else if (o === false) { %>
|
||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||
@ -48,7 +50,7 @@
|
||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||
<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="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>
|
||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||
</div>
|
||||
|
@ -9,12 +9,25 @@ module.exports = Mn.View.extend({
|
||||
tagName: 'tr',
|
||||
|
||||
ui: {
|
||||
able: 'a.able',
|
||||
edit: 'a.edit',
|
||||
delete: 'a.delete',
|
||||
host_link: '.host-link'
|
||||
},
|
||||
|
||||
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) {
|
||||
e.preventDefault();
|
||||
App.Controller.showNginxProxyForm(this.model);
|
||||
|
@ -78,6 +78,24 @@
|
||||
</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 -->
|
||||
<div class="col-sm-12 col-md-12 letsencrypt">
|
||||
|
@ -22,6 +22,8 @@ module.exports = Mn.View.extend({
|
||||
save: 'button.save',
|
||||
certificate_select: 'select[name="certificate_id"]',
|
||||
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'
|
||||
},
|
||||
@ -36,11 +38,44 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
|
||||
let enabled = id === 'new' || parseInt(id, 10) > 0;
|
||||
this.ui.ssl_forced.add(this.ui.http2_support)
|
||||
|
||||
let inputs = this.ui.ssl_forced.add(this.ui.http2_support);
|
||||
inputs
|
||||
.prop('disabled', !enabled)
|
||||
.parents('.form-group')
|
||||
.css('opacity', enabled ? 1 : 0.5);
|
||||
this.ui.http2_support.prop('disabled', !enabled);
|
||||
|
||||
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) {
|
||||
@ -55,16 +90,12 @@ module.exports = Mn.View.extend({
|
||||
let data = this.ui.form.serializeJSON();
|
||||
|
||||
// Manipulate
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
data.preserve_path = !!data.preserve_path;
|
||||
|
||||
if (typeof data.ssl_forced !== 'undefined' && data.ssl_forced === '1') {
|
||||
data.ssl_forced = true;
|
||||
}
|
||||
|
||||
if (typeof data.http2_support !== 'undefined') {
|
||||
data.http2_support = !!data.http2_support;
|
||||
}
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
data.preserve_path = !!data.preserve_path;
|
||||
data.http2_support = !!data.http2_support;
|
||||
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) {
|
||||
data.domain_names = data.domain_names.split(',');
|
||||
|
@ -31,7 +31,9 @@
|
||||
<td>
|
||||
<%
|
||||
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') %>
|
||||
<% } else if (o === false) { %>
|
||||
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||
@ -45,7 +47,7 @@
|
||||
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||
<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="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>
|
||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||
</div>
|
||||
|
@ -9,12 +9,25 @@ module.exports = Mn.View.extend({
|
||||
tagName: 'tr',
|
||||
|
||||
ui: {
|
||||
able: 'a.able',
|
||||
edit: 'a.edit',
|
||||
delete: 'a.delete',
|
||||
host_link: '.host-link'
|
||||
},
|
||||
|
||||
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) {
|
||||
e.preventDefault();
|
||||
App.Controller.showNginxRedirectionForm(this.model);
|
||||
|
@ -27,7 +27,9 @@
|
||||
<td>
|
||||
<%
|
||||
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') %>
|
||||
<% } else if (o === false) { %>
|
||||
<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>
|
||||
<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="able dropdown-item"><i class="dropdown-icon fe fe-power"></i> <%- i18n('str', enabled ? 'disable' : 'enable') %></a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||
</div>
|
||||
|
@ -9,11 +9,24 @@ module.exports = Mn.View.extend({
|
||||
tagName: 'tr',
|
||||
|
||||
ui: {
|
||||
able: 'a.able',
|
||||
edit: 'a.edit',
|
||||
delete: 'a.delete'
|
||||
},
|
||||
|
||||
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) {
|
||||
e.preventDefault();
|
||||
App.Controller.showNginxStreamForm(this.model);
|
||||
|
@ -14,6 +14,8 @@
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"close": "Close",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"sure": "Yes I'm Sure",
|
||||
"disabled": "Disabled",
|
||||
"choose-file": "Choose file",
|
||||
@ -77,7 +79,9 @@
|
||||
"no-ssl": "This host will not use HTTPS",
|
||||
"advanced": "Advanced",
|
||||
"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": {
|
||||
"letsencrypt": "Let's Encrypt",
|
||||
@ -213,6 +217,8 @@
|
||||
"created": "Created {name}",
|
||||
"updated": "Updated {name}",
|
||||
"deleted": "Deleted {name}",
|
||||
"enabled": "Enabled {name}",
|
||||
"disabled": "Disabled {name}",
|
||||
"meta-title": "Details for Event",
|
||||
"view-meta": "View Details",
|
||||
"date": "Date"
|
||||
|
@ -14,6 +14,9 @@ const model = Backbone.Model.extend({
|
||||
certificate_id: 0,
|
||||
ssl_forced: false,
|
||||
http2_support: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
||||
enabled: true,
|
||||
meta: {},
|
||||
advanced_config: '',
|
||||
// The following are expansions:
|
||||
|
@ -17,11 +17,14 @@ const model = Backbone.Model.extend({
|
||||
access_list_id: 0,
|
||||
certificate_id: 0,
|
||||
ssl_forced: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
||||
caching_enabled: false,
|
||||
allow_websocket_upgrade: false,
|
||||
block_exploits: false,
|
||||
http2_support: false,
|
||||
advanced_config: '',
|
||||
enabled: true,
|
||||
meta: {},
|
||||
// The following are expansions:
|
||||
owner: null,
|
||||
|
@ -15,9 +15,12 @@ const model = Backbone.Model.extend({
|
||||
preserve_path: true,
|
||||
certificate_id: 0,
|
||||
ssl_forced: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
||||
block_exploits: false,
|
||||
http2_support: false,
|
||||
advanced_config: '',
|
||||
enabled: true,
|
||||
meta: {},
|
||||
// The following are expansions:
|
||||
owner: null,
|
||||
|
@ -15,6 +15,7 @@ const model = Backbone.Model.extend({
|
||||
forwarding_port: null,
|
||||
tcp_forwarding: true,
|
||||
udp_forwarding: false,
|
||||
enabled: true,
|
||||
meta: {},
|
||||
// The following are expansions:
|
||||
owner: null
|
||||
|
Reference in New Issue
Block a user