diff --git a/README.md b/README.md
index 9a85c3e1..92b47b37 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
-# 3x-ui
+# 3x-ui
+
> **Disclaimer: This project is only for personal learning and communication, please do not use it for illegal purposes, please do not use it in a production environment**
[](https://github.com/MHSanaei/3x-ui/releases)
@@ -12,7 +13,8 @@
**If you think this project is helpful to you, you may wish to give a** :star2:
**Buy Me a Coffee :**
- - Tron USDT (TRC20): `TXncxkvhkDWGts487Pjqq1qT9JmwRUz8CC`
+
+- Tron USDT (TRC20): `TXncxkvhkDWGts487Pjqq1qT9JmwRUz8CC`
# Install & Upgrade
@@ -47,12 +49,12 @@ or you can use x-ui menu then number '16' (Apply for an SSL Certificate)
Before you set ssl on settings
-- http://ip:2053/xui
-- http://domain:2053/xui
+- http://ip:2053/panel
+- http://domain:2053/panel
After you set ssl on settings
-- https://yourdomain:2053/xui
+- https://yourdomain:2053/panel
# Environment Variables
@@ -69,6 +71,31 @@ Example:
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
```
+# Install with Docker
+
+1. Install Docker:
+ ```sh
+ bash <(curl -sSL https://get.docker.com)
+ ```
+2. Run 3x-ui:
+
+ ```sh
+ docker compose up -d
+ ```
+
+ OR
+
+ ```sh
+ docker run -itd \
+ -e XRAY_VMESS_AEAD_FORCED=false \
+ -v $PWD/db/:/etc/x-ui/ \
+ -v $PWD/cert/:/root/cert/ \
+ --network=host \
+ --restart=unless-stopped \
+ --name 3x-ui \
+ ghcr.io/mhsanaei/3x-ui:latest
+ ```
+
# Xray Configurations:
**copy and paste to xray Configuration :** (you don't need to do this if you have a fresh install)
@@ -173,19 +200,19 @@ Reference syntax:
| `POST` | `"/clientIps/:email"` | Client Ip address |
| `POST` | `"/clearClientIps/:email"` | Clear Client Ip address |
| `POST` | `"/addClient"` | Add Client to inbound |
-| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId* |
-| `POST` | `"/updateClient/:clientId"` | Update Client by clientId* |
+| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId\* |
+| `POST` | `"/updateClient/:clientId"` | Update Client by clientId\* |
| `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic |
| `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds |
| `POST` | `"/resetAllClientTraffics/:id"` | Reset traffics of all clients in an inbound |
| `POST` | `"/delDepletedClients/:id"` | Delete inbound depleted clients (-1: all) |
-*- The field `clientId` should be filled by:
+\*- The field `clientId` should be filled by:
+
- `client.id` for VMESS and VLESS
- `client.password` for TROJAN
- `client.email` for Shadowsocks
-
- [Postman Collection](https://gist.github.com/mehdikhody/9a862801a2e41f6b5fb6bbc7e1326044)
# A Special Thanks To
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..f0231309
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,15 @@
+---
+version: "3.9"
+
+services:
+ 3x-ui:
+ image: ghcr.io/mhsanaei/3x-ui:latest
+ container_name: 3x-ui
+ volumes:
+ - $PWD/db/:/etc/x-ui/
+ - $PWD/cert/:/root/cert/
+ environment:
+ XRAY_VMESS_AEAD_FORCED: "false"
+ tty: true
+ network_mode: host
+ restart: unless-stopped
diff --git a/web/controller/index.go b/web/controller/index.go
index 802f3f7d..b0ee83f8 100644
--- a/web/controller/index.go
+++ b/web/controller/index.go
@@ -39,7 +39,7 @@ func (a *IndexController) initRouter(g *gin.RouterGroup) {
func (a *IndexController) index(c *gin.Context) {
if session.IsLogin(c) {
- c.Redirect(http.StatusTemporaryRedirect, "xui/")
+ c.Redirect(http.StatusTemporaryRedirect, "panel/")
return
}
html(c, "login.html", "pages.login.title", nil)
@@ -101,5 +101,4 @@ func (a *IndexController) getSecretStatus(c *gin.Context) {
if err == nil {
jsonObj(c, status, nil)
}
-
}
diff --git a/web/controller/setting.go b/web/controller/setting.go
index bd9c2a5f..248f3ee5 100644
--- a/web/controller/setting.go
+++ b/web/controller/setting.go
@@ -3,6 +3,7 @@ package controller
import (
"errors"
"time"
+ "x-ui/util/common"
"x-ui/web/entity"
"x-ui/web/service"
"x-ui/web/session"
@@ -44,6 +45,7 @@ func (a *SettingController) initRouter(g *gin.RouterGroup) {
g.GET("/getDefaultJsonConfig", a.getDefaultJsonConfig)
g.POST("/updateUserSecret", a.updateSecret)
g.POST("/getUserSecret", a.getUserSecret)
+ g.GET("/searchDatafiles", a.searchDatafiles)
}
func (a *SettingController) getAllSetting(c *gin.Context) {
@@ -149,6 +151,7 @@ func (a *SettingController) updateSecret(c *gin.Context) {
}
jsonMsg(c, I18n(c, "pages.settings.toasts.modifyUser"), err)
}
+
func (a *SettingController) getUserSecret(c *gin.Context) {
loginUser := session.GetLoginUser(c)
user := a.userService.GetUserSecret(loginUser.Id)
@@ -156,3 +159,18 @@ func (a *SettingController) getUserSecret(c *gin.Context) {
jsonObj(c, user, nil)
}
}
+
+func (a *SettingController) searchDatafiles(c *gin.Context) {
+ searchString := c.Query("query")
+ if searchString == "" {
+ err := common.NewError("data query parameter is empty")
+ jsonMsg(c, "Invalid query:", err)
+ return
+ }
+ found, err := a.settingService.SearchDatafiles(searchString)
+ if err != nil {
+ jsonMsg(c, "Something went wrong!", err)
+ return
+ }
+ jsonObj(c, found, nil)
+}
diff --git a/web/controller/xui.go b/web/controller/xui.go
index 1844181d..700bd52c 100644
--- a/web/controller/xui.go
+++ b/web/controller/xui.go
@@ -18,7 +18,7 @@ func NewXUIController(g *gin.RouterGroup) *XUIController {
}
func (a *XUIController) initRouter(g *gin.RouterGroup) {
- g = g.Group("/xui")
+ g = g.Group("/panel")
g.Use(a.checkLogin)
g.GET("/", a.index)
diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html
index 2bd2f00f..855c349a 100644
--- a/web/html/common/qrcode_modal.html
+++ b/web/html/common/qrcode_modal.html
@@ -7,7 +7,10 @@
{{ i18n "pages.inbounds.clickOnQRcode" }}
-
+
+ {{ i18n "pages.inbounds.email" }}: "[[ qrModal.clientName ]]"
+
+