diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ef8afaf969cb21e03928696e7de2ffe9fea2877b..c3a2fb80e26302cec10826c1bde0cb48d43eb2e1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,14 +12,22 @@ test:1.5:
   image: golang:1.5
   script:
   - make verify-lite
+  - make acceptance
 
 test:1.6:
   image: golang:1.6
   script:
   - make verify
+  - make acceptance
 
 test:1.7:
   image: golang:1.7
   script:
   - make verify
   - make acceptance
+
+test:1.8:
+  image: golang:1.8
+  script:
+  - make verify
+  - make acceptance
diff --git a/Makefile b/Makefile
index 2c1b8e1a89690d915928ada480775a79ac8bc2d6..1bee4e6a6537fb603877bb006ddbec8a5e16b0c8 100644
--- a/Makefile
+++ b/Makefile
@@ -40,10 +40,11 @@ complexity:
 
 test:
 	go get golang.org/x/tools/cmd/cover
-	go test ./... -cover
+	go test ./... -short -cover -v -timeout 1m
 
 acceptance: gitlab-pages
-	go test ./... -run-acceptance-tests
+	go get golang.org/x/tools/cmd/cover
+	go test ./... -cover -v -timeout 1m
 
 docker:
 	docker run --rm -it -v ${PWD}:/go/src/pages -w /go/src/pages golang:1.5 /bin/bash
diff --git a/README.md b/README.md
index 295ca7a78ac1c3bce7c6fd72d10aeffeea1b96a2..7ff395cc2055b811390cd9b3aac4b484bbbd7acb 100644
--- a/README.md
+++ b/README.md
@@ -39,15 +39,18 @@ If load balancer is run in SSL-offloading mode the custom TLS certificate will n
 
 Example:
 ```
-go build
+CGO_ENABLED=0 GO15VENDOREXPERIMENT=1 go build
 ./gitlab-pages -listen-https "" -listen-http ":8090" -pages-root path/to/gitlab/shared/pages -pages-domain example.com
 ```
 
 ### Run daemon **in secure mode**
 
-The daemon can be run in chroot with dropped privileges.
+When compiled with `CGO_ENABLED=0` (which is the default), `gitlab-pages` is a
+static binary and so can be run in chroot with dropped privileges.
 
-Run daemon as root user and pass the `-daemon-uid` and `-daemon-gid`.
+To enter this mode, run `gitlab-pages` as the root user and pass it the
+`-daemon-uid` and `-daemon-gid` arguments to specify the user you want it to run
+as.
 
 The daemon start listening on ports as root, reads certificates as root and re-executes itself as specified user.
 When re-executing it copies it's own binary to `pages-root` and changes root to that directory.
@@ -74,8 +77,8 @@ This is most useful in dual-stack environments (IPv4+IPv6) where both Gitlab Pag
 
 ### Enable Prometheus Metrics
 
