feat: Template Xray TCP certificate and key file paths using a domain placeholder.
This commit is contained in:
parent
96a080bdf5
commit
283274e359
@ -211,10 +211,12 @@ func runServer(ctx context.Context, cfg *config.Config, logger *slog.Logger) err
|
||||
{
|
||||
Definition: xrayconfig.XHTTPDefinition(),
|
||||
OutputPath: "/usr/local/etc/xray/config.json", // Match user's xhttp config path
|
||||
Domain: cfg.Xray.Sync.Domain,
|
||||
},
|
||||
{
|
||||
Definition: xrayconfig.TCPDefinition(),
|
||||
OutputPath: "/usr/local/etc/xray/tcp-config.json", // Match user's tcp config path
|
||||
Domain: cfg.Xray.Sync.Domain,
|
||||
},
|
||||
},
|
||||
ValidateCommand: cfg.Xray.Sync.ValidateCommand,
|
||||
|
||||
@ -119,6 +119,7 @@ type Xray struct {
|
||||
type XraySync struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Interval time.Duration `yaml:"interval"`
|
||||
Domain string `yaml:"domain"`
|
||||
OutputPath string `yaml:"outputPath"`
|
||||
TemplatePath string `yaml:"templatePath"`
|
||||
ValidateCommand []string `yaml:"validateCommand"`
|
||||
|
||||
@ -82,10 +82,12 @@ func Run(ctx context.Context, opts Options) error {
|
||||
{
|
||||
Definition: xrayconfig.XHTTPDefinition(),
|
||||
OutputPath: "/usr/local/etc/xray/config.json",
|
||||
Domain: opts.Xray.Sync.Domain,
|
||||
},
|
||||
{
|
||||
Definition: xrayconfig.TCPDefinition(),
|
||||
OutputPath: "/usr/local/etc/xray/tcp-config.json",
|
||||
Domain: opts.Xray.Sync.Domain,
|
||||
},
|
||||
}
|
||||
if templatePath := strings.TrimSpace(opts.Xray.Sync.TemplatePath); templatePath != "" {
|
||||
@ -100,6 +102,7 @@ func Run(ctx context.Context, opts Options) error {
|
||||
{
|
||||
Definition: xrayconfig.JSONDefinition{Raw: append([]byte(nil), payload...)},
|
||||
OutputPath: effectivePath,
|
||||
Domain: opts.Xray.Sync.Domain,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -38,6 +39,9 @@ type Generator struct {
|
||||
// FileMode controls the permissions for the generated file. When zero it
|
||||
// defaults to 0644.
|
||||
FileMode fs.FileMode
|
||||
|
||||
// Domain is the hostname used to interpolate templates (e.g. for cert paths).
|
||||
Domain string
|
||||
}
|
||||
|
||||
// Generate writes a new Xray configuration with the provided clients. The base
|
||||
@ -72,9 +76,9 @@ func (g Generator) Render(clients []Client) ([]byte, error) {
|
||||
definition = DefaultDefinition()
|
||||
}
|
||||
|
||||
root, err := definition.Base()
|
||||
root, err := g.renderTemplate(definition)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load template: %w", err)
|
||||
return nil, fmt.Errorf("render template: %w", err)
|
||||
}
|
||||
|
||||
if err := replaceClients(root, clients); err != nil {
|
||||
@ -89,6 +93,35 @@ func (g Generator) Render(clients []Client) ([]byte, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (g Generator) renderTemplate(definition Definition) (map[string]interface{}, error) {
|
||||
jsonDef, ok := definition.(JSONDefinition)
|
||||
if !ok {
|
||||
return definition.Base()
|
||||
}
|
||||
|
||||
tmpl, err := template.New("xray").Parse(string(jsonDef.Raw))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse template: %w", err)
|
||||
}
|
||||
|
||||
data := struct {
|
||||
Domain string
|
||||
}{
|
||||
Domain: g.Domain,
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
if err := tmpl.Execute(&buf, data); err != nil {
|
||||
return nil, fmt.Errorf("execute template: %w", err)
|
||||
}
|
||||
|
||||
var root map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(buf.String()), &root); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal rendered template: %w", err)
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func replaceClients(root map[string]interface{}, clients []Client) error {
|
||||
inboundsValue, ok := root["inbounds"]
|
||||
if !ok {
|
||||
|
||||
@ -43,8 +43,8 @@
|
||||
"certificates": [
|
||||
{
|
||||
"ocspStapling": 3600,
|
||||
"certificateFile": "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/ha-proxy-jp.svc.plus/ha-proxy-jp.svc.plus.crt",
|
||||
"keyFile": "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/ha-proxy-jp.svc.plus/ha-proxy-jp.svc.plus.key"
|
||||
"certificateFile": "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/{{.Domain}}/{{.Domain}}.crt",
|
||||
"keyFile": "/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/{{.Domain}}/{{.Domain}}.key"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user