Files
archivmail/config/config.go
T
sysops 4a4136e4a6 feat: FQDN-Support, IMAP-TLS und SMTP-TLS via Master-Cert
- config: IMAPServerConfig um TLSCert/TLSKey erweitert
- imapserver: TLS-Support (tls.Listen) mit automatischem Port 993-Default
- Server-Konfiguration: FQDN archivmail.scahome.local
  - nginx server_name auf archivmail.scahome.local gesetzt
  - SMTP domain auf archivmail.scahome.local
  - SMTP TLS aktiviert (/etc/ssl/archivmail/archivmail.crt)
  - IMAP-Server TLS auf Port 993 aktiviert
  - secure_cookies: true (HTTPS)
  - Firewall: Port 993 geöffnet
  - Zertifikat neu ausgestellt (SAN: archivmail.scahome.local + archivmail + 192.168.1.131)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 00:32:25 +01:00

121 lines
3.9 KiB
Go

package config
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// APIConfig holds configuration for the HTTP API server.
type APIConfig struct {
Bind string `yaml:"bind"`
Secret string `yaml:"secret"`
// SecureCookies sets the Secure flag on session cookies.
// Enable when TLS is terminated at this server or at a trusted reverse proxy.
SecureCookies bool `yaml:"secure_cookies"`
// TrustedProxies is a list of IP addresses or CIDR ranges whose
// X-Forwarded-For header is trusted. Empty = trust no proxy (use r.RemoteAddr).
TrustedProxies []string `yaml:"trusted_proxies"`
}
// Config is the full application configuration loaded from YAML.
type Config struct {
Server ServerConfig `yaml:"server"`
Storage StorageConfig `yaml:"storage"`
Database DatabaseConfig `yaml:"database"`
SMTP SMTPConfig `yaml:"smtp"`
API APIConfig `yaml:"api"`
Index IndexConfig `yaml:"index"`
Audit AuditConfig `yaml:"audit"`
Logging LoggingConfig `yaml:"logging"`
IMAPServer IMAPServerConfig `yaml:"imap_server"`
}
// IMAPServerConfig holds settings for the embedded read-only IMAP archive server.
type IMAPServerConfig struct {
Enabled bool `yaml:"enabled"`
Bind string `yaml:"bind"` // plain: ":1143", TLS: ":993"
TLSCert string `yaml:"tls_cert"` // path to PEM certificate; if set, TLS is enabled
TLSKey string `yaml:"tls_key"` // path to PEM private key
}
// ServerConfig holds port settings for the main services.
type ServerConfig struct {
APIPort int `yaml:"api_port"`
SMTPPort int `yaml:"smtp_port"`
}
// StorageConfig holds file system paths for email storage.
type StorageConfig struct {
StorePath string `yaml:"store_path"`
AStorePath string `yaml:"astore_path"`
XapianPath string `yaml:"xapian_path"`
Keyfile string `yaml:"keyfile"`
}
// DatabaseConfig holds PostgreSQL connection settings.
type DatabaseConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Name string `yaml:"name"`
User string `yaml:"user"`
Password string `yaml:"password"`
SSLMode string `yaml:"sslmode"`
}
// DSN builds a PostgreSQL connection string from the config fields.
func (d DatabaseConfig) DSN() string {
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
d.User, d.Password, d.Host, d.Port, d.Name, d.SSLMode)
}
// SMTPConfig holds settings for the embedded SMTP server.
// SEC-26: AllowedIPs uses fail-closed logic. An empty list means NO IP is
// allowed to connect. To accept from any IP, explicitly set:
// allowed_ips: ["0.0.0.0/0", "::/0"]
type SMTPConfig struct {
Enabled bool `yaml:"enabled"`
Bind string `yaml:"bind"`
Domain string `yaml:"domain"`
TLSCert string `yaml:"tls_cert"`
TLSKey string `yaml:"tls_key"`
MaxSizeMB int `yaml:"max_size_mb"`
AllowedIPs []string `yaml:"allowed_ips"`
TenantRouting string `yaml:"tenant_routing"` // "domain" or "default"
DefaultTenantID int64 `yaml:"default_tenant_id"` // used when routing is "default" or domain lookup fails
}
// IndexConfig holds full-text index settings.
type IndexConfig struct {
Path string `yaml:"path"`
Backend string `yaml:"backend"`
BatchSize int `yaml:"batch_size"`
AsyncQueueSize int `yaml:"async_queue_size"`
}
// AuditConfig holds audit log settings.
type AuditConfig struct {
LogPath string `yaml:"log_path"`
RetentionDays int `yaml:"retention_days"`
}
// LoggingConfig holds application logging settings.
type LoggingConfig struct {
Path string `yaml:"path"`
Level string `yaml:"level"`
}
// Load reads a YAML config file from path and returns a parsed Config.
func Load(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var cfg Config
if err := yaml.Unmarshal(data, &cfg); err != nil {
return nil, err
}
return &cfg, nil
}