Index: /trunk/README.md
===================================================================
--- /trunk/README.md	(revision 316)
+++ /trunk/README.md	(revision 317)
@@ -14,5 +14,5 @@
 
     go run ./cmd/sojuctl create-user <username>
-    go run ./cmd/soju
+    go run ./cmd/soju -listen irc+insecure://127.0.0.1:6667
 
 Then connect with username `<username>/chat.freenode.net` and join `#soju`.
Index: /trunk/cmd/soju/main.go
===================================================================
--- /trunk/cmd/soju/main.go	(revision 316)
+++ /trunk/cmd/soju/main.go	(revision 317)
@@ -6,4 +6,6 @@
 	"log"
 	"net"
+	"net/url"
+	"strings"
 
 	"git.sr.ht/~emersion/soju"
@@ -12,7 +14,7 @@
 
 func main() {
-	var addr, configPath string
+	var listen, configPath string
 	var debug bool
-	flag.StringVar(&addr, "listen", "", "listening address")
+	flag.StringVar(&listen, "listen", "", "listening address")
 	flag.StringVar(&configPath, "config", "", "path to configuration file")
 	flag.BoolVar(&debug, "debug", false, "enable debug logging")
@@ -30,6 +32,9 @@
 	}
 
-	if addr != "" {
-		cfg.Addr = addr
+	if listen != "" {
+		cfg.Listen = append(cfg.Listen, listen)
+	}
+	if len(cfg.Listen) == 0 {
+		cfg.Listen = []string{":6697"}
 	}
 
@@ -39,5 +44,5 @@
 	}
 
-	var ln net.Listener
+	var tlsCfg *tls.Config
 	if cfg.TLS != nil {
 		cert, err := tls.LoadX509KeyPair(cfg.TLS.CertPath, cfg.TLS.KeyPath)
@@ -45,16 +50,5 @@
 			log.Fatalf("failed to load TLS certificate and key: %v", err)
 		}
-
-		tlsCfg := &tls.Config{Certificates: []tls.Certificate{cert}}
-		ln, err = tls.Listen("tcp", cfg.Addr, tlsCfg)
-		if err != nil {
-			log.Fatalf("failed to start TLS listener: %v", err)
-		}
-	} else {
-		var err error
-		ln, err = net.Listen("tcp", cfg.Addr)
-		if err != nil {
-			log.Fatalf("failed to start listener: %v", err)
-		}
+		tlsCfg = &tls.Config{Certificates: []tls.Certificate{cert}}
 	}
 
@@ -65,10 +59,49 @@
 	srv.Debug = debug
 
-	log.Printf("server listening on %q", cfg.Addr)
-	go func() {
-		if err := srv.Run(); err != nil {
-			log.Fatal(err)
+	for _, listen := range cfg.Listen {
+		listenURI := listen
+		if !strings.Contains(listenURI, ":/") {
+			// This is a raw domain name, make it an URL with an empty scheme
+			listenURI = "//" + listenURI
 		}
-	}()
-	log.Fatal(srv.Serve(ln))
+		u, err := url.Parse(listenURI)
+		if err != nil {
+			log.Fatalf("failed to parse listen URI %q: %v", listen, err)
+		}
+
+		switch u.Scheme {
+		case "ircs", "":
+			if tlsCfg == nil {
+				log.Fatalf("failed to listen on %q: missing TLS configuration", listen)
+			}
+			host := u.Host
+			if _, _, err := net.SplitHostPort(host); err != nil {
+				host = host + ":6697"
+			}
+			ln, err := tls.Listen("tcp", host, tlsCfg)
+			if err != nil {
+				log.Fatalf("failed to start TLS listener on %q: %v", listen, err)
+			}
+			go func() {
+				log.Fatal(srv.Serve(ln))
+			}()
+		case "irc+insecure":
+			host := u.Host
+			if _, _, err := net.SplitHostPort(host); err != nil {
+				host = host + ":6667"
+			}
+			ln, err := net.Listen("tcp", host)
+			if err != nil {
+				log.Fatalf("failed to start listener on %q: %v", listen, err)
+			}
+			go func() {
+				log.Fatal(srv.Serve(ln))
+			}()
+		default:
+			log.Fatalf("failed to listen on %q: unsupported scheme", listen)
+		}
+
+		log.Printf("server listening on %q", listen)
+	}
+	log.Fatal(srv.Run())
 }
Index: /trunk/config/config.go
===================================================================
--- /trunk/config/config.go	(revision 316)
+++ /trunk/config/config.go	(revision 317)
@@ -15,5 +15,5 @@
 
 type Server struct {
-	Addr      string
+	Listen    []string
 	Hostname  string
 	TLS       *TLS
@@ -29,5 +29,4 @@
 	}
 	return &Server{
-		Addr:      ":6667",
 		Hostname:  hostname,
 		SQLDriver: "sqlite3",
@@ -69,7 +68,9 @@
 		switch d.Name {
 		case "listen":
-			if err := d.parseParams(&srv.Addr); err != nil {
+			var uri string
+			if err := d.parseParams(&uri); err != nil {
 				return nil, err
 			}
+			srv.Listen = append(srv.Listen, uri)
 		case "hostname":
 			if err := d.parseParams(&srv.Hostname); err != nil {
Index: /trunk/doc/soju.1.scd
===================================================================
--- /trunk/doc/soju.1.scd	(revision 316)
+++ /trunk/doc/soju.1.scd	(revision 317)
@@ -57,6 +57,6 @@
 	passwords).
 
-*-listen* <address>
-	Listening address (default: ":6667").
+*-listen* <uri>
+	Listening URI (default: ":6697").
 
 # CONFIG FILE
@@ -64,6 +64,16 @@
 The config file has one directive per line.
 
-*listen* <address>
-	Listening address (default: ":6667").
+*listen* <uri>
+	Listening URI (default: ":6697").
+
+	The following URIs are supported:
+
+	- _[ircs://][host][:port]_ listens with TLS over TCP (default port if
+	  omitted: 6697)
+	- _irc+insecure://[host][:port]_ listens with plain-text over TCP (default
+	  port if omitted: 6667)
+
+	If the scheme is omitted, "ircs" is assumed. If multiple *listen*
+	directives are specified, soju will listen on each of them.
 
 *hostname* <name>
@@ -98,4 +108,5 @@
 
 	_addr_ supports several connection types:
+
 	- _[ircs://]host[:port]_ connects with TLS over TCP
 	- _irc+insecure://host[:port]_ connects with plain-text TCP
