diff --git a/backend/internal/caddy/config.go b/backend/internal/caddy/config.go index ae479556..cef0cb20 100644 --- a/backend/internal/caddy/config.go +++ b/backend/internal/caddy/config.go @@ -10,7 +10,32 @@ import ( // GenerateConfig creates a Caddy JSON configuration from proxy hosts. // This is the core transformation layer from our database model to Caddy config. func GenerateConfig(hosts []models.ProxyHost, storageDir string, acmeEmail string) (*Config, error) { + // Define log file paths + // We assume storageDir is like ".../data/caddy/data", so we go up to ".../data/logs" + // Or we can just use a relative path if Caddy's working directory is set correctly. + // In Docker, WORKDIR is /app, and storageDir passed here is usually /app/data/caddy. + // Let's put logs in /app/data/logs/access.log + logFile := "/app/data/logs/access.log" + config := &Config{ + Logging: &LoggingConfig{ + Logs: map[string]*LogConfig{ + "access": { + Writer: &WriterConfig{ + Output: "file", + Filename: logFile, + Roll: true, + RollSize: 10, // 10 MB + RollKeep: 5, // Keep 5 files + RollKeepDays: 7, // Keep for 7 days + }, + Encoder: &EncoderConfig{ + Format: "json", + }, + Include: []string{"http.log.access.access_log"}, + }, + }, + }, Apps: Apps{ HTTP: &HTTPApp{ Servers: map[string]*Server{}, @@ -47,6 +72,7 @@ func GenerateConfig(hosts []models.ProxyHost, storageDir string, acmeEmail strin return config, nil } + // We already initialized srv0 above, so we just append routes to it routes := make([]*Route, 0) for _, host := range hosts { @@ -123,6 +149,9 @@ func GenerateConfig(hosts []models.ProxyHost, storageDir string, acmeEmail strin Disable: false, DisableRedir: false, }, + Logs: &ServerLogs{ + DefaultLoggerName: "access_log", + }, } return config, nil diff --git a/backend/internal/caddy/types.go b/backend/internal/caddy/types.go index 4cfa60c4..5a8279d4 100644 --- a/backend/internal/caddy/types.go +++ b/backend/internal/caddy/types.go @@ -3,8 +3,44 @@ package caddy // Config represents Caddy's top-level JSON configuration structure. // Reference: https://caddyserver.com/docs/json/ type Config struct { - Apps Apps `json:"apps"` - Storage Storage `json:"storage,omitempty"` + Apps Apps `json:"apps"` + Logging *LoggingConfig `json:"logging,omitempty"` + Storage Storage `json:"storage,omitempty"` +} + +// LoggingConfig configures Caddy's logging facility. +type LoggingConfig struct { + Logs map[string]*LogConfig `json:"logs,omitempty"` + Sinks *SinkConfig `json:"sinks,omitempty"` +} + +// LogConfig configures a specific logger. +type LogConfig struct { + Writer *WriterConfig `json:"writer,omitempty"` + Encoder *EncoderConfig `json:"encoder,omitempty"` + Level string `json:"level,omitempty"` + Include []string `json:"include,omitempty"` + Exclude []string `json:"exclude,omitempty"` +} + +// WriterConfig configures the log writer (output). +type WriterConfig struct { + Output string `json:"output"` + Filename string `json:"filename,omitempty"` + Roll bool `json:"roll,omitempty"` + RollSize int `json:"roll_size_mb,omitempty"` + RollKeep int `json:"roll_keep,omitempty"` + RollKeepDays int `json:"roll_keep_days,omitempty"` +} + +// EncoderConfig configures the log format. +type EncoderConfig struct { + Format string `json:"format"` // "json", "console", etc. +} + +// SinkConfig configures log sinks (e.g. stderr). +type SinkConfig struct { + Writer *WriterConfig `json:"writer,omitempty"` } // Storage configures the storage module.