This commit is contained in:
Gabenov Stanislav
2026-02-09 20:42:24 +03:00
parent 0a8f11397d
commit a6d2623802
38 changed files with 2198 additions and 1 deletions

View File

@@ -0,0 +1,47 @@
{
https_port 4123
default_bind 127.0.0.1
servers {
listener_wrappers {
proxy_protocol {
allow 127.0.0.1/32
}
tls
}
}
auto_https disable_redirects
}
https://$VLESS_DOMAIN {
$CADDY_REVERSE
header {
-Server
}
handle_errors {
header {
-Server
}
}
}
http://$VLESS_DOMAIN {
bind 0.0.0.0
redir https://$VLESS_DOMAIN{uri} permanent
header {
-Server
}
handle_errors {
header {
-Server
}
}
}
:4123 {
tls internal
respond 204
}
:80 {
bind 0.0.0.0
respond 204
}

View File

@@ -0,0 +1,9 @@
services:
caddy:
image: caddy:2.9
container_name: caddy
restart: always
network_mode: host
volumes:
- ./caddy/data:/data
- ./caddy/Caddyfile:/etc/caddy/Caddyfile

View File

@@ -0,0 +1,272 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Вход в Confluence</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background-color: #f4f5f7;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.login-container {
background-color: white;
padding: 40px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
width: 350px;
text-align: center;
}
.logo {
margin-bottom: 20px;
}
.logo img {
width: 120px;
}
h2 {
margin-bottom: 20px;
font-size: 24px;
color: #0052cc;
}
input[type="text"], input[type="password"] {
width: 100%;
padding: 10px;
margin: 10px 0;
border: 1px solid #dfe1e6;
border-radius: 4px;
box-sizing: border-box;
font-size: 16px;
}
.error {
border-color: red;
}
.error-message {
color: red;
font-size: 14px;
display: none;
margin-top: 10px;
}
button {
width: 100%;
padding: 10px;
background-color: #0052cc;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
margin-top: 20px;
}
button:hover {
background-color: #0747a6;
}
.help-links {
margin-top: 20px;
font-size: 14px;
}
.help-links a {
color: #0052cc;
text-decoration: none;
}
.help-links a:hover {
text-decoration: underline;
}
/* Стили для модального окна */
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
padding-top: 60px;
}
.modal-content {
background-color: white;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 400px;
border-radius: 8px;
text-align: center;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
</style>
</head>
<body>
<div class="login-container">
<div class="logo">
<img src="https://cdn.icon-icons.com/icons2/2429/PNG/512/confluence_logo_icon_147305.png" alt="Confluence">
</div>
<h2 id="login-title">Войти в Confluence</h2>
<form id="login-form">
<input type="text" id="username" name="username" placeholder="Адрес электронной почты">
<input type="password" id="password" name="password" placeholder="Введите пароль">
<button type="submit" id="login-button">Войти</button>
</form>
<div id="error-message" class="error-message">Неправильное имя пользователя или пароль.</div>
<div class="help-links">
<a href="#" id="forgot-link">Не удается войти?</a> • <a href="#" id="create-link">Создать аккаунт</a>
</div>
</div>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<p id="modal-text">Для создания аккаунта обратитесь к администратору.</p>
</div>
</div>
<script>
function setLanguage(lang) {
const elements = {
'ru': {
loginTitle: 'Войти в Confluence',
usernamePlaceholder: 'Адрес электронной почты',
passwordPlaceholder: 'Введите пароль',
loginButton: 'Войти',
forgotLink: 'Не удается войти?',
createLink: 'Создать аккаунт',
createAccountText: 'Для создания аккаунта обратитесь к администратору.',
forgotPasswordText: 'Для восстановления доступа обратитесь к администратору.',
errorMessage: 'Неправильное имя пользователя или пароль.'
},
'en': {
loginTitle: 'Login to Confluence',
usernamePlaceholder: 'Email address',
passwordPlaceholder: 'Enter password',
loginButton: 'Login',
forgotLink: 'Can\'t log in?',
createLink: 'Create an account',
createAccountText: 'To create an account, please contact your administrator.',
forgotPasswordText: 'To recover access, please contact your administrator.',
errorMessage: 'Incorrect username or password.'
}
};
document.getElementById('login-title').innerText = elements[lang].loginTitle;
document.getElementById('username').placeholder = elements[lang].usernamePlaceholder;
document.getElementById('password').placeholder = elements[lang].passwordPlaceholder;
document.getElementById('login-button').innerText = elements[lang].loginButton;
document.getElementById('forgot-link').innerText = elements[lang].forgotLink;
document.getElementById('create-link').innerText = elements[lang].createLink;
// Устанавливаем тексты для модальных окон и сообщений об ошибках
document.getElementById('create-link').dataset.modalText = elements[lang].createAccountText;
document.getElementById('forgot-link').dataset.modalText = elements[lang].forgotPasswordText;
document.getElementById('error-message').innerText = elements[lang].errorMessage;
}
function detectLanguage() {
const userLang = navigator.language || navigator.userLanguage;
if (userLang.startsWith('ru')) {
setLanguage('ru');
} else {
setLanguage('en');
}
}
document.addEventListener('DOMContentLoaded', detectLanguage);
var modal = document.getElementById("myModal");
var span = document.getElementsByClassName("close")[0];
function openModal(text) {
document.getElementById('modal-text').innerText = text;
modal.style.display = "block";
}
document.getElementById("create-link").onclick = function(event) {
event.preventDefault();
openModal(this.dataset.modalText);
}
document.getElementById("forgot-link").onclick = function(event) {
event.preventDefault();
openModal(this.dataset.modalText);
}
span.onclick = function() {
modal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
document.getElementById('login-form').onsubmit = function(event) {
event.preventDefault();
var username = document.getElementById('username');
var password = document.getElementById('password');
var errorMessage = document.getElementById('error-message');
username.classList.remove('error');
password.classList.remove('error');
errorMessage.style.display = 'none';
var hasError = false;
if (username.value.trim() === '') {
username.classList.add('error');
hasError = true;
}
if (password.value.trim() === '') {
password.classList.add('error');
hasError = true;
}
if (hasError) {
return;
}
errorMessage.style.display = 'block';
};
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
</body>
</html>

View File

@@ -0,0 +1,95 @@
SUDO_USERNAME = "xray_admin"
SUDO_PASSWORD = "$MARZBAN_PASS"
UVICORN_UDS = "/var/lib/marzban/marzban.socket"
DASHBOARD_PATH = "/$MARZBAN_PATH/"
XRAY_JSON = "xray_config.json"
XRAY_SUBSCRIPTION_URL_PREFIX = "https://$VLESS_DOMAIN"
XRAY_SUBSCRIPTION_PATH = "$MARZBAN_SUB_PATH"
SQLALCHEMY_DATABASE_URL = "sqlite:////var/lib/marzban/db.sqlite3"
# ALLOWED_ORIGINS=http://localhost,http://localhost:8000,http://example.com
# XRAY_EXECUTABLE_PATH = "/usr/local/bin/xray"
# XRAY_ASSETS_PATH = "/usr/local/share/xray"
# XRAY_EXCLUDE_INBOUND_TAGS = "INBOUND_X INBOUND_Y"
# XRAY_FALLBACKS_INBOUND_TAG = "INBOUND_X"
# TELEGRAM_API_TOKEN = 123456789:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# TELEGRAM_ADMIN_ID = 987654321, 123456789
# TELEGRAM_LOGGER_CHANNEL_ID = -1234567890123
# TELEGRAM_DEFAULT_VLESS_FLOW = "xtls-rprx-vision"
# TELEGRAM_PROXY_URL = "http://localhost:8080"
# DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/xxxxxxx"
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/"
# CLASH_SUBSCRIPTION_TEMPLATE="clash/my-custom-template.yml"
SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"
HOME_PAGE_TEMPLATE="home/index.html"
# V2RAY_SUBSCRIPTION_TEMPLATE="v2ray/default.json"
# V2RAY_SETTINGS_TEMPLATE="v2ray/settings.json"
# SINGBOX_SUBSCRIPTION_TEMPLATE="singbox/default.json"
# SINGBOX_SETTINGS_TEMPLATE="singbox/settings.json"
# MUX_TEMPLATE="mux/default.json"
## Enable JSON config for compatible clients to use mux, fragment, etc. Default False.
# USE_CUSTOM_JSON_DEFAULT=True
## Your preferred config type for different clients
## If USE_CUSTOM_JSON_DEFAULT is set True, all following programs will use the JSON config
# USE_CUSTOM_JSON_FOR_V2RAYN=False
# USE_CUSTOM_JSON_FOR_V2RAYNG=True
# USE_CUSTOM_JSON_FOR_STREISAND=False
## Set headers for subscription
# SUB_PROFILE_TITLE = "Susbcription"
# SUB_SUPPORT_URL = "https://t.me/support"
# SUB_UPDATE_INTERVAL = "12"
## External config to import into v2ray format subscription
# EXTERNAL_CONFIG = "config://..."
# SQLALCHEMY_POOL_SIZE = 10
# SQLIALCHEMY_MAX_OVERFLOW = 30
## Custom text for STATUS_TEXT variable
# ACTIVE_STATUS_TEXT = "Active"
# EXPIRED_STATUS_TEXT = "Expired"
# LIMITED_STATUS_TEXT = "Limited"
# DISABLED_STATUS_TEXT = "Disabled"
# ONHOLD_STATUS_TEXT = "On-Hold"
### Use negative values to disable auto-delete by default
# USERS_AUTODELETE_DAYS = -1
# USER_AUTODELETE_INCLUDE_LIMITED_ACCOUNTS = false
## Customize all notifications
# NOTIFY_STATUS_CHANGE = True
# NOTIFY_USER_CREATED = True
# NOTIFY_USER_UPDATED = True
# NOTIFY_USER_DELETED = True
# NOTIFY_USER_DATA_USED_RESET = True
# NOTIFY_USER_SUB_REVOKED = True
# NOTIFY_IF_DATA_USAGE_PERCENT_REACHED = True
# NOTIFY_IF_DAYS_LEF_REACHED = True
# NOTIFY_LOGIN = True
## Whitelist of IPs/hosts to disable login notifications
# LOGIN_NOTIFY_WHITE_LIST = '1.1.1.1,127.0.0.1'
### for developers
# DOCS=True
# DEBUG=True
# If You Want To Send Webhook To Multiple Server Add Multi Address
# WEBHOOK_ADDRESS = "http://127.0.0.1:9000/,http://127.0.0.1:9001/"
# WEBHOOK_SECRET = "something-very-very-secret"
# VITE_BASE_API="https://example.com/api/"
# JWT_ACCESS_TOKEN_EXPIRE_MINUTES = 1440
# JOB_CORE_HEALTH_CHECK_INTERVAL = 10
# JOB_RECORD_NODE_USAGES_INTERVAL = 30
# JOB_RECORD_USER_USAGES_INTERVAL = 10
# JOB_REVIEW_USERS_INTERVAL = 10
# JOB_SEND_NOTIFICATIONS_INTERVAL = 30

View File

@@ -0,0 +1,21 @@
{
"type": "vless",
"server": "$VLESS_DOMAIN",
"server_port": 443,
"uuid": "$XRAY_UUID",
"flow": "xtls-rprx-vision",
"tls": {
"enabled": true,
"insecure": false,
"server_name": "$VLESS_DOMAIN",
"utls": {
"enabled": true,
"fingerprint": "chrome"
},
"reality": {
"enabled": true,
"public_key": "$XRAY_PBK",
"short_id": "$XRAY_SID"
}
}
}

View File

@@ -0,0 +1,77 @@
{
"log": {
"loglevel": "none"
},
"inbounds": [
{
"tag": "VLESS TCP VISION REALITY",
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "$XRAY_UUID",
"email": "default",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"xver": 1,
"dest": "127.0.0.1:4123",
"serverNames": [
"$VLESS_DOMAIN"
],
"privateKey": "$XRAY_PIK",
"shortIds": [
"$XRAY_SID"
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
],
"routeOnly": true
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct",
"settings": {
"domainStrategy": "UseIPv4"
}
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"routing": {
"rules": [
{
"protocol": "bittorrent",
"outboundTag": "block"
}
],
"domainStrategy": "IPIfNonMatch"
},
"dns": {
"servers": [
"1.1.1.1",
"8.8.8.8"
],
"queryStrategy": "UseIPv4",
"disableFallback": false,
"tag": "dns-aux"
}
}

View File

@@ -0,0 +1,30 @@
{
"tag": "default",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "$VLESS_DOMAIN",
"port": 443,
"users": [
{
"id": "$XRAY_UUID",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"serverName": "$VLESS_DOMAIN",
"fingerprint": "chrome",
"publicKey": "$XRAY_PBK",
"shortId": "$XRAY_SID",
"spiderX": ""
}
}
}