mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-18 14:47:03 +00:00
When logging the configuration, we currently don't quote the string values, which can make whitespace-induced problems difficult to identify and troubleshoot. This patch changes the formatting to always quote string values when logging the configuration.
157 lines
4.1 KiB
Go
157 lines
4.1 KiB
Go
// Package config implements the chasquid configuration.
|
|
package config
|
|
|
|
// Generate the config protobuf.
|
|
//go:generate protoc --go_out=. --go_opt=paths=source_relative --experimental_allow_proto3_optional config.proto
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"blitiri.com.ar/go/log"
|
|
|
|
"google.golang.org/protobuf/encoding/prototext"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
var defaultConfig = &Config{
|
|
MaxDataSizeMb: 50,
|
|
|
|
SmtpAddress: []string{"systemd"},
|
|
SubmissionAddress: []string{"systemd"},
|
|
SubmissionOverTlsAddress: []string{"systemd"},
|
|
|
|
MailDeliveryAgentBin: "maildrop",
|
|
MailDeliveryAgentArgs: []string{"-f", "%from%", "-d", "%to_user%"},
|
|
|
|
DataDir: "/var/lib/chasquid",
|
|
|
|
SuffixSeparators: proto.String("+"),
|
|
DropCharacters: proto.String("."),
|
|
|
|
MailLogPath: "<syslog>",
|
|
}
|
|
|
|
// Load the config from the given file, with the given overrides.
|
|
func Load(path, overrides string) (*Config, error) {
|
|
// Start with a copy of the default config.
|
|
c := proto.Clone(defaultConfig).(*Config)
|
|
|
|
// Load from the path.
|
|
buf, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read config at %q: %v", path, err)
|
|
}
|
|
|
|
fromFile := &Config{}
|
|
err = prototext.Unmarshal(buf, fromFile)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parsing config: %v", err)
|
|
}
|
|
override(c, fromFile)
|
|
|
|
// Handle command line overrides.
|
|
fromOverrides := &Config{}
|
|
err = prototext.Unmarshal([]byte(overrides), fromOverrides)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parsing override: %v", err)
|
|
}
|
|
override(c, fromOverrides)
|
|
|
|
// Handle hostname separate, because if it is set, we don't need to call
|
|
// os.Hostname which can fail.
|
|
if c.Hostname == "" {
|
|
c.Hostname, err = os.Hostname()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get hostname: %v", err)
|
|
}
|
|
}
|
|
|
|
return c, nil
|
|
}
|
|
|
|
// Override fields in `c` that are set in `o`. We can't use proto.Merge
|
|
// because the semantics would not be convenient for overriding.
|
|
func override(c, o *Config) {
|
|
if o.Hostname != "" {
|
|
c.Hostname = o.Hostname
|
|
}
|
|
if o.MaxDataSizeMb > 0 {
|
|
c.MaxDataSizeMb = o.MaxDataSizeMb
|
|
}
|
|
if len(o.SmtpAddress) > 0 {
|
|
c.SmtpAddress = o.SmtpAddress
|
|
}
|
|
if len(o.SubmissionAddress) > 0 {
|
|
c.SubmissionAddress = o.SubmissionAddress
|
|
}
|
|
if len(o.SubmissionOverTlsAddress) > 0 {
|
|
c.SubmissionOverTlsAddress = o.SubmissionOverTlsAddress
|
|
}
|
|
if o.MonitoringAddress != "" {
|
|
c.MonitoringAddress = o.MonitoringAddress
|
|
}
|
|
|
|
if o.MailDeliveryAgentBin != "" {
|
|
c.MailDeliveryAgentBin = o.MailDeliveryAgentBin
|
|
}
|
|
if len(o.MailDeliveryAgentArgs) > 0 {
|
|
c.MailDeliveryAgentArgs = o.MailDeliveryAgentArgs
|
|
}
|
|
|
|
if o.DataDir != "" {
|
|
c.DataDir = o.DataDir
|
|
}
|
|
|
|
if o.SuffixSeparators != nil {
|
|
c.SuffixSeparators = o.SuffixSeparators
|
|
}
|
|
if o.DropCharacters != nil {
|
|
c.DropCharacters = o.DropCharacters
|
|
}
|
|
if o.MailLogPath != "" {
|
|
c.MailLogPath = o.MailLogPath
|
|
}
|
|
|
|
if o.DovecotAuth {
|
|
c.DovecotAuth = true
|
|
}
|
|
if o.DovecotUserdbPath != "" {
|
|
c.DovecotUserdbPath = o.DovecotUserdbPath
|
|
}
|
|
if o.DovecotClientPath != "" {
|
|
c.DovecotClientPath = o.DovecotClientPath
|
|
}
|
|
|
|
if o.HaproxyIncoming {
|
|
c.HaproxyIncoming = true
|
|
}
|
|
}
|
|
|
|
// LogConfig logs the given configuration, in a human-friendly way.
|
|
func LogConfig(c *Config) {
|
|
log.Infof("Configuration:")
|
|
log.Infof(" Hostname: %q", c.Hostname)
|
|
log.Infof(" Max data size (MB): %d", c.MaxDataSizeMb)
|
|
log.Infof(" SMTP Addresses: %q", c.SmtpAddress)
|
|
log.Infof(" Submission Addresses: %q", c.SubmissionAddress)
|
|
log.Infof(" Submission+TLS Addresses: %q", c.SubmissionOverTlsAddress)
|
|
log.Infof(" Monitoring address: %q", c.MonitoringAddress)
|
|
log.Infof(" MDA: %q %q", c.MailDeliveryAgentBin, c.MailDeliveryAgentArgs)
|
|
log.Infof(" Data directory: %q", c.DataDir)
|
|
if c.SuffixSeparators == nil {
|
|
log.Infof(" Suffix separators: nil")
|
|
} else {
|
|
log.Infof(" Suffix separators: %q", *c.SuffixSeparators)
|
|
}
|
|
if c.DropCharacters == nil {
|
|
log.Infof(" Drop characters: nil")
|
|
} else {
|
|
log.Infof(" Drop characters: %q", *c.DropCharacters)
|
|
}
|
|
log.Infof(" Mail log: %q", c.MailLogPath)
|
|
log.Infof(" Dovecot auth: %v (%q, %q)",
|
|
c.DovecotAuth, c.DovecotUserdbPath, c.DovecotClientPath)
|
|
log.Infof(" HAProxy incoming: %v", c.HaproxyIncoming)
|
|
}
|