// Command mitmuxd is the mitmux headless proxy daemon. It owns the // listening socket and (in later build steps) the traffic database; a // TUI or other client attaches separately without interrupting capture. package main import ( "context" "flag" "log" "os" "os/signal" "syscall" "time" "mitmux/internal/ca" "mitmux/internal/proxy" ) func main() { listen := flag.String("listen", "127.0.0.1:8080", "proxy listen address") caDir := flag.String("ca-dir", "", "directory for CA cert/key (default: XDG config dir)") flag.Parse() dir := *caDir if dir == "" { d, err := ca.Dir() if err != nil { log.Fatalf("resolve CA dir: %v", err) } dir = d } root, err := ca.EnsureCA(dir) if err != nil { log.Fatalf("load CA: %v", err) } log.Printf("CA ready: %s (install %s/ca.pem in your client's trust store to avoid TLS warnings)", root.Cert.Subject.CommonName, dir) srv := proxy.New(*listen, root) errCh := make(chan error, 1) go func() { errCh <- srv.ListenAndServe() }() sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) select { case err := <-errCh: if err != nil { log.Fatalf("proxy: %v", err) } case sig := <-sigCh: log.Printf("received %s, shutting down", sig) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatalf("shutdown: %v", err) } } }