diff --git a/caddy/caddy.go b/caddy/caddy.go
index b82a58a98..8500d7945 100644
--- a/caddy/caddy.go
+++ b/caddy/caddy.go
@@ -11,9 +11,6 @@
 //
 // You should use caddy.Wait() to wait for all Caddy servers
 // to quit before your process exits.
-//
-// Importing this package has the side-effect of trapping signals.
-// It has to do this in order to perform shutdowns or reloads.
 package caddy
 
 import (
diff --git a/caddy/restart_windows.go b/caddy/restart_windows.go
index 00ec94a71..18478f4bd 100644
--- a/caddy/restart_windows.go
+++ b/caddy/restart_windows.go
@@ -1,5 +1,7 @@
 package caddy
 
+// Restart restarts Caddy forcefully using newCaddyfile,
+// or, if nil, the current/existing Caddyfile is reused.
 func Restart(newCaddyfile Input) error {
 	if newCaddyfile == nil {
 		caddyfileMu.Lock()
diff --git a/caddy/sigtrap.go b/caddy/sigtrap.go
index f18e6ba70..39b7bd77d 100644
--- a/caddy/sigtrap.go
+++ b/caddy/sigtrap.go
@@ -9,10 +9,20 @@ import (
 	"github.com/mholt/caddy/server"
 )
 
-func init() {
-	// Trap interrupt signal (cross-platform); triggers forceful shutdown
-	// that executes shutdown callbacks first. A second interrupt signal
-	// will exit the process immediately.
+// TrapSignals create signal handlers for all applicable signals for this
+// system. If your Go program uses signals, this is a rather invasive
+// function; best to implement them yourself in that case. Signals are not
+// required for the caddy package to function properly, but this is a
+// convenient way to allow the user to control this package of your program.
+func TrapSignals() {
+	trapSignalsCrossPlatform()
+	trapSignalsPosix()
+}
+
+// trapSignalsCrossPlatform captures SIGINT, which triggers forceful
+// shutdown that executes shutdown callbacks first. A second interrupt
+// signal will exit the process immediately.
+func trapSignalsCrossPlatform() {
 	go func() {
 		shutdown := make(chan os.Signal, 1)
 		signal.Notify(shutdown, os.Interrupt)
diff --git a/caddy/sigtrap_posix.go b/caddy/sigtrap_posix.go
index 1d602a910..2777ebc2e 100644
--- a/caddy/sigtrap_posix.go
+++ b/caddy/sigtrap_posix.go
@@ -10,8 +10,8 @@ import (
 	"syscall"
 )
 
-func init() {
-	// Trap all POSIX-only signals
+// trapSignalsPosix captures POSIX-only signals.
+func trapSignalsPosix() {
 	go func() {
 		sigchan := make(chan os.Signal, 1)
 		signal.Notify(sigchan, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGUSR1)
diff --git a/caddy/sigtrap_windows.go b/caddy/sigtrap_windows.go
new file mode 100644
index 000000000..cbe7c0199
--- /dev/null
+++ b/caddy/sigtrap_windows.go
@@ -0,0 +1,3 @@
+package caddy
+
+func trapSignalsPosix() {}
diff --git a/dist/CHANGES.txt b/dist/CHANGES.txt
index 88c35a86d..4b9a1ffbc 100644
--- a/dist/CHANGES.txt
+++ b/dist/CHANGES.txt
@@ -12,6 +12,7 @@ CHANGES
 - New -log flag to enable process log
 - New -pidfile flag to enable writing pidfile
 - New -grace flag to customize the graceful shutdown timeout
+- New support for SIGHUP, SIGTERM, and SIGQUIT signals
 - browse: Render filenames with multiple whitespace properly
 - markdown: Include Last-Modified header in response
 - markdown: Render tables, strikethrough, and fenced code blocks
diff --git a/main.go b/main.go
index 3ec8ad7fc..784fc651e 100644
--- a/main.go
+++ b/main.go
@@ -30,6 +30,7 @@ const (
 )
 
 func init() {
+	caddy.TrapSignals()
 	flag.BoolVar(&letsencrypt.Agreed, "agree", false, "Agree to Let's Encrypt Subscriber Agreement")
 	flag.StringVar(&letsencrypt.CAUrl, "ca", "https://acme-staging.api.letsencrypt.org/directory", "Certificate authority ACME server")
 	flag.StringVar(&conf, "conf", "", "Configuration file to use (default="+caddy.DefaultConfigFile+")")