diff --git a/extenginx/create_dev_keys.sh b/extenginx/create_dev_keys.sh
index 2f6876c0..5c2e6b91 100755
--- a/extenginx/create_dev_keys.sh
+++ b/extenginx/create_dev_keys.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
-set -uexo pipefail
+set -uex
 
 mkdir -p ssl
 test -f ssl/ssl-dhparams.pem || openssl genpkey -genparam -algorithm DH -out ssl/ssl-dhparams.pem -pkeyopt dh_paramgen_prime_len:2048
diff --git a/orbit/test-style.sh b/orbit/test-style.sh
index 62e66bac..c7518fdf 100755
--- a/orbit/test-style.sh
+++ b/orbit/test-style.sh
@@ -1,8 +1,11 @@
-#!/bin/bash
+#!/bin/sh
 
-scan() { echo "[SCAN] ${1}" ; flake8 "${1}" || exit 1 ; }
+require() { command -v "$1" > /dev/null || { echo "error: $1 command required yet absent" ; exit 1 ; } ; }
+require flake8
 
-scan radius.py
-scan config.py
-scan db.py
-scan hyperspace.py
+set -ex
+
+flake8 radius.py
+flake8 config.py
+flake8 db.py
+flake8 hyperspace.py
diff --git a/orbit/warpdrive.sh b/orbit/warpdrive.sh
index 0a294072..ed4ef082 100755
--- a/orbit/warpdrive.sh
+++ b/orbit/warpdrive.sh
@@ -2,12 +2,17 @@
 #
 # the warp drive allows you to enter hyperspace
 
+require() { command -v "$1" > /dev/null || { echo "error: $1 command required yet absent" ; exit 1 ; } ; }
+
 cd "$(dirname "$0")"
 
 DOCKER=${DOCKER:-podman}
+
+require "${DOCKER}"
+
 CONTAINER=${CONTAINER:-singularity_orbit_1}
 
-cat <<EOF | $DOCKER exec -i $CONTAINER /bin/sh
+cat <<EOF | $DOCKER exec -i "$CONTAINER" /bin/sh
 . /radius-venv/bin/activate
 /orbit/hyperspace.py $@
 EOF
diff --git a/script-lint.sh b/script-lint.sh
new file mode 100755
index 00000000..b618f052
--- /dev/null
+++ b/script-lint.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+require() { command -v "$1" > /dev/null || { echo "error: $1 command required yet absent" ; exit 1 ; } ; }
+require shellcheck
+
+set -ex
+
+shellcheck script-lint.sh
+shellcheck test.sh
+shellcheck extenginx/create_dev_keys.sh
+shellcheck orbit/test-style.sh
+shellcheck orbit/warpdrive.sh
diff --git a/test.sh b/test.sh
index 8ed9ed5c..977b301a 100755
--- a/test.sh
+++ b/test.sh
@@ -10,21 +10,35 @@
 #   of the furthest right failing command or zero if no command failed (o pipefail)
 set -exuo pipefail
 
-require() { command -v "$1" || { echo "error: $1 command required yet absent" ; exit 1 ; } ; }
+# This function will push an action to a stack of items to be done on script exit
+# in the reverse order that they are passed to this function
+trap ":" EXIT
+add_cleanup() {
+	trap -- "$(
+		printf '%s\n' "$1"
+		# get stack is invoked in eval but shellcheck cannot tell since it is indirect
+		# shellcheck disable=SC2317
+		get_stack() { printf '%s\n' "$3"; }
+		eval "get_stack $(trap -p EXIT)"
+	)" EXIT
+}
+
+require() { command -v "$1" > /dev/null || { echo "error: $1 command required yet absent" ; exit 1 ; } ; }
 require curl
-require flake8
-require chcon
-require podman
-require shellcheck
 
