mirror of https://github.com/Aidaho12/haproxy-wi
parent
9c961cf6cf
commit
292ca51cc7
|
@ -4,12 +4,14 @@ from flask_pydantic import validate
|
||||||
|
|
||||||
from app import app
|
from app import app
|
||||||
from app.api.routes import bp
|
from app.api.routes import bp
|
||||||
from app.views.install.views import InstallView
|
from app.views.install.views import InstallView, InstallGetStatus
|
||||||
from app.views.server.views import ServerView, ServerGroupView, ServerGroupsView, ServersView, ServerIPView
|
from app.views.server.views import ServerView, ServerGroupView, ServerGroupsView, ServersView, ServerIPView
|
||||||
from app.views.server.cred_views import CredView, CredsView
|
from app.views.server.cred_views import CredView, CredsView
|
||||||
from app.views.server.backup_vews import BackupView, S3BackupView, GitBackupView
|
from app.views.server.backup_vews import BackupView, S3BackupView, GitBackupView
|
||||||
from app.views.service.views import (ServiceView, ServiceActionView, ServiceBackendView, ServiceConfigView,
|
from app.views.service.views import (ServiceView, ServiceActionView, ServiceBackendView, ServiceConfigView,
|
||||||
ServiceConfigVersionsView, ServiceConfigList)
|
ServiceConfigVersionsView, ServiceConfigList)
|
||||||
|
from app.views.service.haproxy_section_views import ListenSectionView, UserListSectionView, PeersSectionView, \
|
||||||
|
GlobalSectionView, DefaultsSectionView
|
||||||
from app.views.ha.views import HAView, HAVIPView, HAVIPsView
|
from app.views.ha.views import HAView, HAVIPView, HAVIPsView
|
||||||
from app.views.user.views import UserView, UserGroupView, UserRoles
|
from app.views.user.views import UserView, UserGroupView, UserRoles
|
||||||
from app.views.udp.views import UDPListener, UDPListeners, UDPListenerActionView
|
from app.views.udp.views import UDPListener, UDPListeners, UDPListenerActionView
|
||||||
|
@ -56,12 +58,22 @@ bp.add_url_rule('/ha/<service>/<int:cluster_id>/vips', view_func=HAVIPsView.as_v
|
||||||
register_api(UDPListener, 'udp_listener', '/<service>/listener', 'listener_id')
|
register_api(UDPListener, 'udp_listener', '/<service>/listener', 'listener_id')
|
||||||
bp.add_url_rule('/<service>/listener/<int:listener_id>/<any(start, stop, reload, restart):action>', view_func=UDPListenerActionView.as_view('listener_action'), methods=['GET'])
|
bp.add_url_rule('/<service>/listener/<int:listener_id>/<any(start, stop, reload, restart):action>', view_func=UDPListenerActionView.as_view('listener_action'), methods=['GET'])
|
||||||
bp.add_url_rule('/<service>/listeners', view_func=UDPListeners.as_view('listeners'), methods=['GET'])
|
bp.add_url_rule('/<service>/listeners', view_func=UDPListeners.as_view('listeners'), methods=['GET'])
|
||||||
|
bp.add_url_rule('/service/<service>/<int:server_id>/install', view_func=InstallGetStatus.as_view('install_status'), methods=['GET'])
|
||||||
|
bp.add_url_rule('/service/<service>/<server_id>/install', view_func=InstallGetStatus.as_view('install_status_ip'), methods=['GET'])
|
||||||
|
|
||||||
|
|
||||||
register_api_id_ip(ServiceView, 'service', '/status', ['GET'])
|
register_api_id_ip(ServiceView, 'service', '/status', ['GET'])
|
||||||
register_api_id_ip(ServiceBackendView, 'service_backend', '/backend', ['GET'])
|
register_api_id_ip(ServiceBackendView, 'service_backend', '/backend', ['GET'])
|
||||||
register_api_id_ip(ServiceConfigView, 'config_view', '/config')
|
register_api_id_ip(ServiceConfigView, 'config_view', '/config')
|
||||||
register_api_id_ip(ServiceConfigVersionsView, 'config_version', '/versions', methods=['GET', 'DELETE'])
|
register_api_id_ip(ServiceConfigVersionsView, 'config_version', '/versions', methods=['GET', 'DELETE'])
|
||||||
|
register_api_id_ip(ListenSectionView, 'haproxy_section_post', '/section/<any(listen, frontend, backend):section_type>', methods=['POST'])
|
||||||
|
register_api_id_ip(ListenSectionView, 'haproxy_section', '/section/<any(listen, frontend, backend):section_type>/<section_name>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
register_api_id_ip(UserListSectionView, 'haproxy_userlist_post', '/section/userlist', methods=['POST'])
|
||||||
|
register_api_id_ip(UserListSectionView, 'haproxy_userlist', '/section/userlist/<section_name>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
register_api_id_ip(PeersSectionView, 'haproxy_peers_post', '/section/peers', methods=['POST'])
|
||||||
|
register_api_id_ip(PeersSectionView, 'haproxy_peers', '/section/peers/<section_name>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
register_api_id_ip(GlobalSectionView, 'haproxy_global', '/section/global', methods=['GET', 'PUT'])
|
||||||
|
register_api_id_ip(DefaultsSectionView, 'haproxy_defaults', '/section/defaults', methods=['GET', 'PUT'])
|
||||||
bp.add_url_rule('/service/<any(nginx, apache):service>/<server_id>/config/list', view_func=ServiceConfigList.as_view('config_list_ip'), methods=['GET'])
|
bp.add_url_rule('/service/<any(nginx, apache):service>/<server_id>/config/list', view_func=ServiceConfigList.as_view('config_list_ip'), methods=['GET'])
|
||||||
bp.add_url_rule('/service/<any(nginx, apache):service>/<int:server_id>/config/list', view_func=ServiceConfigList.as_view('config_list'), methods=['GET'])
|
bp.add_url_rule('/service/<any(nginx, apache):service>/<int:server_id>/config/list', view_func=ServiceConfigList.as_view('config_list'), methods=['GET'])
|
||||||
register_api_id_ip(CheckerView, 'checker', '/tools')
|
register_api_id_ip(CheckerView, 'checker', '/tools')
|
||||||
|
|
|
@ -623,7 +623,7 @@ def update_db_v_8_0_2_1():
|
||||||
|
|
||||||
def update_ver():
|
def update_ver():
|
||||||
try:
|
try:
|
||||||
Version.update(version='8.0.2').execute()
|
Version.update(version='8.1.0').execute()
|
||||||
except Exception:
|
except Exception:
|
||||||
print('Cannot update version')
|
print('Cannot update version')
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from flask import render_template, request
|
from flask import render_template
|
||||||
|
|
||||||
import app.modules.db.sql as sql
|
import app.modules.db.sql as sql
|
||||||
import app.modules.db.add as add_sql
|
import app.modules.db.add as add_sql
|
||||||
|
@ -17,34 +17,6 @@ import app.modules.roxy_wi_tools as roxy_wi_tools
|
||||||
get_config = roxy_wi_tools.GetConfigVar()
|
get_config = roxy_wi_tools.GetConfigVar()
|
||||||
|
|
||||||
|
|
||||||
def save_to_haproxy_config(config: str, server_ip: str, name: str) -> str:
|
|
||||||
roxywi_common.check_is_server_in_group(server_ip)
|
|
||||||
cfg = config_common.generate_config_path('haproxy', server_ip)
|
|
||||||
|
|
||||||
config_mod.get_config(server_ip, cfg)
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(cfg, "a") as conf:
|
|
||||||
conf.write(config)
|
|
||||||
except IOError as e:
|
|
||||||
raise Exception(f"error: Cannot read import config file {e}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
output = config_mod.master_slave_upload_and_restart(server_ip, cfg, "save", 'haproxy')
|
|
||||||
except Exception as e:
|
|
||||||
raise Exception(e)
|
|
||||||
|
|
||||||
try:
|
|
||||||
roxywi_common.logging(server_ip, f"Add has been added a new {name}")
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if output:
|
|
||||||
return output
|
|
||||||
else:
|
|
||||||
return name
|
|
||||||
|
|
||||||
|
|
||||||
def save_nginx_config(config_add: str, server_ip: str, config_name: str) -> str:
|
def save_nginx_config(config_add: str, server_ip: str, config_name: str) -> str:
|
||||||
roxywi_common.check_is_server_in_group(server_ip)
|
roxywi_common.check_is_server_in_group(server_ip)
|
||||||
sub_folder = 'conf.d' if 'upstream' in config_name else 'sites-enabled'
|
sub_folder = 'conf.d' if 'upstream' in config_name else 'sites-enabled'
|
||||||
|
@ -73,83 +45,6 @@ def save_nginx_config(config_add: str, server_ip: str, config_name: str) -> str:
|
||||||
return config_name
|
return config_name
|
||||||
|
|
||||||
|
|
||||||
def get_userlists(config):
|
|
||||||
return_config = ''
|
|
||||||
with open(config, 'r') as f:
|
|
||||||
for line in f:
|
|
||||||
if line.startswith('userlist'):
|
|
||||||
line = line.strip()
|
|
||||||
return_config += line + ','
|
|
||||||
|
|
||||||
return return_config
|
|
||||||
|
|
||||||
|
|
||||||
def show_userlist(server_ip: str) -> str:
|
|
||||||
configs_dir = get_config.get_config_var('configs', 'haproxy_save_configs_dir')
|
|
||||||
format_file = 'cfg'
|
|
||||||
|
|
||||||
try:
|
|
||||||
sections = get_userlists(configs_dir + roxywi_common.get_files(configs_dir, format_file)[0])
|
|
||||||
except Exception as e:
|
|
||||||
roxywi_common.logging('Roxy-WI server', str(e), roxywi=1)
|
|
||||||
try:
|
|
||||||
cfg = config_common.generate_config_path('haproxy', server_ip)
|
|
||||||
except Exception as e:
|
|
||||||
roxywi_common.logging('Roxy-WI server', f' Cannot generate a cfg path {e}', roxywi=1)
|
|
||||||
try:
|
|
||||||
config_mod.get_config(server_ip, cfg)
|
|
||||||
except Exception as e:
|
|
||||||
roxywi_common.logging('Roxy-WI server', f' Cannot download a config {e}', roxywi=1)
|
|
||||||
try:
|
|
||||||
sections = get_userlists(cfg)
|
|
||||||
except Exception as e:
|
|
||||||
roxywi_common.logging('Roxy-WI server', f' Cannot get Userlists from the config file {e}', roxywi=1)
|
|
||||||
sections = 'error: Cannot get Userlists'
|
|
||||||
|
|
||||||
return sections
|
|
||||||
|
|
||||||
|
|
||||||
def add_userlist() -> str:
|
|
||||||
generate = request.form.get('generateconfig')
|
|
||||||
server_ip = request.form.get('serv')
|
|
||||||
name = f"userlist {request.form.get('new_userlist')}\n"
|
|
||||||
|
|
||||||
new_userlist_groups = ""
|
|
||||||
if request.form.get('userlist-group') is not None:
|
|
||||||
groups = request.form.getlist('userlist-group')
|
|
||||||
for group in groups:
|
|
||||||
if group == '':
|
|
||||||
continue
|
|
||||||
new_userlist_groups += f" group {group}\n"
|
|
||||||
|
|
||||||
new_users_list = ""
|
|
||||||
if request.form.get('userlist-user') is not None:
|
|
||||||
users = request.form.getlist('userlist-user')
|
|
||||||
passwords = request.form.getlist('userlist-password')
|
|
||||||
userlist_user_group = request.form.getlist('userlist-user-group')
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
for user in users:
|
|
||||||
if user == '':
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
group = f' groups {userlist_user_group[i]}'
|
|
||||||
except Exception:
|
|
||||||
group = ''
|
|
||||||
new_users_list += f" user {user} insecure-password {passwords[i]} {group}\n"
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
config_add = "\n" + name + new_userlist_groups + new_users_list
|
|
||||||
|
|
||||||
if generate:
|
|
||||||
return config_add
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
return save_to_haproxy_config(config_add, server_ip, name)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
|
|
||||||
|
|
||||||
def get_bwlist(color: str, group: str, list_name: str) -> str:
|
def get_bwlist(color: str, group: str, list_name: str) -> str:
|
||||||
lib_path = get_config.get_config_var('main', 'lib_path')
|
lib_path = get_config.get_config_var('main', 'lib_path')
|
||||||
list_path = f"{lib_path}/lists/{group}/{color}/{list_name}"
|
list_path = f"{lib_path}/lists/{group}/{color}/{list_name}"
|
||||||
|
@ -411,15 +306,6 @@ def get_saved_option(group: str, term: str) -> dict:
|
||||||
return a
|
return a
|
||||||
|
|
||||||
|
|
||||||
def update_saved_option(option, option_id) -> bool:
|
|
||||||
try:
|
|
||||||
add_sql.update_options(option, option_id)
|
|
||||||
except Exception as e:
|
|
||||||
raise Exception(e)
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def create_saved_server(server: str, group: str, desc: str) -> str:
|
def create_saved_server(server: str, group: str, desc: str) -> str:
|
||||||
if add_sql.insert_new_saved_server(server, desc, group):
|
if add_sql.insert_new_saved_server(server, desc, group):
|
||||||
return render_template('ajax/new_saved_servers.html', server=add_sql.select_saved_servers(server=server))
|
return render_template('ajax/new_saved_servers.html', server=add_sql.select_saved_servers(server=server))
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
from app.modules.db.db_model import SavedServer, Option
|
from typing import Union
|
||||||
|
|
||||||
|
from app.modules.db.db_model import SavedServer, Option, HaproxySection
|
||||||
from app.modules.db.common import out_error
|
from app.modules.db.common import out_error
|
||||||
|
from app.modules.roxywi.class_models import HaproxyConfigRequest, HaproxyGlobalRequest, HaproxyDefaultsRequest
|
||||||
from app.modules.roxywi.exception import RoxywiResourceNotFound
|
from app.modules.roxywi.exception import RoxywiResourceNotFound
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,9 +29,6 @@ def delete_option(option_id):
|
||||||
Option.delete().where(Option.id == option_id).execute()
|
Option.delete().where(Option.id == option_id).execute()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
out_error(e)
|
out_error(e)
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def insert_new_saved_server(server, description, group):
|
def insert_new_saved_server(server, description, group):
|
||||||
|
@ -91,3 +91,53 @@ def select_saved_servers(**kwargs):
|
||||||
out_error(e)
|
out_error(e)
|
||||||
else:
|
else:
|
||||||
return query_res
|
return query_res
|
||||||
|
|
||||||
|
|
||||||
|
def insert_new_section(server_id: int, section_type: str, section_name: str, body: HaproxyConfigRequest):
|
||||||
|
try:
|
||||||
|
HaproxySection.insert(
|
||||||
|
server_id=server_id,
|
||||||
|
type=section_type,
|
||||||
|
name=section_name,
|
||||||
|
config=body.model_dump(mode='json')
|
||||||
|
).execute()
|
||||||
|
except Exception as e:
|
||||||
|
out_error(e)
|
||||||
|
|
||||||
|
|
||||||
|
def insert_or_update_new_section(server_id: int, section_type: str, section_name: str, body: Union[HaproxyGlobalRequest, HaproxyDefaultsRequest]):
|
||||||
|
try:
|
||||||
|
HaproxySection.insert(
|
||||||
|
server_id=server_id,
|
||||||
|
type=section_type,
|
||||||
|
name=section_name,
|
||||||
|
config=body.model_dump(mode='json')
|
||||||
|
).on_conflict('replace').execute()
|
||||||
|
except Exception as e:
|
||||||
|
out_error(e)
|
||||||
|
|
||||||
|
|
||||||
|
def update_section(server_id: int, section_type: str, section_name: str, body: HaproxyConfigRequest):
|
||||||
|
try:
|
||||||
|
HaproxySection.update(
|
||||||
|
config=body.model_dump(mode='json')
|
||||||
|
).where(
|
||||||
|
(HaproxySection.server_id == server_id) & (HaproxySection.type == section_type) & (HaproxySection.name == section_name)
|
||||||
|
).execute()
|
||||||
|
except HaproxySection.DoesNotExist:
|
||||||
|
raise RoxywiResourceNotFound
|
||||||
|
except Exception as e:
|
||||||
|
out_error(e)
|
||||||
|
|
||||||
|
|
||||||
|
def get_section(server_id: int, section_type: str, section_name: str) -> HaproxySection:
|
||||||
|
try:
|
||||||
|
return HaproxySection.get(
|
||||||
|
(HaproxySection.server_id == server_id)
|
||||||
|
& (HaproxySection.type == section_type)
|
||||||
|
& (HaproxySection.name == section_name)
|
||||||
|
)
|
||||||
|
except HaproxySection.DoesNotExist:
|
||||||
|
raise RoxywiResourceNotFound
|
||||||
|
except Exception as e:
|
||||||
|
out_error(e)
|
||||||
|
|
|
@ -9,6 +9,11 @@ import app.modules.roxy_wi_tools as roxy_wi_tools
|
||||||
get_config = roxy_wi_tools.GetConfigVar()
|
get_config = roxy_wi_tools.GetConfigVar()
|
||||||
mysql_enable = get_config.get_config_var('mysql', 'enable')
|
mysql_enable = get_config.get_config_var('mysql', 'enable')
|
||||||
|
|
||||||
|
if mysql_enable == '1':
|
||||||
|
from playhouse.mysql_ext import JSONField
|
||||||
|
else:
|
||||||
|
from playhouse.sqlite_ext import JSONField
|
||||||
|
|
||||||
|
|
||||||
class ReconnectMySQLDatabase(ReconnectMixin, MySQLDatabase):
|
class ReconnectMySQLDatabase(ReconnectMixin, MySQLDatabase):
|
||||||
pass
|
pass
|
||||||
|
@ -767,15 +772,27 @@ class UDPBalancer(BaseModel):
|
||||||
constraints = [SQL('UNIQUE (vip, port)')]
|
constraints = [SQL('UNIQUE (vip, port)')]
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxySection(BaseModel):
|
||||||
|
id = AutoField
|
||||||
|
server_id = ForeignKeyField(Server, on_delete='Cascade')
|
||||||
|
type = CharField()
|
||||||
|
name = CharField()
|
||||||
|
config = JSONField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table_name = 'haproxy_sections'
|
||||||
|
constraints = [SQL('UNIQUE (server_id, type, name)')]
|
||||||
|
|
||||||
|
|
||||||
def create_tables():
|
def create_tables():
|
||||||
conn = connect()
|
conn = connect()
|
||||||
with conn:
|
with conn:
|
||||||
conn.create_tables(
|
conn.create_tables(
|
||||||
[User, Server, Role, Telegram, Slack, ApiToken, Groups, UserGroups, ConfigVersion, Setting,
|
[User, Server, Role, Telegram, Slack, ApiToken, Groups, UserGroups, ConfigVersion, Setting, RoxyTool, Alerts,
|
||||||
Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory, PortScannerSettings,
|
Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory, PortScannerSettings,
|
||||||
PortScannerPorts, PortScannerHistory, ServiceSetting, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes,
|
PortScannerPorts, PortScannerHistory, ServiceSetting, MetricsHttpStatus, SMON, WafRules, GeoipCodes,
|
||||||
NginxMetrics, SystemInfo, Services, UserName, GitSetting, CheckerSetting, ApacheMetrics, WafNginx, ServiceStatus,
|
NginxMetrics, SystemInfo, Services, UserName, GitSetting, CheckerSetting, ApacheMetrics, WafNginx, ServiceStatus,
|
||||||
KeepaliveRestart, PD, SmonHistory, SmonAgent, SmonTcpCheck, SmonHttpCheck, SmonPingCheck, SmonDnsCheck, S3Backup, RoxyTool,
|
KeepaliveRestart, PD, SmonHistory, SmonAgent, SmonTcpCheck, SmonHttpCheck, SmonPingCheck, SmonDnsCheck, S3Backup,
|
||||||
SmonStatusPage, SmonStatusPageCheck, HaCluster, HaClusterSlave, HaClusterVip, HaClusterVirt, HaClusterService,
|
SmonStatusPage, SmonStatusPageCheck, HaCluster, HaClusterSlave, HaClusterVip, HaClusterVirt, HaClusterService,
|
||||||
HaClusterRouter, MM, UDPBalancer]
|
HaClusterRouter, MM, UDPBalancer, HaproxySection]
|
||||||
)
|
)
|
||||||
|
|
|
@ -290,3 +290,157 @@ class SSLCertUploadRequest(BaseModel):
|
||||||
class SavedServerRequest(BaseModel):
|
class SavedServerRequest(BaseModel):
|
||||||
server: EscapedString
|
server: EscapedString
|
||||||
description: Optional[EscapedString] = None
|
description: Optional[EscapedString] = None
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyBinds(BaseModel):
|
||||||
|
ip: Optional[str] = None
|
||||||
|
port: Annotated[int, Gt(1), Le(65535)]
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyHeaders(BaseModel):
|
||||||
|
path: Literal['http-request', 'http-response']
|
||||||
|
name: str
|
||||||
|
method: Literal['add-header', 'set-header', 'del-header', 'replace-header', 'pass-header']
|
||||||
|
value: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyAcls(BaseModel):
|
||||||
|
acl_if: int
|
||||||
|
acl_then: int
|
||||||
|
acl_then_value: Optional[str] = None
|
||||||
|
acl_value: str
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyBackendServer(BaseModel):
|
||||||
|
server: Union[IPvAnyAddress, DomainName]
|
||||||
|
port: Annotated[int, Gt(1), Le(65535)]
|
||||||
|
port_check: Annotated[int, Gt(1), Le(65535)]
|
||||||
|
maxconn: Optional[int] = 2000
|
||||||
|
send_proxy: Optional[bool] = 0
|
||||||
|
backup: Optional[bool] = 0
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyCookie(BaseModel):
|
||||||
|
dynamic: str
|
||||||
|
dynamicKey: str
|
||||||
|
domain: Optional[str] = None
|
||||||
|
name: Optional[str] = None
|
||||||
|
nocache: Optional[str] = None
|
||||||
|
postonly: Optional[str] = None
|
||||||
|
prefix: Optional[str] = None
|
||||||
|
rewrite: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyHealthCheck(BaseModel):
|
||||||
|
check: str
|
||||||
|
domain: Optional[str] = None
|
||||||
|
path: str
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxySSL(BaseModel):
|
||||||
|
cert: str
|
||||||
|
ssl_check_backend: Optional[bool] = 1
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyServersCheck(BaseModel):
|
||||||
|
check_enabled: Optional[bool] = 1
|
||||||
|
fall: Optional[int] = 5
|
||||||
|
rise: Optional[int] = 2
|
||||||
|
inter: Optional[int] = 2000
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyCircuitBreaking(BaseModel):
|
||||||
|
observe: Literal['layer7', 'layer4']
|
||||||
|
error_limit: int
|
||||||
|
on_error: Literal['mark-down', 'fastinter', 'fail-check', 'sudden-death']
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyConfigRequest(BaseModel):
|
||||||
|
balance: Optional[Literal['roundrobin', 'source', 'leastconn', 'first', 'rdp-cookie', 'uri', 'uri whole', 'static-rr']] = None
|
||||||
|
mode: Literal['tcp', 'http'] = 'http'
|
||||||
|
type: Literal['listen', 'frontend', 'backend']
|
||||||
|
name: EscapedString
|
||||||
|
option: Optional[str] = None
|
||||||
|
maxconn: Optional[int] = 2000
|
||||||
|
waf: Optional[bool] = 0
|
||||||
|
binds: List[HaproxyBinds]
|
||||||
|
headers: List[HaproxyHeaders] = None
|
||||||
|
acls: List[HaproxyAcls] = None
|
||||||
|
backend_servers: List[HaproxyBackendServer] = None
|
||||||
|
blacklist: Optional[str] = ''
|
||||||
|
whitelist: Optional[str] = ''
|
||||||
|
ssl: Optional[HaproxySSL] = None
|
||||||
|
cache: Optional[bool] = 0
|
||||||
|
compression: Optional[bool] = 0
|
||||||
|
cookie: Optional[HaproxyCookie] = None
|
||||||
|
health_check: Optional[HaproxyHealthCheck] = None
|
||||||
|
servers_check: Optional[HaproxyServersCheck] = None
|
||||||
|
ssl_offloading: Optional[bool] = 0
|
||||||
|
redispatch: Optional[bool] = 0
|
||||||
|
forward_for: Optional[bool] = 0
|
||||||
|
slow_attack: Optional[bool] = 0
|
||||||
|
ddos: Optional[bool] = 0
|
||||||
|
antibot: Optional[bool] = 0
|
||||||
|
backends: Optional[str] = None
|
||||||
|
circuit_breaking: Optional[HaproxyCircuitBreaking] = None
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyUserListUser(BaseModel):
|
||||||
|
user: str
|
||||||
|
password: str
|
||||||
|
group: Optional[str] = ''
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyUserListRequest(BaseModel):
|
||||||
|
name: EscapedString
|
||||||
|
type: Literal['userlist']
|
||||||
|
userlist_users: Optional[List[HaproxyUserListUser]] = ''
|
||||||
|
userlist_groups: Optional[List[str]] = ''
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyPeers(BaseModel):
|
||||||
|
name: str
|
||||||
|
ip: Union[IPvAnyAddress, DomainName]
|
||||||
|
port: Annotated[int, Gt(1), Le(65535)]
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyPeersRequest(BaseModel):
|
||||||
|
name: EscapedString
|
||||||
|
type: Literal['peers']
|
||||||
|
peers: List[HaproxyPeers]
|
||||||
|
|
||||||
|
|
||||||
|
class GenerateConfigRequest(BaseModel):
|
||||||
|
generate: Optional[bool] = 0
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyGlobalRequest(BaseModel):
|
||||||
|
log: Optional[List[str]] = ['127.0.0.1 local', '127.0.0.1 local1 notice']
|
||||||
|
chroot: Optional[str] = '/var/lib/haproxy'
|
||||||
|
pidfile: Optional[str] = '/var/run/haproxy.pid'
|
||||||
|
maxconn: Optional[int] = 5000
|
||||||
|
user: Optional[str] = 'haproxy'
|
||||||
|
group: Optional[str] = 'haproxy'
|
||||||
|
daemon: Optional[bool] = 1
|
||||||
|
socket: Optional[List[str]] = ['*:1999 level admin', '/var/run/haproxy.sock mode 600 level admin', '/var/lib/haproxy/stats']
|
||||||
|
type: Optional[Literal['global']] = 'global'
|
||||||
|
option: Optional[str] = ''
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyDefaultsTimeout(BaseModel):
|
||||||
|
http_request: Optional[int] = 10
|
||||||
|
queue: Optional[int] = 60
|
||||||
|
connect: Optional[int] = 10
|
||||||
|
client: Optional[int] = 60
|
||||||
|
server: Optional[int] = 60
|
||||||
|
check: Optional[int] = 10
|
||||||
|
http_keep_alive: Optional[int] = 10
|
||||||
|
|
||||||
|
|
||||||
|
class HaproxyDefaultsRequest(BaseModel):
|
||||||
|
log: Optional[str] = 'global'
|
||||||
|
retries: Optional[int] = 3
|
||||||
|
timeout: Optional[HaproxyDefaultsTimeout] = HaproxyDefaultsTimeout().model_dump(mode='json')
|
||||||
|
option: Optional[str] = ''
|
||||||
|
maxconn: Optional[int] = 5000
|
||||||
|
type: Optional[Literal['defaults']] = 'defaults'
|
||||||
|
|
|
@ -7,6 +7,7 @@ import ansible
|
||||||
import ansible_runner
|
import ansible_runner
|
||||||
|
|
||||||
import app.modules.db.sql as sql
|
import app.modules.db.sql as sql
|
||||||
|
import app.modules.db.add as add_sql
|
||||||
import app.modules.db.ha_cluster as ha_sql
|
import app.modules.db.ha_cluster as ha_sql
|
||||||
import app.modules.db.server as server_sql
|
import app.modules.db.server as server_sql
|
||||||
import app.modules.db.service as service_sql
|
import app.modules.db.service as service_sql
|
||||||
|
@ -16,7 +17,8 @@ import app.modules.common.common as common
|
||||||
import app.modules.server.server as server_mod
|
import app.modules.server.server as server_mod
|
||||||
import app.modules.roxywi.common as roxywi_common
|
import app.modules.roxywi.common as roxywi_common
|
||||||
from app.modules.server.ssh import return_ssh_keys_path
|
from app.modules.server.ssh import return_ssh_keys_path
|
||||||
from app.modules.roxywi.class_models import ServiceInstall, HAClusterRequest
|
from app.modules.roxywi.class_models import ServiceInstall, HAClusterRequest, HaproxyGlobalRequest, \
|
||||||
|
HaproxyDefaultsRequest, HaproxyConfigRequest
|
||||||
|
|
||||||
|
|
||||||
def generate_udp_inv(listener_id: int, action: str) -> object:
|
def generate_udp_inv(listener_id: int, action: str) -> object:
|
||||||
|
@ -157,6 +159,33 @@ def generate_haproxy_inv(json_data: ServiceInstall, installed_service: str) -> o
|
||||||
return inv, server_ips
|
return inv, server_ips
|
||||||
|
|
||||||
|
|
||||||
|
def generate_haproxy_section_inv(json_data: dict, cfg: str) -> dict:
|
||||||
|
cert_path = sql.get_setting('cert_path')
|
||||||
|
haproxy_dir = sql.get_setting('haproxy_dir')
|
||||||
|
inv = {"server": {"hosts": {}}}
|
||||||
|
inv['server']['hosts']['localhost'] = {
|
||||||
|
"config": json_data,
|
||||||
|
"cert_path": cert_path,
|
||||||
|
"haproxy_dir": haproxy_dir,
|
||||||
|
"cfg": cfg,
|
||||||
|
"action": 'create'
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv
|
||||||
|
|
||||||
|
|
||||||
|
def generate_haproxy_section_inv_for_del(cfg: str, section_type: str, section_name: str) -> dict:
|
||||||
|
config = {'type': section_type, 'name': section_name}
|
||||||
|
inv = {"server": {"hosts": {}}}
|
||||||
|
inv['server']['hosts']['localhost'] = {
|
||||||
|
"config": config,
|
||||||
|
"cfg": cfg,
|
||||||
|
"action": 'delete'
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv
|
||||||
|
|
||||||
|
|
||||||
def generate_service_inv(json_data: ServiceInstall, installed_service: str) -> object:
|
def generate_service_inv(json_data: ServiceInstall, installed_service: str) -> object:
|
||||||
inv = {"server": {"hosts": {}}}
|
inv = {"server": {"hosts": {}}}
|
||||||
server_ips = []
|
server_ips = []
|
||||||
|
@ -297,6 +326,55 @@ def run_ansible(inv: dict, server_ips: list, ansible_role: str) -> dict:
|
||||||
return result.stats
|
return result.stats
|
||||||
|
|
||||||
|
|
||||||
|
def run_ansible_locally(inv: dict, ansible_role: str) -> dict:
|
||||||
|
inventory_path = '/var/www/haproxy-wi/app/scripts/ansible/inventory'
|
||||||
|
inventory = f'{inventory_path}/{ansible_role}.json'
|
||||||
|
# proxy = sql.get_setting('proxy')
|
||||||
|
# proxy_serv = ''
|
||||||
|
|
||||||
|
envvars = {
|
||||||
|
'ANSIBLE_DISPLAY_OK_HOSTS': 'no',
|
||||||
|
'ANSIBLE_SHOW_CUSTOM_STATS': 'no',
|
||||||
|
'ANSIBLE_DISPLAY_SKIPPED_HOSTS': "no",
|
||||||
|
'ANSIBLE_DEPRECATION_WARNINGS': "no",
|
||||||
|
'ANSIBLE_HOST_KEY_CHECKING': "no",
|
||||||
|
'ACTION_WARNINGS': "no",
|
||||||
|
'LOCALHOST_WARNING': "no",
|
||||||
|
'COMMAND_WARNINGS': "no",
|
||||||
|
'AWX_DISPLAY': False,
|
||||||
|
'ANSIBLE_PYTHON_INTERPRETER': '/usr/bin/python3'
|
||||||
|
}
|
||||||
|
kwargs = {
|
||||||
|
'private_data_dir': '/var/www/haproxy-wi/app/scripts/ansible/',
|
||||||
|
'inventory': inventory,
|
||||||
|
'envvars': envvars,
|
||||||
|
'playbook': f'/var/www/haproxy-wi/app/scripts/ansible/roles/{ansible_role}.yml',
|
||||||
|
}
|
||||||
|
if os.path.isfile(inventory):
|
||||||
|
os.remove(inventory)
|
||||||
|
|
||||||
|
if not os.path.isdir(inventory_path):
|
||||||
|
os.makedirs(inventory_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(inventory, 'a') as invent:
|
||||||
|
invent.write(str(inv))
|
||||||
|
except Exception as e:
|
||||||
|
roxywi_common.handle_exceptions(e, 'Roxy-WI server', 'Cannot save inventory file', roxywi=1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = ansible_runner.run(**kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
roxywi_common.handle_exceptions(e, 'Roxy-WI server', 'Cannot run Ansible', roxywi=1)
|
||||||
|
|
||||||
|
os.remove(inventory)
|
||||||
|
|
||||||
|
if result.rc != 0:
|
||||||
|
raise Exception('Something wrong with installation, check <a href="/app/logs/internal?log_file=roxy-wi.error.log" target="_blank" class="link">Apache logs</a> for details')
|
||||||
|
|
||||||
|
return result.stats
|
||||||
|
|
||||||
|
|
||||||
def service_actions_after_install(server_ips: str, service: str, json_data) -> None:
|
def service_actions_after_install(server_ips: str, service: str, json_data) -> None:
|
||||||
is_docker = None
|
is_docker = None
|
||||||
update_functions = {
|
update_functions = {
|
||||||
|
@ -319,6 +397,35 @@ def service_actions_after_install(server_ips: str, service: str, json_data) -> N
|
||||||
service_sql.insert_or_update_service_setting(server_id, service, 'dockerized', '1')
|
service_sql.insert_or_update_service_setting(server_id, service, 'dockerized', '1')
|
||||||
service_sql.insert_or_update_service_setting(server_id, service, 'restart', '1')
|
service_sql.insert_or_update_service_setting(server_id, service, 'restart', '1')
|
||||||
|
|
||||||
|
if service == 'haproxy':
|
||||||
|
try:
|
||||||
|
_create_default_config_in_db(server_id)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _create_default_config_in_db(server_id: int) -> None:
|
||||||
|
hap_sock_p = sql.get_setting('haproxy_sock_port')
|
||||||
|
stats_port = sql.get_setting('haproxy_stats_port')
|
||||||
|
stats_user = sql.get_setting('haproxy_stats_user')
|
||||||
|
stats_password = sql.get_setting('haproxy_stats_password')
|
||||||
|
config = HaproxyGlobalRequest(
|
||||||
|
socket=[f'*:{hap_sock_p} level admin', '/var/run/haproxy.sock mode 600 level admin', '/var/lib/haproxy/stats']
|
||||||
|
)
|
||||||
|
add_sql.insert_or_update_new_section(server_id, 'global', 'global', config)
|
||||||
|
add_sql.insert_or_update_new_section(server_id, 'default', 'defaults', HaproxyDefaultsRequest())
|
||||||
|
option = (
|
||||||
|
'http-request use-service prometheus-exporter if { path /metrics }\r\nstats enable\r\nstats uri /stats\r\n'
|
||||||
|
f'stats realm HAProxy-04\ Statistics\r\nstats auth {stats_user}:{stats_password}\r\nstats admin if TRUE'
|
||||||
|
)
|
||||||
|
stats_config = HaproxyConfigRequest(
|
||||||
|
binds=[{'ip': '', 'port': stats_port}],
|
||||||
|
option=option,
|
||||||
|
type='listen',
|
||||||
|
name='stats',
|
||||||
|
)
|
||||||
|
add_sql.insert_new_section(server_id, 'listen', 'stats', stats_config)
|
||||||
|
|
||||||
|
|
||||||
def install_service(service: str, json_data: Union[str, ServiceInstall, HAClusterRequest], cluster_id: int = None) -> dict:
|
def install_service(service: str, json_data: Union[str, ServiceInstall, HAClusterRequest], cluster_id: int = None) -> dict:
|
||||||
generate_functions = {
|
generate_functions = {
|
||||||
|
|
|
@ -6,17 +6,34 @@ from flask_pydantic import validate
|
||||||
|
|
||||||
from app.modules.roxywi.class_models import SSLCertUploadRequest, DataStrResponse, SavedServerRequest, BaseResponse
|
from app.modules.roxywi.class_models import SSLCertUploadRequest, DataStrResponse, SavedServerRequest, BaseResponse
|
||||||
from app.routes.add import bp
|
from app.routes.add import bp
|
||||||
import app.modules.db.sql as sql
|
|
||||||
import app.modules.db.add as add_sql
|
import app.modules.db.add as add_sql
|
||||||
|
import app.modules.db.server as server_sql
|
||||||
from app.middleware import check_services, get_user_params
|
from app.middleware import check_services, get_user_params
|
||||||
import app.modules.config.add as add_mod
|
import app.modules.config.add as add_mod
|
||||||
import app.modules.common.common as common
|
import app.modules.common.common as common
|
||||||
import app.modules.roxywi.auth as roxywi_auth
|
import app.modules.roxywi.auth as roxywi_auth
|
||||||
import app.modules.roxywi.common as roxywi_common
|
import app.modules.roxywi.common as roxywi_common
|
||||||
import app.modules.roxy_wi_tools as roxy_wi_tools
|
import app.modules.roxy_wi_tools as roxy_wi_tools
|
||||||
|
from app.views.service.haproxy_section_views import (GlobalSectionView, DefaultsSectionView, ListenSectionView,
|
||||||
|
UserListSectionView, PeersSectionView)
|
||||||
|
|
||||||
get_config = roxy_wi_tools.GetConfigVar()
|
get_config = roxy_wi_tools.GetConfigVar()
|
||||||
|
|
||||||
|
def register_api_id_ip(view, endpoint, url: str = '', methods: list = ['GET', 'POST']):
|
||||||
|
for point in ('_id', '_ip'):
|
||||||
|
view_func = view.as_view(f'{endpoint}_{point}')
|
||||||
|
pk = 'int:' if point == '_id' else ''
|
||||||
|
bp.add_url_rule(f'/<any(haproxy, nginx, apache, keepalived):service>/<{pk}server_id>{url}', view_func=view_func, methods=methods)
|
||||||
|
|
||||||
|
register_api_id_ip(ListenSectionView, 'haproxy_section_post_a', '/section/<any(listen, frontend, backend):section_type>', methods=['POST'])
|
||||||
|
register_api_id_ip(ListenSectionView, 'haproxy_section_a', '/section/<any(listen, frontend, backend):section_type>/<section_name>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
register_api_id_ip(UserListSectionView, 'haproxy_userlist_post_a', '/section/userlist', methods=['POST'])
|
||||||
|
register_api_id_ip(UserListSectionView, 'haproxy_userlist_a', '/section/userlist/<section_name>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
register_api_id_ip(PeersSectionView, 'haproxy_peers_post_a', '/section/peers', methods=['POST'])
|
||||||
|
register_api_id_ip(PeersSectionView, 'haproxy_peers_a', '/section/peers/<section_name>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
register_api_id_ip(GlobalSectionView, 'haproxy_global_a', '/section/global', methods=['GET', 'PUT'])
|
||||||
|
register_api_id_ip(DefaultsSectionView, 'haproxy_defaults_a', '/section/defaults', methods=['GET', 'PUT'])
|
||||||
|
|
||||||
|
|
||||||
@bp.before_request
|
@bp.before_request
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
|
@ -72,325 +89,11 @@ def add(service):
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/haproxy/add', methods=['POST'])
|
@bp.route('/haproxy/get_section_html')
|
||||||
@get_user_params()
|
@get_user_params()
|
||||||
def add_haproxy():
|
def get_section_html():
|
||||||
"""
|
lang = g.user_params['lang']
|
||||||
Add HAProxy sections
|
return render_template('ajax/config_show_add_sections.html', lang=lang)
|
||||||
:return: Generated section or output of adding status
|
|
||||||
"""
|
|
||||||
roxywi_auth.page_for_admin(level=3)
|
|
||||||
|
|
||||||
haproxy_dir = sql.get_setting('haproxy_dir')
|
|
||||||
generate = request.form.get('generateconfig')
|
|
||||||
server_ip = request.form.get('serv')
|
|
||||||
port = request.form.getlist('port')
|
|
||||||
bind = ""
|
|
||||||
ip = ""
|
|
||||||
force_close = request.form.get('force_close')
|
|
||||||
balance = ""
|
|
||||||
mode = f" mode {request.form.get('mode')}\n"
|
|
||||||
maxconn = ""
|
|
||||||
options_split = ""
|
|
||||||
ssl = ""
|
|
||||||
ssl_check = ""
|
|
||||||
backend = ""
|
|
||||||
headers = ""
|
|
||||||
acl = ""
|
|
||||||
servers_split = ""
|
|
||||||
new_listener = request.form.get('listener')
|
|
||||||
new_frontend = request.form.get('frontend')
|
|
||||||
new_backend = request.form.get('new_backend')
|
|
||||||
|
|
||||||
if request.form.get('balance') is not None:
|
|
||||||
balance = " balance " + request.form.get('balance') + "\n"
|
|
||||||
|
|
||||||
if request.form.get('health_check') is not None:
|
|
||||||
health_check = request.form.get('health_check')
|
|
||||||
if health_check == 'option httpchk' and request.form.get('checks_http_domain') is not None:
|
|
||||||
health_check = health_check + ' GET ' + request.form.get(
|
|
||||||
'checks_http_path') + ' "HTTP/1.0\\r\\nHost: ' + request.form.get('checks_http_domain') + '"'
|
|
||||||
balance += f" {health_check}\n"
|
|
||||||
|
|
||||||
if request.form.get('ip') is not None:
|
|
||||||
ip = request.form.getlist('ip')
|
|
||||||
|
|
||||||
if new_listener is not None:
|
|
||||||
name = f"listen {new_listener}"
|
|
||||||
end_name = new_listener
|
|
||||||
elif new_frontend is not None:
|
|
||||||
name = f"frontend {new_frontend}"
|
|
||||||
end_name = new_frontend
|
|
||||||
server_ip = request.form.get('serv2')
|
|
||||||
elif new_backend is not None:
|
|
||||||
name = f"backend {new_backend}"
|
|
||||||
end_name = new_backend
|
|
||||||
server_ip = request.form.get('serv3')
|
|
||||||
else:
|
|
||||||
return 'error: The name cannot be empty'
|
|
||||||
|
|
||||||
if request.form.get('backends') != '' and request.form.get('backends'):
|
|
||||||
backend = f" default_backend {request.form.get('backends')}\n"
|
|
||||||
|
|
||||||
if request.form.get('maxconn'):
|
|
||||||
maxconn = f" maxconn {request.form.get('maxconn')}\n"
|
|
||||||
|
|
||||||
if request.form.get('ssl') == "https" and request.form.get('mode') != "tcp":
|
|
||||||
cert_path = sql.get_setting('cert_path')
|
|
||||||
if request.form.get('cert') is not None:
|
|
||||||
ssl = f"ssl crt {cert_path}{request.form.get('cert')}"
|
|
||||||
if request.form.get('ssl-dis-check') is None:
|
|
||||||
if request.form.get('ssl-check') == "ssl-check":
|
|
||||||
ssl_check = " ssl verify none"
|
|
||||||
else:
|
|
||||||
ssl_check = " ssl verify"
|
|
||||||
|
|
||||||
if ip or port:
|
|
||||||
if type(port) is list:
|
|
||||||
i = 0
|
|
||||||
for _p in port:
|
|
||||||
if ip[i] == 'IsEmptY':
|
|
||||||
if ip[i] == 'IsEmptY' and port[i] == 'IsEmptY':
|
|
||||||
i += 1
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
port_value = port[i]
|
|
||||||
bind += f" bind *:{port_value} {ssl}\n"
|
|
||||||
else:
|
|
||||||
if port[i] == 'IsEmptY':
|
|
||||||
return 'error: IP cannot be bind without a port'
|
|
||||||
else:
|
|
||||||
port_value = port[i]
|
|
||||||
bind += f" bind {ip[i]}:{port_value} {ssl}\n"
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
if request.form.get('default-check') == "1":
|
|
||||||
if request.form.get('check-servers') == "1":
|
|
||||||
check = f" check inter {request.form.get('inter')} rise {request.form.get('rise')} fall {request.form.get('fall')}{ssl_check}"
|
|
||||||
else:
|
|
||||||
check = ""
|
|
||||||
else:
|
|
||||||
if request.form.get('check-servers') != "1":
|
|
||||||
check = ""
|
|
||||||
else:
|
|
||||||
check = f" check{ssl_check}"
|
|
||||||
|
|
||||||
if request.form.get('option') is not None:
|
|
||||||
options = request.form.get('option')
|
|
||||||
i = options.split("\n")
|
|
||||||
for j in i:
|
|
||||||
options_split += f" {j}\n"
|
|
||||||
|
|
||||||
if force_close == "1":
|
|
||||||
options_split += " option http-server-close\n"
|
|
||||||
elif force_close == "2":
|
|
||||||
options_split += " option forceclose\n"
|
|
||||||
elif force_close == "3":
|
|
||||||
options_split += " option http-pretend-keepalive\n"
|
|
||||||
|
|
||||||
if request.form.get('whitelist'):
|
|
||||||
options_split += " tcp-request connection accept if { src -f " + haproxy_dir + "/white/" + request.form.get(
|
|
||||||
'whitelist') + " }\n"
|
|
||||||
|
|
||||||
if request.form.get('blacklist'):
|
|
||||||
options_split += " tcp-request connection reject if { src -f " + haproxy_dir + "/black/" + request.form.get(
|
|
||||||
'blacklist') + " }\n"
|
|
||||||
|
|
||||||
if request.form.get('cookie'):
|
|
||||||
cookie = f" cookie {request.form.get('cookie_name')}"
|
|
||||||
if request.form.get('cookie_domain'):
|
|
||||||
cookie += f" domain {request.form.get('cookie_domain')}"
|
|
||||||
if request.form.get('rewrite'):
|
|
||||||
rewrite = request.form.get('rewrite')
|
|
||||||
else:
|
|
||||||
rewrite = ""
|
|
||||||
if request.form.get('prefix'):
|
|
||||||
prefix = request.form.get('prefix')
|
|
||||||
else:
|
|
||||||
prefix = ""
|
|
||||||
if request.form.get('nocache'):
|
|
||||||
nocache = request.form.get('nocache')
|
|
||||||
else:
|
|
||||||
nocache = ""
|
|
||||||
if request.form.get('postonly'):
|
|
||||||
postonly = request.form.get('postonly')
|
|
||||||
else:
|
|
||||||
postonly = ""
|
|
||||||
if request.form.get('dynamic'):
|
|
||||||
dynamic = request.form.get('dynamic')
|
|
||||||
else:
|
|
||||||
dynamic = ""
|
|
||||||
cookie += f" {rewrite} {prefix} {nocache} {postonly} {dynamic}\n"
|
|
||||||
options_split += cookie
|
|
||||||
if request.form.get('dynamic'):
|
|
||||||
options_split += f" dynamic-cookie-key {request.form.get('dynamic-cookie-key')}\n"
|
|
||||||
|
|
||||||
if request.form.get('headers_res'):
|
|
||||||
headers_res = request.form.getlist('headers_res')
|
|
||||||
headers_method = request.form.getlist('headers_method')
|
|
||||||
header_name = request.form.getlist('header_name')
|
|
||||||
header_value = request.form.getlist('header_value')
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
for _h in headers_method:
|
|
||||||
if headers_method[i] != 'del-header':
|
|
||||||
headers += f' {headers_res[i]} {headers_method[i]} {header_name[i]} {header_value[i]}\n'
|
|
||||||
else:
|
|
||||||
headers += f' {headers_res[i]} {headers_method[i]} {header_name[i]}\n'
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
if request.form.get('acl_if'):
|
|
||||||
acl_if = request.form.getlist('acl_if')
|
|
||||||
acl_value = request.form.getlist('acl_value')
|
|
||||||
acl_then = request.form.getlist('acl_then')
|
|
||||||
acl_then_values = request.form.getlist('acl_then_value')
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
for a in acl_if:
|
|
||||||
acl_then_value = '' if acl_then_values[i] == 'IsEmptY' else acl_then_values[i]
|
|
||||||
|
|
||||||
try:
|
|
||||||
if a == '1':
|
|
||||||
acl_if_word = 'hdr_beg(host) -i '
|
|
||||||
if request.form.get('ssl') == "https" and request.form.get('mode') != "tcp":
|
|
||||||
acl_if_word = 'ssl_fc_sni -i '
|
|
||||||
if request.form.get('mode') == "tcp":
|
|
||||||
acl_if_word = 'req.ssl_sni -i '
|
|
||||||
elif a == '2':
|
|
||||||
acl_if_word = 'hdr_end(host) -i '
|
|
||||||
if request.form.get('ssl') == "https" and request.form.get('mode') != "tcp":
|
|
||||||
acl_if_word = 'ssl_fc_sni -i '
|
|
||||||
if request.form.get('mode') == "tcp":
|
|
||||||
acl_if_word = 'req.ssl_sni -i '
|
|
||||||
elif a == '3':
|
|
||||||
acl_if_word = 'path_beg -i '
|
|
||||||
elif a == '4':
|
|
||||||
acl_if_word = 'path_end -i '
|
|
||||||
elif a == '6':
|
|
||||||
acl_if_word = 'src ip '
|
|
||||||
else:
|
|
||||||
acl_if_word = ''
|
|
||||||
|
|
||||||
if acl_then[i] == '5':
|
|
||||||
acl += ' use_backend '
|
|
||||||
elif acl_then[i] == '2':
|
|
||||||
acl += ' http-request redirect location '
|
|
||||||
elif acl_then[i] == '3':
|
|
||||||
acl += ' http-request allow'
|
|
||||||
acl_then_value = ''
|
|
||||||
elif acl_then[i] == '4':
|
|
||||||
acl += ' http-request deny'
|
|
||||||
acl_then_value = ''
|
|
||||||
elif acl_then[i] == '6':
|
|
||||||
acl += f' acl return_{acl_value[i]} {acl_if_word} {acl_value[i]}\n'
|
|
||||||
acl += f' http-request return if return_{acl_value[i]}\n'
|
|
||||||
elif acl_then[i] == '7':
|
|
||||||
acl += f' acl set_header_{acl_value[i]} {acl_if_word} {acl_value[i]}\n'
|
|
||||||
acl += f' http-request set-header if set_header_{acl_value[i]}\n'
|
|
||||||
|
|
||||||
if acl_then[i] in ('2', '3', '4', '5'):
|
|
||||||
acl += acl_then_value + ' if { ' + acl_if_word + acl_value[i] + ' } \n'
|
|
||||||
except Exception:
|
|
||||||
acl = ''
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
if request.form.get('circuit_breaking') == "1":
|
|
||||||
observe = 'observe ' + request.form.get('circuit_breaking_observe')
|
|
||||||
error_limit = ' error-limit ' + request.form.get('circuit_breaking_error_limit')
|
|
||||||
circuit_breaking_on_error = ' on-error ' + request.form.get('circuit_breaking_on_error')
|
|
||||||
default_server = ' default-server ' + observe + error_limit + circuit_breaking_on_error + '\n'
|
|
||||||
servers_split += default_server
|
|
||||||
|
|
||||||
if request.form.get('servers'):
|
|
||||||
servers = request.form.getlist('servers')
|
|
||||||
server_port = request.form.getlist('server_port')
|
|
||||||
send_proxy = request.form.getlist('send_proxy')
|
|
||||||
backup = request.form.getlist('backup')
|
|
||||||
server_maxconn = request.form.getlist('server_maxconn')
|
|
||||||
port_check = request.form.getlist('port_check')
|
|
||||||
i = 0
|
|
||||||
for server in servers:
|
|
||||||
if server == '':
|
|
||||||
continue
|
|
||||||
if request.form.get('template') is None:
|
|
||||||
try:
|
|
||||||
if send_proxy[i] == '1':
|
|
||||||
send_proxy_param = 'send-proxy'
|
|
||||||
else:
|
|
||||||
send_proxy_param = ''
|
|
||||||
except Exception:
|
|
||||||
send_proxy_param = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
if backup[i] == '1':
|
|
||||||
backup_param = 'backup'
|
|
||||||
else:
|
|
||||||
backup_param = ''
|
|
||||||
except Exception:
|
|
||||||
backup_param = ''
|
|
||||||
|
|
||||||
try:
|
|
||||||
maxconn_val = server_maxconn[i]
|
|
||||||
except Exception:
|
|
||||||
maxconn_val = '200'
|
|
||||||
|
|
||||||
try:
|
|
||||||
port_check_val = port_check[i]
|
|
||||||
if port_check_val == '':
|
|
||||||
port_check_val = server_port[i]
|
|
||||||
except Exception:
|
|
||||||
port_check_val = server_port[i]
|
|
||||||
|
|
||||||
servers_split += " server {0} {0}:{1}{2} port {6} maxconn {5} {3} {4} \n".format(
|
|
||||||
server, server_port[i], check, send_proxy_param, backup_param, maxconn_val, port_check_val
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
servers_split += " server-template {0} {1} {2}:{3} {4} \n".format(
|
|
||||||
request.form.get('prefix'), request.form.get('template-number'), server, server_port[i], check
|
|
||||||
)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
compression = request.form.get("compression")
|
|
||||||
cache = request.form.get("cache")
|
|
||||||
compression_s = ""
|
|
||||||
cache_s = ""
|
|
||||||
cache_set = ""
|
|
||||||
filter_com = ""
|
|
||||||
if compression == "1" or cache == "2":
|
|
||||||
filter_com = " filter compression\n"
|
|
||||||
if cache == "2":
|
|
||||||
cache_s = f" http-request cache-use {end_name}\n http-response cache-store {end_name}\n"
|
|
||||||
cache_set = f"cache {end_name}\n total-max-size 4\n max-age 240\n"
|
|
||||||
if compression == "1":
|
|
||||||
compression_s = " compression algo gzip\n compression type text/html text/plain text/css\n"
|
|
||||||
|
|
||||||
waf = ""
|
|
||||||
if request.form.get('waf'):
|
|
||||||
waf = f" filter spoe engine modsecurity config {haproxy_dir}/waf.conf\n"
|
|
||||||
waf += " http-request deny if { var(txn.modsec.code) -m int gt 0 }\n"
|
|
||||||
|
|
||||||
config_add = f"\n{name}\n{bind}{mode}{maxconn}{balance}{options_split}{cache_s}{filter_com}{compression_s}" \
|
|
||||||
f"{waf}{headers}{acl}{backend}{servers_split}\n{cache_set}\n"
|
|
||||||
|
|
||||||
if generate:
|
|
||||||
return config_add
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
return add_mod.save_to_haproxy_config(config_add, server_ip, name)
|
|
||||||
except Exception as e:
|
|
||||||
return f'error: Cannot add to config: {e}'
|
|
||||||
|
|
||||||
|
|
||||||
@bp.post('/haproxy/userlist')
|
|
||||||
@get_user_params()
|
|
||||||
def add_userlist():
|
|
||||||
"""
|
|
||||||
Add HAProxy section userlist
|
|
||||||
:return: Output of adding status
|
|
||||||
"""
|
|
||||||
roxywi_auth.page_for_admin(level=3)
|
|
||||||
return add_mod.add_userlist()
|
|
||||||
|
|
||||||
|
|
||||||
@bp.post('/haproxy/bwlist/create')
|
@bp.post('/haproxy/bwlist/create')
|
||||||
|
@ -441,42 +144,6 @@ def get_bwlists(color, group):
|
||||||
return add_mod.get_bwlists_for_autocomplete(color, group)
|
return add_mod.get_bwlists_for_autocomplete(color, group)
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/haproxy/userlist/<server_ip>')
|
|
||||||
def show_userlist(server_ip):
|
|
||||||
server_ip = common.is_ip_or_dns(server_ip)
|
|
||||||
return add_mod.show_userlist(server_ip)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.post('/haproxy/peers')
|
|
||||||
def add_peers():
|
|
||||||
roxywi_auth.page_for_admin(level=3)
|
|
||||||
|
|
||||||
generate = request.form.get('generateconfig')
|
|
||||||
server_ip = request.form.get('serv')
|
|
||||||
servers_split = ''
|
|
||||||
name = "peers " + request.form.get('peers-name') + "\n"
|
|
||||||
servers = request.form.getlist('servers')
|
|
||||||
server_port = request.form.getlist('server_port')
|
|
||||||
servers_name = request.form.getlist('servers_name')
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
for server in servers:
|
|
||||||
if server == '':
|
|
||||||
continue
|
|
||||||
servers_split += " peer {0} {1}:{2} \n".format(servers_name[i], server, server_port[i])
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
config_add = "\n" + name + servers_split
|
|
||||||
|
|
||||||
if generate:
|
|
||||||
return config_add, 200
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
return add_mod.save_to_haproxy_config(config_add, server_ip, name)
|
|
||||||
except Exception as e:
|
|
||||||
return f'error: Cannot add to config: {e}'
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/option/get/<group>')
|
@bp.route('/option/get/<group>')
|
||||||
def get_option(group):
|
def get_option(group):
|
||||||
term = request.args.get('term')
|
term = request.args.get('term')
|
||||||
|
@ -554,9 +221,14 @@ def delete_saved_server(server_id):
|
||||||
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete server')
|
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete server')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/certs/<int:server_ip>')
|
||||||
@bp.route('/certs/<server_ip>')
|
@bp.route('/certs/<server_ip>')
|
||||||
def get_certs(server_ip):
|
def get_certs(server_ip):
|
||||||
server_ip = common.is_ip_or_dns(server_ip)
|
if isinstance(server_ip, str):
|
||||||
|
server_ip = common.is_ip_or_dns(server_ip)
|
||||||
|
elif isinstance(server_ip, int):
|
||||||
|
server = server_sql.get_server_by_id(server_ip)
|
||||||
|
server_ip = server.ip
|
||||||
return add_mod.get_ssl_certs(server_ip)
|
return add_mod.get_ssl_certs(server_ip)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ def before_request():
|
||||||
|
|
||||||
@bp.route('/<service>/show', methods=['POST'])
|
@bp.route('/<service>/show', methods=['POST'])
|
||||||
@check_services
|
@check_services
|
||||||
|
@get_user_params()
|
||||||
def show_config(service):
|
def show_config(service):
|
||||||
config_file_name = request.json.get('config_file_name')
|
config_file_name = request.json.get('config_file_name')
|
||||||
configver = request.json.get('configver')
|
configver = request.json.get('configver')
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# BEGIN Roxy-WI MANAGED global do not edit it directly
|
||||||
global
|
global
|
||||||
log 127.0.0.2 local0
|
log 127.0.0.2 local0
|
||||||
log 127.0.0.1 local1 notice
|
log 127.0.0.1 local1 notice
|
||||||
|
@ -11,7 +12,9 @@ global
|
||||||
stats socket *:{{SOCK_PORT}} level admin
|
stats socket *:{{SOCK_PORT}} level admin
|
||||||
stats socket /var/run/haproxy.sock mode 600 level admin
|
stats socket /var/run/haproxy.sock mode 600 level admin
|
||||||
server-state-file {{STAT_FILE}}
|
server-state-file {{STAT_FILE}}
|
||||||
|
# END Roxy-WI MANAGED global do not edit it directly
|
||||||
|
|
||||||
|
# BEGIN Roxy-WI MANAGED defaults do not edit it directly
|
||||||
defaults
|
defaults
|
||||||
mode http
|
mode http
|
||||||
log global
|
log global
|
||||||
|
@ -29,7 +32,9 @@ defaults
|
||||||
timeout http-keep-alive 10s
|
timeout http-keep-alive 10s
|
||||||
timeout check 10s
|
timeout check 10s
|
||||||
maxconn 3000
|
maxconn 3000
|
||||||
|
# END Roxy-WI MANAGED defaults do not edit it directly
|
||||||
|
|
||||||
|
# BEGIN Roxy-WI MANAGED listen stats do not edit it directly
|
||||||
listen stats
|
listen stats
|
||||||
bind *:{{STAT_PORT}}
|
bind *:{{STAT_PORT}}
|
||||||
http-request use-service prometheus-exporter if { path /metrics }
|
http-request use-service prometheus-exporter if { path /metrics }
|
||||||
|
@ -38,6 +43,7 @@ listen stats
|
||||||
stats realm HAProxy-04\ Statistics
|
stats realm HAProxy-04\ Statistics
|
||||||
stats auth {{STATS_USER}}:{{STATS_PASS}}
|
stats auth {{STATS_USER}}:{{STATS_PASS}}
|
||||||
stats admin if TRUE
|
stats admin if TRUE
|
||||||
|
# END Roxy-WI MANAGED listen stats do not edit it directly
|
||||||
|
|
||||||
{% if M_OR_S != 'None' %}
|
{% if M_OR_S != 'None' %}
|
||||||
peers default_peers
|
peers default_peers
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
- name: Create HAProxy section
|
||||||
|
hosts: localhost
|
||||||
|
connection: local
|
||||||
|
become: yes
|
||||||
|
become_method: sudo
|
||||||
|
gather_facts: yes
|
||||||
|
roles:
|
||||||
|
- role: haproxy_section
|
|
@ -0,0 +1,37 @@
|
||||||
|
acl_if:
|
||||||
|
1: 'hdr_beg(host) -i'
|
||||||
|
2: 'hdr_end(host) -i'
|
||||||
|
3: 'path_beg -i'
|
||||||
|
4: 'path_end -i'
|
||||||
|
6: 'src ip'
|
||||||
|
acl_then:
|
||||||
|
2: 'http-request redirect location'
|
||||||
|
3: 'http-request allow'
|
||||||
|
4: 'http-request deny'
|
||||||
|
5: 'use_backend'
|
||||||
|
forward_for: 'option forwardfor if-none'
|
||||||
|
redispatch: 'option redispatch'
|
||||||
|
slow_attack: |
|
||||||
|
option http-buffer-request
|
||||||
|
timeout http-request 10s
|
||||||
|
ddos: |
|
||||||
|
# Start config for DDOS atack protect
|
||||||
|
stick-table type ip size 1m expire 1m store gpc0,http_req_rate(10s),http_err_rate(10s)
|
||||||
|
tcp-request connection track-sc1 src
|
||||||
|
tcp-request connection reject if { sc1_get_gpc0 gt 0 }
|
||||||
|
# Abuser means more than 100reqs/10s
|
||||||
|
ssl_offloading: |
|
||||||
|
http-request set-header X-Forwarded-Port %[dst_port]
|
||||||
|
http-request add-header X-Forwarded-Proto https if { ssl_fc }
|
||||||
|
redirect scheme https if !{ ssl_fc }
|
||||||
|
compression: |
|
||||||
|
compression algo gzip
|
||||||
|
compression type text/html text/plain text/css
|
||||||
|
antibot: |
|
||||||
|
# Start config for Antibot protection
|
||||||
|
http-request track-sc0 src table per_ip_rates
|
||||||
|
http-request track-sc1 url32+src table per_ip_and_url_rates unless { path_end .css .js .png .jpeg .gif }
|
||||||
|
acl exceeds_limit sc_gpc0_rate(0) gt 15
|
||||||
|
http-request sc-inc-gpc0(0) if { sc_http_req_rate(1) eq 1 } !exceeds_limit
|
||||||
|
http-request deny if exceeds_limit
|
||||||
|
# End config for Antibot
|
|
@ -0,0 +1,50 @@
|
||||||
|
- name: Create HAProxy section
|
||||||
|
blockinfile:
|
||||||
|
block: "{{ lookup('template', 'section.j2') }}"
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} {{ config.name }} do not edit it directly"
|
||||||
|
when: config.type in ('listen', 'frontend', 'backend') and action == 'create'
|
||||||
|
|
||||||
|
- name: Create Userlist
|
||||||
|
blockinfile:
|
||||||
|
block: "{{ lookup('template', 'userlist.j2') }}"
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} {{ config.name }} do not edit it directly"
|
||||||
|
when: config.type == 'userlist' and action == 'create'
|
||||||
|
|
||||||
|
- name: Create Peers
|
||||||
|
blockinfile:
|
||||||
|
block: "{{ lookup('template', 'peers.j2') }}"
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} {{ config.name }} do not edit it directly"
|
||||||
|
when: config.type == 'peers' and action == 'create'
|
||||||
|
|
||||||
|
- name: Create Global
|
||||||
|
blockinfile:
|
||||||
|
block: "{{ lookup('template', 'global.j2') }}"
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} do not edit it directly"
|
||||||
|
when: config.type == 'global' and action == 'create'
|
||||||
|
|
||||||
|
- name: Create Defaults
|
||||||
|
blockinfile:
|
||||||
|
block: "{{ lookup('template', 'defaults.j2') }}"
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} do not edit it directly"
|
||||||
|
when: config.type == 'defaults' and action == 'create'
|
||||||
|
|
||||||
|
- name: Delete section
|
||||||
|
blockinfile:
|
||||||
|
block: ""
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} {{ config.name }} do not edit it directly"
|
||||||
|
when: action == 'delete' and config.name
|
||||||
|
|
||||||
|
- name: Delete Global or Defaults
|
||||||
|
blockinfile:
|
||||||
|
block: ""
|
||||||
|
dest: "{{ cfg }}"
|
||||||
|
marker: "# {mark} Roxy-WI MANAGED {{ config.type }} do not edit it directly"
|
||||||
|
when:
|
||||||
|
- action == 'delete'
|
||||||
|
- config.type == 'global' or config.type == 'defaults
|
|
@ -0,0 +1,16 @@
|
||||||
|
defaults
|
||||||
|
log {{ config.log }}
|
||||||
|
retries {{ config.retries }}
|
||||||
|
maxconn {{ config.maxconn }}
|
||||||
|
|
||||||
|
{% if config.timeout != '' -%}
|
||||||
|
{% for key, value in config.timeout.items() -%}
|
||||||
|
timeout {{ key.replace('_', '-') }} {{ value }}s
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if config.option != '' -%}
|
||||||
|
{% for o in config.option.split('\\r\\n') -%}
|
||||||
|
{{ o }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif -%}
|
|
@ -0,0 +1,28 @@
|
||||||
|
global
|
||||||
|
{% if config.log != '' -%}
|
||||||
|
{% for log in config.log -%}
|
||||||
|
log {{ log }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
chroot {{ config.chroot }}
|
||||||
|
pidfile {{ config.pidfile }}
|
||||||
|
maxconn {{ config.maxconn }}
|
||||||
|
user {{ config.user }}
|
||||||
|
group {{ config.group }}
|
||||||
|
|
||||||
|
{% if config.daemon -%}
|
||||||
|
daemon
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.socket != '' -%}
|
||||||
|
{% for o in config.socket -%}
|
||||||
|
stats socket {{ o }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.option != '' -%}
|
||||||
|
{% for o in config.option.split('\\r\\n') -%}
|
||||||
|
{{ o }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif -%}
|
|
@ -0,0 +1,5 @@
|
||||||
|
peers {{ config.name }}
|
||||||
|
{% for peer in config.peers -%}
|
||||||
|
peer {{ peer.name }} {{ peer.ip }}:{{ peer.port }}
|
||||||
|
|
||||||
|
{% endfor -%}
|
|
@ -0,0 +1,148 @@
|
||||||
|
{{ config.type }} {{ config.name }}
|
||||||
|
{% for bind in config.binds -%}
|
||||||
|
bind {{ bind.ip }}:{{ bind.port }} {% if config.ssl != 'None' and config.mode == 'http' and config.ssl.cert %} ssl crt {{cert_path}}/{{ config.ssl.cert }}{% endif %}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
mode {{ config.mode }}
|
||||||
|
{% if config.balance != 'None' -%}
|
||||||
|
balance {{ config.balance }}
|
||||||
|
{% endif -%}
|
||||||
|
maxconn {{ config.maxconn }}
|
||||||
|
|
||||||
|
{% if config.health_check != 'None' -%}
|
||||||
|
{% if config.health_check.check == 'httpchk' and config.health_check.domain -%}
|
||||||
|
option {{ config.health_check.check }} GET {{ config.health_check.path }} "HTTP/1.0\\r\\nHost: {{ config.health_check.domain }}
|
||||||
|
{% else -%}
|
||||||
|
option {{ config.health_check.check }}
|
||||||
|
{% endif -%}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if config.headers != 'None' -%}
|
||||||
|
{%- for header in config.headers -%}
|
||||||
|
{{ header.path }} {{ header.method }} {{ header.name }} {{ header.value }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if config.whitelist -%}
|
||||||
|
acl white_list_{{ whitelist }} src -f {{ haproxy_dir }}/white/{{ config.whitelist }}
|
||||||
|
tcp-request content accept if white_list_{{ whitelist }}
|
||||||
|
tcp-request content reject
|
||||||
|
{% endif %}
|
||||||
|
{% if config.blacklist -%}
|
||||||
|
tcp-request connection reject if { src -f {{ haproxy_dir }}/white/{{ config.blacklist }} }
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if config.acls -%}
|
||||||
|
{% for acl in config.acls -%}
|
||||||
|
{% if acl.acl_if in (1, 2) -%}
|
||||||
|
{% if config.mode == 'tcp' -%}
|
||||||
|
{% set acl_then_hdr = 'ssl_fc_sni -i' -%}
|
||||||
|
{% elif config.mode == 'http' and config.ssl == 'None' -%}
|
||||||
|
{% set acl_then_hdr = 'hdr_beg(host) -i' -%}
|
||||||
|
{% else -%}
|
||||||
|
{% set acl_then_hdr = 'ssl_fc_sni -i' -%}
|
||||||
|
{% endif %}
|
||||||
|
{{ acl_then[acl.acl_then] }} {{ acl.acl_then_value }} if { {{ acl_then_hdr }} {{ acl.acl_value }} }
|
||||||
|
{% elif acl.acl_if in (3, 4, 5) -%}
|
||||||
|
{{ acl_then[acl.acl_then] }} {{ acl.acl_then_value }} if { {{ acl_if[acl.acl_if] }} {{ acl.acl_value }} }
|
||||||
|
{% elif acl.acl_if == 6 -%}
|
||||||
|
acl return_{{ acl.acl_value }} {{ acl_if[acl.acl_if] }} {{ acl.acl_value }}
|
||||||
|
http-request return if return_{{ acl.acl_value }}
|
||||||
|
{% elif acl.acl_if == 7 -%}
|
||||||
|
acl set_header_{{ acl.acl_value }} {{ acl_if[acl.acl_if] }} {{ acl.acl_value }}
|
||||||
|
http-request set_header_ if set_header_{{ acl.acl_value }}
|
||||||
|
{% endif -%}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
|
||||||
|
{% if config.slow_attack -%}
|
||||||
|
{{ slow_attack }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if config.forward_for -%}
|
||||||
|
{{ forward_for }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if config.redispatch -%}
|
||||||
|
{{ redispatch }}
|
||||||
|
{% endif -%}
|
||||||
|
{% if config.ssl_offloading -%}
|
||||||
|
{{ ssl_offloading }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.ddos -%}
|
||||||
|
{{ ddos }}
|
||||||
|
acl abuse sc1_http_req_rate({{ config.name }}) ge 100
|
||||||
|
acl flag_abuser sc1_inc_gpc0({{ config.name }})
|
||||||
|
tcp-request content reject if abuse flag_abuser
|
||||||
|
# End config for DDOS
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.waf -%}
|
||||||
|
filter spoe engine modsecurity config {{ haproxy_dir }}/waf.conf
|
||||||
|
http-request deny if { var(txn.modsec.code) -m int gt 0 }
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.compression -%}
|
||||||
|
{{ compression }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.antibot -%}
|
||||||
|
{{ antibot }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.cookie != 'None' -%}
|
||||||
|
cookie {{ config.cookie.name }} {% if config.cookie.domain != 'None' %} {{ config.cookie.domain }}{% endif %} {{ config.cookie.rewrite }} {{ config.cookie.prefix }} {{ config.cookie.nocache }} {{ config.cookie.postonly }} {{ config.cookie.dynamic }}
|
||||||
|
{% if config.cookie.dynamicKey -%}
|
||||||
|
dynamic-cookie-key {{ config.cookie.dynamicKey }}
|
||||||
|
{% endif -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.ssl != 'None' and config.mode == 'http' -%}
|
||||||
|
{%- if config.ssl.ssl_check_backend -%}
|
||||||
|
{%- set ssl_check_option = 'ssl verify' -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set ssl_check_option = 'ssl verify none' -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{% else -%}
|
||||||
|
{%- set ssl_check_option = '' -%}
|
||||||
|
{% endif -%}
|
||||||
|
{% if config.servers_check != 'None' and config.servers_check.check_enabled -%}
|
||||||
|
{%- set check_option = ' check inter ' + config.servers_check.inter|string() + ' rise ' + config.servers_check.rise|string() + ' fall ' + config.servers_check.fall|string() %}
|
||||||
|
{% else -%}
|
||||||
|
{% if config.servers_check != 'None' and config.servers_check.check_enabled == 'None' -%}
|
||||||
|
{% set check_option = '' -%}
|
||||||
|
{% endif -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.option != '' -%}
|
||||||
|
{% for o in config.option.split('\\r\\n') -%}
|
||||||
|
{{ o }}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.cache -%}
|
||||||
|
http-request cache-use {{ config.name }}
|
||||||
|
http-response cache-store {{ config.name }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% if config.circuit_breaking != 'None' -%}
|
||||||
|
default-server observe {{ config.circuit_breaking.observe }} error-limit {{ config.circuit_breaking.error_limit }} on-error {{ config.circuit_breaking.on_error }}
|
||||||
|
{% endif -%}
|
||||||
|
|
||||||
|
{% for backend in config.backend_servers -%}
|
||||||
|
server {{ backend.server }} {{ backend.server }}:{{ backend.port }} port {{ backend.port_check }} {{ check_option }} {{ ssl_check_option }} maxconn {{ backend.maxconn }}{% if backend.send_proxy %} send-proxy{% endif %}{% if backend.backup %} backup {% endif %}
|
||||||
|
|
||||||
|
{% endfor -%}
|
||||||
|
|
||||||
|
{% if config.backends and config.backends != 'None' -%}
|
||||||
|
use_backend {{ config.backends }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{% if config.cache %}
|
||||||
|
cache {{ config.name }}
|
||||||
|
total-max-size 4
|
||||||
|
max-age 240
|
||||||
|
{% endif %}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
userlist {{ config.name }}
|
||||||
|
{% if config.userlist_groups -%}
|
||||||
|
{% for group in config.userlist_groups %}
|
||||||
|
group {{ group }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for user in config.userlist_users -%}
|
||||||
|
user {{ user.user }} insecure-password {{ user.password }}{% if user.group %} groups {{ user.group }}{% endif %}
|
||||||
|
|
||||||
|
{% endfor -%}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1055
app/static/js/add.js
1055
app/static/js/add.js
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,624 @@
|
||||||
|
function openSection(section) {
|
||||||
|
let section_type = section.split(' ')[0];
|
||||||
|
let section_name = section.split(' ')[1];
|
||||||
|
let url = '/add/haproxy/' + $('#serv').val() + '/section/' + section_type + '/' + section_name;
|
||||||
|
clearEditSection();
|
||||||
|
if (section === 'global' || section === 'defaults') {
|
||||||
|
url = '/add/haproxy/' + $('#serv').val() + '/section/' + section_type;
|
||||||
|
section_type = section;
|
||||||
|
section_name = section;
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
statusCode: {
|
||||||
|
404: function (xhr) {
|
||||||
|
window.open('/config/section/haproxy/' + $('#serv').val() + '/' + section, '_blank').focus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async: false,
|
||||||
|
success: function (data) {
|
||||||
|
$('.advance-show-button').click(function () {
|
||||||
|
$('.advance').fadeIn();
|
||||||
|
$('.advance-show-button').css('display', 'none');
|
||||||
|
$('.advance-hide-button').css('display', 'block');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
$('.advance-hide-button').click(function () {
|
||||||
|
$('.advance').fadeOut();
|
||||||
|
$('.advance-show-button').css('display', 'block');
|
||||||
|
$('.advance-hide-button').css('display', 'none');
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
let section_id = '#add-' + section_type;
|
||||||
|
$.getScript(awesome);
|
||||||
|
$('#edit-' + section_type).show();
|
||||||
|
$('#edit-' + section_type + ' caption').hide();
|
||||||
|
$('#' + section_type + '-add-buttons').hide();
|
||||||
|
let i = 0;
|
||||||
|
Object.keys(data.config).forEach(function (key) {
|
||||||
|
if ($(section_id + ' *[name="' + key + '"]').prop("tagName") === 'SELECT') {
|
||||||
|
$(section_id + ' select[name="' + key + '"]').val(data.config[key]).change();
|
||||||
|
} else if ($(section_id + ' *[name="' + key + '"]').prop("tagName") === 'TEXTAREA') {
|
||||||
|
$(section_id + ' select[name="' + key + '"]').val(data.config['option']).change();
|
||||||
|
} else {
|
||||||
|
if ($(section_id + ' *[name="' + key + '"]').prop('type') === 'checkbox') {
|
||||||
|
if (data.config[key]) {
|
||||||
|
$(section_id + ' input[name="' + key + '"]').prop("checked", true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(section_id + ' input[name="' + key + '"]').val(data.config[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (data.config.option) {
|
||||||
|
$(section_id + ' textarea[name="option"]').val(data.config.option);
|
||||||
|
}
|
||||||
|
if (section_type === 'global') {
|
||||||
|
if (data.config.daemon > 0) {
|
||||||
|
$('#global-daemon').prop("checked", true);
|
||||||
|
} else {
|
||||||
|
$('#global-daemon').prop("checked", false);
|
||||||
|
}
|
||||||
|
if (data.config.log) {
|
||||||
|
let logs = '';
|
||||||
|
for (let log of data.config.log) {
|
||||||
|
logs += log + '\n';
|
||||||
|
}
|
||||||
|
$(section_id + ' textarea[name="log"]').val(logs);
|
||||||
|
}
|
||||||
|
if (data.config.socket) {
|
||||||
|
let sockets = '';
|
||||||
|
for (let socket of data.config.socket) {
|
||||||
|
sockets += socket + '\n';
|
||||||
|
}
|
||||||
|
$(section_id + ' textarea[name="socket"]').val(sockets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section_type === 'defaults') {
|
||||||
|
if (data.config.timeout) {
|
||||||
|
Object.keys(data.config.timeout).forEach(function (key) {
|
||||||
|
$(section_id + ' input[name="'+key+'"]').val(data.config.timeout[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section_type === 'listen' || section_type === 'frontend') {
|
||||||
|
if (data.config.binds.length > 0) {
|
||||||
|
for (let i = 1; i < data.config.binds.length; i++) {
|
||||||
|
make_actions_for_adding_bind('#' + section_type + '_bind');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let bind of data.config.binds) {
|
||||||
|
$(section_id + ' input[name="ip"]').get(i).value = bind.ip;
|
||||||
|
$(section_id + ' input[name="port"]').get(i).value = bind.port;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section_type === 'listen' || section_type === 'backend') {
|
||||||
|
if (data.config.backend_servers) {
|
||||||
|
if (data.config.backend_servers.length > 3) {
|
||||||
|
for (let i = 2; i < data.config.backend_servers.length; i++) {
|
||||||
|
$("[name=add_servers]").append(add_server_var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let serv_ports = $('.send_proxy');
|
||||||
|
for (let i = 0; i <= serv_ports.length; i++) {
|
||||||
|
var uniqId = makeid(3);
|
||||||
|
$(serv_ports[i]).append('<label for="' + uniqId + '" class="send_proxy_label" title="Set send-proxy for this server" data-help="The Send-proxy parameter enforces the use of the PROXY protocol over any connection established to this server. The PROXY protocol informs the other end about the layer 3/4 addresses of the incoming connection so that it can know the client\'s address or the public address it accessed to, whatever the upper-layer protocol.">send-proxy</label><input type="checkbox" name="send_proxy" value="1" id="' + uniqId + '">');
|
||||||
|
var uniqId = makeid(3);
|
||||||
|
$(serv_ports[i]).append('<label for="' + uniqId + '" class="send_proxy_label" title="Set this server as backup server" data-help="When all servers in a farm are down, we want to redirect traffic to a backup server which delivers either sorry pages or a degraded mode of the application.\n' +
|
||||||
|
'This can be done easily in HAProxy by adding the keyword backup on the server line. If multiple backup servers are configured, only the first active one is used.">backup</label><input type="checkbox" name="backup" value="1" id="' + uniqId + '">');
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
if (data.config.backend_servers.length > 0) {
|
||||||
|
for (let bind of data.config.backend_servers) {
|
||||||
|
$(section_id + ' input[name="servers"]').get(i).value = bind.server;
|
||||||
|
$(section_id + ' input[name="server_port"]').get(i).value = bind.port;
|
||||||
|
$(section_id + ' input[name="port_check"]').get(i).value = bind.port_check;
|
||||||
|
$(section_id + ' input[name="server_maxconn"]').get(i).value = bind.maxconn;
|
||||||
|
if (bind.send_proxy) {
|
||||||
|
let check_id = $(section_id + ' input[name="send_proxy"]').get(i).id;
|
||||||
|
$('#' + check_id).prop("checked", true);
|
||||||
|
}
|
||||||
|
if (bind.backup) {
|
||||||
|
let backup_id = $(section_id + ' input[name="backup"]').get(i).id;
|
||||||
|
$('#' + backup_id).prop("checked", true);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section_type === 'listen' || section_type === 'frontend' || section_type === 'backend') {
|
||||||
|
$("#options-" + section_type + "-show").click(function () {
|
||||||
|
if ($("#options-" + section_type + "-show").is(':checked')) {
|
||||||
|
$("#options-" + section_type + "-show-div").show("fast");
|
||||||
|
} else {
|
||||||
|
$("#options-" + section_type + "-show-div").hide("fast");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (data.config.headers) {
|
||||||
|
if (data.config.headers.length > 0) {
|
||||||
|
i = 0;
|
||||||
|
$("#add_" + section_type + "_header").on("click", function () {
|
||||||
|
$("#" + section_type + "_header_div").show();
|
||||||
|
$("#" + section_type + "_add_header").show();
|
||||||
|
$("#add_" + section_type + "_header").hide();
|
||||||
|
});
|
||||||
|
$('#add_' + section_type + '_header').trigger('click');
|
||||||
|
for (let header of data.config.headers) {
|
||||||
|
make_actions_for_adding_header('#' + section_type + '_header_div')
|
||||||
|
let headers_res_id = $(section_id + ' select[name="headers_res"]').get(i).id;
|
||||||
|
$('#' + headers_res_id).val(header.path).change();
|
||||||
|
let headers_method_id = $(section_id + ' select[name="headers_method"]').get(i).id;
|
||||||
|
$('#' + headers_method_id).val(header.method).change();
|
||||||
|
$(section_id + ' input[name="header_name"]').get(i).value = header.name;
|
||||||
|
$(section_id + ' input[name="header_value"]').get(i).value = header.value;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.config.option) {
|
||||||
|
$("#options-" + section_type + "-show").trigger('click');
|
||||||
|
}
|
||||||
|
if (data.config.acls) {
|
||||||
|
if (data.config.acls.length > 0) {
|
||||||
|
i = 0;
|
||||||
|
$("#add_" + section_type + "_acl").on("click", function () {
|
||||||
|
$("#" + section_type + "_acl").show();
|
||||||
|
$("#" + section_type + "_add_acl").show();
|
||||||
|
$("#add_" + section_type + "_acl").hide();
|
||||||
|
});
|
||||||
|
$("#add_" + section_type + "_acl").trigger('click');
|
||||||
|
for (let acl of data.config.acls) {
|
||||||
|
make_actions_for_adding_acl_rule('#' + section_type + '_acl');
|
||||||
|
let acl_if_id = $(section_id + ' select[name="acl_if"]').get(i).id;
|
||||||
|
$('#' + acl_if_id).val(acl.acl_if).change();
|
||||||
|
let acl_then_id = $(section_id + ' select[name="acl_then"]').get(i).id;
|
||||||
|
$('#' + acl_then_id).val(acl.acl_then).change();
|
||||||
|
$(section_id + ' input[name="acl_value"]').get(i).value = acl.acl_value;
|
||||||
|
$(section_id + ' input[name="acl_then_value"]').get(i).value = acl.acl_then_value;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section_type === 'userlist') {
|
||||||
|
if (data.config.userlist_groups.length > 0) {
|
||||||
|
i = 0;
|
||||||
|
for (let c of data.config.userlist_groups) {
|
||||||
|
$(section_id + ' input[name="userlist-group"]').get(i).value = c;
|
||||||
|
$('#userlist-groups').append(add_userlist_group_var);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.config.userlist_users.length > 0) {
|
||||||
|
i = 0;
|
||||||
|
for (let c of data.config.userlist_users) {
|
||||||
|
$(section_id + ' input[name="userlist-user"]').get(i).value = c.user;
|
||||||
|
$(section_id + ' input[name="userlist-password"]').get(i).value = c.password;
|
||||||
|
$(section_id + ' input[name="userlist-user-group"]').get(i).value = c.group;
|
||||||
|
$('#userlist-users').append(add_userlist_var);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section_type === 'peers') {
|
||||||
|
$('[name=add-peer-input]').click(function () {
|
||||||
|
$("[name=add_peers]").append(add_peer_var);
|
||||||
|
});
|
||||||
|
if (data.config.peers.length > 0) {
|
||||||
|
i = 0;
|
||||||
|
for (let c of data.config.peers) {
|
||||||
|
$(section_id + ' input[name="servers_name"]').get(i).value = c.name;
|
||||||
|
$(section_id + ' input[name="servers"]').get(i).value = c.ip;
|
||||||
|
$(section_id + ' input[name="server_port"]').get(i).value = c.port;
|
||||||
|
i++;
|
||||||
|
if (i > 1) {
|
||||||
|
$("[name=add_peers]").append(add_peer_var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$("select").selectmenu();
|
||||||
|
$("select").selectmenu('refresh');
|
||||||
|
$("input[type=checkbox]").checkboxradio();
|
||||||
|
$("input[type=checkbox]").checkboxradio('refresh');
|
||||||
|
$(section_id + ' select[name="server"]').val(data.server_id).change();
|
||||||
|
$(section_id + ' select[name="server"]').selectmenu('disable').parent().parent().hide();
|
||||||
|
$(section_id + ' input[name="name"]').prop("readonly", true).parent().parent().hide();
|
||||||
|
$("#edit-section").dialog({
|
||||||
|
resizable: false,
|
||||||
|
height: "auto",
|
||||||
|
width: 1100,
|
||||||
|
modal: true,
|
||||||
|
title: edit_word,
|
||||||
|
close: function () {
|
||||||
|
$('#edit-' + section_type).hide();
|
||||||
|
},
|
||||||
|
buttons: [{
|
||||||
|
text: edit_word,
|
||||||
|
click: function () {
|
||||||
|
editProxy('add-' + section_type, $(this));
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: delete_word,
|
||||||
|
click: function () {
|
||||||
|
delete_section(section_type, section_name, $('#serv').val());
|
||||||
|
$(this).dialog("close");
|
||||||
|
$('#edit-' + section_type).hide();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: cancel_word,
|
||||||
|
click: function () {
|
||||||
|
$(this).dialog("close");
|
||||||
|
$('#edit-' + section_type).hide();
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function delete_section(section_type, section_name, server_id) {
|
||||||
|
$.ajax({
|
||||||
|
url: '/add/haproxy/' + server_id + '/section/' + section_type + '/' + section_name,
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
method: "DELETE",
|
||||||
|
statusCode: {
|
||||||
|
204: function (xhr) {
|
||||||
|
showConfig();
|
||||||
|
},
|
||||||
|
404: function (xhr) {
|
||||||
|
showConfig();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
if (data) {
|
||||||
|
if (data.status === "failed") {
|
||||||
|
toastr.error(data.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function clearEditSection() {
|
||||||
|
$('#edit-section').empty();
|
||||||
|
$.ajax({
|
||||||
|
url: "/add/haproxy/get_section_html",
|
||||||
|
method: "GET",
|
||||||
|
async: false,
|
||||||
|
success: function(data) {
|
||||||
|
$('#edit-section').html(data);
|
||||||
|
$.getScript('/static/js/add.js');
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function addProxy(form_name, generate=false) {
|
||||||
|
let frm = $('#'+form_name);
|
||||||
|
let serv = '';
|
||||||
|
let name_id = '';
|
||||||
|
if (form_name === 'add-listen') {
|
||||||
|
serv = '#serv'
|
||||||
|
name_id = '#listener'
|
||||||
|
} else if (form_name === 'add-frontend') {
|
||||||
|
serv = '#serv2'
|
||||||
|
name_id = '#new_frontend'
|
||||||
|
} else if (form_name === 'add-backend') {
|
||||||
|
serv = '#serv3'
|
||||||
|
name_id = '#new_backend'
|
||||||
|
} else if (form_name === 'add-userlist') {
|
||||||
|
serv = '#userlist_serv'
|
||||||
|
name_id = '#new_userlist'
|
||||||
|
} else {
|
||||||
|
serv = '#peers_serv'
|
||||||
|
name_id = '#peers-name'
|
||||||
|
}
|
||||||
|
if(!checkIsServerFiled(serv)) return false;
|
||||||
|
if(!checkIsServerFiled(name_id, 'The name cannot be empty')) return false;
|
||||||
|
let json_data = getFormData(frm, form_name);
|
||||||
|
let section_type = form_name.split('-')[1]
|
||||||
|
let q_generate = '';
|
||||||
|
if (generate) {
|
||||||
|
q_generate = '?generate=1';
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: '/add/haproxy/' + $(serv).val() + '/section/' + section_type + q_generate,
|
||||||
|
data: JSON.stringify(json_data),
|
||||||
|
type: frm.attr('method'),
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
success: function( data ) {
|
||||||
|
if (data.status === 'failed') {
|
||||||
|
toastr.error(data.error)
|
||||||
|
} else if (data === '') {
|
||||||
|
toastr.clear();
|
||||||
|
toastr.error('error: Something went wrong. Check configuration');
|
||||||
|
} else {
|
||||||
|
if (generate) {
|
||||||
|
$('#dialog-confirm-body').text(data.data);
|
||||||
|
let generated_title = translate_div.attr('data-generated_config');
|
||||||
|
$("#dialog-confirm-cert").dialog({
|
||||||
|
resizable: false,
|
||||||
|
height: "auto",
|
||||||
|
width: 650,
|
||||||
|
modal: true,
|
||||||
|
title: generated_title,
|
||||||
|
buttons: {
|
||||||
|
Ok: function () {
|
||||||
|
$(this).dialog("close");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toastr.clear();
|
||||||
|
data.data = data.data.replace(/\n/g, "<br>");
|
||||||
|
if (returnNiceCheckingConfig(data.data) === 0) {
|
||||||
|
toastr.info('Section has been added. Do not forget to restart the server');
|
||||||
|
let ip = frm.find('select[name=serv]').val();
|
||||||
|
localStorage.setItem('restart', ip);
|
||||||
|
resetProxySettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function editProxy(form_name, dialog_id, generate=false) {
|
||||||
|
let frm = $('#'+form_name);
|
||||||
|
let name_id = '#' +form_name + ' input[name="name"]';
|
||||||
|
if(!checkIsServerFiled(name_id, 'The name cannot be empty')) return false;
|
||||||
|
let json_data = getFormData(frm, form_name);
|
||||||
|
let section_type = form_name.split('-')[1]
|
||||||
|
let url = '/add/haproxy/' + $('#serv').val() + '/section/' + section_type + '/' + $(name_id).val();
|
||||||
|
if (section_type === 'defaults' || section_type === 'global') {
|
||||||
|
url = '/add/haproxy/' + $('#serv').val() + '/section/' + section_type;
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
data: JSON.stringify(json_data),
|
||||||
|
type: 'PUT',
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
success: function( data ) {
|
||||||
|
if (data.status === 'failed') {
|
||||||
|
toastr.error(data.error)
|
||||||
|
} else if (data === '') {
|
||||||
|
toastr.clear();
|
||||||
|
toastr.error('error: Something went wrong. Check configuration');
|
||||||
|
} else {
|
||||||
|
toastr.clear();
|
||||||
|
data.data = data.data.replace(/\n/g, "<br>");
|
||||||
|
if (returnNiceCheckingConfig(data.data) === 0) {
|
||||||
|
toastr.info('Section has been updated. Do not forget to restart the server');
|
||||||
|
let ip = frm.find('select[name=serv]').val();
|
||||||
|
localStorage.setItem('restart', ip);
|
||||||
|
showConfig();
|
||||||
|
$(dialog_id).dialog( "close" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function getFormData($form, form_name) {
|
||||||
|
let section_type = form_name.split('-')[1]
|
||||||
|
let unindexed_array = $form.serializeArray();
|
||||||
|
let indexed_array = {};
|
||||||
|
indexed_array['acls'] = [];
|
||||||
|
indexed_array['binds'] = [];
|
||||||
|
indexed_array['headers'] = [];
|
||||||
|
indexed_array['backend_servers'] = [];
|
||||||
|
indexed_array['type'] = section_type;
|
||||||
|
indexed_array['userlist_users'] = [];
|
||||||
|
indexed_array['userlist_groups'] = [];
|
||||||
|
indexed_array['peers'] = [];
|
||||||
|
indexed_array['daemon'] = 0;
|
||||||
|
|
||||||
|
$.map(unindexed_array, function (n, i) {
|
||||||
|
if (n['name'] === 'cookie') {
|
||||||
|
if ($('input[name="cookie"]').is(':checked')) {
|
||||||
|
let name = $('input[name="cookie_name"]').val();
|
||||||
|
let domain = $('input[name="cookie_domain"]').val();
|
||||||
|
let dynamic = $('input[name="dynamic"]').val();
|
||||||
|
let dynamicKey = $('input[name="dynamic-cookie-key"]').val();
|
||||||
|
let nocache = $('input[name="nocache"]').val();
|
||||||
|
let postonly = $('input[name="postonly"]').val();
|
||||||
|
let rewrite = $('select[name="rewrite"] option:selected').val();
|
||||||
|
let prefix = $('input[name="prefix"]').val();
|
||||||
|
indexed_array['cookie'] = {name, domain, dynamic, dynamicKey, nocache, postonly, rewrite, prefix}
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'whitelist_checkbox') {
|
||||||
|
if ($('input[name="whitelist_checkbox"]').is(':checked')) {
|
||||||
|
indexed_array['whitelist'] = $('input[name="whitelist"]').val();
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'ssl') {
|
||||||
|
if ($('input[name="ssl"]').is(':checked')) {
|
||||||
|
let cert = $('input[name="cert"]').val();
|
||||||
|
let ssl_check_backend = 1;
|
||||||
|
if ($('input[name="ssl-check"]').is(':checked')) {
|
||||||
|
ssl_check_backend = 0;
|
||||||
|
} else {
|
||||||
|
ssl_check_backend = 1;
|
||||||
|
}
|
||||||
|
indexed_array['ssl'] = {cert, ssl_check_backend};
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'health_check') {
|
||||||
|
let check = n['value'];
|
||||||
|
if (check === undefined || check === '' || check === '-------') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let path = $('input[name="checks_http_path"]').val();
|
||||||
|
let domain = $('input[name="checks_http_domain"]').val();
|
||||||
|
indexed_array['health_check'] = {check, path, domain}
|
||||||
|
} else if (n['name'] === 'blacklist_checkbox') {
|
||||||
|
if ($('input[name="blacklist_checkbox"]').is(':checked')) {
|
||||||
|
indexed_array['blacklist'] = $('input[name="blacklist"]').val();
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'ssl_offloading') {
|
||||||
|
if ($('input[name="ssl_offloading"]').is(':checked')) {
|
||||||
|
indexed_array['ssl_offloading'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'forward_for') {
|
||||||
|
if ($('input[name="forward_for"]').is(':checked')) {
|
||||||
|
indexed_array['forward_for'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'redispatch') {
|
||||||
|
if ($('input[name="redispatch"]').is(':checked')) {
|
||||||
|
indexed_array['redispatch'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'slow_attack') {
|
||||||
|
if ($('input[name="slow_attack"]').is(':checked')) {
|
||||||
|
indexed_array['slow_attack'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'ddos') {
|
||||||
|
if ($('input[name="ddos"]').is(':checked')) {
|
||||||
|
indexed_array['ddos'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'antibot') {
|
||||||
|
if ($('input[name="antibot"]').is(':checked')) {
|
||||||
|
indexed_array['antibot'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'cache') {
|
||||||
|
if ($('input[name="cache"]').is(':checked')) {
|
||||||
|
indexed_array['cache'] = 1;
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'circuit_breaking') {
|
||||||
|
if ($('input[name="circuit_breaking"]').is(':checked')) {
|
||||||
|
let observe = $('select[name="circuit_breaking_observe"] option:selected').val();
|
||||||
|
let error_limit = $('input[name="circuit_breaking_error_limit"]').val();
|
||||||
|
let on_error = $('select[name="circuit_breaking_on_error"] option:selected').val();
|
||||||
|
indexed_array['circuit_breaking'] = {observe, error_limit, on_error};
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'check-servers') {
|
||||||
|
if ($('input[name="check-servers"]').is(':checked')) {
|
||||||
|
let check_enabled = 1;
|
||||||
|
let inter = $('select[name="inter"] option:selected').val();
|
||||||
|
let rise = $('select[name="rise"] option:selected').val();
|
||||||
|
let fall = $('select[name="fall"] option:selected').val();
|
||||||
|
indexed_array['servers_check'] = {check_enabled, inter, rise, fall};
|
||||||
|
} else {
|
||||||
|
let check_enabled = 0;
|
||||||
|
indexed_array['servers_check'] = {check_enabled}
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'template') {
|
||||||
|
if ($('input[name="template"]').is(':checked')) {
|
||||||
|
let prefix = $('input[name="template-prefix"]').val();
|
||||||
|
let count = $('input[name="template-number"]').val();
|
||||||
|
let servers = $('input[name="servers"]').val();
|
||||||
|
let port = $('input[name="server_port"]').val();
|
||||||
|
indexed_array['servers_template'] = {prefix, count, servers, port};
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'log' && section_type === 'global') {
|
||||||
|
indexed_array['log'] = [];
|
||||||
|
for (let l of n['value'].split('\r\n')) {
|
||||||
|
if (l != '') {
|
||||||
|
indexed_array['log'].push(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'socket') {
|
||||||
|
indexed_array['socket'] = [];
|
||||||
|
for (let l of n['value'].split('\r\n')) {
|
||||||
|
if (l != '') {
|
||||||
|
indexed_array['socket'].push(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (n['name'] === 'daemon') {
|
||||||
|
if ($('input[name="daemon"]').is(':checked')) {
|
||||||
|
indexed_array['daemon'] = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
indexed_array[n['name']] = n['value'];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#' +section_type+ '_acl p').each(function () {
|
||||||
|
let acl_if = $(this).children().children("select[name='acl_if'] option:selected").val();
|
||||||
|
if (acl_if === undefined || acl_if === '' || acl_if === "Select if") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let acl_value = $(this).children("input[name='acl_value']").val();
|
||||||
|
let acl_then = $(this).children().children("select[name='acl_then'] option:selected").val();
|
||||||
|
let acl_then_value = $(this).children("input[name='acl_then_value']").val();
|
||||||
|
indexed_array['acls'].push({acl_if, acl_value, acl_then, acl_then_value});
|
||||||
|
});
|
||||||
|
$('#' +section_type+ '_bind p').each(function () {
|
||||||
|
let ip = $(this).children("input[name='ip']").val();
|
||||||
|
let port = $(this).children("input[name='port']").val();
|
||||||
|
if (port === undefined || port === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
indexed_array['binds'].push({ip, port});
|
||||||
|
});
|
||||||
|
$('#' +section_type+ '_header_div p').each(function () {
|
||||||
|
let path = $(this).children().children("select[name='headers_res'] option:selected").val();
|
||||||
|
let method = $(this).children().children("select[name='headers_method'] option:selected").val();
|
||||||
|
let name = $(this).children("input[name='header_name']").val();
|
||||||
|
let value = $(this).children("input[name='header_value']").val();
|
||||||
|
if (path === undefined || path === '' || path === '------') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (name === undefined || name === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
indexed_array['headers'].push({path, method, name, value});
|
||||||
|
});
|
||||||
|
$('#userlist-groups p').each(function (){
|
||||||
|
let group = $(this).children("input[name='userlist-group']").val();
|
||||||
|
if (group === undefined || group === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
indexed_array['userlist_groups'].push(group);
|
||||||
|
});
|
||||||
|
$('#userlist-users p').each(function (){
|
||||||
|
let user = $(this).children("input[name='userlist-user']").val();
|
||||||
|
let password = $(this).children("input[name='userlist-password']").val();
|
||||||
|
let group = $(this).children("input[name='userlist-user-group']").val();
|
||||||
|
if (user === undefined || user === '' || password === undefined || password === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
indexed_array['userlist_users'].push({user, password, group});
|
||||||
|
});
|
||||||
|
$('#add_peers p').each(function (){
|
||||||
|
let name = $(this).children("input[name='servers_name']").val();
|
||||||
|
let ip = $(this).children("input[name='servers']").val();
|
||||||
|
let port = $(this).children("input[name='server_port']").val();
|
||||||
|
if (name === undefined || name === '' || ip === undefined || ip === '' || port === undefined || port === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
indexed_array['peers'].push({name, ip, port});
|
||||||
|
});
|
||||||
|
$('#'+form_name+' span[name="add_servers"] p').each(function (){
|
||||||
|
let server = $(this).children("input[name='servers']").val();
|
||||||
|
if (server === undefined || server === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let port = $(this).children("input[name='server_port']").val();
|
||||||
|
let port_check = $(this).children("input[name='port_check']").val();
|
||||||
|
let maxconn = $(this).children("input[name='server_maxconn']").val();
|
||||||
|
let send_proxy = 0;
|
||||||
|
let backup = 0;
|
||||||
|
if ($(this).children().children('input[name="send_proxy"]').is(':checked')) {
|
||||||
|
send_proxy = 1;
|
||||||
|
}
|
||||||
|
if ($(this).children().children('input[name="backup"]').is(':checked')) {
|
||||||
|
backup = 1;
|
||||||
|
}
|
||||||
|
let test_var = {server, port, port_check, maxconn, send_proxy, backup};
|
||||||
|
indexed_array['backend_servers'].push(test_var);
|
||||||
|
});
|
||||||
|
if (section_type === 'defaults') {
|
||||||
|
indexed_array['timeout'] = {};
|
||||||
|
$("input[id^='defaults-timeout']").each(function (i, el) {
|
||||||
|
indexed_array['timeout'][el.name] = el.value;
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let elementsForDelete = ['acl_if', 'acl_value', 'acl_then', 'acl_then_value', 'servers', 'port', 'port_check',
|
||||||
|
'backup', 'send_proxy', 'server_port', 'ip', 'headers_method', 'headers_res', 'header_name', 'header_value', 'server_maxconn',
|
||||||
|
'options', 'options1', 'options2', 'cookie_domain', 'cookie_name', 'dynamic', 'dynamic-cookie-key', 'nocache', 'postonly',
|
||||||
|
'rewrite', 'prefix', 'saved-options', 'blacklist_checkbox', 'whitelist_checkbox', 'circuit_breaking_error_limit',
|
||||||
|
'circuit_breaking_observe', 'circuit_breaking_on_error', 'check-servers', 'checks_http_domain', 'checks_http_path',
|
||||||
|
'options-listen-show', 'cert', 'ssl-check', 'template', 'template-number', 'fall', 'inner', 'rise', 'template-prefix',
|
||||||
|
'saved-options1', 'userlist-group', 'userlist-password', 'userlist-user', 'userlist-user-group', 'servers_name',
|
||||||
|
'servers', 'server_port', 'serv', 'check', 'client', 'connect', 'queue', 'server', 'http_keep_alive', 'http_request']
|
||||||
|
for (let element of elementsForDelete) {
|
||||||
|
delete indexed_array[element]
|
||||||
|
}
|
||||||
|
return indexed_array;
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1152,6 +1152,7 @@ function returnNiceCheckingConfig(data) {
|
||||||
if (alert_error) {
|
if (alert_error) {
|
||||||
toastr.error(server_name + '<pre style="padding: 0; margin: 0;">' + alert_error + '</pre>');
|
toastr.error(server_name + '<pre style="padding: 0; margin: 0;">' + alert_error + '</pre>');
|
||||||
toastr.info('Config not applied');
|
toastr.info('Config not applied');
|
||||||
|
return 1;
|
||||||
} else if (alert_warning) {
|
} else if (alert_warning) {
|
||||||
toastr.warning(server_name + '<pre style="padding: 0; margin: 0;">' + alert_warning + '</pre>');
|
toastr.warning(server_name + '<pre style="padding: 0; margin: 0;">' + alert_warning + '</pre>');
|
||||||
toastr.success('<b>' + server_name + ' Configuration file is valid</b>');
|
toastr.success('<b>' + server_name + ' Configuration file is valid</b>');
|
||||||
|
@ -1165,6 +1166,7 @@ function returnNiceCheckingConfig(data) {
|
||||||
} else if (server_name2) {
|
} else if (server_name2) {
|
||||||
toastr.success('<b>' + server_name2 + ' Configuration file is valid</b>');
|
toastr.success('<b>' + server_name2 + ' Configuration file is valid</b>');
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
function show_version() {
|
function show_version() {
|
||||||
NProgress.configure({showSpinner: false});
|
NProgress.configure({showSpinner: false});
|
||||||
|
@ -1346,9 +1348,8 @@ function showPassword(input) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function removeData() {
|
function removeData() {
|
||||||
let chart;
|
|
||||||
for (let i = 0; i < charts.length; i++) {
|
for (let i = 0; i < charts.length; i++) {
|
||||||
chart = charts[i];
|
let chart = charts[i];
|
||||||
chart.destroy();
|
chart.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,3 +27,14 @@ const csrf_token = Cookies.get('csrf_access_token');
|
||||||
|
|
||||||
// API prefix
|
// API prefix
|
||||||
const api_prefix = '/api'
|
const api_prefix = '/api'
|
||||||
|
|
||||||
|
// Add page
|
||||||
|
const add_server_var = '<br /><input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server" style="margin: 2px 0 4px 0;">: ' +
|
||||||
|
'<input name="server_port" required title="Backend port" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number"> ' +
|
||||||
|
'Port check: <input name="port_check" required title="Maxconn. Default 200" size=5 value="200" class="form-control add_server_number" type="number">' +
|
||||||
|
' maxconn: <input name="server_maxconn" required title="Maxconn. Default 200" size=5 value="200" class="form-control add_server_number" type="number">'
|
||||||
|
const add_userlist_group_var = '<p><input name="userlist-group" title="User`s group" placeholder="group_name" class="form-control"></p>'
|
||||||
|
const add_userlist_var = '<p><input name="userlist-user" title="User name" placeholder="user_name" class="form-control"> <input name="userlist-password" required title="User password. By default it insecure-password" placeholder="password" class="form-control"> <input name="userlist-user-group" title="User`s group" placeholder="user`s group" class="form-control"></p>'
|
||||||
|
const add_peer_var = '<p><input name="servers_name" required title="Peer name" size=14 placeholder="haproxyN" class="form-control">: ' +
|
||||||
|
'<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server">: ' +
|
||||||
|
'<input name="server_port" required title="Backend port" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number"></p>'
|
||||||
|
|
|
@ -3,22 +3,19 @@
|
||||||
{% block h2 %}{{lang.menu_links.add_proxy.title}}{% endblock %}
|
{% block h2 %}{{lang.menu_links.add_proxy.title}}{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% from 'include/input_macros.html' import input, checkbox, select %}
|
{% from 'include/input_macros.html' import input, checkbox, select %}
|
||||||
{% set balance_params = dict() %}
|
|
||||||
{% set balance_params = {'roundrobin':'roundrobin','source':'source','leastconn':'leastconn','first':'first',
|
{% set balance_params = {'roundrobin':'roundrobin','source':'source','leastconn':'leastconn','first':'first',
|
||||||
'rdp-cookie':'rdp-cookie', 'uri':'uri', 'uri whole':'uri whole', 'static-rr': 'static-rr',
|
'rdp-cookie':'rdp-cookie', 'uri':'uri', 'uri whole':'uri whole', 'static-rr': 'static-rr',
|
||||||
'url_param userid':'url_param userid'} %}
|
'url_param userid':'url_param userid'} %}
|
||||||
{% set checks = dict() %}
|
{% set checks = {'':'Choose a custom health check','tcp-check':'Check a TCP Port', 'ssl-hello-chk':'Check a SSL Port',
|
||||||
{% set checks = {'':'Choose a custom health check','option tcp-check':'Check a TCP Port',
|
'httpchk':'Check a HTTP service', 'ldap-check':'Check a LDAP service', 'mysql-check':'Check a MySql Service',
|
||||||
'option ssl-hello-chk':'Check a SSL Port','option httpchk':'Check a HTTP service',
|
'pgsql-check':'Check a PgSQL Service', 'redis-check': 'Check a Redis Service', 'smtpchk':'Check a SMTP service'} %}
|
||||||
'option ldap-check':'Check a LDAP service', 'option mysql-check':'Check a MySql Service',
|
|
||||||
'option pgsql-check':'Check a PgSQL Service', 'option redis-check': 'Check a Redis Service',
|
|
||||||
'option smtpchk':'Check a SMTP service'} %}
|
|
||||||
{% set observe = {'layer7':'layer7', 'layer4': 'layer4'} %}
|
{% set observe = {'layer7':'layer7', 'layer4': 'layer4'} %}
|
||||||
{% set on_error = {'mark-down':'mark-down', 'fastinter': 'fastinter', 'fail-check':'fail-check',
|
{% set on_error = {'mark-down':'mark-down', 'fastinter': 'fastinter', 'fail-check':'fail-check',
|
||||||
'sudden-death':'sudden-death'} %}
|
'sudden-death':'sudden-death'} %}
|
||||||
{% set header_res = {'http-response': 'response', 'http-request': 'request'} %}
|
{% set header_res = {'http-response': 'response', 'http-request': 'request'} %}
|
||||||
{% set header_params = {'add-header': 'add-header', 'set-header': 'set-header', 'del-header': 'del-header'} %}
|
{% set header_params = {'add-header': 'add-header', 'set-header': 'set-header', 'del-header': 'del-header'} %}
|
||||||
{% set if_values = {'1':'Host name starts with','2':'Host name ends with','3':'Path starts with','4':'Path ends with', '6': 'Src ip'} %}
|
{% set if_values = {'1':'Host name starts with','2':'Host name ends with','3':'Path starts with','4':'Path ends with', '6': 'Src ip'} %}
|
||||||
|
{% set force_close = {'0':'Off','1':'Server only','2':'Force close','3':'Pretend keep alive'} %}
|
||||||
|
|
||||||
<script src="/static/js/add.js"></script>
|
<script src="/static/js/add.js"></script>
|
||||||
<div id="tabs">
|
<div id="tabs">
|
||||||
|
@ -36,677 +33,21 @@
|
||||||
<li><a href="#maps" title="{{lang.words.add|title()}} {{lang.words.proxy}}: {{lang.words.create|title()}} {{lang.words.and}} {{lang.words.upload}} {{lang.words.maps}} - Roxy-WI">{{lang.words.maps|title()}}</a></li>
|
<li><a href="#maps" title="{{lang.words.add|title()}} {{lang.words.proxy}}: {{lang.words.create|title()}} {{lang.words.and}} {{lang.words.upload}} {{lang.words.maps}} - Roxy-WI">{{lang.words.maps|title()}}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul id='browse_histroy'></ul>
|
<ul id='browse_histroy'></ul>
|
||||||
{% include 'include/add_proxy.html' %}
|
{% include 'include/add/add_proxy.html' %}
|
||||||
<div id="listen">
|
<div id="listen">
|
||||||
<form name="add-listener" id="add-listener" action="/add/haproxy/add" method="post">
|
{% include 'include/add/listen.html' %}
|
||||||
<table class="add-table">
|
|
||||||
<caption><h3>{{lang.words.add|title()}} {{lang.words.listener}}</h3></caption>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('serv', values=g.user_params['servers'], is_servers='true') }}
|
|
||||||
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
|
||||||
</td>
|
|
||||||
<td rowspan="5" class="add-note addName alert-info">
|
|
||||||
{{lang.add_page.desc.listener_desc1}}
|
|
||||||
<br /><br />
|
|
||||||
{{lang.add_page.desc.listener_desc2}}
|
|
||||||
<br /><br />
|
|
||||||
{{lang.add_page.desc.listener_desc3}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.name|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('name', name='listener', title=lang.words.name|title() + ' ' +lang.words.listener, placeholder="web_80", required='required') }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">IP and {{lang.words.port|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('ip', placeholder="Any", size='15') }}<b>:</b>
|
|
||||||
{{ input('listen-port', name='port', title=lang.add_page.desc.port_for_bind + ' ' + lang.words.listener, placeholder="8080", size='5', required='required') }}
|
|
||||||
<div id="listener_bind" style="display: none"></div>
|
|
||||||
<a class="link add-server" id="add_bind_listener" title="{{lang.add_page.desc.bind_ip_pair}}"></a>
|
|
||||||
<div class="tooltip tooltipTop">
|
|
||||||
{{lang.add_page.desc.ip_port}}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.mode|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'http':'http','tcp':'tcp'} %}
|
|
||||||
{{ select('listen-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
|
|
||||||
<span id="https-listen-span">
|
|
||||||
<label for="https-listen" style="margin-top: 5px;" title="{{lang.words.enable|title()}} SSL Offloading" data-help="{{lang.add_page.desc.ssl_offloading}}">SSL Offloading</label>
|
|
||||||
<input type="checkbox" id="https-listen" name="ssl" value="https" >
|
|
||||||
</span>
|
|
||||||
<div id="https-hide-listen" style="display: none;">
|
|
||||||
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.name}} {{lang.words.of}} pem {{lang.words.file2}}, {{lang.add_page.desc.press_down}}:</span><br />
|
|
||||||
{{ input('path-cert-listen', name="cert", placeholder="some_cert.pem", size='39') }}<br />
|
|
||||||
<label for="ssl-dis-check-listen" style="margin-top: 5px;">{{lang.add_page.buttons.disable_ssl_check}}</label><input type="checkbox" id="ssl-dis-check-listen" name="ssl-dis-check" value="ssl-dis-check">
|
|
||||||
<label for="ssl-check-listen" style="margin-top: 5px;">{{lang.add_page.buttons.disable_ssl_verify}}</label><input type="checkbox" id="ssl-check-listen" name="ssl-check" value="ssl-check" checked>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">Maxconn: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('maxconn', value='2000', type="number", title=lang.add_page.desc.maxconn_fix, size='5', required='required') }}
|
|
||||||
<div class="tooltip tooltipTop">{{lang.add_page.desc.maxconn_desc}}: 2000</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.balance|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('balance', values=balance_params, selected='roundrobin', required='required', class='force_close') }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.health|title()}} {{lang.words.check}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('listener_checks', name='health_check', values=checks, selected='', class='force_close') }}
|
|
||||||
<span id="listener_checks_note" class="tooltip tooltipTop"></span>
|
|
||||||
<br />
|
|
||||||
<span id="listener_checks_http" style="display: none;">
|
|
||||||
URI path for checking: {{ input('listener_checks_http_path', name='checks_http_path', value='/', title="URI for checking e.g. /check") }}
|
|
||||||
Domain name: {{ input('listener_checks_http_domain', name='checks_http_domain', placeholder='domain.com', title="Domain name for checking e.g. domain.com") }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.headers|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span title="{{lang.words.add|title()}} {{lang.words.headers}}" id="add_listener_header" class="link add-server"></span>
|
|
||||||
<div id="listener_header_div" style="display: none;">
|
|
||||||
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="listener_header_p">
|
|
||||||
{{ select('listener_header_res_method', name='headers_res', values=header_res, first='------', class='force_close') }}
|
|
||||||
{{ select('listener_header_method', name='headers_method', values=header_params, selected='add-header', class='force_close') }}
|
|
||||||
<b class="padding10">{{lang.words.name}}</b>
|
|
||||||
{{ input('listener_header_name', name="header_name") }}
|
|
||||||
<b class="padding10">{{lang.words.value}}</b>
|
|
||||||
{{ input('listener_header_value', name="header_value", placeholder='Leave blank if using del-header') }}
|
|
||||||
<span class="minus minus-style" onclick="deleteId('listener_header_p')" title="{{lang.words.delete|title()}}"></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server" id="listener_add_header" title="{{lang.words.add|title()}} {{lang.words.headers}}" style="display: none;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName" title="Access control list">ACL: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span title="{{lang.words.add|title()}} ACL" id="add_listener_acl" class="link add-server"></span>
|
|
||||||
<div id="listener_acl" style="display: none;">
|
|
||||||
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="listener_acl_rule">
|
|
||||||
<b class="padding10">{{lang.words.if|title()}}</b>
|
|
||||||
{{ select('listener_acl_if', name='acl_if', values=if_values, first='Select if', class='force_close', disabled=false) }}
|
|
||||||
<b class="padding10">{{lang.words.value}}</b>
|
|
||||||
{{ input('listener_acl_value', name="acl_value") }}
|
|
||||||
<b class="padding10">{{lang.words.then}}</b>
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'2':'Redirect to','3':'Allow','4':'Deny', '6': 'Return', '7': 'Set-header'} %}
|
|
||||||
{{ select('listener_acl_then', name='acl_then', values=values, first='Select then', class='force_close', disabled=false) }}
|
|
||||||
<b class="padding10">{{lang.words.value}}</b>
|
|
||||||
{{ input('listener_acl_then_value', name='acl_then_value', title="Required if \'then\' is \'Use backend\' or \'Redirect\', \'Return\', or \'Set-header\'") }}
|
|
||||||
<span class="minus minus-style" onclick="deleteId('listener_acl_rule')" title="{{lang.words.delete|title()}} {{lang.words.this}} ACL"></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server" id="listener_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web {{lang.words.acceleration}}:</span></td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('compression', title=lang.add_page.desc.http_compression, value='1', desc=lang.words.compression|title()) }}
|
|
||||||
{{ checkbox('cache', title=lang.words.enable|title()+' '+lang.words.cache, value='2', desc=lang.words.cache|title()) }}
|
|
||||||
{{ checkbox('ssl_offloading', title=lang.add_page.desc.http_https, desc='HTTP->HTTPS') }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName"><span title="Web application firewall" class="help_cursor">WAF:</span></td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('slow_atack', title=lang.add_page.desc.slow_attack,
|
|
||||||
desc='Slow attack') }}
|
|
||||||
{{ checkbox('ddos', title='DDOS attack protect', desc='DDOS') }}
|
|
||||||
{{ checkbox('whitelist_checkbox', title=lang.words.enable|title()+' '+ lang.words.whitelist, desc=lang.words.whitelist|title()) }}
|
|
||||||
{{ checkbox('blacklist_checkbox', title=lang.words.enable|title()+' '+ lang.words.blacklist, desc=lang.words.blacklist|title()) }}
|
|
||||||
{{ checkbox('waf', title='Web application firewall', desc='WAF', value='1') }}
|
|
||||||
{{ checkbox('antibot', title=lang.add_page.desc.antibot, desc='Antibot', value='1') }}
|
|
||||||
</span>
|
|
||||||
<div id="blacklist-hide" style="display: none;">
|
|
||||||
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.blacklist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
|
||||||
{{ input('blacklist-hide-input', size='39', name="blacklist", placeholder="blacklist.lst") }}
|
|
||||||
</div>
|
|
||||||
<div id="whitelist-hide" style="display: none;">
|
|
||||||
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.whitelist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
|
||||||
{{ input('whitelist-hide-input', size='39', name="whitelist", placeholder="whitelist.lst") }}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.options|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('forward_for', title=lang.add_page.desc.forward_for, desc='Forward for') }}
|
|
||||||
{{ checkbox('redispatch', title=lang.add_page.desc.redispatch, desc='Redispatch') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
|
|
||||||
{{ select('force_close', values=values, first='Force HTTP close', title=lang.add_page.desc.force_close, class='force_close') }}
|
|
||||||
{{ checkbox('cookie', title=lang.add_page.desc.cookie, desc=lang.words.set|title()+' cookie', value='1') }}
|
|
||||||
{{ checkbox('options-listen-show', title=lang.add_page.buttons.set_options_m, desc=lang.add_page.buttons.set_options) }}
|
|
||||||
</span>
|
|
||||||
<br>
|
|
||||||
<span id="cookie_div" style="display: none;">
|
|
||||||
<input type="text" placeholder="name" name="cookie_name" id="cookie_name" class="form-control"><br><br>
|
|
||||||
<input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br>
|
|
||||||
<span class="controlgroup">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'None':'None','rewrite':'rewrite','indirect':'indirect','insert':'insert'} %}
|
|
||||||
{{ select('rewrite', values=values, first='rewrite/indirect/insert', class='force_close') }}
|
|
||||||
{{ checkbox('prefix', title=lang.add_page.desc.c_prefix, desc='prefix', value='prefix') }}
|
|
||||||
{{ checkbox('nocache', title=lang.add_page.desc.c_nocache, desc='nocache', value='nocache') }}
|
|
||||||
{{ checkbox('postonly', title=lang.add_page.desc.c_postonly, desc='postonly', value='postonly') }}
|
|
||||||
{{ checkbox('dynamic', title=lang.add_page.desc.c_dynamic, desc='dynamic', value='dynamic') }}
|
|
||||||
<span id="dynamic_div" style="display: none;">
|
|
||||||
dynamic-cookie-key: {{ input('dynamic-cookie-key', placeholder="your-custom-key") }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<div id="options-listen-show-div" style="display: none;">
|
|
||||||
<div class="tooltip">
|
|
||||||
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.options}}: </span>
|
|
||||||
{{ input('options') }}
|
|
||||||
<span style="padding-left: 10px;">
|
|
||||||
{{lang.add_page.desc.press_down}}. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAProxy docs">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} {{lang.words.options}}</a>
|
|
||||||
</span>
|
|
||||||
<br />
|
|
||||||
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.saved}} {{lang.words.options}}: </span>
|
|
||||||
{{ input('saved-options') }}
|
|
||||||
{{lang.add_page.desc.saved_options}}
|
|
||||||
</div>
|
|
||||||
<textarea name="option" title="Options thru" id="optionsInput" cols=80 rows=5 placeholder="acl test hdr_beg(host) -i some_host"></textarea>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.servers|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{% include 'include/add_servers.html' %}
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
{{ checkbox('template-listen', name='template', title=lang.add_page.desc.server_template, value='template', desc=lang.add_page.desc.server_template) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.check|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<div>
|
|
||||||
<label for="controlgroup-listen-show" style="margin-top: 5px;" title="Set custom check parameters">{{lang.words.custom|title()}} {{lang.words.check}} {{lang.words.params}}</label>
|
|
||||||
<input type="checkbox" id="controlgroup-listen-show" name="default-check" value="1">
|
|
||||||
<span class="tooltip tooltipTop">{{lang.add_page.desc.def_check}}: inter 2000 rise 2 fall 5</span>
|
|
||||||
</div>
|
|
||||||
<div class="controlgroup" id="controlgroup-listen" style="display: none;">
|
|
||||||
<label for="check-servers-listen" title="Ebable servers check">{{lang.words.check|title()}}</label>
|
|
||||||
<input type="checkbox" id="check-servers-listen" name="check-servers" checked value="1">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'1000':'1000','2000':'2000','3000':'3000'} %}
|
|
||||||
{{ select('inter-listen', values=values, first='inter', class='force_close') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'1':'1','2':'2','3':'3'} %}
|
|
||||||
{{ select('rise-listen', name='rise', values=values, first='rise', class='force_close') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'4':'4','5':'5','6':'6'} %}
|
|
||||||
{{ select('fall-listen', name='fall', values=values, first='fall', class='force_close') }}
|
|
||||||
</div>
|
|
||||||
<div style="display: block">
|
|
||||||
{{ checkbox('circuit_breaking_listen', name="circuit_breaking", desc='Circuit Breaking', title=lang.add_page.desc.circuit_breaking, value='1') }}
|
|
||||||
</div>
|
|
||||||
<div id="circuit_breaking_listen_div" style="display: none">
|
|
||||||
Observe:
|
|
||||||
{{ select('circuit_breaking_observe', values=observe, class='force_close') }}
|
|
||||||
error-limit: {{ input('circuit_breaking_error_limit', type='number', value='50', style='width: 50px;') }}
|
|
||||||
on-error:
|
|
||||||
{{ select('circuit_breaking_on_error', values=on_error, class='force_close') }}
|
|
||||||
<div class="tooltip tooltipTop">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} Circuit Breaking <a href="https://roxy-wi.org/description/circuit-breaking" title="Circuit Breaking" target="_blank">{{lang.words.here}}</a></div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance-show">
|
|
||||||
<td class="addOption" colspan="2">
|
|
||||||
<button title="{{lang.add_page.buttons.show_full_settings}}" class="row-down advance-show-button">{{lang.words.show|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
|
||||||
<button title="{{lang.add_page.buttons.hide_full_settings}}" class="row-up advance-hide-button" style="display: none">{{lang.words.hide|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.add|title()}} {{lang.words.listener|title()}}" onclick="addProxy('add-listener')">{{lang.words.add|title()}} {{lang.words.linstener|title()}}</a>
|
|
||||||
</td>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="generateConfig('add-listener')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Second tabs -->
|
<!-- Second tabs -->
|
||||||
|
|
||||||
<div id="frontend">
|
<div id="frontend">
|
||||||
<form name="add-frontend" id="add-frontend" action="/add/haproxy/add" method="post">
|
{% include 'include/add/frontend.html' %}
|
||||||
<table>
|
|
||||||
<caption><h3>{{lang.words.add|title()}} {{lang.words.frontend}}</h3></caption>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('serv2', values=g.user_params['servers'], is_servers='true') }}
|
|
||||||
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
|
||||||
</td>
|
|
||||||
<td rowspan="5" class="add-note addName alert-info">
|
|
||||||
{{lang.add_page.desc.front_desc1}}
|
|
||||||
<br /><br />
|
|
||||||
{{lang.add_page.desc.listener_desc2}}
|
|
||||||
<br /><br />
|
|
||||||
{{lang.add_page.desc.listener_desc1}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.name|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<input type="text" name="frontend" id="new_frontend" required title="{{lang.words.name|title()}} {{lang.words.frontend}}" placeholder="web_80" class="form-control">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">IP and {{lang.words.port|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<input type="text" name="ip" id="ip1" size="15" placeholder="Any" class="form-control"><b>:</b>
|
|
||||||
<input type="text" name="port" size="5" required title="{{lang.add_page.desc.port_for_bind}} {{lang.words.frontend}}" placeholder="8080" class="form-control">
|
|
||||||
<div id="frontend_bind" style="display: none"></div>
|
|
||||||
<a class="link add-server" id="add_bind_frontend" title="{{lang.add_page.desc.bind_ip_pair}}"></a>
|
|
||||||
<div class="tooltip tooltipTop">
|
|
||||||
{{lang.add_page.desc.ip_port}}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.mode|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'http':'http','tcp':'tcp'} %}
|
|
||||||
{{ select('frontend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
|
|
||||||
<span id="https-frontend-span">
|
|
||||||
{{ checkbox('https-frontend', title=lang.add_page.desc.ssl_offloading, desc='SSL Offloading') }}
|
|
||||||
|
|
||||||
</span>
|
|
||||||
<div id="https-hide-frontend" style="display: none;">
|
|
||||||
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.name}} {{lang.words.of}} pem {{lang.words.file2}}, {{lang.add_page.desc.press_down}}:</span><br />
|
|
||||||
{{ input('path-cert-frontend', name="cert", placeholder="some_cert.pem", size='39') }}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">Maxconn: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('maxconn', value='2000', type="number", title=lang.add_page.desc.maxconn_fix, size='5', required='required') }}
|
|
||||||
<div class="tooltip tooltipTop">{{lang.add_page.desc.maxconn_desc}}: 2000</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.headers|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span title="{{lang.words.add|title()}} {{lang.words.headers}}" id="add_frontend_header" class="link add-server"></span>
|
|
||||||
<div id="frontend_header_div" style="display: none;">
|
|
||||||
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="frontend_header_p">
|
|
||||||
{{ select('frontend_header_res_method', name='headers_res', values=header_res, first='------', class='force_close') }}
|
|
||||||
{{ select('frontend_header_method', name='headers_method', values=header_params, selected='add-header', class='force_close') }}
|
|
||||||
<b class="padding10">{{lang.words.name}}</b>
|
|
||||||
{{ input('frontend_header_name', name="header_name") }}
|
|
||||||
<b class="padding10">{{lang.words.value}}</b>
|
|
||||||
{{ input('frontend_header_value', name="header_value", placeholder='Leave blank if using del-header') }}
|
|
||||||
<span class="minus minus-style" onclick="deleteId('frontend_header_p')" title="{{lang.words.delete|title()}}"></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server" id="frontend_add_header" title="{{lang.words.add|title()}} {{lang.words.headers}}" style="display: none;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName" title="Access control list">ACL: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span title="{{lang.words.add|title()}} ACL" id="add_frontend_acl" class="link add-server"></span>
|
|
||||||
<div id="frontend_acl" style="display: none;">
|
|
||||||
<p id="frontend_acl_rule" style="border-bottom: 1px solid #ddd; padding-bottom: 10px;">
|
|
||||||
<b class="padding10">if</b>
|
|
||||||
{{ select('frontend_acl_if', name='acl_if', values=if_values, first='Select if', class='force_close', disabled=false) }}
|
|
||||||
<b class="padding10">value</b>
|
|
||||||
{{ input('frontend_acl_value', name='acl_value') }}
|
|
||||||
<b class="padding10">then</b>
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'5':'Use backend','2':'Redirect to','3':'Allow','4':'Deny', '6': 'Return', '7': 'Set-header'} %}
|
|
||||||
{{ select('frontend_acl_then', name='acl_then', values=values, first='Select then', class='force_close', disabled=false) }}
|
|
||||||
<b class="padding10">value</b>
|
|
||||||
{{ input('frontend_acl_then_value', name='acl_then_value', title="Required if \'then\' is \'Use backend\' or \'Redirect\', \'Return\', or \'Set-header\'") }}
|
|
||||||
<span class="minus minus-style" onclick="deleteId('frontend_acl_rule')" title="{{lang.words.delete|title()}}"></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server" id="frontend_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web {{lang.words.acceleration}}:</span></td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('compression2', name="compression", title=lang.add_page.desc.http_compression, value='1', desc=lang.words.compression|title()) }}
|
|
||||||
{{ checkbox('cache2', name="cache", title=lang.words.enable|title()+' '+lang.words.cache, value='2', desc=lang.words.cache|title()) }}
|
|
||||||
{{ checkbox('ssl_offloading1', title=lang.add_page.desc.http_https, desc='HTTP->HTTPS') }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName"><span title="Web application firewall" class="help_cursor">WAF:</span></td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('slow_atack1', title=lang.add_page.desc.slow_attack,
|
|
||||||
desc='Slow attack') }}
|
|
||||||
{{ checkbox('ddos1', title='DDOS attack protect', desc='DDOS') }}
|
|
||||||
{{ checkbox('whitelist_checkbox1', title=lang.words.enable|title()+' '+ lang.words.whitelist, desc=lang.words.whitelist|title()) }}
|
|
||||||
{{ checkbox('blacklist_checkbox1', title=lang.words.enable|title()+' '+ lang.words.blacklist, desc=lang.words.blacklist|title()) }}
|
|
||||||
{{ checkbox('waf2', name='waf', title='Web application firewall', desc='WAF', value='1') }}
|
|
||||||
{{ checkbox('antibot1', title=lang.add_page.desc.antibot, desc='Antibot', value='1') }}
|
|
||||||
</span>
|
|
||||||
<div id="blacklist-hide1" style="display: none;">
|
|
||||||
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.blacklist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
|
||||||
{{ input('blacklist-hide-input1', size='39', name="blacklist", placeholder="blacklist.lst") }}
|
|
||||||
</div>
|
|
||||||
<div id="whitelist-hide1" style="display: none;">
|
|
||||||
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.whitelist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
|
||||||
{{ input('whitelist-hide-input1', size='39', name="whitelist", placeholder="whitelist.lst") }}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.options|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('forward_for1', title=lang.add_page.desc.forward_for,
|
|
||||||
desc='Forward for') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
|
|
||||||
{{ select('force_close', values=values, first='Force HTTP close', title=lang.add_page.desc.force_close, class='force_close') }}
|
|
||||||
{{ checkbox('options-frontend-show', title=lang.add_page.buttons.set_options_m, desc=lang.add_page.buttons.set_options) }}
|
|
||||||
</span>
|
|
||||||
<div id="options-frontend-show-div" style="display: none;">
|
|
||||||
<div style="font-size: 12px; padding-bottom: 10px;">
|
|
||||||
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.options}}: </span>
|
|
||||||
{{ input('options1') }}
|
|
||||||
<span style="padding-left: 10px;">
|
|
||||||
{{lang.add_page.desc.press_down}}. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAProxy docs">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} {{lang.words.options}}</a>
|
|
||||||
</span>
|
|
||||||
<br />
|
|
||||||
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.saved}} {{lang.words.options}}:</span>
|
|
||||||
{{ input('saved-options1') }}
|
|
||||||
{{lang.add_page.desc.saved_options}}
|
|
||||||
</div>
|
|
||||||
<textarea name="option" title="Options thru" cols=80 rows=5 id="optionsInput1" placeholder="acl test hdr_beg(host) -i some_host"></textarea>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.default_backend}}</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('backends', name='backends', placeholder="some_backend", size='30', title=lang.add_page.desc.no_def_backend) }}
|
|
||||||
<div class="tooltip tooltipTop">
|
|
||||||
<b>{{lang.words.note|title()}}</b>: {{lang.add_page.desc.def_backend}}, <span title="{{lang.words.create|title()}} {{lang.words.backend}}" class="redirectBackend link">{{lang.add_page.desc.def_backend_exit}}</span>.
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance-show">
|
|
||||||
<td class="addOption" colspan="2">
|
|
||||||
<button title="{{lang.add_page.buttons.show_full_settings}}" class="row-down advance-show-button">{{lang.words.show|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
|
||||||
<button title="{{lang.add_page.buttons.hide_full_settings}}" class="row-up advance-hide-button" style="display: none">{{lang.words.hide|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="Add Frontend" onclick="addProxy('add-frontend')">Add Frontend</a>
|
|
||||||
</td>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="generateConfig('add-frontend')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Third tabs -->
|
<!-- Third tabs -->
|
||||||
|
|
||||||
<div id="backend">
|
<div id="backend">
|
||||||
<form name="add-backend" id="add-backend" action="/add/haproxy/add" method="post">
|
{% include 'include/add/backend.html' %}
|
||||||
<table>
|
|
||||||
<caption><h3>{{lang.words.add|title()}} {{lang.words.backend}}</h3></caption>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('serv3', values=g.user_params['servers'], is_servers='true') }}
|
|
||||||
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
|
||||||
</td>
|
|
||||||
<td rowspan="4" class="add-note addName alert-info">
|
|
||||||
{{lang.add_page.desc.back_des1}}
|
|
||||||
<br /><br />
|
|
||||||
{{lang.add_page.desc.listener_desc2}}
|
|
||||||
<br /><br />
|
|
||||||
{{lang.add_page.desc.listener_desc3}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.name|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('new_backend', title=lang.words.name|title() + ' ' +lang.words.backend, placeholder="web_80", required='required') }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.mode|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'http':'http','tcp':'tcp'} %}
|
|
||||||
{{ select('backend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
|
|
||||||
<span id="https-backend-span">
|
|
||||||
<label for="https-backend" style="margin-top: 5px;">Is SSL enabled on frontend?</label>
|
|
||||||
<input type="checkbox" id="https-backend" name="ssl" value="https">
|
|
||||||
</span>
|
|
||||||
<div id="https-hide-backend" style="display: none;">
|
|
||||||
<label for="ssl-dis-check-backend" style="margin-top: 5px;">{{lang.add_page.buttons.disable_ssl_check}}</label><input type="checkbox" id="ssl-dis-check-backend" name="ssl-dis-check" value="ssl-dis-check">
|
|
||||||
<label for="ssl-check-backend" style="margin-top: 5px;">{{lang.add_page.buttons.disable_ssl_verify}}</label><input type="checkbox" id="ssl-check-backend" name="ssl-check" value="ssl-check" checked>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.balance|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('balance', values=balance_params, selected='roundrobin', required='required', class='force_close') }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.health|title()}} {{lang.words.check}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('backend_checks', name='health_check', values=checks, selected='', class='force_close') }}
|
|
||||||
<span id="backend_checks_note" class="tooltip tooltipTop"></span>
|
|
||||||
<br />
|
|
||||||
<span id="backend_checks_http" style="display: none;">
|
|
||||||
URI path for checking: {{ input('backend_checks_http_path', name='checks_http_path', value='/', title="URI for checking e.g. /check") }}
|
|
||||||
Domain name: {{ input('backend_checks_http_domain', name='checks_http_domain', placeholder='domain.com', title="Domain name for checking e.g. domain.com") }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.headers|title()}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span title="{{lang.words.add|title()}} {{lang.words.headers}}" id="add_backend_header" class="link add-server"></span>
|
|
||||||
<div id="backend_header_div" style="display: none;">
|
|
||||||
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="backend_header_p">
|
|
||||||
{{ select('backend_header_res_method', name='headers_res', values=header_res, first='------', class='force_close') }}
|
|
||||||
{{ select('backend_header_method', name='headers_method', values=header_params, selected='add-header', class='force_close') }}
|
|
||||||
<b class="padding10">{{lang.words.name}}</b>
|
|
||||||
{{ input('backend_header_name', name="header_name") }}
|
|
||||||
<b class="padding10">{{lang.words.value}}</b>
|
|
||||||
{{ input('lbackend_header_value', name="header_value", placeholder='Leave blank if using del-header') }}
|
|
||||||
<span class="minus minus-style" onclick="deleteId('listener_header_p')" title="{{lang.words.delete|title()}}"></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server" id="backend_add_header" title="{{lang.words.add|title()}} {{lang.words.headers}}" style="display: none;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName" title="Access control list">ACL: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span title="{{lang.words.add|title()}} ACL" id="add_backend_acl" class="link add-server"></span>
|
|
||||||
<div id="backend_acl" style="display: none;">
|
|
||||||
<p id="backend_acl_rule" style="border-bottom: 1px solid #ddd; padding-bottom: 10px;">
|
|
||||||
<b class="padding10">if</b>
|
|
||||||
{{ select('backend_acl_if', name='acl_if', values=if_values, first='Select if', class='force_close', disabled=false) }}
|
|
||||||
<b class="padding10">value</b>
|
|
||||||
{{ input('backend_acl_value', name="acl_value") }}
|
|
||||||
<b class="padding10">then</b>
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'2':'Redirect to','3':'Allow','4':'Deny', '6': 'Return', '7': 'Set-header'} %}
|
|
||||||
{{ select('backend_acl_then', name='acl_then', values=values, first='Select then', class='force_close', disabled=false) }}
|
|
||||||
<b class="padding10">value</b>
|
|
||||||
{{ input('backend_acl_then_value', name='acl_then_value', title="Required if \'then\' is \'Use backend\', \'Redirect\', \'Return\', or \'Set-header\'") }}
|
|
||||||
<span class="minus minus-style" onclick="deleteId('backend_acl_rule')" title="{{lang.words.delete|title()}} {{lang.words.this}} {{lang.words.rule}}"></span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server" id="backend_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web {{lang.words.acceleration}}:</span></td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('compression3', name="compression", title=lang.add_page.desc.http_compression, value='1', desc=lang.words.compression|title()) }}
|
|
||||||
{{ checkbox('cache3', name="cache", title=lang.words.enable|title()+' '+lang.words.cache, value='2', desc=lang.words.cache|title()) }}
|
|
||||||
{{ checkbox('ssl_offloading2', title=lang.add_page.desc.http_https, desc='SSL Offloading') }}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.options|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span class="controlgroup">
|
|
||||||
{{ checkbox('forward_for2', title=lang.add_page.desc.forward_for, desc='Forward for') }}
|
|
||||||
{{ checkbox('redispatch2', title=lang.add_page.desc.redispatch, desc='Redispatch') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
|
|
||||||
{{ select('force_close', values=values, first='Force HTTP close', title=lang.add_page.desc.force_close, class='force_close') }}
|
|
||||||
{{ checkbox('cookie2', title=lang.add_page.desc.cookie, desc=lang.words.set|title()+' cookie', value='1') }}
|
|
||||||
{{ checkbox('options-backend-show', title=lang.add_page.buttons.set_options_m, desc=lang.add_page.buttons.set_options) }}
|
|
||||||
</span>
|
|
||||||
<br>
|
|
||||||
<span id="cookie_div2" style="display: none;">
|
|
||||||
<input type="text" placeholder="name" name="cookie_name" id="cookie_name2" class="form-control"><br><br>
|
|
||||||
<input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br>
|
|
||||||
<span class="controlgroup">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'None':'None','rewrite':'rewrite','indirect':'indirect','insert':'insert'} %}
|
|
||||||
{{ select('rewrite2', values=values, first='rewrite/indirect/insert', class='force_close') }}
|
|
||||||
{{ checkbox('prefix2', name='prefix', title=lang.add_page.desc.c_prefix, desc='prefix', value='prefix') }}
|
|
||||||
{{ checkbox('nocache2', name='nocache', title=lang.add_page.desc.c_nocache, desc='nocache', value='nocache') }}
|
|
||||||
{{ checkbox('postonly2', name='postonly', title=lang.add_page.desc.c_postonly, desc='postonly', value='postonly') }}
|
|
||||||
{{ checkbox('dynamic2', name='dynamic', title=lang.add_page.desc.c_dynamic, desc='dynamic', value='dynamic') }}
|
|
||||||
<span id="dynamic_div2" style="display: none;">
|
|
||||||
dynamic-cookie-key: {{ input('dynamic-cookie-key2', name='dynamic-cookie-key', placeholder="your-custom-key") }}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<div id="options-backend-show-div" style="display: none;">
|
|
||||||
<div style="font-size: 12px; padding-bottom: 10px;">
|
|
||||||
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.options}}: </span>
|
|
||||||
{{ input('options2') }}
|
|
||||||
<span style="padding-left: 10px;">
|
|
||||||
{{lang.add_page.desc.press_down}}. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} {{lang.words.options}}</a>
|
|
||||||
</span>
|
|
||||||
<br />
|
|
||||||
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.saved}} {{lang.words.options}}: </span>
|
|
||||||
<input type="text" id="saved-options2" class="form-control">
|
|
||||||
{{lang.add_page.desc.saved_options}}
|
|
||||||
</div>
|
|
||||||
<textarea name="option" title="Options thru" cols=80 rows=5 id="optionsInput2" placeholder="acl test hdr_beg(host) -i some_host"></textarea>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.servers|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{% include 'include/add_servers.html' %}
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
{{ checkbox('template-backend', name='template', title=lang.add_page.desc.server_template, value='template', desc=lang.add_page.desc.server_template) }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance">
|
|
||||||
<td class="addName">{{lang.words.check|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<div>
|
|
||||||
<label for="controlgroup-backend-show" style="margin-top: 5px;" title="Set custom check parameters">{{lang.words.custom|title()}} {{lang.words.check}} {{lang.words.params}}</label>
|
|
||||||
<input type="checkbox" id="controlgroup-backend-show" name="default-check">
|
|
||||||
<span class="tooltip tooltipTop">{{lang.add_page.desc.def_check}}: inter 2000 rise 2 fall 5</span>
|
|
||||||
</div>
|
|
||||||
<div class="controlgroup" id="controlgroup-backend" style="display: none;">
|
|
||||||
<label for="check-servers-backend" title="Ebable servers check">{{lang.words.check|title()}}</label>
|
|
||||||
<input type="checkbox" id="check-servers-backend" name="check-servers" checked value="1">
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'1000':'1000','2000':'2000','3000':'3000'} %}
|
|
||||||
{{ select('inter-backend', values=values, first='inter', class='force_close') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'1':'1','2':'2','3':'3'} %}
|
|
||||||
{{ select('rise-backend', name='rise', values=values, first='rise', class='force_close') }}
|
|
||||||
{% set values = dict() %}
|
|
||||||
{% set values = {'4':'4','5':'5','6':'6'} %}
|
|
||||||
{{ select('fall-backend', name='fall', values=values, first='fall', class='force_close') }}
|
|
||||||
</div>
|
|
||||||
<div style="display: block">
|
|
||||||
{{ checkbox('circuit_breaking_backend', name="circuit_breaking", desc='Circuit Breaking', title=lang.add_page.desc.circuit_breaking, value='1') }}
|
|
||||||
</div>
|
|
||||||
<div id="circuit_breaking_backend_div" style="display: none">
|
|
||||||
Observe:
|
|
||||||
{{ select('circuit_breaking_observe', values=observe, class='force_close') }}
|
|
||||||
error-limit: {{ input('circuit_breaking_error_limit', type='number', value='50', style='width: 50px;') }}
|
|
||||||
on-error:
|
|
||||||
{{ select('circuit_breaking_on_error', values=on_error, class='force_close') }}
|
|
||||||
<div class="tooltip tooltipTop">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} Circuit Breaking <a href="https://roxy-wi.org/description/circuit-breaking" title="Circuit Breaking" target="_blank">{{lang.words.here}}</a></div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="advance-show">
|
|
||||||
<td class="addOption" colspan="2">
|
|
||||||
<button title="{{lang.add_page.buttons.show_full_settings}}" class="row-down advance-show-button">{{lang.words.show|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
|
||||||
<button title="{{lang.add_page.buttons.hide_full_settings}}" class="row-up advance-hide-button" style="display: none">{{lang.words.hide|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.add|title()}} {{lang.words.backend|title()}}" onclick="addProxy('add-backend')">{{lang.words.add|title()}} {{lang.words.backend|title()}}</a>
|
|
||||||
</td>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="generateConfig('add-backend')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="ssl">
|
<div id="ssl">
|
||||||
|
@ -873,77 +214,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="userlist">
|
<div id="userlist">
|
||||||
<form name="add-userlist" id="add-userlist" action="/add/haproxy/userlist" method="post">
|
{% include 'include/add/userlist.html' %}
|
||||||
<table>
|
|
||||||
<caption><h3>{{lang.words.add|title()}} {{lang.words.userlists}}</h3></caption>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('userlist_serv', name='serv', values=g.user_params['servers'], is_servers='true') }}
|
|
||||||
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
|
||||||
</td>
|
|
||||||
<td rowspan="4" class="add-note addName alert-info">{{lang.add_page.desc.userlist_desc}}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.name|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('new_userlist', required='required', title=lang.add_page.desc.userlist_name, placeholder="basic-auth-list") }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.groups|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span id="userlist-groups">
|
|
||||||
{{ input('userlist-group', title=lang.add_page.desc.userlist_user_grp, placeholder="group_name") }}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<span class="link add-server" id="add-userlist-group" title="Add extra group" style="cursor: pointer;"></span>
|
|
||||||
</span>
|
|
||||||
<div class="tooltip tooltipTop">{{lang.add_page.desc.userlist_group}}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.user|title()}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span id="userlist-users">
|
|
||||||
{{ input('userlist-user', required='required', title=lang.words.username|title(), placeholder="user_name") }}
|
|
||||||
{{ input('userlist-password', required='required', title=lang.add_page.desc.userlist_pass, placeholder="password") }}
|
|
||||||
{{ input('userlist-user-group', title=lang.add_page.desc.userlist_user_grp, placeholder="group") }}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<span class="link add-server" id="add-userlist-user" title="Add extra user" style="cursor: pointer;"></span>
|
|
||||||
</span>
|
|
||||||
<div class="tooltip tooltipTop">{{lang.add_page.desc.userlist_user}}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="Add Userlist" onclick="addProxy('add-userlist')">{{lang.words.add|title()}} {{lang.words.userlist|title()}}</a>
|
|
||||||
</td>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="generateConfig('add-userlist')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
<br />
|
|
||||||
<table>
|
|
||||||
<caption><h3>{{lang.words.existing|title()}} {{lang.words.userlists}}</h3></caption>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('existing_userlist_serv', name='serv', values=g.user_params['servers'], is_servers='true') }}
|
|
||||||
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="Add Userlist" onclick="showUserlists()">{{lang.words.show|title()}} {{lang.words.userlists}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="existing_userlist_tr" style="display: none;">
|
|
||||||
<td class="addName">{{lang.words.existing|title()}} {{lang.words.userlists}}:</td>
|
|
||||||
<td class="addOption" id="existing_userlist_ajax"></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;">
|
<div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;">
|
||||||
{{lang.add_page.desc.userlist}}
|
{{lang.add_page.desc.userlist}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -956,52 +227,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="peers">
|
<div id="peers">
|
||||||
<form name="add-peers" id="add-peers" action="/add/haproxy/peers" method="post">
|
{% include 'include/add/peers.html' %}
|
||||||
<table>
|
|
||||||
<caption><h3>{{lang.words.add|title()}} Peer</h3></caption>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ select('peers_serv', name='serv', values=g.user_params['servers'], is_servers='true') }}
|
|
||||||
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
|
||||||
</td>
|
|
||||||
<td rowspan="4" class="add-note addName alert-info">
|
|
||||||
{{lang.add_page.desc.peers}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">Peers {{lang.words.name}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
{{ input('peers-name', title="Peers "+lang.words.name, placeholder="peers name") }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addName">Peers {{lang.words.servers}}:</td>
|
|
||||||
<td class="addOption">
|
|
||||||
<span name="add_peers">
|
|
||||||
<input name="servers_name" required title="Peer {{lang.words.name}}" size=14 placeholder="haproxy1" class="form-control">:
|
|
||||||
<input name="servers" required title="Peer IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
|
|
||||||
<input name="server_port" required title="Peer {{lang.words.port}}" size=3 placeholder="yyy" class="form-control add_server_number" type="number">
|
|
||||||
<br />
|
|
||||||
<input name="servers_name" required title="Peer {{lang.words.name}}" size=14 placeholder="haproxy2" class="form-control">:
|
|
||||||
<input name="servers" title="Peer IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
|
|
||||||
<input name="server_port" title="Peer {{lang.words.port}}" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number">
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<a class="link add-server backend_server" name="add-peer-input" title="{{lang.words.add|title()}} peer {{lang.words.server}}" style="cursor: pointer;"></a>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.add|title()}} peer" onclick="addProxy('add-peers')">{{lang.words.add|title()}} peer</a>
|
|
||||||
</td>
|
|
||||||
<td class="addButton">
|
|
||||||
<a class="ui-button ui-widget ui-corner-all" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="generateConfig('add-peers')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
<div class="alert addName alert-info" style="width: inherit; margin-right: 15px;">
|
<div class="alert addName alert-info" style="width: inherit; margin-right: 15px;">
|
||||||
{{lang.add_page.desc.peers_master}}
|
{{lang.add_page.desc.peers_master}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% import 'languages/'+lang|default('en')+'.html' as lang %}
|
{% import 'languages/'+lang|default('en')+'.html' as lang %}
|
||||||
|
{% from 'include/input_macros.html' import input, checkbox, select %}
|
||||||
<div class="left-space">
|
<div class="left-space">
|
||||||
<h4>{{lang.words.config|title()}} {% if config_file_name != 'undefined' %}{{config_file_name.replace('92', '/')}}{%endif%} {{lang.words.from}} {{serv}} ({{hostname}})</h4>
|
<h4>{{lang.words.config|title()}} {% if config_file_name != 'undefined' %}{{config_file_name.replace('92', '/')}}{%endif%} {{lang.words.from}} {{serv}} ({{hostname}})</h4>
|
||||||
<p class="accordion-expand-holder">
|
<p class="accordion-expand-holder">
|
||||||
|
@ -206,12 +207,16 @@
|
||||||
</span><br />
|
</span><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% if line.startswith('# BEGIN') or line.startswith('# END') %}
|
||||||
|
{% continue %}
|
||||||
|
{% endif %}
|
||||||
{% if line.startswith('global') %}
|
{% if line.startswith('global') %}
|
||||||
<span class="param">{{ line }}
|
<span class="param">{{ line }}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
{% if service != 'keepalived' %}
|
{% if service != 'keepalived' %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}">{{lang.words.edit|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -221,8 +226,8 @@
|
||||||
{% if line.startswith('defaults') %}
|
{% if line.startswith('defaults') %}
|
||||||
</div><span class="param">{{ line }}
|
</div><span class="param">{{ line }}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}">{{lang.words.edit|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span><div>
|
</span><div>
|
||||||
|
@ -231,8 +236,8 @@
|
||||||
{%- if line.startswith('listen') -%}
|
{%- if line.startswith('listen') -%}
|
||||||
</div><span class="param">{{- line -}}
|
</div><span class="param">{{- line -}}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}" target="_blank">{{lang.words.edit|title()}}/{{lang.words.delete|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- set backend = line.split(' ') -%}
|
{%- set backend = line.split(' ') -%}
|
||||||
|
@ -241,15 +246,15 @@
|
||||||
</span>
|
</span>
|
||||||
{%- set backend = backend|join('_') -%}
|
{%- set backend = backend|join('_') -%}
|
||||||
{%- do section_name.update({i: backend}) -%}
|
{%- do section_name.update({i: backend}) -%}
|
||||||
<span id="{{-section_name[i]|replace('\n', '')-}}" class="accordion-link" target="_blank"></span>
|
<span id="{{-section_name[i]|replace('\n', '')-}}" class="accordion-link"></span>
|
||||||
</span><div>
|
</span><div>
|
||||||
{% continue %}
|
{% continue %}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- if line.startswith('frontend') -%}
|
{%- if line.startswith('frontend') -%}
|
||||||
</div><span class="param">{{ line }}
|
</div><span class="param">{{ line }}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}">{{lang.words.edit|title()}}/{{lang.words.delete|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% set backend = line.split(' ') %}
|
{% set backend = line.split(' ') %}
|
||||||
|
@ -265,8 +270,8 @@
|
||||||
{% if line.startswith('backend') %}
|
{% if line.startswith('backend') %}
|
||||||
</div><span class="param">{{ line }}
|
</div><span class="param">{{ line }}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}">{{lang.words.edit|title()}}/{{lang.words.delete|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% set backend = line.split(' ') %}
|
{% set backend = line.split(' ') %}
|
||||||
|
@ -289,8 +294,8 @@
|
||||||
{% if line.startswith('peers') %}
|
{% if line.startswith('peers') %}
|
||||||
</div><span class="param">{{ line }}
|
</div><span class="param">{{ line }}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}">{{lang.words.edit|title()}}/{{lang.words.delete|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span><div>
|
</span><div>
|
||||||
|
@ -309,8 +314,8 @@
|
||||||
{% if line.startswith('userlist') %}
|
{% if line.startswith('userlist') %}
|
||||||
</div><span class="param">{{ line }}
|
</div><span class="param">{{ line }}
|
||||||
{% if role %}
|
{% if role %}
|
||||||
<span class="accordion-link">
|
<span class="accordion-link" onclick="openSection('{{ line| trim }}')">
|
||||||
<a href="/config/section/haproxy/{{serv}}/{{ line }}">{{lang.words.edit|title()}}/{{lang.words.delete|title()}}</a>
|
{{lang.words.edit|title()}}/{{lang.words.delete|title()}}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span><div>
|
</span><div>
|
||||||
|
@ -406,3 +411,4 @@
|
||||||
$("#expand_link").click();
|
$("#expand_link").click();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<div id="edit-section" style="display: none;"></div>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{% import 'languages/'+lang|default('en')+'.html' as lang %}
|
||||||
|
{% from 'include/input_macros.html' import input, checkbox, select %}
|
||||||
|
{% set balance_params = {'roundrobin':'roundrobin','source':'source','leastconn':'leastconn','first':'first',
|
||||||
|
'rdp-cookie':'rdp-cookie', 'uri':'uri', 'uri whole':'uri whole', 'static-rr': 'static-rr',
|
||||||
|
'url_param userid':'url_param userid'} %}
|
||||||
|
{% set checks = {'':'Choose a custom health check','tcp-check':'Check a TCP Port', 'ssl-hello-chk':'Check a SSL Port',
|
||||||
|
'httpchk':'Check a HTTP service', 'ldap-check':'Check a LDAP service', 'mysql-check':'Check a MySql Service',
|
||||||
|
'pgsql-check':'Check a PgSQL Service', 'redis-check': 'Check a Redis Service', 'smtpchk':'Check a SMTP service'} %}
|
||||||
|
{% set observe = {'layer7':'layer7', 'layer4': 'layer4'} %}
|
||||||
|
{% set on_error = {'mark-down':'mark-down', 'fastinter': 'fastinter', 'fail-check':'fail-check',
|
||||||
|
'sudden-death':'sudden-death'} %}
|
||||||
|
{% set header_res = {'http-response': 'response', 'http-request': 'request'} %}
|
||||||
|
{% set header_params = {'add-header': 'add-header', 'set-header': 'set-header', 'del-header': 'del-header'} %}
|
||||||
|
{% set if_values = {'1':'Host name starts with','2':'Host name ends with','3':'Path starts with','4':'Path ends with', '6': 'Src ip'} %}
|
||||||
|
{% set force_close = {'0':'Off','1':'Server only','2':'Force close','3':'Pretend keep alive'} %}
|
||||||
|
<div id="edit-listen" style="display: none;">
|
||||||
|
{% include 'include/add/listen.html' %}
|
||||||
|
</div>
|
||||||
|
<div id="edit-frontend" style="display: none;">
|
||||||
|
{% include 'include/add/frontend.html' %}
|
||||||
|
</div>
|
||||||
|
<div id="edit-backend" style="display: none;">
|
||||||
|
{% include 'include/add/backend.html' %}
|
||||||
|
</div>
|
||||||
|
<div id="edit-userlist" style="display: none;">
|
||||||
|
{% include 'include/add/userlist.html' %}
|
||||||
|
</div>
|
||||||
|
<div id="edit-peers" style="display: none;">
|
||||||
|
{% include 'include/add/peers.html' %}
|
||||||
|
</div>
|
||||||
|
<div id="edit-global" style="display: none;">
|
||||||
|
{% include 'include/add/global.html' %}
|
||||||
|
</div>
|
||||||
|
<div id="edit-defaults" style="display: none;">
|
||||||
|
{% include 'include/add/defaults.html' %}
|
||||||
|
</div>
|
|
@ -25,6 +25,8 @@
|
||||||
<script src="/static/js/codemirror/mode/haproxy.js"></script>
|
<script src="/static/js/codemirror/mode/haproxy.js"></script>
|
||||||
<script src="/static/js/codemirror/keymap/sublime.js"></script>
|
<script src="/static/js/codemirror/keymap/sublime.js"></script>
|
||||||
<script src="/static/js/configshow.js"></script>
|
<script src="/static/js/configshow.js"></script>
|
||||||
|
<script src="/static/js/add.js"></script>
|
||||||
|
<script src="/static/js/edit_config.js"></script>
|
||||||
{% if is_serv_protected and g.user_params['role'] > 2 %}
|
{% if is_serv_protected and g.user_params['role'] > 2 %}
|
||||||
<meta http-equiv="refresh" content="0; url=/service">
|
<meta http-equiv="refresh" content="0; url=/service">
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -129,7 +131,7 @@
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "breakpoints"],
|
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "breakpoints"],
|
||||||
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: true}
|
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: true}
|
||||||
});
|
});
|
||||||
} else {
|
} else if (cur_url[6] === 'edit') {
|
||||||
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("config_text_area"),
|
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("config_text_area"),
|
||||||
{
|
{
|
||||||
mode: "nginx",
|
mode: "nginx",
|
||||||
|
|
|
@ -4,25 +4,29 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<span name="add_servers">
|
<span name="add_servers">
|
||||||
<input name="prefix" class="prefix form-control" title="servers prefix" size="3" placeholder="web" style="display: none;">
|
<p>
|
||||||
|
<input name="template-prefix" class="prefix form-control" title="servers prefix" size="3" placeholder="web" style="display: none;">
|
||||||
<input name="template-number" class="prefix form-control" title="servers num" value="3" type="number" style="width: 35px; display: none;">
|
<input name="template-number" class="prefix form-control" title="servers num" value="3" type="number" style="width: 35px; display: none;">
|
||||||
<input name="servers" required title="{{lang.words.backend|title()}} IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
|
<input name="servers" required title="{{lang.words.backend|title()}} IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
|
||||||
<input name="server_port" required title="{{lang.words.backend|title()}} {{lang.words.port}}" size=8 placeholder="yyy" class="form-control add_server_number" type="number">
|
<input name="server_port" required title="{{lang.words.backend|title()}} {{lang.words.port}}" size=8 placeholder="yyy" class="form-control add_server_number" type="number">
|
||||||
<span name="port_check_text">{{lang.phrases.port_check}}:</span> <input name="port_check" required title="{{lang.words.port|title()}} {{lang.words.for}} {{lang.words.checking}}" data-help="{{lang.add_page.desc.port_check}}" size=8 class="form-control add_server_number" type="number">
|
<span name="port_check_text">{{lang.phrases.port_check}}:</span> <input name="port_check" required title="{{lang.words.port|title()}} {{lang.words.for}} {{lang.words.checking}}" data-help="{{lang.add_page.desc.port_check}}" size=8 class="form-control add_server_number" type="number">
|
||||||
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="{{lang.add_page.desc.maxconn}}" size=8 value="200" class="form-control add_server_number" type="number">
|
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="{{lang.add_page.desc.maxconn}}" size=8 value="200" class="form-control add_server_number" type="number">
|
||||||
<span class="send_proxy"></span>
|
<span class="send_proxy"></span>
|
||||||
<br />
|
</p>
|
||||||
|
<p>
|
||||||
<input name="servers" title="{{lang.words.backend|title()}} IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
|
<input name="servers" title="{{lang.words.backend|title()}} IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
|
||||||
<input name="server_port" title="{{lang.words.backend|title()}} {{lang.words.port}}" size=8 placeholder="yyy" class="form-control second-server add_server_number" type="number">
|
<input name="server_port" title="{{lang.words.backend|title()}} {{lang.words.port}}" size=8 placeholder="yyy" class="form-control second-server add_server_number" type="number">
|
||||||
<span name="port_check_text">{{lang.phrases.port_check}}:</span> <input name="port_check" required title="{{lang.words.port|title()}} {{lang.words.for}} {{lang.words.checking}}" data-help="{{lang.add_page.desc.port_check}}" size=8 class="form-control add_server_number" type="number">
|
<span name="port_check_text">{{lang.phrases.port_check}}:</span> <input name="port_check" required title="{{lang.words.port|title()}} {{lang.words.for}} {{lang.words.checking}}" data-help="{{lang.add_page.desc.port_check}}" size=8 class="form-control add_server_number" type="number">
|
||||||
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="{{lang.add_page.desc.maxconn}}" size=8 value="200" class="form-control add_server_number" type="number">
|
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="{{lang.add_page.desc.maxconn}}" size=8 value="200" class="form-control add_server_number" type="number">
|
||||||
<span class="send_proxy"></span>
|
<span class="send_proxy"></span>
|
||||||
<br />
|
</p>
|
||||||
|
<p>
|
||||||
<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
|
<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
|
||||||
<input name="server_port" title="{{lang.words.backend|title()}} {{lang.words.port}}" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number">
|
<input name="server_port" title="{{lang.words.backend|title()}} {{lang.words.port}}" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number">
|
||||||
<span name="port_check_text">{{lang.phrases.port_check}}:</span> <input name="port_check" required title="{{lang.words.port|title()}} {{lang.words.for}} {{lang.words.checking}}" data-help="{{lang.add_page.desc.port_check}}" size=8 class="form-control add_server_number" type="number">
|
<span name="port_check_text">{{lang.phrases.port_check}}:</span> <input name="port_check" required title="{{lang.words.port|title()}} {{lang.words.for}} {{lang.words.checking}}" data-help="{{lang.add_page.desc.port_check}}" size=8 class="form-control add_server_number" type="number">
|
||||||
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="{{lang.add_page.desc.maxconn}}" size=8 value="200" class="form-control add_server_number" type="number">
|
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="{{lang.add_page.desc.maxconn}}" size=8 value="200" class="form-control add_server_number" type="number">
|
||||||
<span class="send_proxy"></span>
|
<span class="send_proxy"></span>
|
||||||
|
</p>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<a class="link add-server backend_server" name="add-server-input" title="{{lang.words.add|title()}} {{lang.words.backend}} {{lang.words.server}}" style="cursor: pointer;"></a>
|
<a class="link add-server backend_server" name="add-server-input" title="{{lang.words.add|title()}} {{lang.words.backend}} {{lang.words.server}}" style="cursor: pointer;"></a>
|
|
@ -0,0 +1,208 @@
|
||||||
|
<form name="add-backend" id="add-backend" action="/add/haproxy/add" method="post">
|
||||||
|
<table>
|
||||||
|
<caption><h3>{{lang.words.add|title()}} {{lang.words.backend}}</h3></caption>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('serv3', name='server', values=g.user_params['servers'], is_servers='true', by_id=1) }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
<td rowspan="4" class="add-note addName alert-info">
|
||||||
|
{{lang.add_page.desc.back_des1}}
|
||||||
|
<br /><br />
|
||||||
|
{{lang.add_page.desc.listener_desc2}}
|
||||||
|
<br /><br />
|
||||||
|
{{lang.add_page.desc.listener_desc3}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.name|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('new_backend', name='name', title=lang.words.name|title() + ' ' +lang.words.backend, placeholder="web_80", required='required') }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.mode|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'http':'http','tcp':'tcp'} %}
|
||||||
|
{{ select('backend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
|
||||||
|
<span id="https-backend-span">
|
||||||
|
<label for="https-backend" style="margin-top: 5px;">Is SSL enabled on frontend?</label>
|
||||||
|
<input type="checkbox" name="ssl" id="https-backend" value="https">
|
||||||
|
</span>
|
||||||
|
<div id="https-hide-backend" style="display: none;">
|
||||||
|
<label for="ssl-check-backend" style="margin-top: 5px;">{{lang.add_page.buttons.disable_ssl_verify}}</label><input type="checkbox" id="ssl-check-backend" name="ssl-check" value="ssl-check" checked>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.balance|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('backend-balance', name="balance", values=balance_params, selected='roundrobin', required='required', class='force_close') }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.health|title()}} {{lang.words.check}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('backend_checks', name='health_check', values=checks, selected='', class='force_close') }}
|
||||||
|
<span id="backend_checks_note" class="tooltip tooltipTop"></span>
|
||||||
|
<br />
|
||||||
|
<span id="backend_checks_http" style="display: none;">
|
||||||
|
URI path for checking: {{ input('backend_checks_http_path', name='checks_http_path', value='/', title="URI for checking e.g. /check") }}
|
||||||
|
Domain name: {{ input('backend_checks_http_domain', name='checks_http_domain', placeholder='domain.com', title="Domain name for checking e.g. domain.com") }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.headers|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span title="{{lang.words.add|title()}} {{lang.words.headers}}" id="add_backend_header" class="link add-server"></span>
|
||||||
|
<div id="backend_header_div" style="display: none;">
|
||||||
|
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="backend_header_p">
|
||||||
|
{{ select('backend_header_res_method', name='headers_res', values=header_res, first='------', class='force_close') }}
|
||||||
|
{{ select('backend_header_method', name='headers_method', values=header_params, selected='add-header', class='force_close') }}
|
||||||
|
<b class="padding10">{{lang.words.name}}</b>
|
||||||
|
{{ input('backend_header_name', name="header_name") }}
|
||||||
|
<b class="padding10">{{lang.words.value}}</b>
|
||||||
|
{{ input('backend_header_value', name="header_value", placeholder='Leave blank if using del-header') }}
|
||||||
|
<span class="minus minus-style" onclick="deleteId('backend_header_p')" title="{{lang.words.delete|title()}}"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server" id="backend_add_header" title="{{lang.words.add|title()}} {{lang.words.headers}}" style="display: none;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName" title="Access control list">ACL: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span title="{{lang.words.add|title()}} ACL" id="add_backend_acl" class="link add-server"></span>
|
||||||
|
<div id="backend_acl" style="display: none;">
|
||||||
|
<p id="backend_acl_rule" style="border-bottom: 1px solid #ddd; padding-bottom: 10px;">
|
||||||
|
<b class="padding10">{{lang.words.if|title()}}</b>
|
||||||
|
{{ select('backend_acl_if', name='acl_if', values=if_values, first='Select if', class='force_close', disabled=false) }}
|
||||||
|
<b class="padding10">{{ lang.words.value }}</b>
|
||||||
|
{{ input('backend_acl_value', name="acl_value") }}
|
||||||
|
<b class="padding10">{{ lang.words.then }}</b>
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'2':'Redirect to','3':'Allow','4':'Deny', '6': 'Return', '7': 'Set-header'} %}
|
||||||
|
{{ select('backend_acl_then', name='acl_then', values=values, first='Select then', class='force_close', disabled=false) }}
|
||||||
|
<b class="padding10">{{ lang.words.value }}</b>
|
||||||
|
{{ input('backend_acl_then_value', name='acl_then_value', title="Required if \'then\' is \'Use backend\', \'Redirect\', \'Return\', or \'Set-header\'") }}
|
||||||
|
<span class="minus minus-style" onclick="deleteId('backend_acl_rule')" title="{{lang.words.delete|title()}} {{lang.words.this}} {{lang.words.rule}}"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server" id="backend_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web {{lang.words.acceleration}}:</span></td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('compression3', name="compression", title=lang.add_page.desc.http_compression, value='1', desc=lang.words.compression|title()) }}
|
||||||
|
{{ checkbox('cache3', name="cache", title=lang.words.enable|title()+' '+lang.words.cache, value='2', desc=lang.words.cache|title()) }}
|
||||||
|
{{ checkbox('ssl_offloading2', name='ssl_offloading', title=lang.add_page.desc.http_https, desc='SSL Offloading') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.options|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('forward_for2', name='forward_for', title=lang.add_page.desc.forward_for, desc='Forward for') }}
|
||||||
|
{{ checkbox('redispatch2', name='redispatch', title=lang.add_page.desc.redispatch, desc='Redispatch') }}
|
||||||
|
{{ checkbox('backend_cookie', name='cookie', title=lang.add_page.desc.cookie, desc=lang.words.set|title()+' cookie', value='1') }}
|
||||||
|
{{ checkbox('options-backend-show', title=lang.add_page.buttons.set_options_m, desc=lang.add_page.buttons.set_options) }}
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
<span id="backend_cookie_div" style="display: none;">
|
||||||
|
<input type="text" placeholder="name" name="cookie_name" id="backend_cookie_name" class="form-control"><br><br>
|
||||||
|
<input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br>
|
||||||
|
<span class="controlgroup">
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'None':'None','rewrite':'rewrite','indirect':'indirect','insert':'insert'} %}
|
||||||
|
{{ select('backend_rewrite', name='rewrite', values=values, first='rewrite/indirect/insert', class='force_close') }}
|
||||||
|
{{ checkbox('backend_prefix', name='prefix', title=lang.add_page.desc.c_prefix, desc='prefix', value='prefix') }}
|
||||||
|
{{ checkbox('backend_nocache', name='nocache', title=lang.add_page.desc.c_nocache, desc='nocache', value='nocache') }}
|
||||||
|
{{ checkbox('backend_postonly', name='postonly', title=lang.add_page.desc.c_postonly, desc='postonly', value='postonly') }}
|
||||||
|
{{ checkbox('backend_dynamic', name='dynamic', title=lang.add_page.desc.c_dynamic, desc='dynamic', value='dynamic') }}
|
||||||
|
<span id="backend_dynamic_div" style="display: none;">
|
||||||
|
dynamic-cookie-key: {{ input('backend_dynamic-cookie-key', name='dynamic-cookie-key', placeholder="your-custom-key") }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div id="options-backend-show-div" style="display: none;">
|
||||||
|
<div style="font-size: 12px; padding-bottom: 10px;">
|
||||||
|
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.options}}: </span>
|
||||||
|
{{ input('options2') }}
|
||||||
|
<span style="padding-left: 10px;">
|
||||||
|
{{lang.add_page.desc.press_down}}. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} {{lang.words.options}}</a>
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.saved}} {{lang.words.options}}: </span>
|
||||||
|
<input type="text" id="saved-options2" class="form-control">
|
||||||
|
{{lang.add_page.desc.saved_options}}
|
||||||
|
</div>
|
||||||
|
<textarea name="option" title="Options thru" cols=80 rows=5 id="optionsInput2" placeholder="acl test hdr_beg(host) -i some_host"></textarea>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.servers|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{% include 'include/add/add_servers.html' %}
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
{{ checkbox('template-backend', name='template', title=lang.add_page.desc.server_template, value='template', desc=lang.add_page.desc.server_template) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.check|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<div>
|
||||||
|
<label for="controlgroup-backend-show" style="margin-top: 5px;" title="Set custom check parameters">{{lang.words.custom|title()}} {{lang.words.check}} {{lang.words.params}}</label>
|
||||||
|
<input type="checkbox" id="controlgroup-backend-show" name="default-check">
|
||||||
|
<span class="tooltip tooltipTop">{{lang.add_page.desc.def_check}}: inter 2000 rise 2 fall 5</span>
|
||||||
|
</div>
|
||||||
|
<div class="controlgroup" id="controlgroup-backend" style="display: none;">
|
||||||
|
<label for="check-servers-backend" title="Enable servers check">{{lang.words.check|title()}}</label>
|
||||||
|
<input type="checkbox" id="check-servers-backend" name="check-servers" checked value="1">
|
||||||
|
{% set values = {'1000':'1000','2000':'2000','3000':'3000'} %}
|
||||||
|
{{ select('inter-backend', name='inter', values=values, first='2000', class='force_close') }}
|
||||||
|
{% set values = {'1':'1','2':'2','3':'3'} %}
|
||||||
|
{{ select('rise-backend', name='rise', values=values, first='2', class='force_close') }}
|
||||||
|
{% set values = {'4':'4','5':'5','6':'6'} %}
|
||||||
|
{{ select('fall-backend', name='fall', values=values, first='5', class='force_close') }}
|
||||||
|
</div>
|
||||||
|
<div style="display: block">
|
||||||
|
{{ checkbox('backend_circuit_breaking', name="circuit_breaking", desc='Circuit Breaking', title=lang.add_page.desc.circuit_breaking, value='1') }}
|
||||||
|
</div>
|
||||||
|
<div id="backend_circuit_breaking" style="display: none">
|
||||||
|
Observe:
|
||||||
|
{{ select('circuit_breaking_observe', values=observe, class='force_close') }}
|
||||||
|
error-limit: {{ input('circuit_breaking_error_limit', type='number', value='50', style='width: 50px;') }}
|
||||||
|
on-error:
|
||||||
|
{{ select('circuit_breaking_on_error', values=on_error, class='force_close') }}
|
||||||
|
<div class="tooltip tooltipTop">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} Circuit Breaking <a href="https://roxy-wi.org/description/circuit-breaking" title="Circuit Breaking" target="_blank">{{lang.words.here}}</a></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance-show">
|
||||||
|
<td class="addOption" colspan="2">
|
||||||
|
<button title="{{lang.add_page.buttons.show_full_settings}}" class="row-down advance-show-button">{{lang.words.show|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
||||||
|
<button title="{{lang.add_page.buttons.hide_full_settings}}" class="row-up advance-hide-button" style="display: none">{{lang.words.hide|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="backend-add-buttons">
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="backend-add-button" title="{{lang.words.add|title()}} {{lang.words.backend|title()}}" onclick="addProxy('add-backend')">{{lang.words.add|title()}} {{lang.words.backend|title()}}</a>
|
||||||
|
</td>
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="backend-generate-button" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="addProxy('add-backend', 'true')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -0,0 +1,83 @@
|
||||||
|
<form name="add-defaults" id="add-defaults" action="/add/haproxy/defaults" method="post">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('defaults_serv', name='server', values=g.user_params['servers'], is_servers='true', by_id=1) }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-name', name='name', title="defaults "+lang.words.name, value="name") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.log|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-log', name='log', placeholder="global") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.retries|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-retries', name='retries', type='number') }}
|
||||||
|
<div class="tooltip tooltipTop">Set the number of retries to perform on a server after a failure</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Maxconn:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-maxconn', name='maxconn', type='number') }}
|
||||||
|
<div class="tooltip tooltipTop">Sets the maximum per-process number of concurrent connections to number.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout http request:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_http_request', name='http_request', placeholder="10", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout queue:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_queue', name='queue', placeholder="60", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout connect:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_connect', name='connect', placeholder="10", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout client:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_client', name='client', placeholder="60", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout server:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_server', name='server', placeholder="60", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout check:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_check', name='check', placeholder="10", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Timeout http keep alive:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('defaults-timeout_http_keep_alive', name='http_keep_alive', placeholder="10", type="number") }}{{ lang.words.seconds2 }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{ lang.add_page.buttons.set_options }}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<textarea name="option" title="Options thru" cols=80 rows=5 placeholder="ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets"></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -0,0 +1,184 @@
|
||||||
|
<form name="add-frontend" id="add-frontend" action="/add/haproxy/add" method="post">
|
||||||
|
<table>
|
||||||
|
<caption><h3>{{lang.words.add|title()}} {{lang.words.frontend}}</h3></caption>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('serv2', name='server', values=g.user_params['servers'], is_servers='true', by_id=1) }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
<td rowspan="5" class="add-note addName alert-info">
|
||||||
|
{{lang.add_page.desc.front_desc1}}
|
||||||
|
<br /><br />
|
||||||
|
{{lang.add_page.desc.listener_desc2}}
|
||||||
|
<br /><br />
|
||||||
|
{{lang.add_page.desc.listener_desc1}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.name|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<input type="text" name="name" id="new_frontend" required title="{{lang.words.name|title()}} {{lang.words.frontend}}" placeholder="web_80" class="form-control">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">IP and {{lang.words.port|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<div id="frontend_bind">
|
||||||
|
<p>
|
||||||
|
<input type="text" name="ip" id="ip1" size="15" placeholder="Any" class="form-control"><b>:</b>
|
||||||
|
<input type="text" name="port" size="5" required title="{{lang.add_page.desc.port_for_bind}} {{lang.words.frontend}}" placeholder="8080" class="form-control">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<a class="link add-server" id="add_bind_frontend" title="{{lang.add_page.desc.bind_ip_pair}}"></a>
|
||||||
|
<div class="tooltip tooltipTop">
|
||||||
|
{{lang.add_page.desc.ip_port}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.mode|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'http':'http','tcp':'tcp'} %}
|
||||||
|
{{ select('frontend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
|
||||||
|
<span id="https-frontend-span">
|
||||||
|
{{ checkbox('https-frontend', name='ssl', title=lang.add_page.desc.ssl_offloading, desc='SSL Offloading') }}
|
||||||
|
</span>
|
||||||
|
<div id="https-hide-frontend" style="display: none;">
|
||||||
|
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.name}} {{lang.words.of}} pem {{lang.words.file2}}, {{lang.add_page.desc.press_down}}:</span><br />
|
||||||
|
{{ input('path-cert-frontend', name="cert", placeholder="some_cert.pem", size='39') }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">Maxconn: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('maxconn', value='2000', type="number", title=lang.add_page.desc.maxconn_fix, size='5', required='required') }}
|
||||||
|
<div class="tooltip tooltipTop">{{lang.add_page.desc.maxconn_desc}}: 2000</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.headers|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span title="{{lang.words.add|title()}} {{lang.words.headers}}" id="add_frontend_header" class="link add-server"></span>
|
||||||
|
<div id="frontend_header_div" style="display: none;">
|
||||||
|
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="frontend_header_p">
|
||||||
|
{{ select('frontend_header_res_method', name='headers_res', values=header_res, first='------', class='force_close') }}
|
||||||
|
{{ select('frontend_header_method', name='headers_method', values=header_params, selected='add-header', class='force_close') }}
|
||||||
|
<b class="padding10">{{lang.words.name}}</b>
|
||||||
|
{{ input('frontend_header_name', name="header_name") }}
|
||||||
|
<b class="padding10">{{lang.words.value}}</b>
|
||||||
|
{{ input('frontend_header_value', name="header_value", placeholder='Leave blank if using del-header') }}
|
||||||
|
<span class="minus minus-style" onclick="deleteId('frontend_header_p')" title="{{lang.words.delete|title()}}"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server" id="frontend_add_header" title="{{lang.words.add|title()}} {{lang.words.headers}}" style="display: none;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName" title="Access control list">ACL: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span title="{{lang.words.add|title()}} ACL" id="add_frontend_acl" class="link add-server"></span>
|
||||||
|
<div id="frontend_acl" style="display: none;">
|
||||||
|
<p id="frontend_acl_rule" style="border-bottom: 1px solid #ddd; padding-bottom: 10px;">
|
||||||
|
<b class="padding10">{{lang.words.if|title()}}</b>
|
||||||
|
{{ select('frontend_acl_if', name='acl_if', values=if_values, first='Select if', class='force_close', disabled=false) }}
|
||||||
|
<b class="padding10">{{ lang.words.value }}</b>
|
||||||
|
{{ input('frontend_acl_value', name='acl_value') }}
|
||||||
|
<b class="padding10">{{ lang.words.then }}</b>
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'5':'Use backend','2':'Redirect to','3':'Allow','4':'Deny', '6': 'Return', '7': 'Set-header'} %}
|
||||||
|
{{ select('frontend_acl_then', name='acl_then', values=values, first='Select then', class='force_close', disabled=false) }}
|
||||||
|
<b class="padding10">{{ lang.words.value }}</b>
|
||||||
|
{{ input('frontend_acl_then_value', name='acl_then_value', title="Required if \'then\' is \'Use backend\' or \'Redirect\', \'Return\', or \'Set-header\'") }}
|
||||||
|
<span class="minus minus-style" onclick="deleteId('frontend_acl_rule')" title="{{lang.words.delete|title()}}"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server" id="frontend_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web {{lang.words.acceleration}}:</span></td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('compression2', name="compression", title=lang.add_page.desc.http_compression, value='1', desc=lang.words.compression|title()) }}
|
||||||
|
{{ checkbox('cache2', name="cache", title=lang.words.enable|title()+' '+lang.words.cache, value='2', desc=lang.words.cache|title()) }}
|
||||||
|
{{ checkbox('ssl_offloading1', name='ssl_offloading', title=lang.add_page.desc.http_https, desc='HTTP->HTTPS') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName"><span title="Web application firewall" class="help_cursor">WAF:</span></td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('slow_attack1', title=lang.add_page.desc.slow_attack,
|
||||||
|
desc='Slow attack') }}
|
||||||
|
{{ checkbox('ddos1', title='DDOS attack protect', desc='DDOS') }}
|
||||||
|
{{ checkbox('frontend_whitelist_checkbox', name='whitelist_checkbox', title=lang.words.enable|title()+' '+ lang.words.whitelist, desc=lang.words.whitelist|title()) }}
|
||||||
|
{{ checkbox('frontend_blacklist_checkbox', name='blacklist_checkbox', title=lang.words.enable|title()+' '+ lang.words.blacklist, desc=lang.words.blacklist|title()) }}
|
||||||
|
{{ checkbox('waf2', name='waf', title='Web application firewall', desc='WAF', value='1') }}
|
||||||
|
{{ checkbox('antibot1', name='antibot', title=lang.add_page.desc.antibot, desc='Antibot', value='1') }}
|
||||||
|
</span>
|
||||||
|
<div id="frontend_blacklist-hide" style="display: none;">
|
||||||
|
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.blacklist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
||||||
|
{{ input('frontend_blacklist-hide-input', size='39', name="blacklist", placeholder="blacklist.lst") }}
|
||||||
|
</div>
|
||||||
|
<div id="frontend_whitelist-hide" style="display: none;">
|
||||||
|
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.whitelist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
||||||
|
{{ input('frontend_whitelist-hide-input', size='39', name="whitelist", placeholder="whitelist.lst") }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.options|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('forward_for1', name='forward_for', title=lang.add_page.desc.forward_for, desc='Forward for') }}
|
||||||
|
{{ checkbox('options-frontend-show', title=lang.add_page.buttons.set_options_m, desc=lang.add_page.buttons.set_options) }}
|
||||||
|
</span>
|
||||||
|
<div id="options-frontend-show-div" style="display: none;">
|
||||||
|
<div style="font-size: 12px; padding-bottom: 10px;">
|
||||||
|
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.options}}: </span>
|
||||||
|
{{ input('options1') }}
|
||||||
|
<span style="padding-left: 10px;">
|
||||||
|
{{lang.add_page.desc.press_down}}. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAProxy docs">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} {{lang.words.options}}</a>
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.saved}} {{lang.words.options}}:</span>
|
||||||
|
{{ input('saved-options1') }}
|
||||||
|
{{lang.add_page.desc.saved_options}}
|
||||||
|
</div>
|
||||||
|
<textarea name="option" title="Options thru" cols=80 rows=5 id="optionsInput1" placeholder="acl test hdr_beg(host) -i some_host"></textarea>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.default_backend}}</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('backends', name='backends', placeholder="some_backend", size='30', title=lang.add_page.desc.no_def_backend) }}
|
||||||
|
<div class="tooltip tooltipTop">
|
||||||
|
<b>{{lang.words.note|title()}}</b>: {{lang.add_page.desc.def_backend}}, <span title="{{lang.words.create|title()}} {{lang.words.backend}}" class="redirectBackend link">{{lang.add_page.desc.def_backend_exit}}</span>.
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance-show">
|
||||||
|
<td class="addOption" colspan="2">
|
||||||
|
<button title="{{lang.add_page.buttons.show_full_settings}}" class="row-down advance-show-button">{{lang.words.show|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
||||||
|
<button title="{{lang.add_page.buttons.hide_full_settings}}" class="row-up advance-hide-button" style="display: none">{{lang.words.hide|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="frontend-add-buttons">
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="frontend-add-button" title="{{lang.words.add|title()}} {{lang.words.frontend|title()}}" onclick="addProxy('add-frontend')">{{lang.words.add|title()}} {{lang.words.frontend|title()}}</a>
|
||||||
|
</td>
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="frontend-generate-button" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="addProxy('add-frontend', 'true')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -0,0 +1,79 @@
|
||||||
|
<form name="add-global" id="add-global" action="/add/haproxy/global" method="post">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
{# <td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>#}
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('global_serv', name='server', values=g.user_params['servers'], is_servers='true', by_id=1) }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{# <td class="addName">global {{lang.words.name}}:</td>#}
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('global-name', name='name', title="global "+lang.words.name, value="name") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.log|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<textarea name="log" cols=60 rows=3></textarea>
|
||||||
|
<div class="tooltip tooltipTop">Adds a global syslog server. Several global servers can be defined. They will receive logs for starts and exits</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Chroot:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('global-chroot', name='chroot', placeholder="/var/lib/haproxy") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Pidfile:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('global-pidfile', name='pidfile', placeholder="/var/run/haproxy.pid") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Maxconn:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('global-maxconn', name='maxconn', placeholder="5000", type="number") }}
|
||||||
|
<div class="tooltip tooltipTop">Sets the maximum per-process number of concurrent connections to number.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.user|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('global-user', name='user', placeholder="haproxy") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.group|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('global-group', name='group', placeholder="haproxy") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Stats socket:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<textarea name="socket" title="Binds a UNIX socket" cols=60 rows=4 placeholder="*:1999 level admin"></textarea>
|
||||||
|
<div class="tooltip tooltipTop">
|
||||||
|
Binds a UNIX socket to path or a TCPv4/v6 address to address:port.
|
||||||
|
Connections to this socket will return various statistics outputs and even allow some commands to
|
||||||
|
be issued to change some runtime settings.
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Daemon:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ checkbox('global-daemon', name='daemon') }}
|
||||||
|
<div class="tooltip tooltipTop">Makes the process fork into background. This is the recommended mode of operation.</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{ lang.add_page.buttons.set_options }}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<textarea name="option" title="Options thru" cols=80 rows=5 placeholder="ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets"></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -0,0 +1,254 @@
|
||||||
|
<form name="add-listen" id="add-listen" action="/add/haproxy/add" method="post">
|
||||||
|
<table>
|
||||||
|
<caption><h3>{{lang.words.add|title()}} {{lang.words.listener}}</h3></caption>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('serv', name='server', values=g.user_params['servers'], is_servers='true', by_id=1) }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
<td rowspan="5" class="add-note addName alert-info">
|
||||||
|
{{lang.add_page.desc.listener_desc1}}
|
||||||
|
<br /><br />
|
||||||
|
{{lang.add_page.desc.listener_desc2}}
|
||||||
|
<br /><br />
|
||||||
|
{{lang.add_page.desc.listener_desc3}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.name|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('listener', name='name', title=lang.words.name|title() + ' ' +lang.words.listener, placeholder="web_80", required='required') }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">IP and {{lang.words.port|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<div id="listen_bind">
|
||||||
|
<p>
|
||||||
|
{{ input('ip', placeholder="Any", size='15') }}<b>:</b>
|
||||||
|
{{ input('listen-port', name='port', title=lang.add_page.desc.port_for_bind + ' ' + lang.words.listener, placeholder="8080", size='5', required='required') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<a class="link add-server" id="add_bind_listen" title="{{lang.add_page.desc.bind_ip_pair}}"></a>
|
||||||
|
<div class="tooltip tooltipTop">
|
||||||
|
{{lang.add_page.desc.ip_port}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.mode|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'http':'http','tcp':'tcp'} %}
|
||||||
|
{{ select('listen-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
|
||||||
|
<span id="https-listen-span">
|
||||||
|
<label for="https-listen" style="margin-top: 5px;" title="{{lang.words.enable|title()}} SSL Offloading" data-help="{{lang.add_page.desc.ssl_offloading}}">SSL Offloading</label>
|
||||||
|
<input type="checkbox" id="https-listen" name="ssl" value="https" >
|
||||||
|
</span>
|
||||||
|
<div id="https-hide-listen" style="display: none;">
|
||||||
|
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.name}} {{lang.words.of}} pem {{lang.words.file2}}, {{lang.add_page.desc.press_down}}:</span><br />
|
||||||
|
{{ input('path-cert-listen', name="cert", placeholder="some_cert.pem", size='39') }}<br />
|
||||||
|
<label for="ssl-check-listen" style="margin-top: 5px;">{{lang.add_page.buttons.disable_ssl_verify}}</label><input type="checkbox" id="ssl-check-listen" name="ssl-check" value="ssl-check" checked>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">Maxconn: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('listen_maxconn', name='maxconn', value='2000', type="number", title=lang.add_page.desc.maxconn_fix, size='5', required='required') }}
|
||||||
|
<div class="tooltip tooltipTop">{{lang.add_page.desc.maxconn_desc}}: 2000</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.balance|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('balance', values=balance_params, selected='roundrobin', required='required', class='force_close') }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.health|title()}} {{lang.words.check}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('listen_checks', name='health_check', values=checks, selected='', class='force_close') }}
|
||||||
|
<span id="listen_checks_note" class="tooltip tooltipTop"></span>
|
||||||
|
<br />
|
||||||
|
<span id="listen_checks_http" style="display: none;">
|
||||||
|
URI path for checking: {{ input('listen_checks_http_path', name='checks_http_path', value='/', title="URI for checking e.g. /check") }}
|
||||||
|
Domain name: {{ input('listen_checks_http_domain', name='checks_http_domain', placeholder='domain.com', title="Domain name for checking e.g. domain.com") }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.headers|title()}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span title="{{lang.words.add|title()}} {{lang.words.headers}}" id="add_listen_header" class="link add-server"></span>
|
||||||
|
<div id="listen_header_div" style="display: none;">
|
||||||
|
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="listen_header_p">
|
||||||
|
{{ select('listen_header_res_method', name='headers_res', values=header_res, first='------', class='force_close') }}
|
||||||
|
{{ select('listen_header_method', name='headers_method', values=header_params, selected='add-header', class='force_close') }}
|
||||||
|
<b class="padding10">{{lang.words.name}}</b>
|
||||||
|
{{ input('listen_header_name', name="header_name") }}
|
||||||
|
<b class="padding10">{{lang.words.value}}</b>
|
||||||
|
{{ input('listen_header_value', name="header_value", placeholder='Leave blank if using del-header') }}
|
||||||
|
<span class="minus minus-style" onclick="deleteId('listen_header_p')" title="{{lang.words.delete|title()}}"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server" id="listen_add_header" title="{{lang.words.add|title()}} {{lang.words.headers}}" style="display: none;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName" title="Access control list">ACL: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span title="{{lang.words.add|title()}} ACL" id="add_listen_acl" class="link add-server"></span>
|
||||||
|
<div id="listen_acl" style="display: none;">
|
||||||
|
<p style="border-bottom: 1px solid #ddd; padding-bottom: 10px;" id="listen_acl_rule">
|
||||||
|
<b class="padding10">{{lang.words.if|title()}}</b>
|
||||||
|
{{ select('listen_acl_if', name='acl_if', values=if_values, first='Select if', class='force_close', disabled=false) }}
|
||||||
|
<b class="padding10">{{lang.words.value}}</b>
|
||||||
|
{{ input('listen_acl_value', name="acl_value") }}
|
||||||
|
<b class="padding10">{{lang.words.then}}</b>
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'2':'Redirect to','3':'Allow','4':'Deny', '6': 'Return', '7': 'Set-header'} %}
|
||||||
|
{{ select('listen_acl_then', name='acl_then', values=values, first='Select then', class='force_close', disabled=false) }}
|
||||||
|
<b class="padding10">{{lang.words.value}}</b>
|
||||||
|
{{ input('listen_acl_then_value', name='acl_then_value', title="Required if \'then\' is \'Use backend\' or \'Redirect\', \'Return\', or \'Set-header\'") }}
|
||||||
|
<span class="minus minus-style" onclick="deleteId('listen_acl_rule')" title="{{lang.words.delete|title()}} {{lang.words.this}} ACL"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server" id="listen_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web {{lang.words.acceleration}}:</span></td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('compression', title=lang.add_page.desc.http_compression, value='1', desc=lang.words.compression|title()) }}
|
||||||
|
{{ checkbox('cache', title=lang.words.enable|title()+' '+lang.words.cache, value='2', desc=lang.words.cache|title()) }}
|
||||||
|
{{ checkbox('ssl_offloading', title=lang.add_page.desc.http_https, desc='HTTP->HTTPS') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName"><span title="Web application firewall" class="help_cursor">WAF:</span></td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('slow_attack', title=lang.add_page.desc.slow_attack,
|
||||||
|
desc='Slow attack') }}
|
||||||
|
{{ checkbox('ddos', title='DDOS attack protect', desc='DDOS') }}
|
||||||
|
{{ checkbox('listen_whitelist_checkbox', name='whitelist_checkbox', title=lang.words.enable|title()+' '+ lang.words.whitelist, desc=lang.words.whitelist|title()) }}
|
||||||
|
{{ checkbox('listen_blacklist_checkbox', name='blacklist_checkbox', title=lang.words.enable|title()+' '+ lang.words.blacklist, desc=lang.words.blacklist|title()) }}
|
||||||
|
{{ checkbox('waf', title='Web application firewall', desc='WAF', value='1') }}
|
||||||
|
{{ checkbox('antibot', title=lang.add_page.desc.antibot, desc='Antibot', value='1') }}
|
||||||
|
</span>
|
||||||
|
<div id="listen_blacklist-hide" style="display: none;">
|
||||||
|
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.blacklist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
||||||
|
{{ input('listen_blacklist-hide-input', size='39', name="blacklist", placeholder="blacklist.lst") }}
|
||||||
|
</div>
|
||||||
|
<div id="listen_whitelist-hide" style="display: none;">
|
||||||
|
<br /><span class="tooltip tooltipTop">{{lang.words.enter2|title()}} {{lang.words.w_a}} {{lang.words.whitelist}} {{lang.words.name}}, {{lang.add_page.desc.press_down}}:</span><br />
|
||||||
|
{{ input('listen_whitelist-hide-input', size='39', name="whitelist", placeholder="whitelist.lst") }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.options|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span class="controlgroup">
|
||||||
|
{{ checkbox('forward_for', title=lang.add_page.desc.forward_for, desc='Forward for') }}
|
||||||
|
{{ checkbox('redispatch', title=lang.add_page.desc.redispatch, desc='Redispatch') }}
|
||||||
|
{{ checkbox('listen_cookie', name='cookie', title=lang.add_page.desc.cookie, desc=lang.words.set|title()+' cookie', value='1') }}
|
||||||
|
{{ checkbox('options-listen-show', title=lang.add_page.buttons.set_options_m, desc=lang.add_page.buttons.set_options) }}
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
<span id="listen_cookie_div" style="display: none;">
|
||||||
|
<input type="text" placeholder="name" name="cookie_name" id="listen_cookie_name" class="form-control"><br><br>
|
||||||
|
<input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br>
|
||||||
|
<span class="controlgroup">
|
||||||
|
{% set values = dict() %}
|
||||||
|
{% set values = {'None':'None','rewrite':'rewrite','indirect':'indirect','insert':'insert'} %}
|
||||||
|
{{ select('listen_rewrite', name='rewrite', values=values, first='rewrite/indirect/insert', class='force_close') }}
|
||||||
|
{{ checkbox('listen_prefix', name='prefix', title=lang.add_page.desc.c_prefix, desc='prefix', value='prefix') }}
|
||||||
|
{{ checkbox('listen_nocache', name='nocache', title=lang.add_page.desc.c_nocache, desc='nocache', value='nocache') }}
|
||||||
|
{{ checkbox('listen_postonly', name='postonly', title=lang.add_page.desc.c_postonly, desc='postonly', value='postonly') }}
|
||||||
|
{{ checkbox('listen_dynamic', name='dynamic', title=lang.add_page.desc.c_dynamic, desc='dynamic', value='dynamic') }}
|
||||||
|
<span id="listen_dynamic_div" style="display: none;">
|
||||||
|
dynamic-cookie-key: {{ input('listen_dynamic-cookie-key', name='dynamic-cookie-key', placeholder="your-custom-key") }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div id="options-listen-show-div" style="display: none;">
|
||||||
|
<div class="tooltip">
|
||||||
|
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.options}}: </span>
|
||||||
|
{{ input('options') }}
|
||||||
|
<span style="padding-left: 10px;">
|
||||||
|
{{lang.add_page.desc.press_down}}. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAProxy docs">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} {{lang.words.options}}</a>
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
<span style="padding-right: 10px;">{{lang.words.start2|title()}} {{lang.words.typing}} {{lang.words.saved}} {{lang.words.options}}: </span>
|
||||||
|
{{ input('saved-options') }}
|
||||||
|
{{lang.add_page.desc.saved_options}}
|
||||||
|
</div>
|
||||||
|
<textarea name="option" title="Options thru" id="optionsInput" cols=80 rows=5 placeholder="acl test hdr_beg(host) -i some_host"></textarea>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.servers|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{% include 'include/add/add_servers.html' %}
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
{{ checkbox('template-listen', name='template', title=lang.add_page.desc.server_template, value='template', desc=lang.add_page.desc.server_template) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance">
|
||||||
|
<td class="addName">{{lang.words.check|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<div>
|
||||||
|
<label for="controlgroup-listen-show" style="margin-top: 5px;" title="Set custom check parameters">{{lang.words.custom|title()}} {{lang.words.check}} {{lang.words.params}}</label>
|
||||||
|
<input type="checkbox" id="controlgroup-listen-show" name="default-check" value="1">
|
||||||
|
<span class="tooltip tooltipTop">{{lang.add_page.desc.def_check}}: inter 2000 rise 2 fall 5</span>
|
||||||
|
</div>
|
||||||
|
<div class="controlgroup" id="controlgroup-listen" style="display: none;">
|
||||||
|
<label for="check-servers-listen" title="Ebable servers check">{{lang.words.check|title()}}</label>
|
||||||
|
<input type="checkbox" id="check-servers-listen" name="check-servers" checked value="1">
|
||||||
|
{% set values = {'1000':'1000','2000':'2000','3000':'3000'} %}
|
||||||
|
{{ select('inter-listen', name='inter', values=values, first='1000', class='force_close') }}
|
||||||
|
{% set values = {'1':'1','2':'2','3':'3'} %}
|
||||||
|
{{ select('rise-listen', name='rise', values=values, first='2', class='force_close') }}
|
||||||
|
{% set values = {'4':'4','5':'5','6':'6'} %}
|
||||||
|
{{ select('fall-listen', name='fall', values=values, first='5', class='force_close') }}
|
||||||
|
</div>
|
||||||
|
<div style="display: block">
|
||||||
|
{{ checkbox('listen_circuit_breaking', name="circuit_breaking", desc='Circuit Breaking', title=lang.add_page.desc.circuit_breaking, value='1') }}
|
||||||
|
</div>
|
||||||
|
<div id="listen_circuit_breaking_div" style="display: none">
|
||||||
|
Observe:
|
||||||
|
{{ select('listen_circuit_breaking_observe', name='circuit_breaking_observe', values=observe, class='force_close') }}
|
||||||
|
error-limit: {{ input('listen_circuit_breaking_error_limit', name='circuit_breaking_error_limit', type='number', value='50', style='width: 50px;') }}
|
||||||
|
on-error:
|
||||||
|
{{ select('listen_circuit_breaking_on_error', name='circuit_breaking_on_error', values=on_error, class='force_close') }}
|
||||||
|
<div class="tooltip tooltipTop">{{lang.words.read|title()}} {{lang.words.more}} {{lang.words.about}} Circuit Breaking <a href="https://roxy-wi.org/description/circuit-breaking" title="Circuit Breaking" target="_blank">{{lang.words.here}}</a></div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="advance-show">
|
||||||
|
<td class="addOption" colspan="2">
|
||||||
|
<button title="{{lang.add_page.buttons.show_full_settings}}" class="row-down advance-show-button">{{lang.words.show|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
||||||
|
<button title="{{lang.add_page.buttons.hide_full_settings}}" class="row-up advance-hide-button" style="display: none">{{lang.words.hide|title()}} {{lang.words.advanced}} {{lang.words.settings}}</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="listen-add-buttons">
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="listen-add-button" title="{{lang.words.add|title()}} {{lang.words.listener|title()}}" onclick="addProxy('add-listen')">{{lang.words.add|title()}} {{lang.words.linstener|title()}}</a>
|
||||||
|
</td>
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="listen-generate-button" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="addProxy('add-listen', 'true')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -0,0 +1,49 @@
|
||||||
|
<form name="add-peers" id="add-peers" action="/add/haproxy/peers" method="post">
|
||||||
|
<table>
|
||||||
|
<caption><h3>{{lang.words.add|title()}} Peer</h3></caption>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('peers_serv', name='server', values=g.user_params['servers'], is_servers='true', by_id=1) }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
<td rowspan="4" class="add-note addName alert-info">
|
||||||
|
{{lang.add_page.desc.peers}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Peers {{lang.words.name}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('peers-name', name='name', title="Peers "+lang.words.name, placeholder="peers name") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">Peers {{lang.words.servers}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span name="add_peers" id="add_peers">
|
||||||
|
<p>
|
||||||
|
<input name="servers_name" required title="Peer {{lang.words.name}}" size=14 placeholder="haproxy1" class="form-control">:
|
||||||
|
<input name="servers" required title="Peer IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
|
||||||
|
<input name="server_port" required title="Peer {{lang.words.port}}" size=3 placeholder="yyy" class="form-control add_server_number" type="number">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input name="servers_name" required title="Peer {{lang.words.name}}" size=14 placeholder="haproxy2" class="form-control">:
|
||||||
|
<input name="servers" title="Peer IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
|
||||||
|
<input name="server_port" title="Peer {{lang.words.port}}" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number">
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<a class="link add-server backend_server" name="add-peer-input" title="{{lang.words.add|title()}} peer {{lang.words.server}}" style="cursor: pointer;"></a>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="peers-add-buttons">
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="peers-add-button" title="{{lang.words.add|title()}} peer" onclick="addProxy('add-peers')">{{lang.words.add|title()}} peer</a>
|
||||||
|
</td>
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="peers-generate-button" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="addProxy('add-peers', 'true')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -0,0 +1,57 @@
|
||||||
|
<form name="add-userlist" id="add-userlist" action="/add/haproxy/userlist" method="post">
|
||||||
|
<table>
|
||||||
|
<caption><h3>{{lang.words.add|title()}} {{lang.words.userlists}}</h3></caption>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.select|title()}} {{lang.words.w_a}} {{lang.words.server}}: </td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ select('userlist_serv', name='server', values=g.user_params['servers'], is_servers='true') }}
|
||||||
|
<div class="tooltip tooltipTop"><b>{{lang.words.note|title()}}:</b> {{lang.phrases.master_slave}}</div>
|
||||||
|
</td>
|
||||||
|
<td rowspan="4" class="add-note addName alert-info">{{lang.add_page.desc.userlist_desc}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.name|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
{{ input('new_userlist', name='name', required='required', title=lang.add_page.desc.userlist_name, placeholder="basic-auth-list") }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.groups|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span id="userlist-groups">
|
||||||
|
<p>
|
||||||
|
{{ input('userlist-group', title=lang.add_page.desc.userlist_user_grp, placeholder="group_name") }}
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<span class="link add-server" id="add-userlist-group" title="Add extra group" style="cursor: pointer;"></span>
|
||||||
|
</span>
|
||||||
|
<div class="tooltip tooltipTop">{{lang.add_page.desc.userlist_group}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="addName">{{lang.words.user|title()}}:</td>
|
||||||
|
<td class="addOption">
|
||||||
|
<span id="userlist-users">
|
||||||
|
<p>
|
||||||
|
{{ input('userlist-user', required='required', title=lang.words.username|title(), placeholder="user_name") }}
|
||||||
|
{{ input('userlist-password', required='required', title=lang.add_page.desc.userlist_pass, placeholder="password") }}
|
||||||
|
{{ input('userlist-user-group', title=lang.add_page.desc.userlist_user_grp, placeholder="group") }}
|
||||||
|
</p>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<span class="link add-server" id="add-userlist-user" title="Add extra user" style="cursor: pointer;"></span>
|
||||||
|
</span>
|
||||||
|
<div class="tooltip tooltipTop">{{lang.add_page.desc.userlist_user}}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="userlist-add-buttons">
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="userlist-add-button" title="Add Userlist" onclick="addProxy('add-userlist')">{{lang.words.add|title()}} {{lang.words.userlist|title()}}</a>
|
||||||
|
</td>
|
||||||
|
<td class="addButton">
|
||||||
|
<a class="ui-button ui-widget ui-corner-all" id="userlist-generate-button" title="{{lang.words.generate|title()}} {{lang.words.and}} {{lang.words.display}} {{lang.words.config}}" onclick="addProxy('add-userlist', 'true')">{{lang.words.generate|title()}} {{lang.words.config}}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
|
@ -35,7 +35,7 @@
|
||||||
<link href="{{ url_for('static', filename='css/nprogress.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/nprogress.css') }}" rel="stylesheet">
|
||||||
<link href="{{ url_for('static', filename='css/jquery-ui.min.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/jquery-ui.min.css') }}" rel="stylesheet">
|
||||||
<link href="{{ url_for('static', filename='css/jquery-ui.structure.min.css') }}" rel="stylesheet">
|
<link href="{{ url_for('static', filename='css/jquery-ui.structure.min.css') }}" rel="stylesheet">
|
||||||
<script src="/static/js/jquery-3.6.0.min.js"></script>
|
<script src="/static/js/jquery-3.7.1.min.js"></script>
|
||||||
<script src="/static/js/jquery-ui.min.js"></script>
|
<script src="/static/js/jquery-ui.min.js"></script>
|
||||||
<script src="/static/js/js.cookie.min.js"></script>
|
<script src="/static/js/js.cookie.min.js"></script>
|
||||||
<script src="/static/js/reconnecting-websocket.js"></script>
|
<script src="/static/js/reconnecting-websocket.js"></script>
|
||||||
|
|
|
@ -951,6 +951,7 @@
|
||||||
"listeners": "listeners",
|
"listeners": "listeners",
|
||||||
"weight": "weight",
|
"weight": "weight",
|
||||||
"where": "where",
|
"where": "where",
|
||||||
"shared": "shared"
|
"shared": "shared",
|
||||||
|
"retries": "retries",
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -951,6 +951,7 @@
|
||||||
"listeners": "les auditeurs",
|
"listeners": "les auditeurs",
|
||||||
"weight": "poids",
|
"weight": "poids",
|
||||||
"where": "où",
|
"where": "où",
|
||||||
"shared": "commun"
|
"shared": "commun",
|
||||||
|
"retries": "tentatives",
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -951,6 +951,7 @@
|
||||||
"listeners": "ouvintes",
|
"listeners": "ouvintes",
|
||||||
"weight": "peso",
|
"weight": "peso",
|
||||||
"where": "onde",
|
"where": "onde",
|
||||||
"shared": "partilhado"
|
"shared": "partilhado",
|
||||||
|
"retries": "novas tentativas",
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -951,6 +951,7 @@
|
||||||
"listeners": "слушатели",
|
"listeners": "слушатели",
|
||||||
"weight": "вес",
|
"weight": "вес",
|
||||||
"where": "где",
|
"where": "где",
|
||||||
"shared": "общий"
|
"shared": "общий",
|
||||||
|
"retries": "повторные попытки",
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -11,6 +11,70 @@ import app.modules.service.installation as service_mod
|
||||||
from app.middleware import get_user_params, check_services, page_for_admin, check_group
|
from app.middleware import get_user_params, check_services, page_for_admin, check_group
|
||||||
from app.modules.common.common_classes import SupportClass
|
from app.modules.common.common_classes import SupportClass
|
||||||
from app.modules.roxywi.class_models import BaseResponse, ServiceInstall
|
from app.modules.roxywi.class_models import BaseResponse, ServiceInstall
|
||||||
|
from app.views.service.views import ServiceView
|
||||||
|
|
||||||
|
|
||||||
|
class InstallGetStatus(ServiceView):
|
||||||
|
methods = ['GET']
|
||||||
|
decorators = [jwt_required(), get_user_params(), check_services, page_for_admin(level=3), check_group()]
|
||||||
|
|
||||||
|
def get(self, service: Literal['haproxy', 'nginx', 'apache', 'keepalived'], server_id: Union[int, str]):
|
||||||
|
"""
|
||||||
|
This endpoint retrieves information about a specific service.
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- Service Installation
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: service
|
||||||
|
type: 'string'
|
||||||
|
required: true
|
||||||
|
description: The type of service (haproxy, nginx, apache, keepalived)
|
||||||
|
- in: path
|
||||||
|
name: server_id
|
||||||
|
type: 'integer'
|
||||||
|
required: true
|
||||||
|
description: The ID or IP of the server
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Successful operation
|
||||||
|
schema:
|
||||||
|
type: 'object'
|
||||||
|
properties:
|
||||||
|
CurrConns:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Current connections to HAProxy (only for HAProxy service)'
|
||||||
|
Maxconn:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Maximum connections to HAProxy (only for HAProxy service)'
|
||||||
|
MaxconnReached:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Max connections reached (only for HAProxy service)'
|
||||||
|
Memmax_MB:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Maximum memory in MB (only for HAProxy service)'
|
||||||
|
PoolAlloc_MB:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Memory pool allocated in MB (only for HAProxy service)'
|
||||||
|
PoolUsed_MB:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Memory pool used in MB (only for HAProxy service)'
|
||||||
|
Uptime:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Time the service has been active'
|
||||||
|
Version:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Version of the service'
|
||||||
|
Process:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Number of processes launched by the service'
|
||||||
|
Status:
|
||||||
|
type: 'string'
|
||||||
|
description: 'Status of the service'
|
||||||
|
default:
|
||||||
|
description: Unexpected error
|
||||||
|
"""
|
||||||
|
return super().get(service=service, server_id=server_id)
|
||||||
|
|
||||||
|
|
||||||
class InstallView(MethodView):
|
class InstallView(MethodView):
|
||||||
|
|
|
@ -597,7 +597,8 @@ class ServerIPView(MethodView):
|
||||||
methods = ["GET"]
|
methods = ["GET"]
|
||||||
decorators = [jwt_required(), get_user_params(), page_for_admin(level=3), check_group()]
|
decorators = [jwt_required(), get_user_params(), page_for_admin(level=3), check_group()]
|
||||||
|
|
||||||
def get(self, server_id: int):
|
@staticmethod
|
||||||
|
def get(server_id: int):
|
||||||
"""
|
"""
|
||||||
Retrieves IPs associated with a certain server.
|
Retrieves IPs associated with a certain server.
|
||||||
---
|
---
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue