vpn
This commit is contained in:
4
roles/xray-vps-setup/.gitignore
vendored
Normal file
4
roles/xray-vps-setup/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
gist*.md
|
||||
ansible.cfg
|
||||
inventory.yml
|
||||
playbook.yml
|
||||
60
roles/xray-vps-setup/README.md
Normal file
60
roles/xray-vps-setup/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# xray-vps-setup
|
||||
VLESS со своим доменом. А что еще нужно для счастья?
|
||||
|
||||
В данном варианте VLESS слушает на 443 и принимате все запросы, делая запрос на локальный Caddy только для сертификатов. В таком варианте задержка будет меньше, чем в варианте с Caddy/NGINX перед VLESS, где происходит множество лишних запросов.
|
||||
## Скрипт
|
||||
|
||||
- Установит Xray/Marzban на ваш выбор. Для маскировки страницы используется [Conflunce](https://github.com/Jolymmiles/confluence-marzban-home)
|
||||
- На ваше усмотрение настроит:
|
||||
- - Iptables, запретив все подключения, кроме SSH, 80 и 443.
|
||||
- - Создаст пользователя для подключения, запретив вход от рута
|
||||
- - Добавит этому пользователю ключ для SSH, запретив вход по паролю
|
||||
- Настроит WARP для ру-сайтов.
|
||||
```bash
|
||||
tmux
|
||||
bash <(wget -qO- https://raw.githubusercontent.com/Akiyamov/xray-vps-setup/refs/heads/main/vps-setup.sh)
|
||||
```
|
||||
|
||||
## Плейбук
|
||||
|
||||
[Ansible-galaxy](https://galaxy.ansible.com/ui/standalone/roles/Akiyamov/xray-vps-setup/install/)
|
||||
```yaml
|
||||
- name: Setup vps
|
||||
hosts: some_host
|
||||
roles:
|
||||
- Akiyamov.xray-vps-setup
|
||||
vars:
|
||||
domain: example.com # домен, уровень неважен
|
||||
setup_variant: marzban # marzban or xray
|
||||
setup_warp: false # true or false
|
||||
configure_security: true # true or false
|
||||
user_to_create: xray_user # если configure_security: true, то обязательно
|
||||
user_password: "xray_password" # если configure_security: true, то обязательно
|
||||
SSH_PORT: 22 # если configure_security: true, то обязательно
|
||||
ssh_public_key: "" # если configure_security: true, то обязательно
|
||||
```
|
||||
|
||||
## Добавляем подписку и поддержку Mihomo
|
||||
|
||||
```
|
||||
bash <(wget -qO- https://github.com/legiz-ru/marz-sub/raw/main/marz-sub.sh)
|
||||
```
|
||||
После этого сделайте `docker compose -f /opt/xray-vps-setup/docker-compose.yml down && docker compose -f /opt/xray-vps-setup/docker-compose.yml up -d`
|
||||
|
||||
|
||||
## Ручная установка
|
||||
|
||||
Описана [здесь](https://github.com/Akiyamov/xray-vps-setup/blob/main/install_in_docker.md).
|
||||
|
||||
## Почему не nginx, haproxy, 3x-ui, x-ui, sing-box...
|
||||
|
||||
Caddy сам получит сертификаты, поэтому нам не придется их получать через `acme.sh` или `certbot`.
|
||||
3X-ui мерзотная панель.
|
||||
Sing-box не очень.
|
||||
XHTTP позже, а больше не надо. Уже точно.
|
||||
|
||||
## Связь
|
||||
Issues, PR ну или мой [тг](https://t.me/Akiyamov).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Дайте секс
|
||||
2
roles/xray-vps-setup/defaults/main.yml
Normal file
2
roles/xray-vps-setup/defaults/main.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
# defaults file for vps-setup
|
||||
15
roles/xray-vps-setup/handlers/main.yml
Normal file
15
roles/xray-vps-setup/handlers/main.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
# handlers file for vps-setup
|
||||
- name: Restart xray
|
||||
service:
|
||||
name: xray
|
||||
state: restarted
|
||||
- name: Restart caddy
|
||||
service:
|
||||
name: caddy
|
||||
state: restarted
|
||||
- name: Restart ssh
|
||||
service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
356
roles/xray-vps-setup/install_in_docker.md
Normal file
356
roles/xray-vps-setup/install_in_docker.md
Normal file
@@ -0,0 +1,356 @@
|
||||
<h1 align="center">VLESS + Reality Self Steal в Docker</h2>
|
||||
|
||||
### Что потребуется:
|
||||
- VPS
|
||||
- Свой домен
|
||||
|
||||
В статье будет рассмотрена установка как чистого Xray, так и Marzban.
|
||||
|
||||
## Настройка сервера
|
||||
|
||||
### Настройка SSH
|
||||
|
||||
На своем ПК, неважно, GNU/Linux или Windows. __На Windows используйте Powershell__. Открываем терминал и выполняем следующую команду:
|
||||
```bash
|
||||
ssh-keygen -t ed25519
|
||||
```
|
||||
После выполнения команды вам предложат изменить место хранения ключа и добавить пароль к нему. Менять локацию не надо, пароль же можете добавить ради безопасности.
|
||||
Создав ключ, вам будет выведена локация публичной и приватной его части, нам нужно перекинуть публичную часть этого ключа на нашу VPS.
|
||||
На Linux:
|
||||
```bash
|
||||
ssh-copy-id -i ~/.ssh/id_ed25519.pub ваш_пользователь@ваша_vps
|
||||
```
|
||||
На Windows:
|
||||
```powershell
|
||||
ssh-copy-id -i $env:USERPROFILE\.ssh\id_ed25519.pub ваш_пользователь@ваша_vps
|
||||
```
|
||||
Если данная команда у вас не сработала на Windows, то нужно выполнить следующую:
|
||||
```powershell
|
||||
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh ваш_пользователь@ваша_vps "cat >> .ssh/authorized_keys"
|
||||
```
|
||||
__Далее все делается на VPS.__
|
||||
Для отключения входа по паролю выполняем следующую команду:
|
||||
```bash
|
||||
grep -r PasswordAuthentication /etc/ssh -l | xargs -n 1 sed -i -e "/PasswordAuthentication /c\PasswordAuthentication no"
|
||||
```
|
||||
Сделав это можно перезапустить SSH.
|
||||
```bash
|
||||
sudo systemctl restart ssh
|
||||
```
|
||||
|
||||
### Настройки iptables
|
||||
Нам нужно оставить открытыми порты для SSH, 80(HTTP) и 443(HTTPS).
|
||||
Для этого нужно выполнить следующие команды:
|
||||
```bash
|
||||
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
|
||||
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
|
||||
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
iptables -A OUTPUT -o lo -j ACCEPT
|
||||
iptables -P INPUT DROP
|
||||
iptables-save > /etc/network/iptables.rules
|
||||
```
|
||||
|
||||
### Включение BBR
|
||||
Достаточно выполнить следующие команды:
|
||||
```bash
|
||||
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
|
||||
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
|
||||
sysctl -p
|
||||
```
|
||||
|
||||
## Создание прокси
|
||||
|
||||
### Установка Docker
|
||||
Для установки нужно выполнить следующую команду:
|
||||
```bash
|
||||
bash <(wget -qO- https://get.docker.com) @ -o get-docker.sh
|
||||
```
|
||||
Если вы работаете не от админа, то выполните следующие команды, чтобы не писать `sudo` каждый раз:
|
||||
```bash
|
||||
sudo groupadd docker
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
### Получение данных для прокси
|
||||
В этой части будут описаны необходимые данные, а также способ их получения. Позже эти данные будут использованы в конфигурации.
|
||||
- __VLESS_DOMAIN__: Ваш домен. Если используется punycode, то далее используется ТОЛЬКО на латинице.
|
||||
- __XRAY_PBK+PIK__: `docker run --rm ghcr.io/xtls/xray-core x25519`
|
||||
Оба значения для нас важны, Public key = PBK, Private key = PIK.
|
||||
- __XRAY_SID__: `openssl rand -hex 8`
|
||||
Short id, используется для различения разных клиентов
|
||||
|
||||
Следующие данные нужны только если вы будете устанавливать панель Marzban.
|
||||
- __MARZBAN_USER__: `tr -dc A-Za-z0-9 </dev/urandom | head -c 8; echo`
|
||||
Пользователь панели
|
||||
- __MARZBAN_PASS__: `tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo`
|
||||
Пароль пользователя панели
|
||||
- __MARZBAN_PATH__: `openssl rand -hex 8`
|
||||
URL панели
|
||||
- __MARZBAN_SUB_PATH__: `openssl rand -hex 8`
|
||||
URL подписок
|
||||
|
||||
### Настройка прокси
|
||||
Создадим папку `/opt/xray-vps-setup` командой `mkdir -p /opt/xray-vps-setup`.
|
||||
После этого переходим в папку и создаем в ней файл `docker-compose.yml`
|
||||
|
||||
<details>
|
||||
<summary>Marzban</summary>
|
||||
|
||||
```yaml
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2.9
|
||||
restart: always
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./caddy/data:/data
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./marzban_lib:/run/marzban
|
||||
marzban:
|
||||
image: gozargah/marzban:latest
|
||||
restart: always
|
||||
env_file: ./marzban/.env
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./marzban_lib:/var/lib/marzban
|
||||
- ./marzban/xray_config.json:/code/xray_config.json
|
||||
- ./marzban/templates:/var/lib/marzban/templates
|
||||
```
|
||||
</details>
|
||||
<details>
|
||||
<summary>Xray</summary>
|
||||
|
||||
```yaml
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2.9
|
||||
restart: always
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./caddy/data:/data
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./caddy/templates:/srv
|
||||
xray:
|
||||
image: ghcr.io/xtls/xray-core:latest
|
||||
restart: always
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./xray:/etc/xray
|
||||
```
|
||||
</details>
|
||||
Создаем папку `/opt/xray-vps-setup/caddy` и в ней создаем файл `Caddyfile` и меняем его следующим образом.
|
||||
<details><summary>Marzban</summary>
|
||||
|
||||
```yaml
|
||||
{
|
||||
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 {
|
||||
reverse_proxy * unix//run/marzban/marzban.socket
|
||||
}
|
||||
http://$VLESS_DOMAIN {
|
||||
bind 0.0.0.0
|
||||
redir https://$VLESS_DOMAIN{uri} permanent
|
||||
}
|
||||
:4123 {
|
||||
tls internal
|
||||
respond 204
|
||||
}
|
||||
:80 {
|
||||
bind 0.0.0.0
|
||||
respond 204
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
<details><summary>Чистый Xray</summary>
|
||||
|
||||
```yaml
|
||||
{
|
||||
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 {
|
||||
root * /srv
|
||||
file_server
|
||||
}
|
||||
http://$VLESS_DOMAIN {
|
||||
bind 0.0.0.0
|
||||
redir https://$VLESS_DOMAIN{uri} permanent
|
||||
}
|
||||
:4123 {
|
||||
tls internal
|
||||
respond 204
|
||||
}
|
||||
:80 {
|
||||
bind 0.0.0.0
|
||||
respond 204
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
Настроив caddy требуется добавить страницу для маскировки. Для xray и marzban команды отличаются:
|
||||
Xray
|
||||
|
||||
```bash
|
||||
wget -qO- https://raw.githubusercontent.com/Jolymmiles/confluence-marzban-home/main/index.html | envsubst > /opt/xray-vps-setup/caddy/templates/index.html
|
||||
```
|
||||
Marzban
|
||||
```bash
|
||||
wget -qO- https://raw.githubusercontent.com/Jolymmiles/confluence-marzban-home/main/index.html | envsubst > /opt/xray-vps-setup/marzban/templates/home/index.html
|
||||
```
|
||||
|
||||
После этого надо создать файл конфигурации Xray, если вы ставите marzban, то он будет находится в `/opt/xray-vps-setup/marzban/xray_config.json`, если чистый xray, то `/opt/xray-vps-setup/xray/config.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "VLESS TCP VISION REALITY",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 443,
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "XRAY_UUDI", // ПОМЕНЯТЬ НА СВОЕ
|
||||
"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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Для Marzban необходимо также добавить `.env` файл. Создайте файл `/opt/xray-vps-setup/marzban/.env` и вставьте следующее:
|
||||
```
|
||||
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"
|
||||
CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/"
|
||||
SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"
|
||||
HOME_PAGE_TEMPLATE="home/index.html"
|
||||
```
|
||||
|
||||
## Настройка WARP
|
||||
|
||||
Для того, чтобы доабвить WARP для того, чтобы в Россию наш юзер ходил черзе него, то надо сделать следующее.
|
||||
Устанавливаем WARP:
|
||||
```bash
|
||||
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/cloudflare-client.list
|
||||
apt update
|
||||
apt install cloudflare-warp -y
|
||||
```
|
||||
Настроим WARP:
|
||||
```bash
|
||||
warp-cli registration new
|
||||
warp-cli mode proxy
|
||||
warp-cli proxy port 40000
|
||||
warp-cli connect
|
||||
```
|
||||
Если на этом этапе ловим ошибку подключения, то не продолжайте, WARP не рабоатет.
|
||||
Установка `yq`:
|
||||
```bash
|
||||
wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq && chmod +x /usr/bin/yq
|
||||
```
|
||||
Далее с помощью `yq` мы установим в уже существующий кофниг WARP:
|
||||
```bash
|
||||
yq eval '.outbounds += {"tag": "warp","protocol": "socks","settings": {"servers": [{"address": "127.0.0.1","port": 40000}]}}' -i $XRAY_CONFIG_WARP
|
||||
yq eval '.routing.rules += {"outboundTag": "warp", "domain": ["geosite:category-ru", "regexp:.*\\.xn--$", "regexp:.*\\.ru$", "regexp:.*\\.su$"]}' -i $XRAY_CONFIG_WARP
|
||||
|
||||
```
|
||||
Заменяем $XRAY_CONFIG_WARP на `/opt/xray-vps-setup/marzban/xray_config.json` для marzban и на `/opt/xray-vps-setup/xray/config.json` для чистого xray. После этого перезапускаем все:
|
||||
```bash
|
||||
docker compose -f /opt/xray-vps-setup/docker-compose.yml down && docker compose -f /opt/xray-vps-setup/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
#
|
||||
|
||||
Если вы хотите помочь что-то исправить, добавить и тд, то делайте PR или пишите в [ТГ](https://t.me/Akiyamov).
|
||||
2
roles/xray-vps-setup/meta/.galaxy_install_info
Normal file
2
roles/xray-vps-setup/meta/.galaxy_install_info
Normal file
@@ -0,0 +1,2 @@
|
||||
install_date: Mon Feb 9 17:35:32 2026
|
||||
version: null
|
||||
18
roles/xray-vps-setup/meta/main.yml
Normal file
18
roles/xray-vps-setup/meta/main.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
galaxy_info:
|
||||
author: Akiyamov
|
||||
description: Setup VPS for XRay
|
||||
company: your company (optional)
|
||||
license: BSD-3-Clause
|
||||
min_ansible_version: 2.1
|
||||
platforms:
|
||||
- name: Ubuntu
|
||||
versions:
|
||||
- 16
|
||||
- 18
|
||||
- 20
|
||||
- 22
|
||||
- 24
|
||||
galaxy_tags:
|
||||
- xray
|
||||
- vps
|
||||
dependencies: []
|
||||
10
roles/xray-vps-setup/tasks/bbr.yml
Normal file
10
roles/xray-vps-setup/tasks/bbr.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
- name: Set BBR
|
||||
ansible.posix.sysctl:
|
||||
name: net.core.default_qdisc
|
||||
value: "fq"
|
||||
state: present
|
||||
- name: Set queue
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.tcp_congestion_control
|
||||
value: "bbr"
|
||||
state: present
|
||||
63
roles/xray-vps-setup/tasks/end_xray.yml
Normal file
63
roles/xray-vps-setup/tasks/end_xray.yml
Normal file
@@ -0,0 +1,63 @@
|
||||
- name: Print clipboard string
|
||||
debug:
|
||||
msg: "vless://{{ xray_uuid.stdout }}@{{ vless.domain }}:443?type=tcp&security=reality&pbk={{ x25519_pbk.stdout }}&fp=chrome&sni={{ vless.domain }}&sid={{ short_id.stdout }}&spx=%2F&flow=xtls-rprx-vision"
|
||||
- name: XRay outbound config
|
||||
debug:
|
||||
msg: |
|
||||
{
|
||||
"tag": "default",
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "{{ vless.domain }}",
|
||||
"port": 443,
|
||||
"users": [
|
||||
{
|
||||
"id": "{{ xray_uuid.stdout }}",
|
||||
"encryption": "none",
|
||||
"flow": "xtls-rprx-vision"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"serverName": "{{ vless.domain }}",
|
||||
"fingerprint": "chrome",
|
||||
"publicKey": "{{ x25519_pbk.stdout }}",
|
||||
"shortId": "{{ short_id.stdout }}",
|
||||
"spiderX": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
- name: Sing-box outbound config
|
||||
debug:
|
||||
msg: |
|
||||
{
|
||||
"type": "vless",
|
||||
"server": "{{ vless.domain }}",
|
||||
"server_port": 443,
|
||||
"uuid": "{{ xray_uuid.stdout }}",
|
||||
"flow": "xtls-rprx-vision",
|
||||
"tls": {
|
||||
"enabled": true,
|
||||
"insecure": false,
|
||||
"server_name": "{{ vless.domain }}",
|
||||
"utls": {
|
||||
"enabled": true,
|
||||
"fingerprint": "chrome"
|
||||
},
|
||||
"reality": {
|
||||
"enabled": true,
|
||||
"public_key": "{{ x25519_pbk.stdout }}",
|
||||
"short_id": "{{ short_id.stdout }}"
|
||||
}
|
||||
}
|
||||
}
|
||||
- name: Print PBK, SID and UUID to connect to server.
|
||||
debug:
|
||||
msg: "UUID: {{ xray_uuid.stdout }}, SID: {{ short_id.stdout }}, PBK: {{ x25519_pbk.stdout }}"
|
||||
13
roles/xray-vps-setup/tasks/install_docker.yml
Normal file
13
roles/xray-vps-setup/tasks/install_docker.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
- name: Add Docker GPG apt Key
|
||||
ansible.builtin.apt_key:
|
||||
url: https://download.docker.com/linux/ubuntu/gpg
|
||||
state: present
|
||||
- name: Add Docker Repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: deb https://download.docker.com/linux/ubuntu focal stable
|
||||
state: present
|
||||
- name: Update install docker-ce
|
||||
ansible.builtin.apt:
|
||||
name: docker-ce
|
||||
state: latest
|
||||
update_cache: true
|
||||
31
roles/xray-vps-setup/tasks/install_marzban.yml
Normal file
31
roles/xray-vps-setup/tasks/install_marzban.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
- name: Generate marzban specific values
|
||||
block:
|
||||
- name: Generate marzban password
|
||||
set_fact:
|
||||
MARZBAN_PASS: "{{ lookup('password', '/dev/null length=13 chars=ascii_letters') }}"
|
||||
- name: Generate marzban password
|
||||
set_fact:
|
||||
MARZBAN_PATH: "{{ lookup('password', '/dev/null length=8 chars=ascii_letters') }}"
|
||||
- name: Generate marzban password
|
||||
set_fact:
|
||||
MARZBAN_SUB_PATH: "{{ lookup('password', '/dev/null length=8 chars=ascii_letters') }}"
|
||||
- name: Create dirs
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
loop:
|
||||
- /opt/xray-vps-setup/caddy
|
||||
- /opt/xray-vps-setup/marzban
|
||||
- /opt/xray-vps-setup/marzban/templates/home
|
||||
- name: Copy config files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
loop:
|
||||
- { src: "caddyfile.j2", dest: "/opt/xray-vps-setup/caddy/Caddyfile" }
|
||||
- { src: "xray.json.j2", dest: "/opt/xray-vps-setup/marzban/xray_config.json" }
|
||||
- { src: "marzban.j2", dest: "/opt/xray-vps-setup/marzban/.env" }
|
||||
- { src: "confluence.j2", dest: "/opt/xray-vps-setup/marzban/templates/home/index.html" }
|
||||
- { src: "marzban_docker.j2", dest: "/opt/xray-vps-setup/docker-compose.yml" }
|
||||
- debug:
|
||||
msg: "Marzban password: {{ MARZBAN_PASS }}, marzban path: {{ MARZBAN_PATH }}"
|
||||
16
roles/xray-vps-setup/tasks/install_xray.yml
Normal file
16
roles/xray-vps-setup/tasks/install_xray.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
- name: Create dirs
|
||||
file:
|
||||
path: "{{ item }}"
|
||||
state: directory
|
||||
loop:
|
||||
- /opt/xray-vps-setup/caddy/templates
|
||||
- /opt/xray-vps-setup/xray
|
||||
- name: Copy config files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ item.dest }}"
|
||||
loop:
|
||||
- { src: "caddyfile.j2", dest: "/opt/xray-vps-setup/caddy/Caddyfile" }
|
||||
- { src: "confluence.j2", dest: "/opt/xray-vps-setup/caddy/templates/index.html" }
|
||||
- { src: "xray.json.j2", dest: "/opt/xray-vps-setup/xray/config.json" }
|
||||
- { src: "xray_docker.j2", dest: "/opt/xray-vps-setup/docker-compose.yml" }
|
||||
5
roles/xray-vps-setup/tasks/install_yq.yml
Normal file
5
roles/xray-vps-setup/tasks/install_yq.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: Download yq
|
||||
ansible.builtin.get_url:
|
||||
url: https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
|
||||
dest: /usr/bin/yq
|
||||
mode: '0755'
|
||||
46
roles/xray-vps-setup/tasks/iptables.yml
Normal file
46
roles/xray-vps-setup/tasks/iptables.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
- name: IPTables rules
|
||||
block:
|
||||
- name: Install netfilter-persistent
|
||||
apt:
|
||||
name: netfilter-persistent
|
||||
state: present
|
||||
- name: Allow related and established connections
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
ctstate: ESTABLISHED,RELATED
|
||||
jump: ACCEPT
|
||||
become: yes
|
||||
- name: Allow new incoming SYN packets on specified port
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
destination_port: "{{ SSH_PORT }}"
|
||||
ctstate: NEW
|
||||
syn: match
|
||||
jump: ACCEPT
|
||||
- name: Allow ICMP
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: icmp
|
||||
jump: ACCEPT
|
||||
- name: Allow 80, 443 connections
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
protocol: tcp
|
||||
destination_ports:
|
||||
- "80"
|
||||
- "443"
|
||||
jump: ACCEPT
|
||||
- name: Allow loopback in
|
||||
shell:
|
||||
cmd: iptables -A INPUT -i lo -j ACCEPT
|
||||
- name: Allow loopback out
|
||||
shell:
|
||||
cmd: iptables -A OUTPUT -o lo -j ACCEPT
|
||||
- name: INPUT DROP
|
||||
ansible.builtin.iptables:
|
||||
chain: INPUT
|
||||
policy: DROP
|
||||
- name: Save iptables rules
|
||||
shell:
|
||||
cmd: netfilter-persistent save
|
||||
54
roles/xray-vps-setup/tasks/main.yml
Normal file
54
roles/xray-vps-setup/tasks/main.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
- name: Populate service facts
|
||||
ansible.builtin.service_facts:
|
||||
- name: Enable BBR
|
||||
include_tasks: bbr.yml
|
||||
- name: Install docker
|
||||
include_tasks: install_docker.yml
|
||||
when: ansible_facts.services['docker'] is undefined
|
||||
- name: Install/update yq
|
||||
include_tasks: install_yq.yml
|
||||
- name: Security block
|
||||
block:
|
||||
- name: Edit SSHD config
|
||||
include_tasks: ssh.yml
|
||||
- name: Edit iptables
|
||||
include_tasks: iptables.yml
|
||||
- name: Add user
|
||||
include_tasks: user.yml
|
||||
when: configure_security|default(false)|bool == true
|
||||
- name: Generate values
|
||||
block:
|
||||
- name: Generate x25519 PIK
|
||||
shell:
|
||||
cmd: docker run --rm ghcr.io/xtls/xray-core x25519 | head -n1 | cut -d' ' -f 3
|
||||
register: x25519_pik
|
||||
- name: Generate x25519 PBK
|
||||
shell:
|
||||
cmd: docker run --rm ghcr.io/xtls/xray-core x25519 -i {{ x25519_pik.stdout }} | tail -1 | cut -d' ' -f 3
|
||||
register: x25519_pbk
|
||||
- name: Generate SID
|
||||
shell:
|
||||
cmd: openssl rand -hex 8
|
||||
register: short_id
|
||||
- name: Generate default user
|
||||
shell:
|
||||
cmd: docker run --rm ghcr.io/xtls/xray-core uuid
|
||||
register: xray_uuid
|
||||
- name: Install marzban
|
||||
include_tasks: install_marzban.yml
|
||||
when: setup_variant == "marzban"
|
||||
- name: Install xray
|
||||
include_tasks: install_xray.yml
|
||||
when: setup_variant == "xray"
|
||||
- name: Install warp
|
||||
include_tasks: setup_warp.yml
|
||||
when: setup_warp|default(false)|bool == true
|
||||
- name: Start proxy
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: /opt/xray-vps-setup
|
||||
files:
|
||||
- docker-compose.yml
|
||||
- name: End xray
|
||||
include_tasks: end_xray.yml
|
||||
when: setup_variant == "xray"
|
||||
61
roles/xray-vps-setup/tasks/setup_warp.yml
Normal file
61
roles/xray-vps-setup/tasks/setup_warp.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
#- name: Add WARP GPG key
|
||||
# ansible.builtin.get_url:
|
||||
# url: https://pkg.cloudflareclient.com/pubkey.gpg
|
||||
# dest: /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
|
||||
# mode: '0644'
|
||||
# force: true
|
||||
- name: Add WARP GPG key
|
||||
ansible.builtin.shell:
|
||||
cmd: curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
|
||||
- name: Add WARP repo
|
||||
ansible.builtin.apt_repository:
|
||||
filename: cloudflare-client
|
||||
repo: "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ {{ ansible_facts['distribution_release'] }} main"
|
||||
- name:
|
||||
apt:
|
||||
name: cloudflare-warp
|
||||
state: present
|
||||
update_cache: yes
|
||||
- name: Register WARP
|
||||
shell:
|
||||
cmd: echo "y" | warp-cli registration new
|
||||
- shell:
|
||||
cmd: warp-cli mode proxy
|
||||
- shell:
|
||||
cmd: warp-cli proxy port 40000
|
||||
- shell:
|
||||
cmd: warp-cli connect
|
||||
- name: Edit xray config
|
||||
block:
|
||||
- command:
|
||||
argv:
|
||||
- yq
|
||||
- eval
|
||||
- '.outbounds += {"tag": "warp","protocol": "socks","settings": {"servers": [{"address": "127.0.0.1","port": 40000}]}}'
|
||||
- -i
|
||||
- /opt/xray-vps-setup/xray/config.json
|
||||
- command:
|
||||
argv:
|
||||
- yq
|
||||
- eval
|
||||
- '.routing.rules += {"outboundTag": "warp", "domain": ["geosite:category-ru", "regexp:.*\\.xn--$", "regexp:.*\\.ru$", "regexp:.*\\.su$"]}'
|
||||
- -i
|
||||
- /opt/xray-vps-setup/xray/config.json
|
||||
when: setup_variant == "xray"
|
||||
- name: Edit marzban config
|
||||
block:
|
||||
- command:
|
||||
argv:
|
||||
- yq
|
||||
- eval
|
||||
- '.outbounds += {"tag": "warp","protocol": "socks","settings": {"servers": [{"address": "127.0.0.1","port": 40000}]}}'
|
||||
- -i
|
||||
- /opt/xray-vps-setup/marzban/xray_config.json
|
||||
- command:
|
||||
argv:
|
||||
- yq
|
||||
- eval
|
||||
- '.routing.rules += {"outboundTag": "warp", "domain": ["geosite:category-ru", "regexp:.*\\.xn--$", "regexp:.*\\.ru$", "regexp:.*\\.su$"]}'
|
||||
- -i
|
||||
- /opt/xray-vps-setup/marzban/xray_config.json
|
||||
when: setup_variant == "marzban"
|
||||
14
roles/xray-vps-setup/tasks/ssh.yml
Normal file
14
roles/xray-vps-setup/tasks/ssh.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
- name: Change SSH port
|
||||
shell:
|
||||
cmd: grep -r Port /etc/ssh -l | xargs -n 1 sed -i -e "/Port /c\Port {{ SSH_PORT }}"
|
||||
- name: Disable password login
|
||||
shell:
|
||||
cmd: grep -r PasswordAuthentication /etc/ssh -l | xargs -n 1 sed -i -e "/PasswordAuthentication /c\PasswordAuthentication no"
|
||||
- name: Disable root login
|
||||
shell:
|
||||
cmd: grep -r PermitRootLogin /etc/ssh -l | xargs -n 1 sed -i -e "/PermitRootLogin /c\PermitRootLogin no"
|
||||
- name: Restart ssh
|
||||
service:
|
||||
name: ssh
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
14
roles/xray-vps-setup/tasks/user.yml
Normal file
14
roles/xray-vps-setup/tasks/user.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
- name: Add user
|
||||
ansible.builtin.user:
|
||||
name: "{{ user_to_create }}"
|
||||
shell: /bin/bash
|
||||
groups: sudo,docker
|
||||
password: "{{ user_password | password_hash('sha512') }}"
|
||||
append: yes
|
||||
update_password: on_create
|
||||
register: "xray_user"
|
||||
- name: Add ssh_pbk to user
|
||||
ansible.posix.authorized_key:
|
||||
user: "{{ user_to_create }}"
|
||||
state: "present"
|
||||
key: "{{ ssh_public_key }}"
|
||||
50
roles/xray-vps-setup/templates/caddyfile.j2
Normal file
50
roles/xray-vps-setup/templates/caddyfile.j2
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
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://{{ domain }} {
|
||||
{% if setup_variant == "marzban" %}
|
||||
reverse_proxy * unix//run/marzban/marzban.socket
|
||||
{% else %}
|
||||
root * /srv
|
||||
file_server
|
||||
{% endif %}
|
||||
header {
|
||||
-Server
|
||||
}
|
||||
handle_errors {
|
||||
header {
|
||||
-Server
|
||||
}
|
||||
}
|
||||
}
|
||||
http://{{ domain }} {
|
||||
bind 0.0.0.0
|
||||
redir https://{host}{uri} permanent
|
||||
|
||||
header {
|
||||
-Server
|
||||
}
|
||||
handle_errors {
|
||||
header {
|
||||
-Server
|
||||
}
|
||||
}
|
||||
}
|
||||
:4123 {
|
||||
tls internal
|
||||
respond 204
|
||||
}
|
||||
:80 {
|
||||
bind 0.0.0.0
|
||||
respond 204
|
||||
}
|
||||
272
roles/xray-vps-setup/templates/confluence.j2
Normal file
272
roles/xray-vps-setup/templates/confluence.j2
Normal 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">×</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>
|
||||
95
roles/xray-vps-setup/templates/marzban.j2
Normal file
95
roles/xray-vps-setup/templates/marzban.j2
Normal 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://{{ 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
|
||||
20
roles/xray-vps-setup/templates/marzban_docker.j2
Normal file
20
roles/xray-vps-setup/templates/marzban_docker.j2
Normal file
@@ -0,0 +1,20 @@
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2.9
|
||||
container_name: caddy
|
||||
restart: always
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./caddy/data:/data
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./marzban_lib:/run/marzban
|
||||
marzban:
|
||||
image: gozargah/marzban:v0.8.4
|
||||
container_name: marzban
|
||||
restart: always
|
||||
env_file: ./marzban/.env
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./marzban_lib:/var/lib/marzban
|
||||
- ./marzban/xray_config.json:/code/xray_config.json
|
||||
- ./marzban/templates:/var/lib/marzban/templates
|
||||
76
roles/xray-vps-setup/templates/xray.json.j2
Normal file
76
roles/xray-vps-setup/templates/xray.json.j2
Normal file
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "info"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "VLESS TCP VISION REALITY",
|
||||
"listen": "0.0.0.0",
|
||||
"port": 443,
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "{{ xray_uuid.stdout}}",
|
||||
"email": "default",
|
||||
"flow": "xtls-rprx-vision"
|
||||
}],
|
||||
"decryption": "none"
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp",
|
||||
"security": "reality",
|
||||
"realitySettings": {
|
||||
"xver": 1,
|
||||
"dest": "127.0.0.1:4123",
|
||||
"serverNames": [
|
||||
"{{ domain }}"
|
||||
],
|
||||
"privateKey": "{{ x25519_pik.stdout }}",
|
||||
"shortIds": [
|
||||
"{{ short_id.stdout }}"
|
||||
]
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
19
roles/xray-vps-setup/templates/xray_docker.j2
Normal file
19
roles/xray-vps-setup/templates/xray_docker.j2
Normal file
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
caddy:
|
||||
image: caddy:2.9
|
||||
container_name: caddy
|
||||
restart: always
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./caddy/data:/data
|
||||
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
|
||||
- ./caddy/templates:/srv
|
||||
xray:
|
||||
image: ghcr.io/xtls/xray-core:25.6.8
|
||||
restart: always
|
||||
container_name: xray
|
||||
user: root
|
||||
command: run -c /etc/xray/config.json
|
||||
network_mode: host
|
||||
volumes:
|
||||
- ./xray:/etc/xray
|
||||
47
roles/xray-vps-setup/templates_for_script/caddy
Normal file
47
roles/xray-vps-setup/templates_for_script/caddy
Normal 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
|
||||
}
|
||||
9
roles/xray-vps-setup/templates_for_script/compose
Normal file
9
roles/xray-vps-setup/templates_for_script/compose
Normal 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
|
||||
272
roles/xray-vps-setup/templates_for_script/confluence_page
Normal file
272
roles/xray-vps-setup/templates_for_script/confluence_page
Normal 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">×</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>
|
||||
95
roles/xray-vps-setup/templates_for_script/marzban
Normal file
95
roles/xray-vps-setup/templates_for_script/marzban
Normal 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
|
||||
21
roles/xray-vps-setup/templates_for_script/sing_box_outbound
Normal file
21
roles/xray-vps-setup/templates_for_script/sing_box_outbound
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
77
roles/xray-vps-setup/templates_for_script/xray
Normal file
77
roles/xray-vps-setup/templates_for_script/xray
Normal 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"
|
||||
}
|
||||
}
|
||||
30
roles/xray-vps-setup/templates_for_script/xray_outbound
Normal file
30
roles/xray-vps-setup/templates_for_script/xray_outbound
Normal 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": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
5
roles/xray-vps-setup/tests/test.yml
Normal file
5
roles/xray-vps-setup/tests/test.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
- hosts: localhost
|
||||
remote_user: root
|
||||
roles:
|
||||
- vps-setup
|
||||
2
roles/xray-vps-setup/vars/main.yml
Normal file
2
roles/xray-vps-setup/vars/main.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
# vars file for vps-setup
|
||||
304
roles/xray-vps-setup/vps-setup.sh
Normal file
304
roles/xray-vps-setup/vps-setup.sh
Normal file
@@ -0,0 +1,304 @@
|
||||
#/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export GIT_BRANCH="main"
|
||||
export GIT_REPO="Akiyamov/xray-vps-setup"
|
||||
|
||||
# Check if script started as root
|
||||
if [ "$EUID" -ne 0 ]
|
||||
then echo "Please run as root"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Install idn
|
||||
apt-get update
|
||||
apt-get install idn sudo dnsutils -y
|
||||
|
||||
# Read domain input
|
||||
read -ep "Enter your domain:"$'\n' input_domain
|
||||
|
||||
export VLESS_DOMAIN=$(echo $input_domain | idn)
|
||||
|
||||
SERVER_IPS=($(hostname -I))
|
||||
|
||||
RESOLVED_IP=$(dig +short $VLESS_DOMAIN | tail -n1)
|
||||
|
||||
if [ -z "$RESOLVED_IP" ]; then
|
||||
echo "Warning: Domain has no DNS record"
|
||||
read -ep "Are you sure? That domain has no DNS record. If you didn't add that you will have to restart xray and caddy by yourself [y/N]"$'\n' prompt_response
|
||||
if [[ "$prompt_response" =~ ^([yY])$ ]]; then
|
||||
echo "Ok, proceeding without DNS verification"
|
||||
else
|
||||
echo "Come back later"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
MATCH_FOUND=false
|
||||
for server_ip in "${SERVER_IPS[@]}"; do
|
||||
if [ "$RESOLVED_IP" == "$server_ip" ]; then
|
||||
MATCH_FOUND=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$MATCH_FOUND" = true ]; then
|
||||
echo "✓ DNS record points to this server ($RESOLVED_IP)"
|
||||
else
|
||||
echo "Warning: DNS record exists but points to different IP"
|
||||
echo " Domain resolves to: $RESOLVED_IP"
|
||||
echo " This server's IPs: ${SERVER_IPS[*]}"
|
||||
read -ep "Continue anyway? [y/N]"$'\n' prompt_response
|
||||
if [[ "$prompt_response" =~ ^([yY])$ ]]; then
|
||||
echo "Ok, proceeding"
|
||||
else
|
||||
echo "Come back later"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
read -ep "Do you want to install marzban? [y/N] "$'\n' marzban_input
|
||||
|
||||
read -ep "Do you want to configure server security? Do this on first run only. [y/N] "$'\n' configure_ssh_input
|
||||
if [[ ${configure_ssh_input,,} == "y" ]]; then
|
||||
# Read SSH port
|
||||
read -ep "Enter SSH port. Default 22, can't use ports: 80, 443 and 4123:"$'\n' input_ssh_port
|
||||
|
||||
while [[ "$input_ssh_port" -eq "80" || "$input_ssh_port" -eq "443" || "$input_ssh_port" -eq "4123" ]]; do
|
||||
read -ep "No, ssh can't use $input_ssh_port as port, write again:"$'\n' input_ssh_port
|
||||
done
|
||||
# Read SSH Pubkey
|
||||
read -ep "Enter SSH public key:"$'\n' input_ssh_pbk
|
||||
echo "$input_ssh_pbk" > ./test_pbk
|
||||
ssh-keygen -l -f ./test_pbk
|
||||
PBK_STATUS=$(echo $?)
|
||||
if [ "$PBK_STATUS" -eq 255 ]; then
|
||||
echo "Can't verify the public key. Try again and make sure to include 'ssh-rsa' or 'ssh-ed25519' followed by 'user@pcname' at the end of the file."
|
||||
exit
|
||||
fi
|
||||
rm ./test_pbk
|
||||
fi
|
||||
|
||||
read -ep "Do you want to install WARP and use it on russian websites? [y/N] "$'\n' configure_warp_input
|
||||
if [[ ${configure_warp_input,,} == "y" ]]; then
|
||||
if ! curl -I https://api.cloudflareclient.com --connect-timeout 10 > /dev/null 2>&1; then
|
||||
echo "Warp can't be used"
|
||||
configure_warp_input="n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check congestion protocol
|
||||
if sysctl net.ipv4.tcp_congestion_control | grep bbr; then
|
||||
echo "BBR is already used"
|
||||
else
|
||||
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
|
||||
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
|
||||
sysctl -p > /dev/null
|
||||
echo "Enabled BBR"
|
||||
fi
|
||||
|
||||
export ARCH=$(dpkg --print-architecture)
|
||||
|
||||
yq_install() {
|
||||
wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_$ARCH -O /usr/bin/yq && chmod +x /usr/bin/yq
|
||||
}
|
||||
|
||||
yq_install
|
||||
|
||||
docker_install() {
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
}
|
||||
|
||||
if ! command -v docker 2>&1 >/dev/null; then
|
||||
docker_install
|
||||
fi
|
||||
|
||||
# Generate values for XRay
|
||||
export SSH_USER=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 8; echo)
|
||||
export SSH_USER_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)
|
||||
export SSH_PORT=${input_ssh_port:-22}
|
||||
export ROOT_LOGIN="yes"
|
||||
export IP_CADDY=$(hostname -I | cut -d' ' -f1)
|
||||
export CADDY_BASIC_AUTH=$(docker run --rm caddy caddy hash-password --plaintext $SSH_USER_PASS)
|
||||
export XRAY_PIK=$(docker run --rm ghcr.io/xtls/xray-core x25519 | head -n1 | cut -d' ' -f 2)
|
||||
export XRAY_PBK=$(docker run --rm ghcr.io/xtls/xray-core x25519 -i $XRAY_PIK | tail -2 | head -1 | cut -d' ' -f 2)
|
||||
export XRAY_SID=$(openssl rand -hex 8)
|
||||
export XRAY_UUID=$(docker run --rm ghcr.io/xtls/xray-core uuid)
|
||||
export XRAY_CFG="/usr/local/etc/xray/config.json"
|
||||
|
||||
# Install marzban
|
||||
xray_setup() {
|
||||
mkdir -p /opt/xray-vps-setup
|
||||
cd /opt/xray-vps-setup
|
||||
if [[ "${marzban_input,,}" == "y" ]]; then
|
||||
export MARZBAN_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo)
|
||||
export MARZBAN_PATH=$(openssl rand -hex 8)
|
||||
export MARZBAN_SUB_PATH=$(openssl rand -hex 8)
|
||||
wget -qO- https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/compose | envsubst > ./docker-compose.yml
|
||||
yq eval \
|
||||
'.services.marzban.image = "gozargah/marzban:v0.8.4" |
|
||||
.services.marzban.container_name = "marzban" |
|
||||
.services.marzban.restart = "always" |
|
||||
.services.marzban.env_file = "./marzban/.env" |
|
||||
.services.marzban.network_mode = "host" |
|
||||
.services.marzban.volumes[0] = "./marzban_lib:/var/lib/marzban" |
|
||||
.services.marzban.volumes[1] = "./marzban/xray_config.json:/code/xray_config.json" |
|
||||
.services.marzban.volumes[2] = "./marzban/templates:/var/lib/marzban/templates" |
|
||||
.services.caddy.volumes[2] = "./marzban_lib:/run/marzban"' -i /opt/xray-vps-setup/docker-compose.yml
|
||||
mkdir -p marzban caddy
|
||||
wget -qO- https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/marzban | envsubst > ./marzban/.env
|
||||
mkdir -p /opt/xray-vps-setup/marzban/templates/home
|
||||
wget -qO- https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/confluence_page | envsubst > ./marzban/templates/home/index.html
|
||||
export CADDY_REVERSE="reverse_proxy * unix//run/marzban/marzban.socket"
|
||||
wget -qO- "https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/caddy" | envsubst > ./caddy/Caddyfile
|
||||
wget -qO- "https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/xray" | envsubst > ./marzban/xray_config.json
|
||||
else
|
||||
wget -qO- https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/compose | envsubst > ./docker-compose.yml
|
||||
mkdir -p /opt/xray-vps-setup/caddy/templates
|
||||
yq eval \
|
||||
'.services.xray.image = "ghcr.io/xtls/xray-core:25.6.8" |
|
||||
.services.xray.container_name = "xray" |
|
||||
.services.xray.user = "root" |
|
||||
.services.xray.command = "run -c /etc/xray/config.json" |
|
||||
.services.xray.restart = "always" |
|
||||
.services.xray.network_mode = "host" |
|
||||
.services.caddy.volumes[2] = "./caddy/templates:/srv" |
|
||||
.services.xray.volumes[0] = "./xray:/etc/xray"' -i /opt/xray-vps-setup/docker-compose.yml
|
||||
wget -qO- https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/confluence_page | envsubst > ./caddy/templates/index.html
|
||||
export CADDY_REVERSE="root * /srv
|
||||
file_server"
|
||||
mkdir -p xray caddy
|
||||
wget -qO- "https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/xray" | envsubst > ./xray/config.json
|
||||
wget -qO- "https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/caddy" | envsubst > ./caddy/Caddyfile
|
||||
fi
|
||||
}
|
||||
|
||||
xray_setup
|
||||
|
||||
sshd_edit() {
|
||||
grep -r Port /etc/ssh -l | xargs -n 1 sed -i -e "/Port /c\Port $SSH_PORT"
|
||||
grep -r PasswordAuthentication /etc/ssh -l | xargs -n 1 sed -i -e "/PasswordAuthentication /c\PasswordAuthentication no"
|
||||
grep -r PermitRootLogin /etc/ssh -l | xargs -n 1 sed -i -e "/PermitRootLogin /c\PermitRootLogin no"
|
||||
systemctl daemon-reload
|
||||
systemctl restart ssh
|
||||
}
|
||||
|
||||
add_user() {
|
||||
useradd $SSH_USER -s /bin/bash
|
||||
usermod -aG sudo $SSH_USER
|
||||
echo $SSH_USER:$SSH_USER_PASS | chpasswd
|
||||
mkdir -p /home/$SSH_USER/.ssh
|
||||
touch /home/$SSH_USER/.ssh/authorized_keys
|
||||
echo $input_ssh_pbk >> /home/$SSH_USER/.ssh/authorized_keys
|
||||
chmod 700 /home/$SSH_USER/.ssh/
|
||||
chmod 600 /home/$SSH_USER/.ssh/authorized_keys
|
||||
chown $SSH_USER:$SSH_USER -R /home/$SSH_USER
|
||||
usermod -aG docker $SSH_USER
|
||||
}
|
||||
|
||||
debconf-set-selections <<EOF
|
||||
iptables-persistent iptables-persistent/autosave_v4 boolean true
|
||||
iptables-persistent iptables-persistent/autosave_v6 boolean true
|
||||
EOF
|
||||
|
||||
# Configure iptables
|
||||
edit_iptables() {
|
||||
apt-get install iptables-persistent netfilter-persistent -y
|
||||
iptables -A INPUT -p icmp -j ACCEPT
|
||||
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport $SSH_PORT -j ACCEPT
|
||||
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
|
||||
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
iptables -A OUTPUT -o lo -j ACCEPT
|
||||
iptables -P INPUT DROP
|
||||
netfilter-persistent save
|
||||
}
|
||||
|
||||
if [[ ${configure_ssh_input,,} == "y" ]]; then
|
||||
add_user
|
||||
sshd_edit
|
||||
edit_iptables
|
||||
fi
|
||||
|
||||
# WARP Install function
|
||||
warp_install() {
|
||||
apt install gpg -y
|
||||
echo "If this fails then warp won't be added to routing and everything will work without it"
|
||||
curl -fsSL https://pkg.cloudflareclient.com/pubkey.gpg | gpg --yes --dearmor --output /usr/share/keyrings/cloudflare-warp-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/cloudflare-warp-archive-keyring.gpg] https://pkg.cloudflareclient.com/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/cloudflare-client.list
|
||||
apt update
|
||||
apt install cloudflare-warp -y
|
||||
|
||||
echo "y" | warp-cli registration new
|
||||
export TRY_WARP=$(echo $?)
|
||||
if [[ $TRY_WARP != 0 ]]; then
|
||||
echo "Couldn't connect to WARP"
|
||||
exit 0
|
||||
else
|
||||
warp-cli mode proxy
|
||||
warp-cli proxy port 40000
|
||||
warp-cli connect
|
||||
if [[ "${marzban_input,,}" == "y" ]]; then
|
||||
export XRAY_CONFIG_WARP="/opt/xray-vps-setup/marzban/xray_config.json"
|
||||
else
|
||||
export XRAY_CONFIG_WARP="/opt/xray-vps-setup/xray/config.json"
|
||||
fi
|
||||
yq eval \
|
||||
'.outbounds += {"tag": "warp","protocol": "socks","settings": {"servers": [{"address": "127.0.0.1","port": 40000}]}}' \
|
||||
-i $XRAY_CONFIG_WARP
|
||||
yq eval \
|
||||
'.routing.rules += {"outboundTag": "warp", "domain": ["geosite:category-ru", "regexp:.*\\.xn--$", "regexp:.*\\.ru$", "regexp:.*\\.su$"]}' \
|
||||
-i $XRAY_CONFIG_WARP
|
||||
docker compose -f /opt/xray-vps-setup/docker-compose.yml down && docker compose -f /opt/xray-vps-setup/docker-compose.yml up -d
|
||||
fi
|
||||
}
|
||||
|
||||
end_script() {
|
||||
if [[ ${configure_warp_input,,} == "y" ]]; then
|
||||
warp_install
|
||||
fi
|
||||
|
||||
if [[ "${marzban_input,,}" == "y" ]]; then
|
||||
docker run -v /opt/xray-vps-setup/caddy/Caddyfile:/opt/xray-vps-setup/Caddyfile --rm caddy caddy fmt --overwrite /opt/xray-vps-setup/Caddyfile
|
||||
docker compose -f /opt/xray-vps-setup/docker-compose.yml up -d
|
||||
|
||||
final_msg="Marzban panel location: https://$VLESS_DOMAIN/$MARZBAN_PATH
|
||||
User: xray_admin
|
||||
Password: $MARZBAN_PASS
|
||||
"
|
||||
if [[ ${configure_ssh_input,,} == "y" ]]; then
|
||||
echo "New user for ssh: $SSH_USER, password for user: $SSH_USER_PASS. New port for SSH: $SSH_PORT."
|
||||
fi
|
||||
else
|
||||
docker run -v /opt/xray-vps-setup/caddy/Caddyfile:/opt/xray-vps-setup/Caddyfile --rm caddy caddy fmt --overwrite /opt/xray-vps-setup/Caddyfile
|
||||
docker compose -f /opt/xray-vps-setup/docker-compose.yml up -d
|
||||
|
||||
xray_config=$(wget -qO- "https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/xray_outbound" | envsubst)
|
||||
singbox_config=$(wget -qO- "https://raw.githubusercontent.com/$GIT_REPO/refs/heads/$GIT_BRANCH/templates_for_script/sing_box_outbound" | envsubst)
|
||||
|
||||
final_msg="Clipboard string format:
|
||||
vless://$XRAY_UUID@$VLESS_DOMAIN:443?type=tcp&security=reality&pbk=$XRAY_PBK&fp=chrome&sni=$VLESS_DOMAIN&sid=$XRAY_SID&spx=%2F&flow=xtls-rprx-vision
|
||||
|
||||
XRay outbound config:
|
||||
$xray_config
|
||||
|
||||
Sing-box outbound config:
|
||||
$singbox_config
|
||||
|
||||
Plain data:
|
||||
PBK: $XRAY_PBK, SID: $XRAY_SID, UUID: $XRAY_UUID
|
||||
"
|
||||
fi
|
||||
|
||||
docker rmi ghcr.io/xtls/xray-core:latest caddy:latest
|
||||
clear
|
||||
echo "$final_msg"
|
||||
if [[ ${configure_ssh_input,,} == "y" ]]; then
|
||||
echo "New user for ssh: $SSH_USER, password for user: $SSH_USER_PASS. New port for SSH: $SSH_PORT."
|
||||
fi
|
||||
}
|
||||
|
||||
end_script
|
||||
set +e
|
||||
Reference in New Issue
Block a user