-For monitoring purposes, one could pass the `-metrics-address` flag when 
-starting. This will expose general metrics about the Go runtime and pages 
+For monitoring purposes, one could pass the `-metrics-address` flag when
+starting. This will expose general metrics about the Go runtime and pages
 application for [Prometheus](https://prometheus.io/) to scrape.
 
 Example:
diff --git a/acceptance_test.go b/acceptance_test.go
index 1cfd133a6cc3e464546c9978ffe84322c6db6081..e1a7167ac7ed9519286201f41bdd9cb40450cbb3 100644
--- a/acceptance_test.go
+++ b/acceptance_test.go
@@ -4,12 +4,12 @@ import (
 	"flag"
 	"io/ioutil"
 	"net/http"
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
 )
 
-var shouldRun = flag.Bool("run-acceptance-tests", false, "Run the acceptance tests?")
 var pagesBinary = flag.String("gitlab-pages-binary", "./gitlab-pages", "Path to the gitlab-pages binary")
 
 // TODO: Use TCP port 0 everywhere to avoid conflicts. The binary could output
@@ -25,12 +25,15 @@ var listeners = []ListenSpec{
 }
 
 func skipUnlessEnabled(t *testing.T) {
-	if *shouldRun {
-		return
+	if testing.Short() {
+		t.Log("Acceptance tests disabled")
+		t.SkipNow()
 	}
 
-	t.Log("Acceptance tests disabled")
-	t.SkipNow()
+	if _, err := os.Stat(*pagesBinary); os.IsNotExist(err) {
+		t.Errorf("Couldn't find gitlab-pages binary at %s", *pagesBinary)
+		t.FailNow()
+	}
 }
 
 func TestUnknownHostReturnsNotFound(t *testing.T) {
diff --git a/daemon.go b/daemon.go
index 8d68bb446efe1806c6b42eef6c64af4266251ebd..bbe69118ffdda145ae5510838809a9590d2836fb 100644
--- a/daemon.go
+++ b/daemon.go
@@ -188,7 +188,7 @@ func daemonize(config appConfig, uid, gid uint) {
 	// Run daemon in chroot environment
 	temporaryExecutable, err := daemonChroot(cmd)
 	if err != nil {
-		println("Chroot failed", err)
+		log.Println("Chroot failed", err)
 		return
 	}
 	defer os.Remove(temporaryExecutable)
@@ -211,7 +211,7 @@ func daemonize(config appConfig, uid, gid uint) {
 
 	// Start the process
 	if err = cmd.Start(); err != nil {
-		println("Start failed", err)
+		log.Println("Start failed", err)
 		return
 	}
 
diff --git a/domain.go b/domain.go
index 46f57ed028d6795228ffeb558c3e5c74c710a58e..19e099ac16aef9f2cd7575198f6f7ddf640a285e 100644
--- a/domain.go
+++ b/domain.go
@@ -34,7 +34,7 @@ func (d *domain) serveFile(w http.ResponseWriter, r *http.Request, fullPath stri
 		return err
 	}
 
-	println("Serving", fullPath, "for", r.URL.Path)
+	fmt.Println("Serving", fullPath, "for", r.URL.Path)
 	http.ServeContent(w, r, filepath.Base(file.Name()), fi.ModTime(), file)
 	return nil
 }
@@ -52,7 +52,7 @@ func (d *domain) serveCustomFile(w http.ResponseWriter, r *http.Request, code in
 		return err
 	}
 
-	println("Serving", fullPath, "for", r.URL.Path, "with", code)
+	fmt.Println("Serving", fullPath, "for", r.URL.Path, "with", code)
 
 	// Serve the file
 	_, haveType := w.Header()["Content-Type"]
diff --git a/helpers_test.go b/helpers_test.go
index e7fd744e6d7986a84966c81452aeaeca5a3dc488..99a44ea17cb32d06182e914a202a1bd5d04e94e0 100644
--- a/helpers_test.go
+++ b/helpers_test.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"bytes"
 	"crypto/tls"
 	"fmt"
 	"io/ioutil"
@@ -15,6 +16,16 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
+type tWriter struct {
+	t *testing.T
+}
+
+func (t *tWriter) Write(b []byte) (int, error) {
+	t.t.Log(string(bytes.TrimRight(b, "\r\n")))
+
+	return len(b), nil
+}
+
 var chdirSet = false
 
 func setUpTests() {
@@ -131,6 +142,8 @@ func RunPagesProcess(t *testing.T, pagesPath string, listeners []ListenSpec, pro
 
 	args, tempfiles := getPagesArgs(t, listeners, promPort)
 	cmd := exec.Command(pagesPath, args...)
+	cmd.Stdout = &tWriter{t}
+	cmd.Stderr = &tWriter{t}
 	cmd.Start()
 	t.Logf("Running %s %v", pagesPath, args)
 
@@ -144,10 +157,10 @@ func RunPagesProcess(t *testing.T, pagesPath string, listeners []ListenSpec, pro
 	for _, spec := range listeners {
 		spec.WaitUntilListening()
 	}
-	time.Sleep(50 * time.Millisecond)
+	time.Sleep(500 * time.Millisecond)
 
 	return func() {
-		cmd.Process.Kill()
+		cmd.Process.Signal(os.Interrupt)
 		cmd.Process.Wait()
 		for _, tempfile := range tempfiles {
 			os.Remove(tempfile)
@@ -176,9 +189,11 @@ func getPagesArgs(t *testing.T, listeners []ListenSpec, promPort string) (args,
 		args = append(args, "-metrics-address", promPort)
 	}
 
-	if os.Geteuid() == 0 && os.Getenv("SUDO_UID") != "" && os.Getenv("SUDO_GID") != "" {
-		t.Log("Pages process will drop privileges")
-		args = append(args, "-daemon-uid", os.Getenv("SUDO_UID"), "-daemon-gid", os.Getenv("SUDO_GID"))
+	// At least one of `-daemon-uid` and `-daemon-gid` must be non-zero
+	if os.Geteuid() == 0 {
+		t.Log("Running pages as a daemon")
+		args = append(args, "-daemon-uid", "0")
+		args = append(args, "-daemon-gid", "65534") // Root user can switch to "nobody"
 	}
 
 	return