4.1 KiB
AGENTS.md
This file provides guidance to agents when working with code in this repository.
Critical Architecture Patterns
Telegram Bot Restart Pattern: MUST call service.StopBot() before any server restart (SIGHUP or shutdown) to prevent Telegram bot 409 conflicts. This is critical in main.go signal handlers (lines 82-84, 120-122).
Embedded Assets: All web resources (HTML, CSS, JS, translations in web/translation/) are embedded at compile time using //go:embed. Changes to these files require full recompilation - no hot-reload available.
Dual Server Design: Main web panel and subscription server run concurrently, both managed by web/global package. Subscription server uses separate port.
Database Seeder System: Uses HistoryOfSeeders model to track one-time migrations (e.g., password bcrypt migration). Check this table before running migrations to prevent re-execution.
Xray Integration: Panel dynamically generates config.json from inbound/outbound settings and communicates via gRPC API (xray/api.go) for real-time traffic stats. Xray binary is platform-specific (xray-{os}-{arch}) and managed by installer scripts.
Signal-Based Restart: SIGHUP triggers graceful restart. Always stop Telegram bot first via service.StopBot(), then restart both web and sub servers.
Build & Development Commands
# Build (creates bin/3x-ui.exe)
go build -o bin/3x-ui.exe ./main.go
# Run with debug logging
XUI_DEBUG=true go run ./main.go
# Test all packages
go test ./...
# Vet code
go vet ./...
Production Build: Uses CGO_ENABLED=1 with static linking via Bootlin musl toolchains for cross-platform builds (see .github/workflows/release.yml).
Configuration & Environment
Environment Variables:
XUI_DEBUG=true- Enable detailed debug loggingXUI_LOG_LEVEL- Set log level (debug/info/notice/warning/error)XUI_MAIN_FOLDER- Override default installation folderXUI_BIN_FOLDER- Override binary folder (default: "bin")XUI_DB_FOLDER- Override database folder (default:/etc/x-uion Linux)XUI_LOG_FOLDER- Override log folder (default:/var/log/x-uion Linux)
Database Path: config.GetDBPath() returns /etc/x-ui/x-ui.db on Linux, current directory on Windows. GORM models auto-migrate on startup.
Listen Address: If inbound listen field is empty, defaults to 0.0.0.0 for proper dual-stack IPv4/IPv6 binding (see database/model/model.go lines 85-87).
Project-Specific Patterns
IP Limitation: Implements "last IP wins" strategy. When client exceeds LimitIP, oldest connections are automatically disconnected via Xray API to allow newest IPs.
Session Management: Uses gin-contrib/sessions with cookie-based store for authentication.
Internationalization: Translation files in web/translation/translate.*.toml. Access via I18nWeb(c, "key") in controllers using locale.I18nType enum.
Job Scheduling: Uses robfig/cron/v3 for periodic tasks (traffic monitoring, CPU checks, LDAP sync, IP tracking). Jobs registered in web/web.go during server initialization.
Service Layer Pattern: Services inject dependencies (like xray.XrayAPI) and operate on GORM models. Example: InboundService in web/service/inbound.go.
Controller Pattern: Controllers use Gin context (*gin.Context) and inherit from BaseController. Check auth via checkLogin middleware.
Xray Binary Management: Download platform-specific Xray binary to bin folder during installation. GeoIP/GeoSite rules downloaded from external repositories (Loyalsoldier, chocolate4u, runetfreedom).
Gotchas
- Bot Restart: Always stop Telegram bot before server restart to avoid 409 conflict
- Embedded Assets: Changes to HTML/CSS/JS require recompilation
- Password Migration: Seeder system tracks bcrypt migration - check
HistoryOfSeederstable - Port Binding: Subscription server uses different port from main panel
- Xray Binary: Must match OS/arch exactly - managed by installer scripts
- No Test Files: Project currently has no
_test.gofiles, thoughgo test ./...is available