mirror of
https://github.com/jc21/nginx-proxy-manager.git
synced 2024-08-30 18:22:48 +00:00
Added support for redirection and 404 hosts
This commit is contained in:
parent
61820840e0
commit
64de096565
14
README.md
14
README.md
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
# Nginx Proxy Manager
|
# Nginx Proxy Manager
|
||||||
|
|
||||||
![Version](https://img.shields.io/badge/version-1.0.0-green.svg)
|
![Version](https://img.shields.io/badge/version-1.0.1-green.svg)
|
||||||
![Stars](https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg)
|
![Stars](https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg)
|
||||||
![Pulls](https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg)
|
![Pulls](https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg)
|
||||||
|
|
||||||
![Build Status](http://bamboo.jc21.com/plugins/servlet/wittified/build-status/AB-NPM)
|
![Build Status](http://bamboo.jc21.com/plugins/servlet/wittified/build-status/AB-NPM)
|
||||||
|
|
||||||
This NPM comes as a pre-built docker image that enables you to easily forward to your websites
|
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||||
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
||||||
|
|
||||||
|
|
||||||
@ -19,6 +19,10 @@ running at home or otherwise, including free SSL, without having to know too muc
|
|||||||
- Secure your sites with SSL and optionally force SSL
|
- Secure your sites with SSL and optionally force SSL
|
||||||
- Secure your sites with Basic HTTP Authentication Access Lists
|
- Secure your sites with Basic HTTP Authentication Access Lists
|
||||||
- Advanced Nginx config option for super users
|
- Advanced Nginx config option for super users
|
||||||
|
- 3 domain uses:
|
||||||
|
- Proxy requests to upstream server
|
||||||
|
- Redirect requests to another domain
|
||||||
|
- Return immediate 404's
|
||||||
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
@ -84,7 +88,7 @@ I won't go in to too much detail here but here are the basics for someone new to
|
|||||||
1. Your home router will have a Port Forwarding section somewhere. Log in and find it
|
1. Your home router will have a Port Forwarding section somewhere. Log in and find it
|
||||||
2. Add port forwarding for port 80 and 443 to the server hosting this project
|
2. Add port forwarding for port 80 and 443 to the server hosting this project
|
||||||
3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS
|
3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS
|
||||||
4. Use the NPM here as your gateway to forward to your other web based services
|
4. Use the Nginx Proxy Manager here as your gateway to forward to your other web based services
|
||||||
|
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
@ -98,8 +102,8 @@ I won't go in to too much detail here but here are the basics for someone new to
|
|||||||
|
|
||||||
- Pass on human readable ssl cert errors to the ui
|
- Pass on human readable ssl cert errors to the ui
|
||||||
- Allow a host to be a redirection to another domain
|
- Allow a host to be a redirection to another domain
|
||||||
- Allow a host to return immediate 404's
|
|
||||||
- UI: Allow column sorting on tables
|
- UI: Allow column sorting on tables
|
||||||
- UI: Allow filtering hosts by types
|
- UI: Allow filtering hosts by types
|
||||||
- Advanced option to overwrite the default location block (or regex to do it automatically)
|
- Advanced option to overwrite the default location block (or regex to do it automatically)
|
||||||
- Change the renew ssl process to use the letsencrypt renew procedure so as to avoid rate limits
|
- Add nice upstream error pages
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nginx-proxy-manager",
|
"name": "nginx-proxy-manager",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Nginx proxt with built in Web based management",
|
"description": "Nginx proxt with built in Web based management",
|
||||||
"main": "src/backend/index.js",
|
"main": "src/backend/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -155,15 +155,14 @@ const internalHost = {
|
|||||||
*
|
*
|
||||||
* @param {Object} host
|
* @param {Object} host
|
||||||
* @param {Boolean} [reload_nginx]
|
* @param {Boolean} [reload_nginx]
|
||||||
* @param {Boolean} [force_ssl_renew]
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
configure: (host, reload_nginx, force_ssl_renew) => {
|
configure: (host, reload_nginx) => {
|
||||||
return new Promise((resolve/*, reject*/) => {
|
return new Promise((resolve/*, reject*/) => {
|
||||||
resolve(internalNginx.deleteConfig(host));
|
resolve(internalNginx.deleteConfig(host));
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (host.ssl && (force_ssl_renew || !internalSsl.hasValidSslCerts(host))) {
|
if (host.ssl && !internalSsl.hasValidSslCerts(host)) {
|
||||||
return internalSsl.configureSsl(host);
|
return internalSsl.configureSsl(host);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -248,7 +247,7 @@ const internalHost = {
|
|||||||
reject(new error.ValidationError('Host does not have SSL enabled'));
|
reject(new error.ValidationError('Host does not have SSL enabled'));
|
||||||
} else {
|
} else {
|
||||||
// 3. Fire the ssl and config generation for this host, forcing ssl
|
// 3. Fire the ssl and config generation for this host, forcing ssl
|
||||||
internalHost.configure(host, true, true)
|
internalSsl.renewSsl(host)
|
||||||
.then((/*result*/) => {
|
.then((/*result*/) => {
|
||||||
resolve(host);
|
resolve(host);
|
||||||
})
|
})
|
||||||
|
@ -45,7 +45,11 @@ const internalNginx = {
|
|||||||
let filename = internalNginx.getConfigName(host);
|
let filename = internalNginx.getConfigName(host);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/host.conf.ejs', {encoding: 'utf8'});
|
if (typeof host.type === 'undefined' || !host.type) {
|
||||||
|
host.type = 'proxy';
|
||||||
|
}
|
||||||
|
|
||||||
|
template = fs.readFileSync(__dirname + '/../templates/' + host.type + '.conf.ejs', {encoding: 'utf8'});
|
||||||
let config_text = ejs.render(template, host);
|
let config_text = ejs.render(template, host);
|
||||||
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
||||||
resolve(true);
|
resolve(true);
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"readonly": true
|
"readonly": true
|
||||||
},
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^(proxy|redirection|404)$"
|
||||||
|
},
|
||||||
"hostname": {
|
"hostname": {
|
||||||
"$ref": "../definitions.json#/definitions/hostname"
|
"$ref": "../definitions.json#/definitions/hostname"
|
||||||
},
|
},
|
||||||
@ -17,6 +21,9 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "ipv4"
|
"format": "ipv4"
|
||||||
},
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"forward_port": {
|
"forward_port": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"minumum": 1,
|
"minumum": 1,
|
||||||
@ -79,14 +86,19 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"hostname",
|
"type",
|
||||||
"forward_server",
|
"hostname"
|
||||||
"forward_port"
|
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/type"
|
||||||
|
},
|
||||||
"hostname": {
|
"hostname": {
|
||||||
"$ref": "#/definitions/hostname"
|
"$ref": "#/definitions/hostname"
|
||||||
},
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"$ref": "#/definitions/forward_host"
|
||||||
|
},
|
||||||
"forward_server": {
|
"forward_server": {
|
||||||
"$ref": "#/definitions/forward_server"
|
"$ref": "#/definitions/forward_server"
|
||||||
},
|
},
|
||||||
@ -137,6 +149,9 @@
|
|||||||
"hostname": {
|
"hostname": {
|
||||||
"$ref": "#/definitions/hostname"
|
"$ref": "#/definitions/hostname"
|
||||||
},
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"$ref": "#/definitions/forward_host"
|
||||||
|
},
|
||||||
"forward_server": {
|
"forward_server": {
|
||||||
"$ref": "#/definitions/forward_server"
|
"$ref": "#/definitions/forward_server"
|
||||||
},
|
},
|
||||||
@ -188,9 +203,15 @@
|
|||||||
"_id": {
|
"_id": {
|
||||||
"$ref": "#/definitions/_id"
|
"$ref": "#/definitions/_id"
|
||||||
},
|
},
|
||||||
|
"type": {
|
||||||
|
"$ref": "#/definitions/type"
|
||||||
|
},
|
||||||
"hostname": {
|
"hostname": {
|
||||||
"$ref": "#/definitions/hostname"
|
"$ref": "#/definitions/hostname"
|
||||||
},
|
},
|
||||||
|
"forward_host": {
|
||||||
|
"$ref": "#/definitions/forward_host"
|
||||||
|
},
|
||||||
"forward_server": {
|
"forward_server": {
|
||||||
"$ref": "#/definitions/forward_server"
|
"$ref": "#/definitions/forward_server"
|
||||||
},
|
},
|
||||||
|
19
manager/src/backend/templates/404.conf.ejs
Normal file
19
manager/src/backend/templates/404.conf.ejs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# <%- hostname %>
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
<%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %>
|
||||||
|
|
||||||
|
server_name <%- hostname %>;
|
||||||
|
|
||||||
|
access_log /config/logs/<%- hostname %>.log proxy;
|
||||||
|
|
||||||
|
<% if (typeof ssl !== 'undefined' && ssl) { -%>
|
||||||
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
|
ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem;
|
||||||
|
<% } -%>
|
||||||
|
|
||||||
|
<%- typeof advanced !== 'undefined' && advanced ? advanced : '' %>
|
||||||
|
|
||||||
|
return 404;
|
||||||
|
}
|
22
manager/src/backend/templates/redirection.conf.ejs
Normal file
22
manager/src/backend/templates/redirection.conf.ejs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# <%- hostname %>
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
<%- typeof ssl !== 'undefined' && ssl ? 'listen 443 ssl;' : '' %>
|
||||||
|
|
||||||
|
server_name <%- hostname %>;
|
||||||
|
|
||||||
|
access_log /config/logs/<%- hostname %>.log proxy;
|
||||||
|
|
||||||
|
<%- typeof asset_caching !== 'undefined' && asset_caching ? 'include conf.d/include/assets.conf;' : '' %>
|
||||||
|
<%- typeof block_exploits !== 'undefined' && block_exploits ? 'include conf.d/include/block-exploits.conf;' : '' %>
|
||||||
|
|
||||||
|
<% if (typeof ssl !== 'undefined' && ssl) { -%>
|
||||||
|
include conf.d/include/ssl-ciphers.conf;
|
||||||
|
ssl_certificate /etc/letsencrypt/live/<%- hostname %>/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/<%- hostname %>/privkey.pem;
|
||||||
|
<% } -%>
|
||||||
|
|
||||||
|
<%- typeof advanced !== 'undefined' && advanced ? advanced : '' %>
|
||||||
|
|
||||||
|
return 301 $scheme://<%- forward_host %>$request_uri;
|
||||||
|
}
|
@ -54,12 +54,34 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Host Form
|
* Show Proxy Host Form
|
||||||
*
|
*
|
||||||
* @param model
|
* @param model
|
||||||
*/
|
*/
|
||||||
showHostForm: function (model) {
|
showProxyHostForm: function (model) {
|
||||||
require(['./main', './host/form'], function (App, View) {
|
require(['./main', './host/proxy_form'], function (App, View) {
|
||||||
|
App.UI.showModalDialog(new View({model: model}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show Redirection Host Form
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
*/
|
||||||
|
showRedirectionHostForm: function (model) {
|
||||||
|
require(['./main', './host/redirection_form'], function (App, View) {
|
||||||
|
App.UI.showModalDialog(new View({model: model}));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show 404 Host Form
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
*/
|
||||||
|
show404HostForm: function (model) {
|
||||||
|
require(['./main', './host/404_form'], function (App, View) {
|
||||||
App.UI.showModalDialog(new View({model: model}));
|
App.UI.showModalDialog(new View({model: model}));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
<td colspan="10" class="text-center">
|
<td colspan="10" class="text-center">
|
||||||
<br><br>
|
<br><br>
|
||||||
<p>It looks like there are no hosts configured.</p>
|
<p>It looks like there are no hosts configured.</p>
|
||||||
<p><button type="button" class="btn btn-sm btn-success">Create your first Host</button></p>
|
<p>
|
||||||
|
<button type="button" class="btn btn-sm btn-success proxy">Create Proxy Host</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-success redirection">Create Redirection Host</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-success 404">Create 404 Host</button>
|
||||||
|
</p>
|
||||||
</td>
|
</td>
|
||||||
|
@ -11,13 +11,25 @@ module.exports = Mn.View.extend({
|
|||||||
tagName: 'tr',
|
tagName: 'tr',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
create: 'button'
|
proxy: 'button.proxy',
|
||||||
|
redirection: 'button.redirection',
|
||||||
|
'404': 'button.404'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click @ui.create': function (e) {
|
'click @ui.proxy': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Controller.showHostForm(new HostModel.Model);
|
Controller.showProxyHostForm(new HostModel.Model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.redirection': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showRedirectionHostForm(new HostModel.Model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.404': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.show404HostForm(new HostModel.Model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
<table class="table table-condensed table-striped">
|
<table class="table table-condensed table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<th>Hostname</th>
|
<th>Hostname</th>
|
||||||
<th>Forward</th>
|
<th>Destination</th>
|
||||||
<th>SSL</th>
|
<th>SSL</th>
|
||||||
<th>Access List</th>
|
<th>Access List</th>
|
||||||
<th class="text-right"><button type="button" class="btn btn-xs btn-info">Create Host</button></th>
|
<th class="text-right">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-xs btn-info dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
Create Host <span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="#" class="new-proxy">Proxy Host</a></li>
|
||||||
|
<li><a href="#" class="new-redirection">Redirection Host</a></li>
|
||||||
|
<li><a href="#" class="new-404">404 Host</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<!-- items -->
|
<!-- items -->
|
||||||
|
@ -26,13 +26,25 @@ module.exports = Mn.View.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
'create': 'th button'
|
new_proxy: 'th .new-proxy',
|
||||||
|
new_redirection: 'th .new-redirection',
|
||||||
|
new_404: 'th .new-404'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click @ui.create': function (e) {
|
'click @ui.new_proxy': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Controller.showHostForm(new HostModel.Model);
|
Controller.showProxyHostForm(new HostModel.Model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.new_redirection': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.showRedirectionHostForm(new HostModel.Model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.new_404': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Controller.show404HostForm(new HostModel.Model);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
<td><a href="<%- ssl ? 'https' : 'http' %>://<%- hostname %>" target="_blank"><%- hostname %></a></td>
|
<td><a href="<%- ssl ? 'https' : 'http' %>://<%- hostname %>" target="_blank"><%- hostname %></a></td>
|
||||||
<td><span class="monospace"><%- forward_server %>:<%- forward_port %></span></td>
|
<td>
|
||||||
|
<span class="monospace">
|
||||||
|
<% if (type === 'proxy') { %>
|
||||||
|
<%- forward_server %>:<%- forward_port %>
|
||||||
|
<% } else if (type === 'redirection') { %>
|
||||||
|
<%- forward_host %>
|
||||||
|
<% } else if (type === '404') { %>
|
||||||
|
404
|
||||||
|
<% } %>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<% if (ssl && force_ssl) { %>
|
<% if (ssl && force_ssl) { %>
|
||||||
Forced
|
Forced
|
||||||
|
@ -22,7 +22,17 @@ module.exports = Mn.View.extend({
|
|||||||
events: {
|
events: {
|
||||||
'click @ui.edit': function (e) {
|
'click @ui.edit': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Controller.showHostForm(this.model);
|
switch (this.model.get('type')) {
|
||||||
|
case 'proxy':
|
||||||
|
Controller.showProxyHostForm(this.model);
|
||||||
|
break;
|
||||||
|
case 'redirection':
|
||||||
|
Controller.showRedirectionHostForm(this.model);
|
||||||
|
break;
|
||||||
|
case '404':
|
||||||
|
Controller.show404HostForm(this.model);
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'click @ui.delete': function (e) {
|
'click @ui.delete': function (e) {
|
||||||
|
50
manager/src/frontend/js/app/host/404_form.ejs
Normal file
50
manager/src/frontend/js/app/host/404_form.ejs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="modal-header text-left">
|
||||||
|
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> 404 Host</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>A 404 host will simply return a 404 not found page for any hits to any path on the domain.</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Hostname</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" class="form-control" placeholder="myhost.example.com" name="hostname" value="<%- hostname %>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-4 col-sm-8">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="ssl" value="true"<%- ssl ? ' checked' : '' %>> Enable SSL with Letsencrypt
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ssl_options"<%= ssl ? '' : ' style="display: none;"' %>>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Letsencrypt Email</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="email" class="form-control" placeholder="" name="letsencrypt_email" value="<%- letsencrypt_email %>"<%- ssl ? ' required' : '' %>>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-4 col-sm-8">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="accept_tos" value="true"<%- ssl && typeof _id !== 'undefined' ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-success save">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
78
manager/src/frontend/js/app/host/404_form.js
Normal file
78
manager/src/frontend/js/app/host/404_form.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Mn from 'backbone.marionette';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const template = require('./404_form.ejs');
|
||||||
|
const Controller = require('../controller');
|
||||||
|
const Api = require('../api');
|
||||||
|
const App = require('../main');
|
||||||
|
|
||||||
|
require('jquery-serializejson');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
form: 'form',
|
||||||
|
buttons: 'form button',
|
||||||
|
ssl_options: '.ssl_options',
|
||||||
|
ssl: 'input[name="ssl"]',
|
||||||
|
letsencrypt_email: 'input[name="letsencrypt_email"]',
|
||||||
|
accept_tos: 'input[name="accept_tos"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'change @ui.ssl': function (e) {
|
||||||
|
let inputs = this.ui.letsencrypt_email.add(this.ui.accept_tos);
|
||||||
|
if (this.ui.ssl.prop('checked')) {
|
||||||
|
this.ui.ssl_options.show();
|
||||||
|
inputs.prop('required', true);
|
||||||
|
} else {
|
||||||
|
this.ui.ssl_options.hide();
|
||||||
|
inputs.prop('required', false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.form': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let data = _.extend({}, this.ui.form.serializeJSON());
|
||||||
|
|
||||||
|
// Change text true's to bools
|
||||||
|
_.map(data, function (val, key) {
|
||||||
|
if (val === 'true') {
|
||||||
|
data[key] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// This is a 404 host
|
||||||
|
data.type = '404';
|
||||||
|
|
||||||
|
// accept_tos is not required for backend
|
||||||
|
delete data.accept_tos;
|
||||||
|
|
||||||
|
if (!data.ssl) {
|
||||||
|
delete data.letsencrypt_email;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
let method = Api.Hosts.create;
|
||||||
|
|
||||||
|
if (this.model.get('_id')) {
|
||||||
|
// edit
|
||||||
|
method = Api.Hosts.update;
|
||||||
|
data._id = this.model.get('_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
method(data)
|
||||||
|
.then((/*result*/) => {
|
||||||
|
App.UI.closeModal();
|
||||||
|
Controller.showDashboard();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -2,7 +2,7 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="modal-header text-left">
|
<div class="modal-header text-left">
|
||||||
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Host</h4>
|
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Proxy Host</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -62,7 +62,7 @@
|
|||||||
<div class="col-sm-offset-4 col-sm-8">
|
<div class="col-sm-offset-4 col-sm-8">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="accept_tos" value="true"<%- accept_tos ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
<input type="checkbox" name="accept_tos" value="true"<%- ssl && typeof _id !== 'undefined' ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
@ -3,7 +3,7 @@
|
|||||||
import Mn from 'backbone.marionette';
|
import Mn from 'backbone.marionette';
|
||||||
|
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const template = require('./form.ejs');
|
const template = require('./proxy_form.ejs');
|
||||||
const Controller = require('../controller');
|
const Controller = require('../controller');
|
||||||
const Api = require('../api');
|
const Api = require('../api');
|
||||||
const App = require('../main');
|
const App = require('../main');
|
||||||
@ -46,6 +46,8 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
data.type = 'proxy';
|
||||||
|
|
||||||
// Port is integer
|
// Port is integer
|
||||||
data.forward_port = parseInt(data.forward_port, 10);
|
data.forward_port = parseInt(data.forward_port, 10);
|
||||||
|
|
62
manager/src/frontend/js/app/host/redirection_form.ejs
Normal file
62
manager/src/frontend/js/app/host/redirection_form.ejs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="modal-header text-left">
|
||||||
|
<h4 class="modal-title"><% if (typeof _id !== 'undefined') { %>Edit<% } else { %>Create<% } %> Redirection Host</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>A redirection host will forward browser requests on this hostname to the new hostname while keeping the same path.</p>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Hostname</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" class="form-control" placeholder="myhost.example.com" name="hostname" value="<%- hostname %>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Forwarding Hostname</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" class="form-control" placeholder="mynewhost.example.com" name="forward_host" value="<%- forward_host %>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-4 col-sm-8">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="block_exploits" value="true"<%- block_exploits ? ' checked' : '' %>> Block Common Exploits
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="ssl" value="true"<%- ssl ? ' checked' : '' %>> Enable SSL with Letsencrypt
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ssl_options"<%= ssl ? '' : ' style="display: none;"' %>>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-4 control-label">Letsencrypt Email</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="email" class="form-control" placeholder="" name="letsencrypt_email" value="<%- letsencrypt_email %>"<%- ssl ? ' required' : '' %>>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-4 col-sm-8">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="accept_tos" value="true"<%- ssl && typeof _id !== 'undefined' ? ' checked' : '' %><%- ssl ? ' required' : '' %>> I accept the <a href="https://letsencrypt.org/repository/" target="_blank">Letsencrypt Terms of Service</a>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-success save">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
78
manager/src/frontend/js/app/host/redirection_form.js
Normal file
78
manager/src/frontend/js/app/host/redirection_form.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Mn from 'backbone.marionette';
|
||||||
|
|
||||||
|
const _ = require('lodash');
|
||||||
|
const template = require('./redirection_form.ejs');
|
||||||
|
const Controller = require('../controller');
|
||||||
|
const Api = require('../api');
|
||||||
|
const App = require('../main');
|
||||||
|
|
||||||
|
require('jquery-serializejson');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
form: 'form',
|
||||||
|
buttons: 'form button',
|
||||||
|
ssl_options: '.ssl_options',
|
||||||
|
ssl: 'input[name="ssl"]',
|
||||||
|
letsencrypt_email: 'input[name="letsencrypt_email"]',
|
||||||
|
accept_tos: 'input[name="accept_tos"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'change @ui.ssl': function (e) {
|
||||||
|
let inputs = this.ui.letsencrypt_email.add(this.ui.accept_tos);
|
||||||
|
if (this.ui.ssl.prop('checked')) {
|
||||||
|
this.ui.ssl_options.show();
|
||||||
|
inputs.prop('required', true);
|
||||||
|
} else {
|
||||||
|
this.ui.ssl_options.hide();
|
||||||
|
inputs.prop('required', false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.form': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let data = _.extend({}, this.ui.form.serializeJSON());
|
||||||
|
|
||||||
|
// Change text true's to bools
|
||||||
|
_.map(data, function (val, key) {
|
||||||
|
if (val === 'true') {
|
||||||
|
data[key] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
data.type = 'redirection';
|
||||||
|
|
||||||
|
// accept_tos is not required for backend
|
||||||
|
delete data.accept_tos;
|
||||||
|
|
||||||
|
if (!data.ssl) {
|
||||||
|
delete data.letsencrypt_email;
|
||||||
|
delete data.force_ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
let method = Api.Hosts.create;
|
||||||
|
|
||||||
|
if (this.model.get('_id')) {
|
||||||
|
// edit
|
||||||
|
method = Api.Hosts.update;
|
||||||
|
data._id = this.model.get('_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
method(data)
|
||||||
|
.then((/*result*/) => {
|
||||||
|
App.UI.closeModal();
|
||||||
|
Controller.showDashboard();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -7,8 +7,10 @@ const model = Backbone.Model.extend({
|
|||||||
|
|
||||||
defaults: function () {
|
defaults: function () {
|
||||||
return {
|
return {
|
||||||
|
type: 'proxy',
|
||||||
hostname: '',
|
hostname: '',
|
||||||
forward_server: '',
|
forward_server: '',
|
||||||
|
forward_host: '',
|
||||||
forward_port: 80,
|
forward_port: 80,
|
||||||
asset_caching: false,
|
asset_caching: false,
|
||||||
block_exploits: true,
|
block_exploits: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user