-# Reset the tests and mail directories
-sudo rm -rf test email/logs/* email/mail/*
-mkdir -p test
+# Check for shell script style compliance with shellcheck
+./script-lint.sh
 
-# This is a temporary workaround until we properly implement volumes
-chcon -R -t container_file_t email
+# Check python style compliance with flake8
+pushd orbit
+./test-style.sh
+popd
 
-# TODO: login returns 401 so we don't set --fail on the curl command
+# Create test dir if it does not exist yet
+mkdir -p test
+
+# Reset the tests and mail directories
+rm -f test/* email/logs/* email/mail/*
 
 DEVEL=${DEVEL:-""}
 STAGING=${STAGING:-""}
@@ -46,21 +60,24 @@ if [ -n "$STAGING" ]; then
 	EMAIL_HOSTNAME="dev.underground.software"
 fi
 
+CURL_OPTS=( \
+--verbose \
+--cacert ssl/fullchain.pem \
+--fail \
+--no-progress-meter \
+)
+
+
 # Check that registration fails before user creation
 curl --url "https://localhost:$PORT/register" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "student_id=1234" \
   | tee test/register_fail_no_user \
   | grep "msg = no such student"
 
 # Check that login fails before user creation
 curl --url "https://localhost:$PORT/login" \
-  --verbose \
-  --insecure \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "username=user&password=pass" \
   | tee test/login_fail_no_user \
   | grep "msg = authentication failure"
@@ -71,61 +88,49 @@ orbit/warpdrive.sh \
   | tee test/create_user \
   | grep "credentials(username: user, password:pass)"
 
+add_cleanup "orbit/warpdrive.sh \
+  -u user -w \
+  | tee test/delete_user \
+  | grep 'user'"
+
 # Check that registration fails with incorrect student id
 curl --url "https://localhost:$PORT/register" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "student_id=123" \
   | tee test/register_fail_wrong \
   | grep "msg = no such student"
 
 # Check that registration succeeds with correct student id
 curl --url "https://localhost:$PORT/register" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "student_id=1234" \
   | tee test/register_success \
   | grep "msg = welcome to the classroom"
 
 # Check that registration fails when student id is used for a second time
 curl --url "https://localhost:$PORT/register" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "student_id=1234" \
   | tee test/register_fail_duplicate \
   | grep "msg = no such student"
 
 # Check that login fails when credentials are invalid
 curl --url "https://localhost:$PORT/login" \
-  --verbose \
-  --insecure \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "username=user&password=invalid" \
   | tee test/login_fail_invalid \
   | grep "msg = authentication failure"
 
 # Check that login succeeds when credentials are valid
 curl --url "https://localhost:$PORT/login" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --data "username=user&password=pass" \
   | tee test/login_success \
   | grep "msg = user authenticated by password"
 
 # Check that the user can get the empty list of email on the server
 curl --url "pop3s://localhost:$POP_PORT" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --user user:pass \
   | tee test/pop_get_empty \
   | diff <(printf '\r\n') /dev/stdin
@@ -134,10 +139,7 @@ CR=$(printf "\r")
 # Check that the user can send a message to the server
 (
 curl --url "smtps://localhost:$SMTP_PORT" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --mail-from "user@$EMAIL_HOSTNAME" \
   --mail-rcpt "other@$EMAIL_HOSTNAME" \
   --upload-file - \
@@ -150,29 +152,10 @@ Bottom text$CR
 EOF
 ) | tee test/smtp_send_email \
   | diff <(printf "") /dev/stdin
-  
+
 # Check that the user can get the most recent message sent to the server
 curl --url "pop3s://localhost:$POP_PORT/1" \
-  --verbose \
-  --insecure \
-  --fail \
-  --no-progress-meter \
+  "${CURL_OPTS[@]}" \
   --user user:pass \
   | tee test/pop_get_message \
   | grep "Bottom text"
-
-# Check that we can delete a user
-orbit/warpdrive.sh \
-  -u user -w \
-  | tee test/delete_user \
-  | grep "user"
-
-# Check for shell script styyle compliance with shellcheck
-shellcheck test.sh
-shellcheck orbit/test-style.sh
-
-# Check python style compliance with flake8
-pushd orbit
-./test-style.sh
-popd
-
