[ARVADOS-DEV] created: f1a99fd359995d13096de04c48da4466f5cd1239

git at public.curoverse.com git at public.curoverse.com
Tue Jan 19 10:51:50 EST 2016


        at  f1a99fd359995d13096de04c48da4466f5cd1239 (commit)


commit f1a99fd359995d13096de04c48da4466f5cd1239
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 19 10:44:03 2016 -0500

    8080: Add ARVBOX_PUBLISH_IP

diff --git a/arvbox/README.md b/arvbox/README.md
index bfd390e..b4a9c25 100644
--- a/arvbox/README.md
+++ b/arvbox/README.md
@@ -91,6 +91,9 @@ default: $ARVBOX_DATA/arvados-dev
 The root directory of the SSO source tree
 default: $ARVBOX_DATA/sso-devise-omniauth-provider
 
+### ARVBOX_PUBLISH_IP
+The IP address on which to publish services when running in public
+configuration.  Overrides default detection of the host's IP address.
 
 ## Notes
 
diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index b87d1f7..284f0ef 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -97,8 +97,12 @@ run() {
     fi
 
     if echo "$1" | grep '^public' ; then
-        defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
-        localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
+        if test -n "$ARVBOX_PUBLISH_IP" ; then
+            localip=$ARVBOX_PUBLISH_IP
+        else
+            defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
+            localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
+        fi
         iptemp=$(tempfile)
         echo $localip > $iptemp
         chmod og+r $iptemp

commit 75592aa246ecae9c1616108658e477c938829892
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 19 09:16:13 2016 -0500

    8080: Fix typo $localip

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index a3a53e1..b87d1f7 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -84,7 +84,7 @@ wait_for_arvbox() {
     rm $FF
     echo
     if test -n "$localip" ; then
-        echo "export ARVADOS_API_HOST=localip:8000"
+        echo "export ARVADOS_API_HOST=$localip:8000"
     else
         echo "export ARVADOS_API_HOST=$(getip):8000"
     fi

commit 87b03de6b853c00b6c275df6d8595bb5f5de76be
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 17:38:24 2016 -0500

    8080: Quickstart tells you to use "localdemo" by default.

diff --git a/arvbox/README.md b/arvbox/README.md
index b924b2d..bfd390e 100644
--- a/arvbox/README.md
+++ b/arvbox/README.md
@@ -4,7 +4,7 @@ Self-contained development, demonstration and testing environment for Arvados.
 
 ## Quick start
 
-$ bin/arvbox reboot dev
+$ bin/arvbox reboot localdemo
 
 ## Usage
 

commit 1db2227f01a7ac88078ac04504f6b3d4c3623ec7
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 17:35:43 2016 -0500

    8080: Fix typo postgres -> postgresql data volume.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 82af625..a3a53e1 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -124,7 +124,7 @@ run() {
         fi
 
         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
-            docker create -v /var/lib/postgres -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
+            docker create -v /var/lib/postgresql -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
         fi
 
         docker run \
@@ -216,11 +216,13 @@ stop() {
     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
         docker stop $ARVBOX_CONTAINER
     fi
+
+    VOLUMES=--volumes=true
     if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
-        docker rm --volumes=true $ARVBOX_CONTAINER
+        docker rm $VOLUMES $ARVBOX_CONTAINER
     fi
     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
-        docker rm --volumes=true $ARVBOX_CONTAINER
+        docker rm $VOLUMES $ARVBOX_CONTAINER
     fi
 }
 

commit cdd4636a69dcc7e77a353c4939e12720ec5da17d
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 17:17:19 2016 -0500

    8080: Scrub default postgres database, demo config finally works!

diff --git a/arvbox/lib/arvbox/docker/Dockerfile.base b/arvbox/lib/arvbox/docker/Dockerfile.base
index 23fca74..cdbface 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.base
+++ b/arvbox/lib/arvbox/docker/Dockerfile.base
@@ -14,6 +14,8 @@ RUN apt-get update && \
 RUN curl -sSL https://get.docker.com/ | sh
 VOLUME /var/lib/docker
 
+RUN rm -rf /var/lib/postgresql && mkdir -p /var/lib/postgresql
+
 RUN cd /root && \
     GOPATH=$PWD go get github.com/curoverse/runsvinit && \
     install bin/runsvinit /usr/local/bin
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.demo b/arvbox/lib/arvbox/docker/Dockerfile.demo
index d40cd5c..1085abc 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.demo
+++ b/arvbox/lib/arvbox/docker/Dockerfile.demo
@@ -5,7 +5,6 @@ RUN cd /usr/src && \
     git clone https://github.com/curoverse/sso-devise-omniauth-provider.git sso
 
 RUN chown -R 1000:1000 /usr/src && /usr/local/lib/arvbox/createusers.sh
-RUN rm -rf /var/lib/postgresql && mkdir -p /var/lib/postgresql
 
 RUN sudo -u arvbox /usr/local/lib/arvbox/service/sso/run-service --only-deps
 RUN sudo -u arvbox /usr/local/lib/arvbox/service/api/run-service --only-deps

commit 5c79db7500c16043edc2aabc5ef0c9a73205719c
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 16:21:54 2016 -0500

    8080: Fixes for "publicdemo" mode

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 3d58315..82af625 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -101,6 +101,7 @@ run() {
         localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
         iptemp=$(tempfile)
         echo $localip > $iptemp
+        chmod og+r $iptemp
         PUBLIC="--volume=$iptemp:/var/run/localip_override
               --publish=80:80
               --publish=8000:8000
diff --git a/arvbox/lib/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
index a90992a..cc7e11f 100755
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@ -20,7 +20,7 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
     useradd --groups docker,fuse crunch
 
-    chown arvbox:arvbox -R /usr/local /var/lib/arvados /var/lib/gems /var/lib/passenger
+    chown arvbox:arvbox -R /usr/local /var/lib/arvados /var/lib/gems /var/lib/passenger /var/lib/postgresql
 
     mkdir -p /var/lib/gems/ruby/2.1.0
     chown arvbox:arvbox -R /var/lib/gems/ruby/2.1.0
diff --git a/arvbox/lib/arvbox/docker/service/ready/run-service b/arvbox/lib/arvbox/docker/service/ready/run-service
index c027360..f560de0 100755
--- a/arvbox/lib/arvbox/docker/service/ready/run-service
+++ b/arvbox/lib/arvbox/docker/service/ready/run-service
@@ -21,7 +21,7 @@ waiting=""
 for s in "${!services[@]}"
 do
   if ! [[ -f /tmp/arvbox-ready/$s ]] ; then
-    if nc -z $localip ${services[$s]} ; then
+    if nc -z localhost ${services[$s]} ; then
       echo "$s is ready at $localip:${services[$s]}"
       touch /tmp/arvbox-ready/$s
     else

commit 1773318d588bc85cd9a56d520e5e4abaa7a78eb1
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 17:00:27 2016 -0500

    8080: Working on demo mode.

diff --git a/arvbox/README.md b/arvbox/README.md
index 3537119..b924b2d 100644
--- a/arvbox/README.md
+++ b/arvbox/README.md
@@ -4,7 +4,7 @@ Self-contained development, demonstration and testing environment for Arvados.
 
 ## Quick start
 
-$ ./bin/arvbox reboot localdemo
+$ bin/arvbox reboot dev
 
 ## Usage
 
@@ -31,18 +31,18 @@ clone <from> <to>   clone an arvbox
 
 ### dev
 Development configuration.  Boots a complete Arvados environment inside the
-container.  The "arvados", "arvado-dev" and "sso" code directories along data
-directories "postresql", "var", "passenger" and "gems" are bind mounted from
-the host file system for easy access and persistence across container rebuilds.
-Services are bound to the Docker container's network IP address and can only be
-access on the local host.
+container.  The "arvados", "arvado-dev" and "sso-devise-omniauth-provider" code
+directories along data directories "postgres", "var", "passenger" and "gems"
+are bind mounted from the host file system for easy access and persistence
+across container rebuilds.  Services are bound to the Docker container's
+network IP address and can only be accessed on the local host.
 
 ### localdemo
 Demo configuration.  Boots a complete Arvados environment inside the container.
 Unlike the development configuration, code directories are included in the demo
 image, and data directories are stored in a separate data volume container.
 Services are bound to the Docker container's network IP address and can only be
-access on the local host.
+accessed on the local host.
 
 ### test
 Run the test suite.
@@ -50,13 +50,16 @@ Run the test suite.
 ### publicdev
 Publicly accessible development configuration.  Similar to 'dev' except that
 service ports are published to the host's IP address and can accessed by anyone
-who can connect to the host system.
+who can connect to the host system.  WARNING! The public arvbox configuration
+is NOT SECURE and must not be placed on a public IP address or used for
+production work.
 
 ### publicdemo
 Publicly accessible development configuration.  Similar to 'localdemo' except
 that service ports are published to the host's IP address and can accessed by
-anyone who can connect to the host system.
-
+anyone who can connect to the host system.  WARNING! The public arvbox configuration
+is NOT SECURE and must not be placed on a public IP address or used for
+production work.
 
 ## Environment variables
 
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.demo b/arvbox/lib/arvbox/docker/Dockerfile.demo
index 1085abc..d40cd5c 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.demo
+++ b/arvbox/lib/arvbox/docker/Dockerfile.demo
@@ -5,6 +5,7 @@ RUN cd /usr/src && \
     git clone https://github.com/curoverse/sso-devise-omniauth-provider.git sso
 
 RUN chown -R 1000:1000 /usr/src && /usr/local/lib/arvbox/createusers.sh
+RUN rm -rf /var/lib/postgresql && mkdir -p /var/lib/postgresql
 
 RUN sudo -u arvbox /usr/local/lib/arvbox/service/sso/run-service --only-deps
 RUN sudo -u arvbox /usr/local/lib/arvbox/service/api/run-service --only-deps

commit 7d7a71dc92338c5a8194f10dbd42f7cf0a34eea6
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 16:43:50 2016 -0500

    8080: Tweak formatting

diff --git a/arvbox/README.md b/arvbox/README.md
index c50a547..3537119 100644
--- a/arvbox/README.md
+++ b/arvbox/README.md
@@ -26,10 +26,10 @@ log       <service> tail log of specified service
 svrestart <service> restart specified service inside arvbox
 clone <from> <to>   clone an arvbox
 
-## Configs
 
-* dev
+## Configs
 
+### dev
 Development configuration.  Boots a complete Arvados environment inside the
 container.  The "arvados", "arvado-dev" and "sso" code directories along data
 directories "postresql", "var", "passenger" and "gems" are bind mounted from
@@ -37,60 +37,58 @@ the host file system for easy access and persistence across container rebuilds.
 Services are bound to the Docker container's network IP address and can only be
 access on the local host.
 
-* localdemo
-
+### localdemo
 Demo configuration.  Boots a complete Arvados environment inside the container.
 Unlike the development configuration, code directories are included in the demo
 image, and data directories are stored in a separate data volume container.
 Services are bound to the Docker container's network IP address and can only be
 access on the local host.
 
-* test
-
+### test
 Run the test suite.
 
-* publicdev
-
+### publicdev
 Publicly accessible development configuration.  Similar to 'dev' except that
 service ports are published to the host's IP address and can accessed by anyone
 who can connect to the host system.
 
-* publicdemo
-
+### publicdemo
 Publicly accessible development configuration.  Similar to 'localdemo' except
 that service ports are published to the host's IP address and can accessed by
 anyone who can connect to the host system.
 
+
 ## Environment variables
 
-ARVBOX_DOCKER
+### ARVBOX_DOCKER
 The location of Dockerfile.base and associated files used by "arvbox build".
 default: result of $(readlink -f $(dirname $0)/../lib/arvbox/docker)
 
-ARVBOX_CONTAINER
+### ARVBOX_CONTAINER
 The name of the Docker container to manipulate.
 default: arvbox
 
-ARVBOX_BASE
+### ARVBOX_BASE
 The base directory to store persistent data for arvbox containers.
 default: $HOME/.arvbox
 
-ARVBOX_DATA
+### ARVBOX_DATA
 The base directory to store persistent data for the current container.
 default: $ARVBOX_BASE/$ARVBOX_CONTAINER
 
-ARVADOS_ROOT
+### ARVADOS_ROOT
 The root directory of the Arvados source tree
 default: $ARVBOX_DATA/arvados
 
-ARVADOS_DEV_ROOT
+### ARVADOS_DEV_ROOT
 The root directory of the Arvados-dev source tree
 default: $ARVBOX_DATA/arvados-dev
 
-SSO_ROOT
+### SSO_ROOT
 The root directory of the SSO source tree
 default: $ARVBOX_DATA/sso-devise-omniauth-provider
 
+
 ## Notes
 
 Services are designed to install and auto-configure on start or restart.  For

commit 2ea94dd246e2124720f810c6dad6a25d941ebd62
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 16:42:05 2016 -0500

    8080: Add more documentation about different configurations

diff --git a/arvbox/README b/arvbox/README.md
similarity index 57%
rename from arvbox/README
rename to arvbox/README.md
index d8179bc..c50a547 100644
--- a/arvbox/README
+++ b/arvbox/README.md
@@ -1,14 +1,12 @@
-Arvados-in-a-box
-
-Development and demonstration environment for Arvados.
+# Arvados-in-a-box
 
+Self-contained development, demonstration and testing environment for Arvados.
 
-Quick start:
+## Quick start
 
-$ ./bin/arvbox reboot dev
+$ ./bin/arvbox reboot localdemo
 
-
-Usage:
+## Usage
 
 Arvados-in-a-box
 
@@ -28,20 +26,42 @@ log       <service> tail log of specified service
 svrestart <service> restart specified service inside arvbox
 clone <from> <to>   clone an arvbox
 
+## Configs
 
-Notes:
+* dev
 
-Services are designed to install and auto-configure on start or restart.  For
-example, the service script for keepstore always compiles keepstore from source
-and registers the daemon with the API server.
+Development configuration.  Boots a complete Arvados environment inside the
+container.  The "arvados", "arvado-dev" and "sso" code directories along data
+directories "postresql", "var", "passenger" and "gems" are bind mounted from
+the host file system for easy access and persistence across container rebuilds.
+Services are bound to the Docker container's network IP address and can only be
+access on the local host.
 
-Services are run with process supervision, so a service which exits will be
-restarted.  Dependencies between services are handled by repeatedly trying and
-failing the service script until dependencies are fulfilled (by other service
-scripts) enabling the service script to complete.
+* localdemo
+
+Demo configuration.  Boots a complete Arvados environment inside the container.
+Unlike the development configuration, code directories are included in the demo
+image, and data directories are stored in a separate data volume container.
+Services are bound to the Docker container's network IP address and can only be
+access on the local host.
+
+* test
+
+Run the test suite.
 
+* publicdev
 
-Environment variables:
+Publicly accessible development configuration.  Similar to 'dev' except that
+service ports are published to the host's IP address and can accessed by anyone
+who can connect to the host system.
+
+* publicdemo
+
+Publicly accessible development configuration.  Similar to 'localdemo' except
+that service ports are published to the host's IP address and can accessed by
+anyone who can connect to the host system.
+
+## Environment variables
 
 ARVBOX_DOCKER
 The location of Dockerfile.base and associated files used by "arvbox build".
@@ -70,3 +90,14 @@ default: $ARVBOX_DATA/arvados-dev
 SSO_ROOT
 The root directory of the SSO source tree
 default: $ARVBOX_DATA/sso-devise-omniauth-provider
+
+## Notes
+
+Services are designed to install and auto-configure on start or restart.  For
+example, the service script for keepstore always compiles keepstore from source
+and registers the daemon with the API server.
+
+Services are run with process supervision, so a service which exits will be
+restarted.  Dependencies between services are handled by repeatedly trying and
+failing the service script until dependencies are fulfilled (by other service
+scripts) enabling the service script to complete.
diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 73c3803..3d58315 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -351,7 +351,7 @@ case "$subcmd" in
     *)
         echo "Arvados-in-a-box"
         echo
-        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|destroy|log|svrestart)"
+        echo "$(basename $0) (build|start|run|open|shell|ip|stop|reboot|reset|destroy|log|svrestart)"
         echo
         echo "build <config>      build arvbox Docker image"
         echo "start|run <config>  start $ARVBOX_CONTAINER container"

commit 80391687c4cdf1ab167e67f9a48d4c7354c3a4d8
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 18 14:37:10 2016 -0500

    8080: Add "public" configuration which is configured to advertise services with
    the host's IP addresses and uses --publish to expose the service ports on the
    host.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index ecbbfbf..73c3803 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -70,28 +70,71 @@ EOF
     fi
 }
 
+wait_for_arvbox() {
+    FF=/tmp/arvbox-fifo-$$
+    mkfifo $FF
+    docker logs -f $ARVBOX_CONTAINER > $FF &
+    LOGPID=$!
+    while read line ; do
+        echo $line
+        if echo $line | grep "Workbench is running at" >/dev/null ; then
+            kill $LOGPID
+        fi
+    done < $FF
+    rm $FF
+    echo
+    if test -n "$localip" ; then
+        echo "export ARVADOS_API_HOST=localip:8000"
+    else
+        echo "export ARVADOS_API_HOST=$(getip):8000"
+    fi
+}
+
 run() {
     if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
         echo "Container $ARVBOX_CONTAINER is already running, use stop, restart or reboot"
         exit 0
     fi
 
-    if test "$1" = demo ; then
+    if echo "$1" | grep '^public' ; then
+        defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
+        localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
+        iptemp=$(tempfile)
+        echo $localip > $iptemp
+        PUBLIC="--volume=$iptemp:/var/run/localip_override
+              --publish=80:80
+              --publish=8000:8000
+              --publish=8900:8900
+              --publish=9001:9001
+              --publish=9002:9002
+              --publish=25100:25100
+              --publish=25107:25107
+              --publish=25108:25108
+              --publish=8001:8001"
+    else
+        PUBLIC=""
+    fi
+
+    if echo "$1" | grep 'demo$' ; then
         if test -d "$ARVBOX_DATA" ; then
             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
-            echo "Set ARVBOX_CONTAINER to set the demo container name"
+            echo "Set ARVBOX_CONTAINER to set a different name for your demo container"
             exit 1
         fi
 
         if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
             docker create -v /var/lib/postgres -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
         fi
+
         docker run \
+               --detach \
                --name=$ARVBOX_CONTAINER \
                --privileged \
                --volumes-from $ARVBOX_CONTAINER-data \
+               $PUBLIC \
                arvados/arvbox-demo
         updateconf
+        wait_for_arvbox
     else
         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS"
 
@@ -159,21 +202,10 @@ run() {
                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
                    "--volume=$GEMS:/var/lib/gems:rw" \
+                   $PUBLIC \
                    arvados/arvbox-dev
             updateconf
-            FF=/tmp/arvbox-fifo-$$
-            mkfifo $FF
-            docker logs -f $ARVBOX_CONTAINER > $FF &
-            LOGPID=$!
-            while read line ; do
-                echo $line
-                if echo $line | grep "Workbench is running at" >/dev/null ; then
-                    kill $LOGPID
-                fi
-            done < $FF
-            rm $FF
-            echo
-            echo "export ARVADOS_API_HOST=$(getip):8000"
+            wait_for_arvbox
             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
         fi
     fi
@@ -183,6 +215,9 @@ stop() {
     if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
         docker stop $ARVBOX_CONTAINER
     fi
+    if docker ps -a --filter "status=created" | grep -E "$ARVBOX_CONTAINER$" -q ; then
+        docker rm --volumes=true $ARVBOX_CONTAINER
+    fi
     if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
         docker rm --volumes=true $ARVBOX_CONTAINER
     fi
@@ -194,18 +229,23 @@ build() {
         exit 1
     fi
     docker build -t arvados/arvbox-base -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
-    if test "$1" = dev -o "$1" = test ; then
-        docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
-    else
+    if test "$1" = localdemo -o "$1" = publicdemo ; then
         docker build -t arvados/arvbox-demo -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
+    else
+        docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
     fi
 }
 
 check() {
-    if test -z "$1" ; then
-        echo "Argument to $subcmd must be one of dev, test, demo"
-        exit 1
-    fi
+    case "$1" in
+        localdemo|publicdemo|dev|publicdev|test)
+            true
+            ;;
+        *)
+            echo "Argument to $subcmd must be one of localdemo, publicdemo, dev, publicdev, test"
+            exit 1
+        ;;
+    esac
 }
 
 subcmd="$1"
diff --git a/arvbox/lib/arvbox/docker/common.sh b/arvbox/lib/arvbox/docker/common.sh
index 69869a7..4c2de47 100644
--- a/arvbox/lib/arvbox/docker/common.sh
+++ b/arvbox/lib/arvbox/docker/common.sh
@@ -1,5 +1,11 @@
 
-localip=$(ip addr show eth0 |grep "inet " | sed 's/ *inet \([^/]*\).*/\1/')
+if test -s /var/run/localip_override ; then
+    localip=$(cat /var/run/localip_override)
+else
+    defaultdev=$(/sbin/ip route|awk '/default/ { print $5 }')
+    localip=$(ip addr show $defaultdev | grep 'inet ' | sed 's/ *inet \(.*\)\/.*/\1/')
+fi
+
 export GEM_HOME=/var/lib/gems
 export GEM_PATH=/var/lib/gems
 

commit 50aded0e2ff25457b78c2a3b5967b42c6ec2c75f
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Fri Jan 15 16:38:30 2016 -0500

    8080: Fix typo.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 3e765db..ecbbfbf 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -5,7 +5,7 @@ set -e
 if ! test -d /sys/fs/cgroup ; then
      echo "Arvbox requires cgroups to be mounted at /sys/fs/cgroup in order to use"
      echo "Docker-in-Docker.  Older operating systems that put cgroups in other"
-     echo "places (such as /cgroup) are not supported.""
+     echo "places (such as /cgroup) are not supported."
      exit 1
 fi
 

commit e1d3dce509cc5e139ca6de2c3adc96c9f8e23cf6
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Fri Jan 15 09:18:21 2016 -0500

    8080: Add unsupported error if /sys/fs/cgroups not found (e.g. Centos6).  Set
    default_replication to 1.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 691b79d..3e765db 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -2,7 +2,14 @@
 
 set -e
 
-if ! which docker >/dev/null 2>/dev/null ; then 
+if ! test -d /sys/fs/cgroup ; then
+     echo "Arvbox requires cgroups to be mounted at /sys/fs/cgroup in order to use"
+     echo "Docker-in-Docker.  Older operating systems that put cgroups in other"
+     echo "places (such as /cgroup) are not supported.""
+     exit 1
+fi
+
+if ! which docker >/dev/null 2>/dev/null ; then
   echo "Arvbox requires Docker.  To install, run the following command as root:"
   echo "curl -sSL https://get.docker.com/ | sh"
   exit 1
diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index aa41f6b..31f90d1 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -61,6 +61,7 @@ development:
   auto_setup_new_users: true
   auto_setup_new_users_with_vm_uuid: $vm_uuid
   auto_setup_new_users_with_repository: true
+  default_collection_replication: 1
 EOF
 
 if ! test -f /var/lib/arvados/api_database_pw ; then
diff --git a/arvbox/lib/arvbox/docker/service/docker/run b/arvbox/lib/arvbox/docker/service/docker/run
index 67bd58f..1ecdc16 100755
--- a/arvbox/lib/arvbox/docker/service/docker/run
+++ b/arvbox/lib/arvbox/docker/service/docker/run
@@ -10,17 +10,14 @@ dmsetup mknodes
 : {LOG:=stdio}
 
 # First, make sure that cgroups are mounted correctly.
-for CGROUP in /sys/fs/cgroup /cgroup ; do
-    [ -d $CGROUP ] || mkdir $CGROUP
-
-    if mountpoint -q $CGROUP ; then
-        break
-    else
-	if mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP ; then
-            break
-        fi
-    fi
-done
+CGROUP=/sys/fs/cgroup
+[ -d $CGROUP ] || mkdir $CGROUP
+
+if mountpoint -q $CGROUP ; then
+    break
+else
+    mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP
+fi
 
 if ! mountpoint -q $CGROUP ; then
     echo "Could not find or mount cgroups. Tried /sys/fs/cgroup and /cgroup.  Did you use --privileged?"

commit 53b5baa5eda1499e4b5c15f71adefc3b85a8c71c
Author: peter <peter at peter-centos6-test.ny3nnviyjnku5mvo2sgdg2iv2h.bx.internal.cloudapp.net>
Date:   Thu Jan 14 17:03:52 2016 +0000

    8080: Check for Docker.  Suppress some messages generated by `which`.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index d1d1bb2..691b79d 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -2,8 +2,14 @@
 
 set -e
 
+if ! which docker >/dev/null 2>/dev/null ; then 
+  echo "Arvbox requires Docker.  To install, run the following command as root:"
+  echo "curl -sSL https://get.docker.com/ | sh"
+  exit 1
+fi
+
 if test -z "$ARVBOX_DOCKER" ; then
-    if which greadlink >/dev/null ; then
+    if which greadlink >/dev/null 2>/dev/null ; then
         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
     else
         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)

commit d42510f7df41351c540f7caa991720e7293ae669
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Jan 13 13:05:26 2016 -0500

    8080: Automatically set up new users with VM and git repo.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index f6aa0bc..d1d1bb2 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -160,7 +160,7 @@ run() {
             done < $FF
             rm $FF
             echo
-            echo "export ARVADOS_API_HOST="
+            echo "export ARVADOS_API_HOST=$(getip):8000"
             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
         fi
     fi
diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 508c411..aa41f6b 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -37,6 +37,13 @@ test -s /var/lib/arvados/self-signed.key
 
 sso_app_secret=$(cat /var/lib/arvados/sso_app_secret)
 
+if test -s /var/lib/arvados/vm-uuid ; then
+    vm_uuid=$(cat /var/lib/arvados/vm-uuid)
+else
+    vm_uuid=$uuid_prefix-2x53u-$(ruby -e 'puts rand(2**400).to_s(36)[0,15]')
+    echo $vm_uuid > /var/lib/arvados/vm-uuid
+fi
+
 cat >config/application.yml <<EOF
 development:
   uuid_prefix: $uuid_prefix
@@ -49,7 +56,11 @@ development:
   workbench_address: "http://$localip/"
   git_repo_ssh_base: "git@$localip:"
   git_repo_https_base: "http://$localip:${services[arv-git-httpd]}/"
+  new_users_are_active: true
   auto_admin_first_user: true
+  auto_setup_new_users: true
+  auto_setup_new_users_with_vm_uuid: $vm_uuid
+  auto_setup_new_users_with_repository: true
 EOF
 
 if ! test -f /var/lib/arvados/api_database_pw ; then
diff --git a/arvbox/lib/arvbox/docker/service/docker/run b/arvbox/lib/arvbox/docker/service/docker/run
index 64fcc75..67bd58f 100755
--- a/arvbox/lib/arvbox/docker/service/docker/run
+++ b/arvbox/lib/arvbox/docker/service/docker/run
@@ -22,6 +22,11 @@ for CGROUP in /sys/fs/cgroup /cgroup ; do
     fi
 done
 
+if ! mountpoint -q $CGROUP ; then
+    echo "Could not find or mount cgroups. Tried /sys/fs/cgroup and /cgroup.  Did you use --privileged?"
+    exit 1
+fi
+
 if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security
 then
     mount -t securityfs none /sys/kernel/security || {
diff --git a/arvbox/lib/arvbox/docker/service/gitolite/run-service b/arvbox/lib/arvbox/docker/service/gitolite/run-service
index 2e5f1e9..8e6cb0e 100755
--- a/arvbox/lib/arvbox/docker/service/gitolite/run-service
+++ b/arvbox/lib/arvbox/docker/service/gitolite/run-service
@@ -33,8 +33,11 @@ fi
 if ! test -f /var/lib/arvados/gitolite-setup ; then
     cd ~git
 
+    # Do a no-op login to populate known_hosts
+    # with the hostkey, so it won't try to ask
+    # about it later.
     cp .ssh/id_rsa.pub .ssh/authorized_keys
-    ssh -o stricthostkeychecking=no git at localhost
+    ssh -o stricthostkeychecking=no git at localhost true
     rm .ssh/authorized_keys
 
     cp -r /usr/local/lib/arvbox/gitolite.rc .
@@ -53,6 +56,10 @@ if ! test -f /var/lib/arvados/gitolite-setup ; then
 
     touch /var/lib/arvados/gitolite-setup
 else
+    # Do a no-op login to populate known_hosts
+    # with the hostkey, so it won't try to ask
+    # about it later.  Don't run anything,
+    # get the default gitolite behavior.
     ssh -o stricthostkeychecking=no git at localhost
 fi
 
diff --git a/arvbox/lib/arvbox/docker/service/ready/run-service b/arvbox/lib/arvbox/docker/service/ready/run-service
index 52c0adc..c027360 100755
--- a/arvbox/lib/arvbox/docker/service/ready/run-service
+++ b/arvbox/lib/arvbox/docker/service/ready/run-service
@@ -44,6 +44,22 @@ if ! (ps x | grep -v grep | grep "crunch-dispatch") > /dev/null ; then
     waiting="$waiting crunch-dispatch"
 fi
 
+export ARVADOS_API_HOST=$localip:${services[api]}
+export ARVADOS_API_HOST_INSECURE=1
+
+vm_ok=0
+if test -s /var/lib/arvados/vm-uuid -a -s /var/lib/arvados/superuser_token; then
+    vm_uuid=$(cat /var/lib/arvados/vm-uuid)
+    export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+    if (which arv && arv virtual_machine get --uuid $vm_uuid) >/dev/null 2>/dev/null ; then
+        vm_ok=1
+    fi
+fi
+
+if test $vm_ok = 0 ; then
+    waiting="$waiting vm"
+fi
+
 if ! [[ -z "$waiting" ]] ; then
     if ps x | grep -v grep | grep "bundle install" > /dev/null; then
         gemcount=$(ls /var/lib/gems/ruby/2.1.0/gems 2>/dev/null | wc -l)
diff --git a/arvbox/lib/arvbox/docker/service/vm/run-service b/arvbox/lib/arvbox/docker/service/vm/run-service
index a845e44..5bb6825 100755
--- a/arvbox/lib/arvbox/docker/service/vm/run-service
+++ b/arvbox/lib/arvbox/docker/service/vm/run-service
@@ -18,25 +18,23 @@ set -u
 export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
+export ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
 
 set +e
 read -rd $'\000' vm <<EOF
 {
+ "uuid": "$ARVADOS_VIRTUAL_MACHINE_UUID",
  "hostname":"$localip"
 }
 EOF
 set -e
 
-if test -s /var/lib/arvados/vm-uuid ; then
-    ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
+if arv virtual_machine get --uuid $ARVADOS_VIRTUAL_MACHINE_UUID ; then
     arv virtual_machine update --uuid $ARVADOS_VIRTUAL_MACHINE_UUID --virtual-machine "$vm"
 else
-    ARVADOS_VIRTUAL_MACHINE_UUID=$(arv --format=uuid virtual_machine create --virtual-machine "$vm")
-    echo $ARVADOS_VIRTUAL_MACHINE_UUID > /var/lib/arvados/vm-uuid
+    arv virtual_machine create --virtual-machine "$vm"
 fi
 
-export ARVADOS_VIRTUAL_MACHINE_UUID
-
 while true ; do
       bundle exec arvados-login-sync
       sleep 120

commit 9e77eee58a6b6d4470b405dcf9d285c452e278eb
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Jan 13 10:20:14 2016 -0500

    8080: Use run-tests --temp.  Attempt to add support for centos6 for docker-in-docker.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 83a09b5..f6aa0bc 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -96,6 +96,8 @@ run() {
                 git clone https://github.com/curoverse/arvados-dev.git "$ARVADOS_DEV_ROOT"
             fi
 
+            mkdir -p $VAR_DATA/test
+
             docker run \
                    --detach \
                    --name=$ARVBOX_CONTAINER \
@@ -129,12 +131,8 @@ run() {
                    $ARVBOX_CONTAINER \
                    /usr/local/lib/arvbox/runsu.sh \
                    /usr/src/arvados-dev/jenkins/run-tests.sh \
-                   --leave-temp \
+                   --temp /var/lib/arvados/test \
                    WORKSPACE=/usr/src/arvados \
-                   VENVDIR=/var/lib/arvados/tests-venv \
-                   VENV3DIR=/var/lib/arvados/tests-venv3 \
-                   GOPATH=/var/lib/arvados/tests-gostuff \
-                   GEMHOME=/var/lib/gems/ruby/2.1.0 \
                    GEM_HOME=/var/lib/gems \
                    "$@"
         else
@@ -273,7 +271,7 @@ case "$subcmd" in
     log|svrestart)
         if test -n "$1" ; then
             if test "$subcmd" = log ; then
-                docker exec -ti $ARVBOX_CONTAINER tail -n100 "/etc/service/$1/log/main/current"
+                docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM less --follow-name +GF "/etc/service/$1/log/main/current"
             fi
             if test "$subcmd" = svrestart ; then
                 docker exec -ti $ARVBOX_CONTAINER sv restart "$1"
diff --git a/arvbox/lib/arvbox/docker/service/docker/run b/arvbox/lib/arvbox/docker/service/docker/run
index 83537d3..64fcc75 100755
--- a/arvbox/lib/arvbox/docker/service/docker/run
+++ b/arvbox/lib/arvbox/docker/service/docker/run
@@ -4,23 +4,23 @@
 
 exec 2>&1
 
-#!/bin/bash
-
 # Ensure that all nodes in /dev/mapper correspond to mapped devices currently loaded by the device-mapper kernel driver
 dmsetup mknodes
 
-# First, make sure that cgroups are mounted correctly.
-CGROUP=/sys/fs/cgroup
 : {LOG:=stdio}
 
-[ -d $CGROUP ] ||
-	mkdir $CGROUP
-
-mountpoint -q $CGROUP ||
-	mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP || {
-		echo "Could not make a tmpfs mount. Did you use --privileged?"
-		exit 1
-	}
+# First, make sure that cgroups are mounted correctly.
+for CGROUP in /sys/fs/cgroup /cgroup ; do
+    [ -d $CGROUP ] || mkdir $CGROUP
+
+    if mountpoint -q $CGROUP ; then
+        break
+    else
+	if mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP ; then
+            break
+        fi
+    fi
+done
 
 if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security
 then
diff --git a/jenkins/run-tests.sh b/jenkins/run-tests.sh
index e50d485..a7b5fda 100755
--- a/jenkins/run-tests.sh
+++ b/jenkins/run-tests.sh
@@ -589,6 +589,7 @@ bundle_install_trylocal() {
             echo "(Running bundle install again, without --local.)"
             bundle install --no-deployment
         fi
+        bundle package --all
     )
 }
 

commit 92546f434119eba728ef2e1cb4591d36324fa703
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 12 16:02:12 2016 -0500

    8080: Add waitforpostgres.sh script.  Expand README.

diff --git a/arvbox/README b/arvbox/README
index bfc4ab4..d8179bc 100644
--- a/arvbox/README
+++ b/arvbox/README
@@ -2,9 +2,32 @@ Arvados-in-a-box
 
 Development and demonstration environment for Arvados.
 
+
+Quick start:
+
+$ ./bin/arvbox reboot dev
+
+
 Usage:
 
-$ ./bin/arvbox reboot
+Arvados-in-a-box
+
+arvbox (build|start|run|open|shell|ip|stop|reboot|reset|destroy|log|svrestart)
+
+build <config>      build arvbox Docker image
+start|run <config>  start arvbox container
+open       open arvbox workbench in a web browser
+shell      enter arvbox shell
+ip         print arvbox ip address
+stop       stop arvbox container
+restart <config>  stop, then run again
+reboot  <config>  stop, build arvbox Docker image, run
+reset      delete arvbox arvados data (be careful!)
+destroy    delete all arvbox code and data (be careful!)
+log       <service> tail log of specified service
+svrestart <service> restart specified service inside arvbox
+clone <from> <to>   clone an arvbox
+
 
 Notes:
 
@@ -16,3 +39,34 @@ Services are run with process supervision, so a service which exits will be
 restarted.  Dependencies between services are handled by repeatedly trying and
 failing the service script until dependencies are fulfilled (by other service
 scripts) enabling the service script to complete.
+
+
+Environment variables:
+
+ARVBOX_DOCKER
+The location of Dockerfile.base and associated files used by "arvbox build".
+default: result of $(readlink -f $(dirname $0)/../lib/arvbox/docker)
+
+ARVBOX_CONTAINER
+The name of the Docker container to manipulate.
+default: arvbox
+
+ARVBOX_BASE
+The base directory to store persistent data for arvbox containers.
+default: $HOME/.arvbox
+
+ARVBOX_DATA
+The base directory to store persistent data for the current container.
+default: $ARVBOX_BASE/$ARVBOX_CONTAINER
+
+ARVADOS_ROOT
+The root directory of the Arvados source tree
+default: $ARVBOX_DATA/arvados
+
+ARVADOS_DEV_ROOT
+The root directory of the Arvados-dev source tree
+default: $ARVBOX_DATA/arvados-dev
+
+SSO_ROOT
+The root directory of the SSO source tree
+default: $ARVBOX_DATA/sso-devise-omniauth-provider
diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 2e23a98..83a09b5 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -39,6 +39,24 @@ VAR_DATA="$ARVBOX_DATA/var"
 PASSENGER="$ARVBOX_DATA/passenger"
 GEMS="$ARVBOX_DATA/gems"
 
+getip() {
+    docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-
+}
+
+updateconf() {
+    if test -f ~/.config/arvados/$ARVBOX_CONTAINER.conf ; then
+        sed "s/ARVADOS_API_HOST=.*/ARVADOS_API_HOST=$(getip):8000/" <$HOME/.config/arvados/$ARVBOX_CONTAINER.conf >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf.tmp
+        mv ~/.config/arvados/$ARVBOX_CONTAINER.conf.tmp ~/.config/arvados/$ARVBOX_CONTAINER.conf
+    else
+        mkdir -p $HOME/.config/arvados
+        cat >$HOME/.config/arvados/$ARVBOX_CONTAINER.conf <<EOF
+ARVADOS_API_HOST=$(getip):8000
+ARVADOS_API_TOKEN=
+ARVADOS_API_HOST_INSECURE=true
+EOF
+    fi
+}
+
 run() {
     if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
         echo "Container $ARVBOX_CONTAINER is already running, use stop, restart or reboot"
@@ -60,6 +78,7 @@ run() {
                --privileged \
                --volumes-from $ARVBOX_CONTAINER-data \
                arvados/arvbox-demo
+        updateconf
     else
         mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS"
 
@@ -91,12 +110,10 @@ run() {
                    arvados/arvbox-dev \
                    /usr/local/bin/runsvinit -svdir=/etc/test-service
 
-            while ! docker exec -ti \
+            docker exec -ti \
                     $ARVBOX_CONTAINER \
                     /usr/local/lib/arvbox/runsu.sh \
-                    psql -c'\du' ; do
-                sleep 1
-            done
+                    /usr/local/lib/arvbox/waitforpostgres.sh
 
             docker exec -ti \
                    $ARVBOX_CONTAINER \
@@ -132,6 +149,7 @@ run() {
                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
                    "--volume=$GEMS:/var/lib/gems:rw" \
                    arvados/arvbox-dev
+            updateconf
             FF=/tmp/arvbox-fifo-$$
             mkfifo $FF
             docker logs -f $ARVBOX_CONTAINER > $FF &
@@ -144,6 +162,7 @@ run() {
             done < $FF
             rm $FF
             echo
+            echo "export ARVADOS_API_HOST="
             echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
         fi
     fi
@@ -215,11 +234,10 @@ case "$subcmd" in
         ;;
 
     ip|open)
-        IP=$(docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-)
         if test "$subcmd" = 'ip' ; then
-            echo $IP
+            echo $(getip)
         else
-            xdg-open http://$IP
+            xdg-open http://$(getip)
         fi
         ;;
 
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.base b/arvbox/lib/arvbox/docker/Dockerfile.base
index e9b90ac..23fca74 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.base
+++ b/arvbox/lib/arvbox/docker/Dockerfile.base
@@ -21,7 +21,8 @@ RUN cd /root && \
 ADD fuse.conf /etc/
 
 ADD crunch-setup.sh gitolite.rc \
-    keep-setup.sh common.sh createusers.sh logger runsu.sh \
+    keep-setup.sh common.sh createusers.sh \
+    logger runsu.sh waitforpostgres.sh \
     /usr/local/lib/arvbox/
 ADD service/ /usr/local/lib/arvbox/service
 RUN rmdir /etc/service && ln -sf /usr/local/lib/arvbox/service /etc
diff --git a/arvbox/lib/arvbox/docker/waitforpostgres.sh b/arvbox/lib/arvbox/docker/waitforpostgres.sh
new file mode 100755
index 0000000..a07fa8c
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/waitforpostgres.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+while ! psql -c\\du >/dev/null 2>/dev/null ; do
+    sleep 1
+done

commit 3f61293fb2c19f658e13c9e6b09b5d1c104acf48
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 12 13:13:31 2016 -0500

    8080: Add note about provenance of gitolite.rc

diff --git a/arvbox/lib/arvbox/docker/gitolite.rc b/arvbox/lib/arvbox/docker/gitolite.rc
index b735870..03c4b29 100644
--- a/arvbox/lib/arvbox/docker/gitolite.rc
+++ b/arvbox/lib/arvbox/docker/gitolite.rc
@@ -1,3 +1,7 @@
+# This is based on the default Gitolite configuration file with the following
+# changes applied as described here:
+# http://doc.arvados.org/install/install-arv-git-httpd.html
+
 # configuration variables for gitolite
 
 # This file is in perl syntax.  But you do NOT need to know perl to edit it --

commit 9d5fa0c0b0c63f4b370ca0bea8fdce1e43adab30
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 12 10:07:00 2016 -0500

    8080: Use runsvinit for tests too.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 8b3aa0b..2e23a98 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -89,7 +89,7 @@ run() {
                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
                    "--volume=$GEMS:/var/lib/gems:rw" \
                    arvados/arvbox-dev \
-                   /usr/local/lib/arvbox/service/postgres/run
+                   /usr/local/bin/runsvinit -svdir=/etc/test-service
 
             while ! docker exec -ti \
                     $ARVBOX_CONTAINER \
@@ -282,19 +282,18 @@ case "$subcmd" in
     *)
         echo "Arvados-in-a-box"
         echo
-        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|destroy|run-tests|log|svrestart)"
+        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|destroy|log|svrestart)"
         echo
-        echo "build      build arvbox Docker image"
-        echo "start|run  start $ARVBOX_CONTAINER container "
+        echo "build <config>      build arvbox Docker image"
+        echo "start|run <config>  start $ARVBOX_CONTAINER container"
         echo "open       open arvbox workbench in a web browser"
         echo "shell      enter arvbox shell"
         echo "ip         print arvbox ip address"
         echo "stop       stop arvbox container"
-        echo "restart    stop, then run again"
-        echo "reboot     stop, build arvbox Docker image, run"
+        echo "restart <config>  stop, then run again"
+        echo "reboot  <config>  stop, build arvbox Docker image, run"
         echo "reset      delete arvbox arvados data (be careful!)"
         echo "destroy    delete all arvbox code and data (be careful!)"
-        echo "run-tests  run run-tests.sh inside $ARVBOX_CONTAINER container"
         echo "log       <service> tail log of specified service"
         echo "svrestart <service> restart specified service inside arvbox"
         echo "clone <from> <to>   clone an arvbox"
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.dev b/arvbox/lib/arvbox/docker/Dockerfile.dev
index 9883d37..408e2de 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.dev
+++ b/arvbox/lib/arvbox/docker/Dockerfile.dev
@@ -9,3 +9,5 @@ RUN set -e && \
  curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
  tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
  ln -s ../$PJS/bin/phantomjs /usr/local/bin/
+
+RUN mkdir /etc/test-service && ln -sf /usr/local/lib/arvbox/service/postgres /etc/test-service

commit 7ee4a20ed997c534abe00213c511c1ebd5d134b5
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 11 17:31:46 2016 -0500

    8080: Rails projects use explicit 'development' section instead of 'common' to
    avoid interfering with test configuration.

diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index ceccb72..508c411 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -38,23 +38,18 @@ test -s /var/lib/arvados/self-signed.key
 sso_app_secret=$(cat /var/lib/arvados/sso_app_secret)
 
 cat >config/application.yml <<EOF
-common:
+development:
+  uuid_prefix: $uuid_prefix
   secret_token: $secret_token
+  blob_signing_key: $blob_signing_key
   sso_app_secret: $sso_app_secret
   sso_app_id: arvados-server
   sso_provider_url: "https://$localip:${services[sso]}"
-  workbench_address: "http://$localip/"
   sso_insecure: true
-development:
-  uuid_prefix: $uuid_prefix
-  auto_admin_first_user: true
-  blob_signing_key: $blob_signing_key
+  workbench_address: "http://$localip/"
   git_repo_ssh_base: "git@$localip:"
   git_repo_https_base: "http://$localip:${services[arv-git-httpd]}/"
-test:
-  uuid_prefix: zzzzz
-  git_repo_ssh_base: "git at git.zzzzz.arvadosapi.com:"
-  git_repo_https_base: "http://git.zzzzz.arvadosapi.com/"
+  auto_admin_first_user: true
 EOF
 
 if ! test -f /var/lib/arvados/api_database_pw ; then
@@ -67,24 +62,7 @@ if ! (psql -c "\du" | grep "^ arvados ") >/dev/null ; then
     psql -c "ALTER USER arvados CREATEDB;"
 fi
 
-cat >config/database.yml <<EOF
-development:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_development
-  username: arvados
-  password: $database_pw
-  host: localhost
-  template: template0
-test:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_test
-  username: arvados
-  password: $database_pw
-  host: localhost
-  template: template0
-EOF
+sed "s/password:.*/password: $database_pw/" <config/database.yml.example >config/database.yml
 
 if ! test -f /var/lib/arvados/api_database_setup ; then
    bundle exec rake db:setup
diff --git a/arvbox/lib/arvbox/docker/service/sso/run-service b/arvbox/lib/arvbox/docker/service/sso/run-service
index d1c566a..8a96d47 100755
--- a/arvbox/lib/arvbox/docker/service/sso/run-service
+++ b/arvbox/lib/arvbox/docker/service/sso/run-service
@@ -32,7 +32,7 @@ if ! test -s /var/lib/arvados/self-signed.key ; then
 fi
 
 cat >config/application.yml <<EOF
-common:
+development:
   uuid_prefix: $uuid_prefix
   secret_token: $secret_token
   default_link_url: "http://$localip"
@@ -49,24 +49,7 @@ if ! (psql -c "\du" | grep "^ arvados_sso ") >/dev/null ; then
     psql -c "ALTER USER arvados_sso CREATEDB;"
 fi
 
-cat >config/database.yml <<EOF
-development:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_sso_development
-  username: arvados_sso
-  password: $database_pw
-  host: localhost
-  template: template0
-test:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_sso_test
-  username: arvados_sso
-  password: $database_pw
-  host: localhost
-  template: template0
-EOF
+sed "s/password:.*/password: $database_pw/" <config/database.yml.example >config/database.yml
 
 if ! test -f /var/lib/arvados/sso_database_setup ; then
    bundle exec rake db:setup
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run-service b/arvbox/lib/arvbox/docker/service/workbench/run-service
index a5f7195..7f0542f 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run-service
+++ b/arvbox/lib/arvbox/docker/service/workbench/run-service
@@ -27,7 +27,7 @@ if ! test -s self-signed.key ; then
 fi
 
 cat >config/application.yml <<EOF
-common:
+development:
   secret_token: $secret_token
   arvados_login_base: https://$localip:${services[api]}/login
   arvados_v1_base: https://$localip:${services[api]}/arvados/v1

commit a0d297b64c24caff3a85167fb9c179c2ae605098
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 11 16:42:08 2016 -0500

    Remove test image, use the same image for dev and test.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 0d34783..8b3aa0b 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -14,8 +14,12 @@ if test -z "$ARVBOX_CONTAINER" ; then
     ARVBOX_CONTAINER=arvbox
 fi
 
+if test -z "$ARVBOX_BASE" ; then
+    ARVBOX_BASE="$HOME/.arvbox"
+fi
+
 if test -z "$ARVBOX_DATA" ; then
-    ARVBOX_DATA="$HOME/.arvbox/$ARVBOX_CONTAINER"
+    ARVBOX_DATA="$ARVBOX_BASE/$ARVBOX_CONTAINER"
 fi
 
 if test -z "$ARVADOS_ROOT" ; then
@@ -84,28 +88,29 @@ run() {
                    "--volume=$VAR_DATA:/var/lib/arvados:rw" \
                    "--volume=$PASSENGER:/var/lib/passenger:rw" \
                    "--volume=$GEMS:/var/lib/gems:rw" \
-                   arvados/arvbox-test
+                   arvados/arvbox-dev \
+                   /usr/local/lib/arvbox/service/postgres/run
 
             while ! docker exec -ti \
                     $ARVBOX_CONTAINER \
-                    /etc/tests-service/runsu.sh \
+                    /usr/local/lib/arvbox/runsu.sh \
                     psql -c'\du' ; do
                 sleep 1
             done
 
             docker exec -ti \
                    $ARVBOX_CONTAINER \
-                   /etc/tests-service/runsu.sh \
-                   /etc/service/sso/run-service --only-setup
+                   /usr/local/lib/arvbox/runsu.sh \
+                   /usr/local/lib/arvbox/service/sso/run-service --only-setup
 
             docker exec -ti \
                    $ARVBOX_CONTAINER \
-                   /etc/tests-service/runsu.sh \
-                   /etc/service/api/run-service --only-setup
+                   /usr/local/lib/arvbox/runsu.sh \
+                   /usr/local/lib/arvbox/service/api/run-service --only-setup
 
             docker exec -ti \
                    $ARVBOX_CONTAINER \
-                   /etc/tests-service/runsu.sh \
+                   /usr/local/lib/arvbox/runsu.sh \
                    /usr/src/arvados-dev/jenkins/run-tests.sh \
                    --leave-temp \
                    WORKSPACE=/usr/src/arvados \
@@ -159,9 +164,10 @@ build() {
         exit 1
     fi
     docker build -t arvados/arvbox-base -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
-    docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
-    if test "$1" = demo -o "$1" = test ; then
-        docker build -t arvados/arvbox-$1 -f "$ARVBOX_DOCKER/Dockerfile.$1" "$ARVBOX_DOCKER"
+    if test "$1" = dev -o "$1" = test ; then
+        docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
+    else
+        docker build -t arvados/arvbox-demo -f "$ARVBOX_DOCKER/Dockerfile.demo" "$ARVBOX_DOCKER"
     fi
 }
 
@@ -173,7 +179,9 @@ check() {
 }
 
 subcmd="$1"
-shift
+if test -n "$subcmd" ; then
+    shift
+fi
 case "$subcmd" in
     build)
         check $@
@@ -195,7 +203,7 @@ case "$subcmd" in
 
     restart)
         check $@
-        stop $@
+        stop
         run $@
         ;;
 
@@ -247,10 +255,10 @@ case "$subcmd" in
     log|svrestart)
         if test -n "$1" ; then
             if test "$subcmd" = log ; then
-                docker exec -ti $ARVBOX_CONTAINER tail -n100 /etc/service/$1/log/main/current
+                docker exec -ti $ARVBOX_CONTAINER tail -n100 "/etc/service/$1/log/main/current"
             fi
             if test "$subcmd" = svrestart ; then
-                docker exec -ti $ARVBOX_CONTAINER sv restart $1
+                docker exec -ti $ARVBOX_CONTAINER sv restart "$1"
                 docker exec -ti $ARVBOX_CONTAINER sv restart ready
             fi
         else
@@ -262,11 +270,12 @@ case "$subcmd" in
 
     clone)
         if test -n "$2" ; then
-            cp -r $HOME/.arvbox/$1 $HOME/.arvbox/$2
+            cp -r "$ARVBOX_BASE/$1" "$ARVBOX_BASE/$2"
             echo "Created new arvbox $2"
             echo "export ARVBOX_CONTAINER=$2"
         else
             echo "clone <from> <to>   clone an arvbox"
+            echo "available arvboxes: $(ls $ARVBOX_BASE)"
         fi
         ;;
 
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.base b/arvbox/lib/arvbox/docker/Dockerfile.base
index e73ba92..e9b90ac 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.base
+++ b/arvbox/lib/arvbox/docker/Dockerfile.base
@@ -23,6 +23,8 @@ ADD fuse.conf /etc/
 ADD crunch-setup.sh gitolite.rc \
     keep-setup.sh common.sh createusers.sh logger runsu.sh \
     /usr/local/lib/arvbox/
+ADD service/ /usr/local/lib/arvbox/service
+RUN rmdir /etc/service && ln -sf /usr/local/lib/arvbox/service /etc
 
 # Start the supervisor.
 CMD ["/usr/local/bin/runsvinit"]
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.demo b/arvbox/lib/arvbox/docker/Dockerfile.demo
index 8a255f8..1085abc 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.demo
+++ b/arvbox/lib/arvbox/docker/Dockerfile.demo
@@ -1,4 +1,4 @@
-FROM arvados/arvbox-dev
+FROM arvados/arvbox-base
 
 RUN cd /usr/src && \
     git clone https://github.com/curoverse/arvados.git && \
@@ -6,9 +6,9 @@ RUN cd /usr/src && \
 
 RUN chown -R 1000:1000 /usr/src && /usr/local/lib/arvbox/createusers.sh
 
-RUN sudo -u arvbox /etc/service/sso/run-service --only-deps
-RUN sudo -u arvbox /etc/service/api/run-service --only-deps
-RUN sudo -u arvbox /etc/service/workbench/run-service --only-deps
-RUN sudo -u arvbox /etc/service/doc/run-service --only-deps
-RUN sudo -u arvbox /etc/service/vm/run-service --only-deps
-RUN sudo -u arvbox /etc/service/sdk/run-service
+RUN sudo -u arvbox /usr/local/lib/arvbox/service/sso/run-service --only-deps
+RUN sudo -u arvbox /usr/local/lib/arvbox/service/api/run-service --only-deps
+RUN sudo -u arvbox /usr/local/lib/arvbox/service/workbench/run-service --only-deps
+RUN sudo -u arvbox /usr/local/lib/arvbox/service/doc/run-service --only-deps
+RUN sudo -u arvbox /usr/local/lib/arvbox/service/vm/run-service --only-deps
+RUN sudo -u arvbox /usr/local/lib/arvbox/service/sdk/run-service
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.dev b/arvbox/lib/arvbox/docker/Dockerfile.dev
index fc81bb6..9883d37 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.dev
+++ b/arvbox/lib/arvbox/docker/Dockerfile.dev
@@ -1,3 +1,11 @@
 FROM arvados/arvbox-base
 
-ADD service /etc/service
+RUN apt-get update && \
+    DEBIAN_FRONTEND=noninteractive apt-get -yq install \
+    python-virtualenv python3-virtualenv linkchecker xvfb iceweasel
+
+RUN set -e && \
+ PJS=phantomjs-1.9.7-linux-x86_64 && \
+ curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
+ tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
+ ln -s ../$PJS/bin/phantomjs /usr/local/bin/
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.test b/arvbox/lib/arvbox/docker/Dockerfile.test
deleted file mode 100644
index c84dfb5..0000000
--- a/arvbox/lib/arvbox/docker/Dockerfile.test
+++ /dev/null
@@ -1,13 +0,0 @@
-FROM arvados/arvbox-base
-
-RUN apt-get update && \
-    DEBIAN_FRONTEND=noninteractive apt-get -yq install \
-    python-virtualenv python3-virtualenv linkchecker xvfb iceweasel
-
-RUN set -e && \
- PJS=phantomjs-1.9.7-linux-x86_64 && \
- curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
- tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
- ln -s ../$PJS/bin/phantomjs /usr/local/bin/
-
-ADD service/postgres /etc/service/
diff --git a/arvbox/lib/arvbox/docker/common.sh b/arvbox/lib/arvbox/docker/common.sh
index d508c5c..69869a7 100644
--- a/arvbox/lib/arvbox/docker/common.sh
+++ b/arvbox/lib/arvbox/docker/common.sh
@@ -17,7 +17,7 @@ services=(
   [doc]=8001
 )
 
-if test $(id arvbox -u) = 0 ; then
+if test "$(id arvbox -u 2>/dev/null)" = 0 ; then
     PGUSER=postgres
     PGGROUP=postgres
 else

commit f3b90d4c543dcfbcbd4ea8023cfec78a1e65690b
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 11 15:26:34 2016 -0500

    8080: Better quoting.  Refactor git initialization.  Move runsh and logger
    scripts.  Rename some services.  Add -o pipefail.

diff --git a/arvbox/README b/arvbox/README
index f6b7267..bfc4ab4 100644
--- a/arvbox/README
+++ b/arvbox/README
@@ -4,7 +4,7 @@ Development and demonstration environment for Arvados.
 
 Usage:
 
-$ ./arvbox reboot
+$ ./bin/arvbox reboot
 
 Notes:
 
diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index af13ab9..0d34783 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -15,77 +15,117 @@ if test -z "$ARVBOX_CONTAINER" ; then
 fi
 
 if test -z "$ARVBOX_DATA" ; then
-    ARVBOX_DATA=$HOME/.arvbox/$ARVBOX_CONTAINER
+    ARVBOX_DATA="$HOME/.arvbox/$ARVBOX_CONTAINER"
 fi
 
 if test -z "$ARVADOS_ROOT" ; then
-    ARVADOS_ROOT=$ARVBOX_DATA/arvados
+    ARVADOS_ROOT="$ARVBOX_DATA/arvados"
 fi
 
 if test -z "$ARVADOS_DEV_ROOT" ; then
-    ARVADOS_DEV_ROOT=$ARVBOX_DATA/arvados-dev
+    ARVADOS_DEV_ROOT="$ARVBOX_DATA/arvados-dev"
 fi
 
 if test -z "$SSO_ROOT" ; then
-    SSO_ROOT=$ARVBOX_DATA/sso-devise-omniauth-provider
+    SSO_ROOT="$ARVBOX_DATA/sso-devise-omniauth-provider"
 fi
 
-PG_DATA=$ARVBOX_DATA/postgres
-VAR_DATA=$ARVBOX_DATA/var
-PASSENGER=$ARVBOX_DATA/passenger
-GEMS=$ARVBOX_DATA/gems
+PG_DATA="$ARVBOX_DATA/postgres"
+VAR_DATA="$ARVBOX_DATA/var"
+PASSENGER="$ARVBOX_DATA/passenger"
+GEMS="$ARVBOX_DATA/gems"
 
 run() {
+    if docker ps -a | grep -E "$ARVBOX_CONTAINER$" -q ; then
+        echo "Container $ARVBOX_CONTAINER is already running, use stop, restart or reboot"
+        exit 0
+    fi
+
     if test "$1" = demo ; then
-        if test -d $ARVBOX_DATA ; then
+        if test -d "$ARVBOX_DATA" ; then
             echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
-            echo "Set ARVBOX_CONTAINER to something else"
+            echo "Set ARVBOX_CONTAINER to set the demo container name"
             exit 1
         fi
 
-        if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
-            docker start -a $ARVBOX_CONTAINER
-        else
-            docker run \
-                   --name=$ARVBOX_CONTAINER \
-                   --privileged \
-                   arvados/arvbox-demo
+        if ! (docker ps -a | grep -E "$ARVBOX_CONTAINER-data$" -q) ; then
+            docker create -v /var/lib/postgres -v /var/lib/arvados --name $ARVBOX_CONTAINER-data arvados/arvbox-demo /bin/true
         fi
+        docker run \
+               --name=$ARVBOX_CONTAINER \
+               --privileged \
+               --volumes-from $ARVBOX_CONTAINER-data \
+               arvados/arvbox-demo
     else
-        mkdir -p $PG_DATA $VAR_DATA $PASSENGER $GEMS
+        mkdir -p "$PG_DATA" "$VAR_DATA" "$PASSENGER" "$GEMS"
 
-        if ! test -d $ARVADOS_ROOT ; then
-            git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
+        if ! test -d "$ARVADOS_ROOT" ; then
+            git clone https://github.com/curoverse/arvados.git "$ARVADOS_ROOT"
         fi
-        if ! test -d $SSO_ROOT ; then
-            git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
+        if ! test -d "$SSO_ROOT" ; then
+            git clone https://github.com/curoverse/sso-devise-omniauth-provider.git "$SSO_ROOT"
         fi
 
-        if test "$1" = testing ; then
+        if test "$1" = test ; then
+            shift
+
+            if ! test -d "$ARVADOS_DEV_ROOT" ; then
+                git clone https://github.com/curoverse/arvados-dev.git "$ARVADOS_DEV_ROOT"
+            fi
+
             docker run \
                    --detach \
                    --name=$ARVBOX_CONTAINER \
                    --privileged \
-                   --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-                   --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
-                   --volume=$SSO_ROOT:/usr/src/sso:rw \
-                   --volume=$PG_DATA:/var/lib/postgresql:rw \
-                   --volume=$VAR_DATA:/var/lib/arvados:rw \
-                   --volume=$PASSENGER:/var/lib/passenger:rw \
-                   --volume=$GEMS:/var/lib/gems:rw \
-                   arvados/arvbox-dev \
-                   LD_PRELOAD=/lib/runit-docker.so exec runsvdir /etc/tests-service
+                   "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
+                   "--volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw" \
+                   "--volume=$SSO_ROOT:/usr/src/sso:rw" \
+                   "--volume=$PG_DATA:/var/lib/postgresql:rw" \
+                   "--volume=$VAR_DATA:/var/lib/arvados:rw" \
+                   "--volume=$PASSENGER:/var/lib/passenger:rw" \
+                   "--volume=$GEMS:/var/lib/gems:rw" \
+                   arvados/arvbox-test
+
+            while ! docker exec -ti \
+                    $ARVBOX_CONTAINER \
+                    /etc/tests-service/runsu.sh \
+                    psql -c'\du' ; do
+                sleep 1
+            done
+
+            docker exec -ti \
+                   $ARVBOX_CONTAINER \
+                   /etc/tests-service/runsu.sh \
+                   /etc/service/sso/run-service --only-setup
+
+            docker exec -ti \
+                   $ARVBOX_CONTAINER \
+                   /etc/tests-service/runsu.sh \
+                   /etc/service/api/run-service --only-setup
+
+            docker exec -ti \
+                   $ARVBOX_CONTAINER \
+                   /etc/tests-service/runsu.sh \
+                   /usr/src/arvados-dev/jenkins/run-tests.sh \
+                   --leave-temp \
+                   WORKSPACE=/usr/src/arvados \
+                   VENVDIR=/var/lib/arvados/tests-venv \
+                   VENV3DIR=/var/lib/arvados/tests-venv3 \
+                   GOPATH=/var/lib/arvados/tests-gostuff \
+                   GEMHOME=/var/lib/gems/ruby/2.1.0 \
+                   GEM_HOME=/var/lib/gems \
+                   "$@"
         else
             docker run \
                    --detach \
                    --name=$ARVBOX_CONTAINER \
                    --privileged \
-                   --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-                   --volume=$SSO_ROOT:/usr/src/sso:rw \
-                   --volume=$PG_DATA:/var/lib/postgresql:rw \
-                   --volume=$VAR_DATA:/var/lib/arvados:rw \
-                   --volume=$PASSENGER:/var/lib/passenger:rw \
-                   --volume=$GEMS:/var/lib/gems:rw \
+                   "--volume=$ARVADOS_ROOT:/usr/src/arvados:rw" \
+                   "--volume=$SSO_ROOT:/usr/src/sso:rw" \
+                   "--volume=$PG_DATA:/var/lib/postgresql:rw" \
+                   "--volume=$VAR_DATA:/var/lib/arvados:rw" \
+                   "--volume=$PASSENGER:/var/lib/passenger:rw" \
+                   "--volume=$GEMS:/var/lib/gems:rw" \
                    arvados/arvbox-dev
             FF=/tmp/arvbox-fifo-$$
             mkfifo $FF
@@ -105,32 +145,44 @@ run() {
 }
 
 stop() {
-    if docker ps -a --filter "status=running" |grep -E "$ARVBOX_CONTAINER$" -q ; then
+    if docker ps -a --filter "status=running" | grep -E "$ARVBOX_CONTAINER$" -q ; then
         docker stop $ARVBOX_CONTAINER
     fi
-    if test "$1" != demo ; then
-        if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
-            docker rm --volumes=true $ARVBOX_CONTAINER
-        fi
+    if docker ps -a --filter "status=exited" | grep -E "$ARVBOX_CONTAINER$" -q ; then
+        docker rm --volumes=true $ARVBOX_CONTAINER
     fi
 }
 
 build() {
-    docker build -t arvados/arvbox-base -f $ARVBOX_DOCKER/Dockerfile.base $ARVBOX_DOCKER
-    if test "$1" = demo ; then
-        docker build -t arvados/arvbox-demo -f $ARVBOX_DOCKER/Dockerfile.demo $ARVBOX_DOCKER
-    else
-        docker build -t arvados/arvbox-dev -f $ARVBOX_DOCKER/Dockerfile.dev $ARVBOX_DOCKER
+    if ! test -f "$ARVBOX_DOCKER/Dockerfile.base" ;  then
+        echo "Could not find Dockerfile ($ARVBOX_DOCKER/Dockerfile.base)"
+        exit 1
+    fi
+    docker build -t arvados/arvbox-base -f "$ARVBOX_DOCKER/Dockerfile.base" "$ARVBOX_DOCKER"
+    docker build -t arvados/arvbox-dev -f "$ARVBOX_DOCKER/Dockerfile.dev" "$ARVBOX_DOCKER"
+    if test "$1" = demo -o "$1" = test ; then
+        docker build -t arvados/arvbox-$1 -f "$ARVBOX_DOCKER/Dockerfile.$1" "$ARVBOX_DOCKER"
     fi
 }
 
-case $1 in
+check() {
+    if test -z "$1" ; then
+        echo "Argument to $subcmd must be one of dev, test, demo"
+        exit 1
+    fi
+}
+
+subcmd="$1"
+shift
+case "$subcmd" in
     build)
-        build $2
+        check $@
+        build $@
         ;;
 
     start|run)
-        run $2
+        check $@
+        run $@
         ;;
 
     sh*)
@@ -138,111 +190,81 @@ case $1 in
         ;;
 
     stop)
-        stop $2
+        stop
         ;;
 
     restart)
-        stop
-        run
+        check $@
+        stop $@
+        run $@
         ;;
 
     reboot)
+        check $@
         stop
-        build
-        run
+        build $@
+        run $@
         ;;
 
     ip|open)
         IP=$(docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-)
-        if test $1 = 'ip' ; then
+        if test "$subcmd" = 'ip' ; then
             echo $IP
         else
             xdg-open http://$IP
         fi
         ;;
 
-    reset)
-        if test "$2" != -f ; then
-            echo "WARNING!  This will delete your database, git and keep files inside your arvbox ($ARVBOX_DATA).  Use reset -f if you really mean it."
-            exit 1
-        fi
+    reset|destroy)
         stop
-        rm -rf $ARVBOX_DATA/postgres
-        rm -rf $ARVBOX_DATA/var
-        ;;
-
-    destroy)
-        if test "$2" != -f ; then
-            echo "WARNING!  This will delete all code and data inside your arvbox ($ARVBOX_DATA).  Use destroy -f if you really mean it."
-            exit 1
+        if test -d "$ARVBOX_DATA" ; then
+            if test "$subcmd" = destroy ; then
+                if test "$1" != -f ; then
+                    echo "WARNING!  This will delete your entire arvbox ($ARVBOX_DATA)."
+                    echo "Use destroy -f if you really mean it."
+                    exit 1
+                fi
+                rm -rf "$ARVBOX_DATA"
+            else
+                if test "$1" != -f ; then
+                    echo "WARNING!  This will delete your arvbox data ($ARVBOX_DATA)."
+                    echo "Code and downloaded packages will be preserved."
+                    echo "Use reset -f if you really mean it."
+                    exit 1
+                fi
+                rm -rf "$ARVBOX_DATA/postgres"
+                rm -rf "$ARVBOX_DATA/var"
+            fi
+        else
+            if test "$1" != -f ; then
+                echo "WARNING!  This will delete your data container $ARVBOX_CONTAINER-data.  Use -f if you really mean it."
+                exit 1
+            fi
+            docker rm "$ARVBOX_CONTAINER-data"
         fi
-        stop
-        rm -rf $ARVBOX_DATA
         ;;
 
     log|svrestart)
-        if test -n "$2" ; then
-            if test "$1" = log ; then
-                docker exec -ti $ARVBOX_CONTAINER tail -n100 /etc/service/$2/log/main/current
+        if test -n "$1" ; then
+            if test "$subcmd" = log ; then
+                docker exec -ti $ARVBOX_CONTAINER tail -n100 /etc/service/$1/log/main/current
             fi
-            if test "$1" = svrestart ; then
-                docker exec -ti $ARVBOX_CONTAINER sv restart $2
+            if test "$subcmd" = svrestart ; then
+                docker exec -ti $ARVBOX_CONTAINER sv restart $1
                 docker exec -ti $ARVBOX_CONTAINER sv restart ready
             fi
         else
-            echo "Usage: $0 $1 <service>"
+            echo "Usage: $0 $subcmd <service>"
             echo "Available services:"
             docker exec -ti $ARVBOX_CONTAINER ls /etc/service
         fi
         ;;
 
-    run-tests)
-        stop
-
-        if ! test -d $ARVADOS_DEV_ROOT ; then
-            git clone https://github.com/curoverse/arvados-dev.git $ARVADOS_DEV_ROOT
-        fi
-
-        run testing
-
-        shift
-
-        while ! docker exec -ti \
-                $ARVBOX_CONTAINER \
-                /etc/tests-service/runsu.sh \
-                psql -c'\du' ; do
-            sleep 1
-        done
-
-        docker exec -ti \
-               $ARVBOX_CONTAINER \
-               /etc/tests-service/runsu.sh \
-               /etc/service/sso/run-service --only-setup
-
-        docker exec -ti \
-               $ARVBOX_CONTAINER \
-               /etc/tests-service/runsu.sh \
-               /etc/service/api/run-service --only-setup
-
-        docker exec -ti \
-               $ARVBOX_CONTAINER \
-               /etc/tests-service/runsu.sh \
-               /usr/src/arvados-dev/jenkins/run-tests.sh \
-               --leave-temp \
-               WORKSPACE=/usr/src/arvados \
-               VENVDIR=/var/lib/arvados/tests-venv \
-               VENV3DIR=/var/lib/arvados/tests-venv3 \
-               GOPATH=/var/lib/arvados/tests-gostuff \
-               GEMHOME=/var/lib/gems/ruby/2.1.0 \
-               GEM_HOME=/var/lib/gems/ruby/2.1.0 \
-               "$@"
-        ;;
-
     clone)
-        if test -n "$3" ; then
-            cp -r $HOME/.arvbox/$2 $HOME/.arvbox/$3
-            echo "Created new arvbox $3"
-            echo "export ARVBOX_CONTAINER=$3"
+        if test -n "$2" ; then
+            cp -r $HOME/.arvbox/$1 $HOME/.arvbox/$2
+            echo "Created new arvbox $2"
+            echo "export ARVBOX_CONTAINER=$2"
         else
             echo "clone <from> <to>   clone an arvbox"
         fi
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.base b/arvbox/lib/arvbox/docker/Dockerfile.base
index 274dceb..e73ba92 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.base
+++ b/arvbox/lib/arvbox/docker/Dockerfile.base
@@ -14,13 +14,15 @@ RUN apt-get update && \
 RUN curl -sSL https://get.docker.com/ | sh
 VOLUME /var/lib/docker
 
-ADD runit-docker /root/runit-docker
-
-RUN cd /root/runit-docker && \
-    make && \
-    make install
+RUN cd /root && \
+    GOPATH=$PWD go get github.com/curoverse/runsvinit && \
+    install bin/runsvinit /usr/local/bin
 
 ADD fuse.conf /etc/
 
+ADD crunch-setup.sh gitolite.rc \
+    keep-setup.sh common.sh createusers.sh logger runsu.sh \
+    /usr/local/lib/arvbox/
+
 # Start the supervisor.
-CMD LD_PRELOAD=/lib/runit-docker.so exec runsvdir /etc/service
+CMD ["/usr/local/bin/runsvinit"]
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.demo b/arvbox/lib/arvbox/docker/Dockerfile.demo
index 46ab21e..8a255f8 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.demo
+++ b/arvbox/lib/arvbox/docker/Dockerfile.demo
@@ -1,12 +1,9 @@
-FROM arvados/arvbox-base
+FROM arvados/arvbox-dev
 
 RUN cd /usr/src && \
     git clone https://github.com/curoverse/arvados.git && \
     git clone https://github.com/curoverse/sso-devise-omniauth-provider.git sso
 
-ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
-ADD service /etc/service
-
 RUN chown -R 1000:1000 /usr/src && /usr/local/lib/arvbox/createusers.sh
 
 RUN sudo -u arvbox /etc/service/sso/run-service --only-deps
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.dev b/arvbox/lib/arvbox/docker/Dockerfile.dev
index cb2873b..fc81bb6 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.dev
+++ b/arvbox/lib/arvbox/docker/Dockerfile.dev
@@ -1,15 +1,3 @@
 FROM arvados/arvbox-base
 
-RUN apt-get update && \
-    DEBIAN_FRONTEND=noninteractive apt-get -yq install \
-    python-virtualenv python3-virtualenv linkchecker xvfb iceweasel
-
-RUN set -e && \
- PJS=phantomjs-1.9.7-linux-x86_64 && \
- curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
- tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
- ln -s ../$PJS/bin/phantomjs /usr/local/bin/
-
-ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
 ADD service /etc/service
-ADD tests-service /etc/tests-service
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.dev b/arvbox/lib/arvbox/docker/Dockerfile.test
similarity index 68%
copy from arvbox/lib/arvbox/docker/Dockerfile.dev
copy to arvbox/lib/arvbox/docker/Dockerfile.test
index cb2873b..c84dfb5 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.dev
+++ b/arvbox/lib/arvbox/docker/Dockerfile.test
@@ -10,6 +10,4 @@ RUN set -e && \
  tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
  ln -s ../$PJS/bin/phantomjs /usr/local/bin/
 
-ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
-ADD service /etc/service
-ADD tests-service /etc/tests-service
+ADD service/postgres /etc/service/
diff --git a/arvbox/lib/arvbox/docker/common.sh b/arvbox/lib/arvbox/docker/common.sh
index d58c39b..d508c5c 100644
--- a/arvbox/lib/arvbox/docker/common.sh
+++ b/arvbox/lib/arvbox/docker/common.sh
@@ -1,7 +1,22 @@
+
 localip=$(ip addr show eth0 |grep "inet " | sed 's/ *inet \([^/]*\).*/\1/')
 export GEM_HOME=/var/lib/gems
 export GEM_PATH=/var/lib/gems
 
+declare -A services
+services=(
+  [workbench]=80
+  [api]=8000
+  [sso]=8900
+  [arv-git-httpd]=9001
+  [keep-web]=9002
+  [keepproxy]=25100
+  [keepstore0]=25107
+  [keepstore1]=25108
+  [ssh]=22
+  [doc]=8001
+)
+
 if test $(id arvbox -u) = 0 ; then
     PGUSER=postgres
     PGGROUP=postgres
diff --git a/arvbox/lib/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
index 680d9fe..a90992a 100755
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@ -1,6 +1,6 @@
-#!/bin/sh
+#!/bin/bash
 
-set -e
+set -e -o pipefail
 
 if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
diff --git a/arvbox/lib/arvbox/docker/crunch-setup.sh b/arvbox/lib/arvbox/docker/crunch-setup.sh
index b6f5cda..178fec1 100755
--- a/arvbox/lib/arvbox/docker/crunch-setup.sh
+++ b/arvbox/lib/arvbox/docker/crunch-setup.sh
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -11,10 +11,10 @@ cd /var/lib/arvados/gostuff
 export GOPATH=$PWD
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/crunchstat"
+flock /var/lib/arvados/gostuff.lock go get -t "git.curoverse.com/arvados.git/services/crunchstat"
 install bin/crunchstat /usr/local/bin
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /usr/src/arvados/services/api/superuser_token)
 export CRUNCH_JOB_BIN=/usr/src/arvados/sdk/cli/bin/crunch-job
diff --git a/arvbox/lib/arvbox/docker/gitolite-setup.sh b/arvbox/lib/arvbox/docker/gitolite-setup.sh
deleted file mode 100755
index 9a2ff9e..0000000
--- a/arvbox/lib/arvbox/docker/gitolite-setup.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-set -e
-
-cd ~
-
-gitolite setup -pk .ssh/id_rsa.pub
-
-if ! test -d gitolite-admin ; then
-    git clone git at localhost:gitolite-admin
-fi
-
-cd gitolite-admin
-git config user.email arvados
-git config user.name arvados
-git config push.default simple
-git push
-
-cp ~git/gitolite.rc ~git/.gitolite.rc
diff --git a/arvbox/lib/arvbox/docker/gitssh-setup.sh b/arvbox/lib/arvbox/docker/gitssh-setup.sh
deleted file mode 100755
index aad7dd4..0000000
--- a/arvbox/lib/arvbox/docker/gitssh-setup.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-cd ~
-
-if ! test -s .ssh/id_rsa ; then
-    mkdir -p .ssh
-    chmod -R 0700 .ssh
-    ssh-keygen -t rsa -P '' -f .ssh/id_rsa
-fi
-
-if test -s /var/lib/arvados/git/.ssh/known_hosts ; then
-    ssh-keygen -f "/var/lib/arvados/git/.ssh/known_hosts" -R localhost
-fi
-
-if ! test -s .ssh/authorized_keys ; then
-    cp .ssh/id_rsa.pub .ssh/authorized_keys
-    ssh -o stricthostkeychecking=no localhost
-    rm .ssh/authorized_keys
-else
-    ssh -o stricthostkeychecking=no localhost
-fi
diff --git a/arvbox/lib/arvbox/docker/keep-setup.sh b/arvbox/lib/arvbox/docker/keep-setup.sh
index 529360e..b66463f 100755
--- a/arvbox/lib/arvbox/docker/keep-setup.sh
+++ b/arvbox/lib/arvbox/docker/keep-setup.sh
@@ -2,7 +2,7 @@
 
 exec 2>&1
 sleep 2
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -12,29 +12,17 @@ cd /var/lib/arvados/gostuff
 export GOPATH=$PWD
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/keepstore"
+flock /var/lib/arvados/gostuff.lock go get -t "git.curoverse.com/arvados.git/services/keepstore"
 install bin/keepstore /usr/local/bin
 
-mkdir -p /var/lib/arvados/keep
+mkdir -p /var/lib/arvados/$1
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
-if test -s /var/lib/arvados/$1-uuid ; then
-    keep_uuid=$(cat /var/lib/arvados/$1-uuid)
-    set +e
-    read -rd $'\000' keepservice <<EOF
-{
- "service_host":"$localip",
- "service_port":$2
-}
-EOF
-    set -e
-    arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
-else
-    set +e
-    read -rd $'\000' keepservice <<EOF
+set +e
+read -rd $'\000' keepservice <<EOF
 {
  "service_host":"$localip",
  "service_port":$2,
@@ -42,14 +30,22 @@ else
  "service_type":"disk"
 }
 EOF
-    set -e
+set -e
+
+if test -s /var/lib/arvados/$1-uuid ; then
+    keep_uuid=$(cat /var/lib/arvados/$1-uuid)
+    arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
+else
     UUID=$(arv --format=uuid keep_service create --keep-service "$keepservice")
     echo $UUID > /var/lib/arvados/$1-uuid
 fi
 
+set +e
+killall -HUP keepproxy
+
 exec /usr/local/bin/keepstore \
      -listen=:$2 \
      -enforce-permissions=true \
      -blob-signing-key-file=/var/lib/arvados/blob_signing_key \
      -max-buffers=20 \
-     -volume=/var/lib/arvados/keep
+     -volume=/var/lib/arvados/$1
diff --git a/arvbox/lib/arvbox/docker/service/logger b/arvbox/lib/arvbox/docker/logger
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/logger
rename to arvbox/lib/arvbox/docker/logger
diff --git a/arvbox/lib/arvbox/docker/service/runsu.sh b/arvbox/lib/arvbox/docker/runsu.sh
similarity index 75%
rename from arvbox/lib/arvbox/docker/service/runsu.sh
rename to arvbox/lib/arvbox/docker/runsu.sh
index d702709..1557d09 100755
--- a/arvbox/lib/arvbox/docker/service/runsu.sh
+++ b/arvbox/lib/arvbox/docker/runsu.sh
@@ -8,7 +8,7 @@ flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
 export HOME=/var/lib/arvados
 
 if test -z "$1" ; then
-    exec chpst -u arvbox:arvbox $0-service
+    exec chpst -u arvbox:arvbox:docker $0-service
 else
-    exec chpst -u arvbox:arvbox $@
+    exec chpst -u arvbox:arvbox:docker $@
 fi
diff --git a/arvbox/lib/arvbox/docker/service/api/log/run b/arvbox/lib/arvbox/docker/service/api/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/api/log/run
+++ b/arvbox/lib/arvbox/docker/service/api/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/api/run b/arvbox/lib/arvbox/docker/service/api/run
index ef446b5..a388c8b 120000
--- a/arvbox/lib/arvbox/docker/service/api/run
+++ b/arvbox/lib/arvbox/docker/service/api/run
@@ -1 +1 @@
-../runsu.sh
\ No newline at end of file
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 6615736..ceccb72 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -ex
+set -ex -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -42,7 +42,7 @@ common:
   secret_token: $secret_token
   sso_app_secret: $sso_app_secret
   sso_app_id: arvados-server
-  sso_provider_url: "https://$localip:3002"
+  sso_provider_url: "https://$localip:${services[sso]}"
   workbench_address: "http://$localip/"
   sso_insecure: true
 development:
@@ -50,7 +50,7 @@ development:
   auto_admin_first_user: true
   blob_signing_key: $blob_signing_key
   git_repo_ssh_base: "git@$localip:"
-  git_repo_https_base: "http://$localip:9001/"
+  git_repo_https_base: "http://$localip:${services[arv-git-httpd]}/"
 test:
   uuid_prefix: zzzzz
   git_repo_ssh_base: "git at git.zzzzz.arvadosapi.com:"
@@ -104,7 +104,7 @@ if test "$1" = "--only-setup" ; then
     exit
 fi
 
-ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start --port=3001 \
+ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start --port=${services[api]} \
                   --runtime-dir=/var/lib/passenger \
                   --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
                   --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/lib/arvbox/docker/service/keepweb/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/keepweb/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/arv-git-httpd/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/run b/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/arv-git-httpd/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/arv-git-httpd/run b/arvbox/lib/arvbox/docker/service/arv-git-httpd/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/arv-git-httpd/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/githttp/run-service b/arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service
similarity index 54%
rename from arvbox/lib/arvbox/docker/service/githttp/run-service
rename to arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service
index 7e4f1de..7bd6a7c 100755
--- a/arvbox/lib/arvbox/docker/service/githttp/run-service
+++ b/arvbox/lib/arvbox/docker/service/arv-git-httpd/run-service
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -11,13 +11,17 @@ cd /var/lib/arvados/gostuff
 export GOPATH=$PWD
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/arv-git-httpd"
+flock /var/lib/arvados/gostuff.lock go get -t "git.curoverse.com/arvados.git/services/arv-git-httpd"
 install bin/arv-git-httpd /usr/local/bin
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export GITOLITE_HTTP_HOME=/var/lib/arvados/git
 export GL_BYPASS_ACCESS_CHECKS=1
 export PATH="$PATH:/var/lib/arvados/git/bin"
 cd ~git
-/usr/local/bin/arv-git-httpd -address=:9001 -git-command=/var/lib/arvados/git/gitolite/src/gitolite-shell -repo-root=/var/lib/arvados/git/repositories 2>&1
+
+exec /usr/local/bin/arv-git-httpd \
+     -address=:${services[arv-git-httpd]} \
+     -git-command=/var/lib/arvados/git/gitolite/src/gitolite-shell \
+     -repo-root=/var/lib/arvados/git/repositories
diff --git a/arvbox/lib/arvbox/docker/service/keep1/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/crunch-dispatch0/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/keep1/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/crunch-dispatch0/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/crunch-dispatch0/log/run b/arvbox/lib/arvbox/docker/service/crunch-dispatch0/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/crunch-dispatch0/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch-dispatch0/run b/arvbox/lib/arvbox/docker/service/crunch-dispatch0/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/crunch-dispatch0/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch0/run-service b/arvbox/lib/arvbox/docker/service/crunch-dispatch0/run-service
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/crunch0/run-service
rename to arvbox/lib/arvbox/docker/service/crunch-dispatch0/run-service
diff --git a/arvbox/lib/arvbox/docker/service/keep0/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/crunch-dispatch1/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/keep0/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/crunch-dispatch1/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/crunch-dispatch1/log/run b/arvbox/lib/arvbox/docker/service/crunch-dispatch1/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/crunch-dispatch1/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch-dispatch1/run b/arvbox/lib/arvbox/docker/service/crunch-dispatch1/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/crunch-dispatch1/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch1/run-service b/arvbox/lib/arvbox/docker/service/crunch-dispatch1/run-service
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/crunch1/run-service
rename to arvbox/lib/arvbox/docker/service/crunch-dispatch1/run-service
diff --git a/arvbox/lib/arvbox/docker/service/crunch0/log/run b/arvbox/lib/arvbox/docker/service/crunch0/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/crunch0/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch0/run b/arvbox/lib/arvbox/docker/service/crunch0/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/crunch0/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch1/log/run b/arvbox/lib/arvbox/docker/service/crunch1/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/crunch1/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/crunch1/run b/arvbox/lib/arvbox/docker/service/crunch1/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/crunch1/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/doc/log/run b/arvbox/lib/arvbox/docker/service/doc/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/doc/log/run
+++ b/arvbox/lib/arvbox/docker/service/doc/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/doc/run b/arvbox/lib/arvbox/docker/service/doc/run
index ef446b5..a388c8b 120000
--- a/arvbox/lib/arvbox/docker/service/doc/run
+++ b/arvbox/lib/arvbox/docker/service/doc/run
@@ -1 +1 @@
-../runsu.sh
\ No newline at end of file
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/doc/run-service b/arvbox/lib/arvbox/docker/service/doc/run-service
index a64d5c8..acbe21c 100755
--- a/arvbox/lib/arvbox/docker/service/doc/run-service
+++ b/arvbox/lib/arvbox/docker/service/doc/run-service
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -ex
+set -ex -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -14,6 +14,28 @@ fi
 
 set -u
 
-bundle exec rake generate baseurl=http://$localip:8000 arvados_api_host=$localip:3001 arvados_workbench_host=http://$localip
+cat <<EOF >/var/lib/arvados/doc-nginx.conf
+worker_processes auto;
+pid /var/lib/arvados/doc-nginx.pid;
+daemon off;
 
-exec bundle exec rake run
+events {
+	worker_connections 64;
+}
+
+http {
+     include /etc/nginx/mime.types;
+     default_type application/octet-stream;
+     server {
+            listen ${services[doc]} default_server;
+            listen [::]:${services[doc]} default_server;
+            root /usr/src/arvados/doc/.site;
+            index index.html;
+            server_name _;
+     }
+}
+EOF
+
+bundle exec rake generate baseurl=http://$localip:${services[doc]} arvados_api_host=$localip:${services[api]} arvados_workbench_host=http://$localip
+
+exec nginx -c /var/lib/arvados/doc-nginx.conf
diff --git a/arvbox/lib/arvbox/docker/service/docker/log/run b/arvbox/lib/arvbox/docker/service/docker/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/docker/log/run
+++ b/arvbox/lib/arvbox/docker/service/docker/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/git/log/run b/arvbox/lib/arvbox/docker/service/git/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/git/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/git/run b/arvbox/lib/arvbox/docker/service/git/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/git/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/githttp/log/run b/arvbox/lib/arvbox/docker/service/githttp/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/githttp/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/githttp/run b/arvbox/lib/arvbox/docker/service/githttp/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/githttp/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/githttp/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/gitolite/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/githttp/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/gitolite/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/gitolite/log/run b/arvbox/lib/arvbox/docker/service/gitolite/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/gitolite/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/gitolite/run b/arvbox/lib/arvbox/docker/service/gitolite/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/gitolite/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/git/run-service b/arvbox/lib/arvbox/docker/service/gitolite/run-service
similarity index 62%
rename from arvbox/lib/arvbox/docker/service/git/run-service
rename to arvbox/lib/arvbox/docker/service/gitolite/run-service
index 4f08040..2e5f1e9 100755
--- a/arvbox/lib/arvbox/docker/service/git/run-service
+++ b/arvbox/lib/arvbox/docker/service/gitolite/run-service
@@ -1,28 +1,59 @@
 #!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/git
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
+export USER=git
+export USERNAME=git
+export LOGNAME=git
+export HOME=/var/lib/arvados/git
+
+cd ~arvbox
+
+mkdir -p ~arvbox/.ssh ~git/.ssh
+chmod 0700 ~arvbox/.ssh ~git/.ssh
+
+if ! test -s ~arvbox/.ssh/id_rsa ; then
+    ssh-keygen -t rsa -P '' -f .ssh/id_rsa
+    cp ~arvbox/.ssh/id_rsa ~arvbox/.ssh/id_rsa.pub ~git/.ssh
+fi
+
+if test -s ~arvbox/.ssh/known_hosts ; then
+    ssh-keygen -f ".ssh/known_hosts" -R localhost
+fi
+
 if ! test -f /var/lib/arvados/gitolite-setup ; then
-   cp -r /usr/local/lib/arvbox/gitolite-setup.sh /usr/local/lib/arvbox/gitssh-setup.sh /usr/local/lib/arvbox/gitolite.rc /var/lib/arvados/git/
+    cd ~git
+
+    cp .ssh/id_rsa.pub .ssh/authorized_keys
+    ssh -o stricthostkeychecking=no git at localhost
+    rm .ssh/authorized_keys
+
+    cp -r /usr/local/lib/arvbox/gitolite.rc .
+
+    gitolite setup -pk .ssh/id_rsa.pub
 
-   chown -R git:git ~git
+    if ! test -d gitolite-admin ; then
+        git clone git at localhost:gitolite-admin
+    fi
 
-   su git -c "/var/lib/arvados/git/gitssh-setup.sh"
-   su git -c "/var/lib/arvados/git/gitolite-setup.sh"
+    cd gitolite-admin
+    git config user.email arvados
+    git config user.name arvados
+    git config push.default simple
+    git push
 
-   touch /var/lib/arvados/gitolite-setup
+    touch /var/lib/arvados/gitolite-setup
 else
-    chown -R git:git ~git
-    su git -c "/var/lib/arvados/git/gitssh-setup.sh"
+    ssh -o stricthostkeychecking=no git at localhost
 fi
 
 prefix=$(arv --format=uuid user current | cut -d- -f1)
@@ -66,7 +97,7 @@ cat > config/arvados-clients.yml <<EOF
 development:
   gitolite_url: /var/lib/arvados/git/repositories/gitolite-admin.git
   gitolite_tmp: /var/lib/arvados/git
-  arvados_api_host: $localip:3001
+  arvados_api_host: $localip:${services[api]}
   arvados_api_token: "$ARVADOS_API_TOKEN"
   arvados_api_host_insecure: true
   gitolite_arvados_git_user_key: "$git_user_key"
diff --git a/arvbox/lib/arvbox/docker/service/git/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keep-web/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/git/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keep-web/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/keep-web/log/run b/arvbox/lib/arvbox/docker/service/keep-web/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keep-web/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keep-web/run b/arvbox/lib/arvbox/docker/service/keep-web/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keep-web/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepweb/run-service b/arvbox/lib/arvbox/docker/service/keep-web/run-service
similarity index 59%
rename from arvbox/lib/arvbox/docker/service/keepweb/run-service
rename to arvbox/lib/arvbox/docker/service/keep-web/run-service
index 38c31f0..a2c6aa1 100755
--- a/arvbox/lib/arvbox/docker/service/keepweb/run-service
+++ b/arvbox/lib/arvbox/docker/service/keep-web/run-service
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -11,11 +11,11 @@ cd /var/lib/arvados/gostuff
 export GOPATH=$PWD
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/keep-web"
+flock /var/lib/arvados/gostuff.lock go get -t "git.curoverse.com/arvados.git/services/keep-web"
 install bin/keep-web /usr/local/bin
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
-exec /usr/local/bin/keep-web -trust-all-content -listen=":25099"
+exec /usr/local/bin/keep-web -trust-all-content -listen=:${services[keep-web]}
diff --git a/arvbox/lib/arvbox/docker/service/keep0/log/run b/arvbox/lib/arvbox/docker/service/keep0/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/keep0/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keep0/run b/arvbox/lib/arvbox/docker/service/keep0/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/keep0/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keep0/run-service b/arvbox/lib/arvbox/docker/service/keep0/run-service
deleted file mode 100755
index 7f87b88..0000000
--- a/arvbox/lib/arvbox/docker/service/keep0/run-service
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec /usr/local/lib/arvbox/keep-setup.sh keep0 25107
diff --git a/arvbox/lib/arvbox/docker/service/keep1/log/run b/arvbox/lib/arvbox/docker/service/keep1/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/keep1/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keep1/run b/arvbox/lib/arvbox/docker/service/keep1/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/keep1/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keep1/run-service b/arvbox/lib/arvbox/docker/service/keep1/run-service
deleted file mode 100755
index a44c8dd..0000000
--- a/arvbox/lib/arvbox/docker/service/keep1/run-service
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-sleep 1
-exec /usr/local/lib/arvbox/keep-setup.sh keep1 25108
diff --git a/arvbox/lib/arvbox/docker/service/keepproxy/log/run b/arvbox/lib/arvbox/docker/service/keepproxy/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/keepproxy/log/run
+++ b/arvbox/lib/arvbox/docker/service/keepproxy/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepproxy/run b/arvbox/lib/arvbox/docker/service/keepproxy/run
index ef446b5..a388c8b 120000
--- a/arvbox/lib/arvbox/docker/service/keepproxy/run
+++ b/arvbox/lib/arvbox/docker/service/keepproxy/run
@@ -1 +1 @@
-../runsu.sh
\ No newline at end of file
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepproxy/run-service b/arvbox/lib/arvbox/docker/service/keepproxy/run-service
index 87b46d9..413a67e 100755
--- a/arvbox/lib/arvbox/docker/service/keepproxy/run-service
+++ b/arvbox/lib/arvbox/docker/service/keepproxy/run-service
@@ -2,7 +2,7 @@
 
 exec 2>&1
 sleep 2
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -12,38 +12,30 @@ cd /var/lib/arvados/gostuff
 export GOPATH=$PWD
 mkdir -p "$GOPATH/src/git.curoverse.com"
 ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/keepproxy"
+flock /var/lib/arvados/gostuff.lock go get -t "git.curoverse.com/arvados.git/services/keepproxy"
 install bin/keepproxy /usr/local/bin
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
-if test -s /var/lib/arvados/keepproxy-uuid ; then
-    keep_uuid=$(cat /var/lib/arvados/keepproxy-uuid)
-    set +e
-    read -rd $'\000' keepservice <<EOF
-{
- "service_host":"$localip",
- "service_port":25100,
- "service_type":"proxy"
-}
-EOF
-   set -e
-   arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
-else
-    set +e
-    read -rd $'\000' keepservice <<EOF
+set +e
+read -rd $'\000' keepservice <<EOF
 {
  "service_host":"$localip",
- "service_port":25100,
+ "service_port":${services[keepproxy]},
  "service_ssl_flag":false,
  "service_type":"proxy"
 }
 EOF
-    set -e
+set -e
+
+if test -s /var/lib/arvados/keepproxy-uuid ; then
+    keep_uuid=$(cat /var/lib/arvados/keepproxy-uuid)
+    arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
+else
     UUID=$(arv --format=uuid keep_service create --keep-service "$keepservice")
     echo $UUID > /var/lib/arvados/keepproxy-uuid
 fi
 
-exec /usr/local/bin/keepproxy -listen=":25100"
+exec /usr/local/bin/keepproxy -listen=:${services[keepproxy]}
diff --git a/arvbox/lib/arvbox/docker/service/crunch1/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keepstore0/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/crunch1/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keepstore0/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/keepstore0/log/run b/arvbox/lib/arvbox/docker/service/keepstore0/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keepstore0/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepstore0/run b/arvbox/lib/arvbox/docker/service/keepstore0/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keepstore0/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepstore0/run-service b/arvbox/lib/arvbox/docker/service/keepstore0/run-service
new file mode 100755
index 0000000..cf411e4
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keepstore0/run-service
@@ -0,0 +1,3 @@
+#!/bin/bash
+. /usr/local/lib/arvbox/common.sh
+exec /usr/local/lib/arvbox/keep-setup.sh keep0 ${services[keepstore0]}
diff --git a/arvbox/lib/arvbox/docker/service/crunch0/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keepstore1/log/main/.gitstub
similarity index 100%
rename from arvbox/lib/arvbox/docker/service/crunch0/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keepstore1/log/main/.gitstub
diff --git a/arvbox/lib/arvbox/docker/service/keepstore1/log/run b/arvbox/lib/arvbox/docker/service/keepstore1/log/run
new file mode 120000
index 0000000..d6aef4a
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keepstore1/log/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepstore1/run b/arvbox/lib/arvbox/docker/service/keepstore1/run
new file mode 120000
index 0000000..a388c8b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keepstore1/run
@@ -0,0 +1 @@
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepstore1/run-service b/arvbox/lib/arvbox/docker/service/keepstore1/run-service
new file mode 100755
index 0000000..8d34d06
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/keepstore1/run-service
@@ -0,0 +1,3 @@
+#!/bin/bash
+. /usr/local/lib/arvbox/common.sh
+exec /usr/local/lib/arvbox/keep-setup.sh keep1 ${services[keepstore1]}
diff --git a/arvbox/lib/arvbox/docker/service/keepweb/log/run b/arvbox/lib/arvbox/docker/service/keepweb/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/lib/arvbox/docker/service/keepweb/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/keepweb/run b/arvbox/lib/arvbox/docker/service/keepweb/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/keepweb/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/postgres/log/run b/arvbox/lib/arvbox/docker/service/postgres/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/postgres/log/run
+++ b/arvbox/lib/arvbox/docker/service/postgres/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/postgres/run b/arvbox/lib/arvbox/docker/service/postgres/run
index ad9cc37..4918bd7 100755
--- a/arvbox/lib/arvbox/docker/service/postgres/run
+++ b/arvbox/lib/arvbox/docker/service/postgres/run
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
 
diff --git a/arvbox/lib/arvbox/docker/service/postgres/run-service b/arvbox/lib/arvbox/docker/service/postgres/run-service
index 0a67d6c..dd2eb1a 100755
--- a/arvbox/lib/arvbox/docker/service/postgres/run-service
+++ b/arvbox/lib/arvbox/docker/service/postgres/run-service
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 if ! test -d /var/lib/postgresql/9.4/main ; then
     /usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main
diff --git a/arvbox/lib/arvbox/docker/service/ready/run b/arvbox/lib/arvbox/docker/service/ready/run
index ef446b5..a388c8b 120000
--- a/arvbox/lib/arvbox/docker/service/ready/run
+++ b/arvbox/lib/arvbox/docker/service/ready/run
@@ -1 +1 @@
-../runsu.sh
\ No newline at end of file
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/ready/run-service b/arvbox/lib/arvbox/docker/service/ready/run-service
index a26d47c..52c0adc 100755
--- a/arvbox/lib/arvbox/docker/service/ready/run-service
+++ b/arvbox/lib/arvbox/docker/service/ready/run-service
@@ -2,7 +2,7 @@
 
 . /usr/local/lib/arvbox/common.sh
 
-set -eu
+set -eu -o pipefail
 
 if ! [[ -d /tmp/arvbox-ready ]] ; then
    echo
@@ -16,24 +16,8 @@ fi
 
 sleep 3
 
-declare -A services
-services=(
-  [workbench]=80
-  [api]=3001
-  [sso]=3002
-  [githttp]=9001
-  [keepweb]=25099
-  [keepproxy]=25100
-  [keep0]=25107
-  [keep1]=25108
-  [ssh]=22
-  [doc]=8000
-)
-
 waiting=""
 
-. /usr/local/lib/arvbox/common.sh
-
 for s in "${!services[@]}"
 do
   if ! [[ -f /tmp/arvbox-ready/$s ]] ; then
diff --git a/arvbox/lib/arvbox/docker/service/sdk/log/run b/arvbox/lib/arvbox/docker/service/sdk/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/sdk/log/run
+++ b/arvbox/lib/arvbox/docker/service/sdk/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/sdk/run b/arvbox/lib/arvbox/docker/service/sdk/run
index e6c844d..816b166 100755
--- a/arvbox/lib/arvbox/docker/service/sdk/run
+++ b/arvbox/lib/arvbox/docker/service/sdk/run
@@ -1,5 +1,5 @@
 #!/bin/sh
 set -e
 
-/etc/service/runsu.sh $0-service
+/usr/local/lib/arvbox/runsu.sh $0-service
 sv stop sdk
diff --git a/arvbox/lib/arvbox/docker/service/sdk/run-service b/arvbox/lib/arvbox/docker/service/sdk/run-service
index fd376ba..b51f0fc 100755
--- a/arvbox/lib/arvbox/docker/service/sdk/run-service
+++ b/arvbox/lib/arvbox/docker/service/sdk/run-service
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
diff --git a/arvbox/lib/arvbox/docker/service/ssh/log/run b/arvbox/lib/arvbox/docker/service/ssh/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/ssh/log/run
+++ b/arvbox/lib/arvbox/docker/service/ssh/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/ssh/run b/arvbox/lib/arvbox/docker/service/ssh/run
index 0db3ffa..0f23542 100755
--- a/arvbox/lib/arvbox/docker/service/ssh/run
+++ b/arvbox/lib/arvbox/docker/service/ssh/run
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -eux
+set -eux -o pipefail
 
 if ! test -d /var/run/sshd ; then
    mkdir /var/run/sshd
diff --git a/arvbox/lib/arvbox/docker/service/sso/log/run b/arvbox/lib/arvbox/docker/service/sso/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/sso/log/run
+++ b/arvbox/lib/arvbox/docker/service/sso/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/sso/run b/arvbox/lib/arvbox/docker/service/sso/run
index ef446b5..a388c8b 120000
--- a/arvbox/lib/arvbox/docker/service/sso/run
+++ b/arvbox/lib/arvbox/docker/service/sso/run
@@ -1 +1 @@
-../runsu.sh
\ No newline at end of file
+/usr/local/lib/arvbox/runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/sso/run-service b/arvbox/lib/arvbox/docker/service/sso/run-service
index 29951f5..d1c566a 100755
--- a/arvbox/lib/arvbox/docker/service/sso/run-service
+++ b/arvbox/lib/arvbox/docker/service/sso/run-service
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -ex
+set -ex -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -96,7 +96,7 @@ if test "$1" = "--only-setup" ; then
     exit
 fi
 
-exec bundle exec passenger start --port=3002 \
+exec bundle exec passenger start --port=${services[sso]} \
      --runtime-dir=/var/lib/passenger \
      --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
      --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/lib/arvbox/docker/service/vm/log/run b/arvbox/lib/arvbox/docker/service/vm/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/vm/log/run
+++ b/arvbox/lib/arvbox/docker/service/vm/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/vm/run b/arvbox/lib/arvbox/docker/service/vm/run
deleted file mode 120000
index ef446b5..0000000
--- a/arvbox/lib/arvbox/docker/service/vm/run
+++ /dev/null
@@ -1 +0,0 @@
-../runsu.sh
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/vm/run b/arvbox/lib/arvbox/docker/service/vm/run
new file mode 100755
index 0000000..b7fb9cc
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/service/vm/run
@@ -0,0 +1,9 @@
+#!/bin/bash
+set -e
+
+. /usr/local/lib/arvbox/common.sh
+
+git config --system "credential.http://$localip:${services[arv-git-httpd]}/.username" none
+git config --system "credential.http://$localip:${services[arv-git-httpd]}/.helper" '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'
+
+exec /usr/local/lib/arvbox/runsu.sh $0-service
diff --git a/arvbox/lib/arvbox/docker/service/vm/run-service b/arvbox/lib/arvbox/docker/service/vm/run-service
index 9b894ff..a845e44 100755
--- a/arvbox/lib/arvbox/docker/service/vm/run-service
+++ b/arvbox/lib/arvbox/docker/service/vm/run-service
@@ -2,7 +2,7 @@
 
 exec 2>&1
 sleep 2
-set -eux
+set -ex -o pipefail
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -13,31 +13,24 @@ if test "$1" = "--only-deps" ; then
     exit
 fi
 
-git config --system "credential.http://$localip:9001/.username" none
-git config --system "credential.http://$localip:9001/.helper" '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'
+set -u
 
-export ARVADOS_API_HOST=$localip:3001
+export ARVADOS_API_HOST=$localip:${services[api]}
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
-if test -s /var/lib/arvados/vm-uuid ; then
-    ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
-    set +e
-    read -rd $'\000' vm <<EOF
+set +e
+read -rd $'\000' vm <<EOF
 {
  "hostname":"$localip"
 }
 EOF
-    set -e
+set -e
+
+if test -s /var/lib/arvados/vm-uuid ; then
+    ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
     arv virtual_machine update --uuid $ARVADOS_VIRTUAL_MACHINE_UUID --virtual-machine "$vm"
 else
-    set +e
-    read -rd $'\000' vm <<EOF
-{
- "hostname":"$localip"
-}
-EOF
-    set -e
     ARVADOS_VIRTUAL_MACHINE_UUID=$(arv --format=uuid virtual_machine create --virtual-machine "$vm")
     echo $ARVADOS_VIRTUAL_MACHINE_UUID > /var/lib/arvados/vm-uuid
 fi
diff --git a/arvbox/lib/arvbox/docker/service/workbench/log/run b/arvbox/lib/arvbox/docker/service/workbench/log/run
index f99cc1d..d6aef4a 120000
--- a/arvbox/lib/arvbox/docker/service/workbench/log/run
+++ b/arvbox/lib/arvbox/docker/service/workbench/log/run
@@ -1 +1 @@
-../../logger
\ No newline at end of file
+/usr/local/lib/arvbox/logger
\ No newline at end of file
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run b/arvbox/lib/arvbox/docker/service/workbench/run
index f121ce7..6ac0476 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run
+++ b/arvbox/lib/arvbox/docker/service/workbench/run
@@ -1,7 +1,7 @@
 #!/bin/sh
 set -e
 
-/etc/service/runsu.sh $0-service $1
+/usr/local/lib/arvbox/runsu.sh $0-service $1
 
 cd /usr/src/arvados/apps/workbench
 
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run-service b/arvbox/lib/arvbox/docker/service/workbench/run-service
index dadd989..a5f7195 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run-service
+++ b/arvbox/lib/arvbox/docker/service/workbench/run-service
@@ -1,13 +1,12 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
-set -ex
+set -ex -o pipefail
 
 .  /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/arvados/apps/workbench
 export RAILS_ENV=development
-export GEM_HOME=/var/lib/gems
 
 run_bundler --without=development
 bundle exec passenger start --runtime-check-only --runtime-dir=/var/lib/passenger
@@ -30,10 +29,10 @@ fi
 cat >config/application.yml <<EOF
 common:
   secret_token: $secret_token
-  arvados_login_base: https://$localip:3001/login
-  arvados_v1_base: https://$localip:3001/arvados/v1
+  arvados_login_base: https://$localip:${services[api]}/login
+  arvados_v1_base: https://$localip:${services[api]}/arvados/v1
   arvados_insecure_https: true
-  keep_web_download_url: http://$localip:25099/c=%{uuid_or_pdh}
-  keep_web_url: http://$localip:25099/c=%{uuid_or_pdh}
-  arvados_docsite: http://$localip:8000/
+  keep_web_download_url: http://$localip:${services[keep-web]}/c=%{uuid_or_pdh}
+  keep_web_url: http://$localip:${services[keep-web]}/c=%{uuid_or_pdh}
+  arvados_docsite: http://$localip:${services[doc]}/
 EOF

commit ba698c52e9be47f547dd743f4e13d7992db80743
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Fri Jan 8 16:24:43 2016 -0500

    Working on getting demo image to work.  Not quite there yet.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 57c0905..af13ab9 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -35,12 +35,16 @@ VAR_DATA=$ARVBOX_DATA/var
 PASSENGER=$ARVBOX_DATA/passenger
 GEMS=$ARVBOX_DATA/gems
 
-mkdir -p $PG_DATA $VAR_DATA $PASSENGER $GEMS
-
 run() {
     if test "$1" = demo ; then
+        if test -d $ARVBOX_DATA ; then
+            echo "It looks like you already have a development container named $ARVBOX_CONTAINER."
+            echo "Set ARVBOX_CONTAINER to something else"
+            exit 1
+        fi
+
         if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
-            docker start $ARVBOX_CONTAINER
+            docker start -a $ARVBOX_CONTAINER
         else
             docker run \
                    --name=$ARVBOX_CONTAINER \
@@ -48,6 +52,8 @@ run() {
                    arvados/arvbox-demo
         fi
     else
+        mkdir -p $PG_DATA $VAR_DATA $PASSENGER $GEMS
+
         if ! test -d $ARVADOS_ROOT ; then
             git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
         fi
@@ -68,7 +74,7 @@ run() {
                    --volume=$PASSENGER:/var/lib/passenger:rw \
                    --volume=$GEMS:/var/lib/gems:rw \
                    arvados/arvbox-dev \
-                   runsvdir /etc/tests-service
+                   LD_PRELOAD=/lib/runit-docker.so exec runsvdir /etc/tests-service
         else
             docker run \
                    --detach \
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.base b/arvbox/lib/arvbox/docker/Dockerfile.base
index 9308d9c..274dceb 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.base
+++ b/arvbox/lib/arvbox/docker/Dockerfile.base
@@ -20,9 +20,7 @@ RUN cd /root/runit-docker && \
     make && \
     make install
 
-ENV LD_PRELOAD /lib/runit-docker.so
-
 ADD fuse.conf /etc/
 
 # Start the supervisor.
-CMD ["runsvdir", "/etc/service"]
+CMD LD_PRELOAD=/lib/runit-docker.so exec runsvdir /etc/service
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.demo b/arvbox/lib/arvbox/docker/Dockerfile.demo
index 2ab772e..46ab21e 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile.demo
+++ b/arvbox/lib/arvbox/docker/Dockerfile.demo
@@ -7,10 +7,11 @@ RUN cd /usr/src && \
 ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
 ADD service /etc/service
 
-RUN mkdir -p /var/lib/arvados
-RUN /etc/service/sso/run-service --only-deps
-RUN /etc/service/api/run-service --only-deps
-RUN /etc/service/workbench/run-service --only-deps
-RUN /etc/service/doc/run-service --only-deps
-RUN /etc/service/vm/run-service --only-deps
-RUN /etc/service/sdk/run-service
+RUN chown -R 1000:1000 /usr/src && /usr/local/lib/arvbox/createusers.sh
+
+RUN sudo -u arvbox /etc/service/sso/run-service --only-deps
+RUN sudo -u arvbox /etc/service/api/run-service --only-deps
+RUN sudo -u arvbox /etc/service/workbench/run-service --only-deps
+RUN sudo -u arvbox /etc/service/doc/run-service --only-deps
+RUN sudo -u arvbox /etc/service/vm/run-service --only-deps
+RUN sudo -u arvbox /etc/service/sdk/run-service
diff --git a/arvbox/lib/arvbox/docker/common.sh b/arvbox/lib/arvbox/docker/common.sh
index bc328f7..d58c39b 100644
--- a/arvbox/lib/arvbox/docker/common.sh
+++ b/arvbox/lib/arvbox/docker/common.sh
@@ -2,6 +2,14 @@ localip=$(ip addr show eth0 |grep "inet " | sed 's/ *inet \([^/]*\).*/\1/')
 export GEM_HOME=/var/lib/gems
 export GEM_PATH=/var/lib/gems
 
+if test $(id arvbox -u) = 0 ; then
+    PGUSER=postgres
+    PGGROUP=postgres
+else
+    PGUSER=arvbox
+    PGGROUP=arvbox
+fi
+
 run_bundler() {
     if test -f Gemfile.lock ; then
         frozen=--frozen
diff --git a/arvbox/lib/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
index 8d27990..680d9fe 100755
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@ -7,7 +7,8 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
     FUSEGID=$(ls -nd /dev/fuse | sed 's/ */ /' | cut -d' ' -f5)
 
-    mkdir -p /var/lib/arvados/git
+    mkdir -p /var/lib/arvados/git /var/lib/gems /var/lib/passenger
+
     groupadd --gid $HOSTGID --non-unique arvbox
     groupadd --gid $FUSEGID --non-unique fuse
     groupadd --gid $HOSTGID --non-unique git
@@ -19,7 +20,7 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
     useradd --groups docker,fuse crunch
 
-    chown arvbox:arvbox -R /usr/local
+    chown arvbox:arvbox -R /usr/local /var/lib/arvados /var/lib/gems /var/lib/passenger
 
     mkdir -p /var/lib/gems/ruby/2.1.0
     chown arvbox:arvbox -R /var/lib/gems/ruby/2.1.0
diff --git a/arvbox/lib/arvbox/docker/service/postgres/run b/arvbox/lib/arvbox/docker/service/postgres/run
index 55d11a0..ad9cc37 100755
--- a/arvbox/lib/arvbox/docker/service/postgres/run
+++ b/arvbox/lib/arvbox/docker/service/postgres/run
@@ -2,17 +2,11 @@
 
 flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
 
-if test $(id arvbox -u) = 0 ; then
-    USER=postgres
-    GROUP=postgres
-else
-    USER=arvbox
-    GROUP=arvbox
-fi
+. /usr/local/lib/arvbox/common.sh
 
-chown -R $USER:$GROUP /var/lib/postgresql
-chown -R $USER:$GROUP /var/run/postgresql
-chown -R $USER:$GROUP /etc/postgresql
-chown -R $USER:$GROUP /etc/ssl/private
+chown -R $PGUSER:$PGGROUP /var/lib/postgresql
+chown -R $PGUSER:$PGGROUP /var/run/postgresql
+chown -R $PGUSER:$PGGROUP /etc/postgresql
+chown -R $PGUSER:$PGGROUP /etc/ssl/private
 
-exec su $USER $0-service
+exec chpst -u $PGUSER:$PGGROUP $0-service
diff --git a/arvbox/lib/arvbox/docker/service/runsu.sh b/arvbox/lib/arvbox/docker/service/runsu.sh
index 32eccdf..d702709 100755
--- a/arvbox/lib/arvbox/docker/service/runsu.sh
+++ b/arvbox/lib/arvbox/docker/service/runsu.sh
@@ -8,7 +8,7 @@ flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
 export HOME=/var/lib/arvados
 
 if test -z "$1" ; then
-    exec sudo -u arvbox -- $0-service
+    exec chpst -u arvbox:arvbox $0-service
 else
-    exec sudo -u arvbox -- $@
+    exec chpst -u arvbox:arvbox $@
 fi

commit b6bd09f01642d2ad2dc33259a2382615daadf059
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Jan 7 14:03:01 2016 -0500

    8080: Refactor to base image and dev or demo images.  Working on support for a
    "demo" image that comes with everything packed in.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index e90dce1..57c0905 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -38,54 +38,63 @@ GEMS=$ARVBOX_DATA/gems
 mkdir -p $PG_DATA $VAR_DATA $PASSENGER $GEMS
 
 run() {
-    if ! test -d $ARVADOS_ROOT ; then
-        git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
-    fi
-    if ! test -d $SSO_ROOT ; then
-        git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
-    fi
-
-    if test "$1" = testing ; then
-        docker run \
-               --detach \
-               --name=$ARVBOX_CONTAINER \
-               --privileged \
-               --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-               --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
-               --volume=$SSO_ROOT:/usr/src/sso:rw \
-               --volume=$PG_DATA:/var/lib/postgresql:rw \
-               --volume=$VAR_DATA:/var/lib/arvados:rw \
-               --volume=$PASSENGER:/var/lib/passenger:rw \
-               --volume=$GEMS:/var/lib/gems:rw \
-               --volume=/var/lib/docker \
-               arvados/arvbox \
-               runsvdir /etc/tests-service
+    if test "$1" = demo ; then
+        if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
+            docker start $ARVBOX_CONTAINER
+        else
+            docker run \
+                   --name=$ARVBOX_CONTAINER \
+                   --privileged \
+                   arvados/arvbox-demo
+        fi
     else
-        docker run \
-               --detach \
-               --name=$ARVBOX_CONTAINER \
-               --privileged \
-               --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-               --volume=$SSO_ROOT:/usr/src/sso:rw \
-               --volume=$PG_DATA:/var/lib/postgresql:rw \
-               --volume=$VAR_DATA:/var/lib/arvados:rw \
-               --volume=$PASSENGER:/var/lib/passenger:rw \
-               --volume=$GEMS:/var/lib/gems:rw \
-               --volume=/var/lib/docker \
-               arvados/arvbox
-        FF=/tmp/arvbox-fifo-$$
-        mkfifo $FF
-        docker logs -f $ARVBOX_CONTAINER > $FF &
-        LOGPID=$!
-        while read line ; do
-            echo $line
-            if echo $line | grep "Workbench is running at" >/dev/null ; then
-                kill $LOGPID
-            fi
-        done < $FF
-        rm $FF
-        echo
-        echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
+        if ! test -d $ARVADOS_ROOT ; then
+            git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
+        fi
+        if ! test -d $SSO_ROOT ; then
+            git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
+        fi
+
+        if test "$1" = testing ; then
+            docker run \
+                   --detach \
+                   --name=$ARVBOX_CONTAINER \
+                   --privileged \
+                   --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+                   --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
+                   --volume=$SSO_ROOT:/usr/src/sso:rw \
+                   --volume=$PG_DATA:/var/lib/postgresql:rw \
+                   --volume=$VAR_DATA:/var/lib/arvados:rw \
+                   --volume=$PASSENGER:/var/lib/passenger:rw \
+                   --volume=$GEMS:/var/lib/gems:rw \
+                   arvados/arvbox-dev \
+                   runsvdir /etc/tests-service
+        else
+            docker run \
+                   --detach \
+                   --name=$ARVBOX_CONTAINER \
+                   --privileged \
+                   --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+                   --volume=$SSO_ROOT:/usr/src/sso:rw \
+                   --volume=$PG_DATA:/var/lib/postgresql:rw \
+                   --volume=$VAR_DATA:/var/lib/arvados:rw \
+                   --volume=$PASSENGER:/var/lib/passenger:rw \
+                   --volume=$GEMS:/var/lib/gems:rw \
+                   arvados/arvbox-dev
+            FF=/tmp/arvbox-fifo-$$
+            mkfifo $FF
+            docker logs -f $ARVBOX_CONTAINER > $FF &
+            LOGPID=$!
+            while read line ; do
+                echo $line
+                if echo $line | grep "Workbench is running at" >/dev/null ; then
+                    kill $LOGPID
+                fi
+            done < $FF
+            rm $FF
+            echo
+            echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
+        fi
     fi
 }
 
@@ -93,18 +102,29 @@ stop() {
     if docker ps -a --filter "status=running" |grep -E "$ARVBOX_CONTAINER$" -q ; then
         docker stop $ARVBOX_CONTAINER
     fi
-    if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
-        docker rm --volumes=true $ARVBOX_CONTAINER
+    if test "$1" != demo ; then
+        if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
+            docker rm --volumes=true $ARVBOX_CONTAINER
+        fi
+    fi
+}
+
+build() {
+    docker build -t arvados/arvbox-base -f $ARVBOX_DOCKER/Dockerfile.base $ARVBOX_DOCKER
+    if test "$1" = demo ; then
+        docker build -t arvados/arvbox-demo -f $ARVBOX_DOCKER/Dockerfile.demo $ARVBOX_DOCKER
+    else
+        docker build -t arvados/arvbox-dev -f $ARVBOX_DOCKER/Dockerfile.dev $ARVBOX_DOCKER
     fi
 }
 
 case $1 in
     build)
-        docker build -t arvados/arvbox $ARVBOX_DOCKER
+        build $2
         ;;
 
     start|run)
-        run
+        run $2
         ;;
 
     sh*)
@@ -112,7 +132,7 @@ case $1 in
         ;;
 
     stop)
-        stop
+        stop $2
         ;;
 
     restart)
@@ -122,7 +142,7 @@ case $1 in
 
     reboot)
         stop
-        docker build -t arvados/arvbox $ARVBOX_DOCKER
+        build
         run
         ;;
 
@@ -180,6 +200,24 @@ case $1 in
         run testing
 
         shift
+
+        while ! docker exec -ti \
+                $ARVBOX_CONTAINER \
+                /etc/tests-service/runsu.sh \
+                psql -c'\du' ; do
+            sleep 1
+        done
+
+        docker exec -ti \
+               $ARVBOX_CONTAINER \
+               /etc/tests-service/runsu.sh \
+               /etc/service/sso/run-service --only-setup
+
+        docker exec -ti \
+               $ARVBOX_CONTAINER \
+               /etc/tests-service/runsu.sh \
+               /etc/service/api/run-service --only-setup
+
         docker exec -ti \
                $ARVBOX_CONTAINER \
                /etc/tests-service/runsu.sh \
diff --git a/arvbox/lib/arvbox/docker/Dockerfile b/arvbox/lib/arvbox/docker/Dockerfile.base
similarity index 56%
rename from arvbox/lib/arvbox/docker/Dockerfile
rename to arvbox/lib/arvbox/docker/Dockerfile.base
index 22ad5d2..9308d9c 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile
+++ b/arvbox/lib/arvbox/docker/Dockerfile.base
@@ -9,16 +9,10 @@ RUN apt-get update && \
     libpython-dev fuse libfuse-dev python-pip \
     pkg-config libattr1-dev python-llfuse python-pycurl \
     libwww-perl libio-socket-ssl-perl libcrypt-ssleay-perl \
-    libjson-perl python-virtualenv python3-virtualenv nginx \
-    gitolite3 lsof python-epydoc linkchecker xvfb iceweasel graphviz
+    libjson-perl nginx gitolite3 lsof python-epydoc graphviz
 
 RUN curl -sSL https://get.docker.com/ | sh
-
-RUN set -e && \
- PJS=phantomjs-1.9.7-linux-x86_64 && \
- curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
- tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
- ln -s ../$PJS/bin/phantomjs /usr/local/bin/
+VOLUME /var/lib/docker
 
 ADD runit-docker /root/runit-docker
 
@@ -30,9 +24,5 @@ ENV LD_PRELOAD /lib/runit-docker.so
 
 ADD fuse.conf /etc/
 
-ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
-ADD service /etc/service
-ADD tests-service /etc/tests-service
-
 # Start the supervisor.
 CMD ["runsvdir", "/etc/service"]
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.demo b/arvbox/lib/arvbox/docker/Dockerfile.demo
new file mode 100644
index 0000000..2ab772e
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/Dockerfile.demo
@@ -0,0 +1,16 @@
+FROM arvados/arvbox-base
+
+RUN cd /usr/src && \
+    git clone https://github.com/curoverse/arvados.git && \
+    git clone https://github.com/curoverse/sso-devise-omniauth-provider.git sso
+
+ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
+ADD service /etc/service
+
+RUN mkdir -p /var/lib/arvados
+RUN /etc/service/sso/run-service --only-deps
+RUN /etc/service/api/run-service --only-deps
+RUN /etc/service/workbench/run-service --only-deps
+RUN /etc/service/doc/run-service --only-deps
+RUN /etc/service/vm/run-service --only-deps
+RUN /etc/service/sdk/run-service
diff --git a/arvbox/lib/arvbox/docker/Dockerfile.dev b/arvbox/lib/arvbox/docker/Dockerfile.dev
new file mode 100644
index 0000000..cb2873b
--- /dev/null
+++ b/arvbox/lib/arvbox/docker/Dockerfile.dev
@@ -0,0 +1,15 @@
+FROM arvados/arvbox-base
+
+RUN apt-get update && \
+    DEBIAN_FRONTEND=noninteractive apt-get -yq install \
+    python-virtualenv python3-virtualenv linkchecker xvfb iceweasel
+
+RUN set -e && \
+ PJS=phantomjs-1.9.7-linux-x86_64 && \
+ curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
+ tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
+ ln -s ../$PJS/bin/phantomjs /usr/local/bin/
+
+ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
+ADD service /etc/service
+ADD tests-service /etc/tests-service
diff --git a/arvbox/lib/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
index 25b1dd7..8d27990 100755
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@ -33,4 +33,7 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     rm -r /var/log/nginx
     mkdir -p /var/log/nginx
     chown arvbox:arvbox -R /var/log/nginx
+
+    mkdir -p /tmp/crunch0 /tmp/crunch1
+    chown crunch:crunch -R /tmp/crunch0 /tmp/crunch1
 fi
diff --git a/arvbox/lib/arvbox/docker/crunch-setup.sh b/arvbox/lib/arvbox/docker/crunch-setup.sh
index c52b034..b6f5cda 100755
--- a/arvbox/lib/arvbox/docker/crunch-setup.sh
+++ b/arvbox/lib/arvbox/docker/crunch-setup.sh
@@ -14,9 +14,6 @@ ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
 go get -t "git.curoverse.com/arvados.git/services/crunchstat"
 install bin/crunchstat /usr/local/bin
 
-mkdir -p /tmp/$1
-chown crunch:crunch -R /tmp/$1
-
 export ARVADOS_API_HOST=$localip:3001
 export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /usr/src/arvados/services/api/superuser_token)
diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index b4ab386..6615736 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 exec 2>&1
-set -eux
+set -ex
 
 . /usr/local/lib/arvbox/common.sh
 
@@ -9,6 +9,13 @@ cd /usr/src/arvados/services/api
 export RAILS_ENV=development
 
 run_bundler --without=development
+bundle exec passenger start --runtime-check-only --runtime-dir=/var/lib/passenger
+
+if test "$1" = "--only-deps" ; then
+    exit
+fi
+
+set -u
 
 if ! test -s /var/lib/arvados/api_uuid_prefix ; then
     ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/api_uuid_prefix
@@ -92,7 +99,12 @@ rm -rf tmp
 
 bundle exec rake db:migrate
 
+set +u
+if test "$1" = "--only-setup" ; then
+    exit
+fi
+
 ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start --port=3001 \
-    --runtime-dir=/var/lib/passenger \
-    --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
-    --ssl-certificate-key=/var/lib/arvados/self-signed.key
+                  --runtime-dir=/var/lib/passenger \
+                  --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
+                  --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/lib/arvbox/docker/service/doc/run-service b/arvbox/lib/arvbox/docker/service/doc/run-service
index bb0f0e4..a64d5c8 100755
--- a/arvbox/lib/arvbox/docker/service/doc/run-service
+++ b/arvbox/lib/arvbox/docker/service/doc/run-service
@@ -1,11 +1,19 @@
 #!/bin/sh
 
 exec 2>&1
-set -eux
+set -ex
 
 . /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/arvados/doc
 run_bundler --without=development
+
+if test "$1" = "--only-deps" ; then
+    exit
+fi
+
+set -u
+
 bundle exec rake generate baseurl=http://$localip:8000 arvados_api_host=$localip:3001 arvados_workbench_host=http://$localip
+
 exec bundle exec rake run
diff --git a/arvbox/lib/arvbox/docker/service/postgres/run b/arvbox/lib/arvbox/docker/service/postgres/run
index cf8250c..55d11a0 100755
--- a/arvbox/lib/arvbox/docker/service/postgres/run
+++ b/arvbox/lib/arvbox/docker/service/postgres/run
@@ -1,11 +1,18 @@
 #!/bin/sh
 
-HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
-HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
+flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
 
-chown -R $HOSTUID:$HOSTGID /var/lib/postgresql
-chown -R $HOSTUID:$HOSTGID /var/run/postgresql
-chown -R $HOSTUID:$HOSTGID /etc/postgresql
-chown -R $HOSTUID:$HOSTGID /etc/ssl/private
+if test $(id arvbox -u) = 0 ; then
+    USER=postgres
+    GROUP=postgres
+else
+    USER=arvbox
+    GROUP=arvbox
+fi
 
-exec chpst -u:$HOSTUID:$HOSTGID $0-service
+chown -R $USER:$GROUP /var/lib/postgresql
+chown -R $USER:$GROUP /var/run/postgresql
+chown -R $USER:$GROUP /etc/postgresql
+chown -R $USER:$GROUP /etc/ssl/private
+
+exec su $USER $0-service
diff --git a/arvbox/lib/arvbox/docker/service/postgres/run-service b/arvbox/lib/arvbox/docker/service/postgres/run-service
index 6f72ba6..0a67d6c 100755
--- a/arvbox/lib/arvbox/docker/service/postgres/run-service
+++ b/arvbox/lib/arvbox/docker/service/postgres/run-service
@@ -5,7 +5,7 @@ set -eux
 
 if ! test -d /var/lib/postgresql/9.4/main ; then
     /usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main
-    sh -c "while ! createdb ; do sleep 1 ; done" &
+    sh -c "while ! psql -c'\du' >/dev/null 2>/dev/null ; do createdb ; sleep 1 ; done" &
 fi
 mkdir -p /var/run/postgresql/9.4-main.pg_stat_tmp
 
diff --git a/arvbox/lib/arvbox/docker/service/ready/run-service b/arvbox/lib/arvbox/docker/service/ready/run-service
index e99570b..a26d47c 100755
--- a/arvbox/lib/arvbox/docker/service/ready/run-service
+++ b/arvbox/lib/arvbox/docker/service/ready/run-service
@@ -8,13 +8,13 @@ if ! [[ -d /tmp/arvbox-ready ]] ; then
    echo
    echo "Arvados-in-a-box starting"
    echo
-   echo "Note: if this is a fresh arvbox installation, it may take 10-15 minutes to download and"
+   echo "Note: if this is a fresh arvbox installation, it may take 10-15 minutes (or longer) to download and"
    echo "install dependencies.  Use \"arvbox log\" to monitor the progress of specific services."
    echo
    mkdir -p /tmp/arvbox-ready
 fi
 
-sleep 2
+sleep 3
 
 declare -A services
 services=(
@@ -56,6 +56,10 @@ elif ! which arv-get >/dev/null ; then
   waiting="$waiting sdk"
 fi
 
+if ! (ps x | grep -v grep | grep "crunch-dispatch") > /dev/null ; then
+    waiting="$waiting crunch-dispatch"
+fi
+
 if ! [[ -z "$waiting" ]] ; then
     if ps x | grep -v grep | grep "bundle install" > /dev/null; then
         gemcount=$(ls /var/lib/gems/ruby/2.1.0/gems 2>/dev/null | wc -l)
diff --git a/arvbox/lib/arvbox/docker/service/runsu.sh b/arvbox/lib/arvbox/docker/service/runsu.sh
index 329067f..32eccdf 100755
--- a/arvbox/lib/arvbox/docker/service/runsu.sh
+++ b/arvbox/lib/arvbox/docker/service/runsu.sh
@@ -8,7 +8,7 @@ flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
 export HOME=/var/lib/arvados
 
 if test -z "$1" ; then
-    exec su arvbox -c -- "exec $0-service"
+    exec sudo -u arvbox -- $0-service
 else
-    exec su arvbox --shell /bin/bash -- $@
+    exec sudo -u arvbox -- $@
 fi
diff --git a/arvbox/lib/arvbox/docker/service/sso/run-service b/arvbox/lib/arvbox/docker/service/sso/run-service
index 26defa7..29951f5 100755
--- a/arvbox/lib/arvbox/docker/service/sso/run-service
+++ b/arvbox/lib/arvbox/docker/service/sso/run-service
@@ -1,15 +1,21 @@
 #!/bin/sh
 
 exec 2>&1
-set -eux
+set -ex
 
 . /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/sso
 export RAILS_ENV=development
-export GEM_HOME=/var/lib/gems
 
 run_bundler --without=development
+bundle exec passenger start --runtime-check-only --runtime-dir=/var/lib/passenger
+
+if test "$1" = "--only-deps" ; then
+    exit
+fi
+
+set -u
 
 if ! test -s /var/lib/arvados/sso_uuid_prefix ; then
   ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/sso_uuid_prefix
@@ -84,7 +90,12 @@ fi
 rm -rf tmp
 
 bundle exec rake db:migrate
-export HOME=/var/lib/passenger
+
+set +u
+if test "$1" = "--only-setup" ; then
+    exit
+fi
+
 exec bundle exec passenger start --port=3002 \
      --runtime-dir=/var/lib/passenger \
      --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
diff --git a/arvbox/lib/arvbox/docker/service/vm/run-service b/arvbox/lib/arvbox/docker/service/vm/run-service
index f6844d8..9b894ff 100755
--- a/arvbox/lib/arvbox/docker/service/vm/run-service
+++ b/arvbox/lib/arvbox/docker/service/vm/run-service
@@ -6,6 +6,13 @@ set -eux
 
 . /usr/local/lib/arvbox/common.sh
 
+cd /usr/src/arvados/services/login-sync
+run_bundler
+
+if test "$1" = "--only-deps" ; then
+    exit
+fi
+
 git config --system "credential.http://$localip:9001/.username" none
 git config --system "credential.http://$localip:9001/.helper" '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'
 
@@ -37,9 +44,6 @@ fi
 
 export ARVADOS_VIRTUAL_MACHINE_UUID
 
-cd /usr/src/arvados/services/login-sync
-run_bundler
-
 while true ; do
       bundle exec arvados-login-sync
       sleep 120
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run b/arvbox/lib/arvbox/docker/service/workbench/run
index 665d848..f121ce7 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run
+++ b/arvbox/lib/arvbox/docker/service/workbench/run
@@ -1,7 +1,7 @@
 #!/bin/sh
 set -e
 
-/etc/service/runsu.sh $0-service
+/etc/service/runsu.sh $0-service $1
 
 cd /usr/src/arvados/apps/workbench
 
@@ -9,5 +9,7 @@ rm -rf tmp
 mkdir tmp
 chown arvbox:arvbox tmp
 
-exec bundle exec passenger start --port 80 \
-     --user arvbox --runtime-dir=/var/lib/passenger
+if test "$1" != "--only-deps" ; then
+    exec bundle exec passenger start --port 80 \
+         --user arvbox --runtime-dir=/var/lib/passenger
+fi
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run-service b/arvbox/lib/arvbox/docker/service/workbench/run-service
index 359f1e9..dadd989 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run-service
+++ b/arvbox/lib/arvbox/docker/service/workbench/run-service
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 exec 2>&1
-set -eux
+set -ex
 
 .  /usr/local/lib/arvbox/common.sh
 
@@ -10,6 +10,13 @@ export RAILS_ENV=development
 export GEM_HOME=/var/lib/gems
 
 run_bundler --without=development
+bundle exec passenger start --runtime-check-only --runtime-dir=/var/lib/passenger
+
+if test "$1" = "--only-deps" ; then
+    exit
+fi
+
+set -u
 
 if ! test -s /var/lib/arvados/workbench_secret_token ; then
   ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/workbench_secret_token
@@ -30,7 +37,3 @@ common:
   keep_web_url: http://$localip:25099/c=%{uuid_or_pdh}
   arvados_docsite: http://$localip:8000/
 EOF
-
-#bundle exec passenger start -p443 --ssl --ssl-certificate=self-signed.pem --ssl-certificate-key=self-signed.key
-
-bundle exec passenger start --runtime-check-only --runtime-dir=/var/lib/passenger

commit dbd9987ed8c1514938216504d8ee1f13282f82c3
Merge: 514df69 91b7d5d
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Jan 7 10:26:54 2016 -0500

    Merge branch '8080-arvbox' of git.curoverse.com:arvados-dev into 8080-arvbox
    
    Conflicts:
    	arvbox/lib/arvbox/docker/service/api/run-service

diff --cc arvbox/lib/arvbox/docker/createusers.sh
index 65c5463,ec02811..25b1dd7
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@@ -5,29 -5,17 +5,31 @@@ set -
  if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
      HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
      HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
++    FUSEGID=$(ls -nd /dev/fuse | sed 's/ */ /' | cut -d' ' -f5)
  
      mkdir -p /var/lib/arvados/git
 -    groupadd --gid $HOSTGID arvbox
 +    groupadd --gid $HOSTGID --non-unique arvbox
++    groupadd --gid $FUSEGID --non-unique fuse
      groupadd --gid $HOSTGID --non-unique git
      useradd --home-dir /var/lib/arvados \
              --uid $HOSTUID --gid $HOSTGID \
 -            --groups docker arvbox
 +            --non-unique \
-             --groups docker \
++            --groups docker,fuse \
 +            arvbox
      useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
--    useradd --groups docker crunch
++    useradd --groups docker,fuse crunch
 +
      chown arvbox:arvbox -R /usr/local
 +
 +    mkdir -p /var/lib/gems/ruby/2.1.0
 +    chown arvbox:arvbox -R /var/lib/gems/ruby/2.1.0
 +
      chown arvbox:arvbox -R /var/lib/nginx
 +
 +    # There's something weird about /var/log/nginx that prevents a non-root
 +    # arvbox user from writing to it, even after the ownership has been
 +    # changed.  As a workaround, delete it and recreate it.
 +
      rm -r /var/log/nginx
      mkdir -p /var/log/nginx
      chown arvbox:arvbox -R /var/log/nginx
diff --cc arvbox/lib/arvbox/docker/service/api/run-service
index ae7acd9,5b5bb1c..b4ab386
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@@ -55,9 -55,10 +55,9 @@@ if ! test -f /var/lib/arvados/api_datab
  fi
  database_pw=$(cat /var/lib/arvados/api_database_pw)
  
 -if ! test -f /var/lib/arvados/api_user_setup ; then
 +if ! (psql -c "\du" | grep "^ arvados ") >/dev/null ; then
-    psql -c "create user arvados with password '$database_pw'"
-    psql -c "ALTER USER arvados CREATEDB;"
+     psql -c "create user arvados with password '$database_pw'"
+     psql -c "ALTER USER arvados CREATEDB;"
 -    touch /var/lib/arvados/api_user_setup
  fi
  
  cat >config/database.yml <<EOF

commit 514df6920bdb330af068a20e1c88d971179cf124
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Jan 7 10:05:29 2016 -0500

    8080: Set up ruby gems directory as part of createusers.sh.  Detect if database
    user already exists.  Try Docker overlay driver first before using default.

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 8e01457..e90dce1 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -127,7 +127,7 @@ case $1 in
         ;;
 
     ip|open)
-        IP=$(docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | tr -d ' ":,\n' | cut -c10-)
+        IP=$(docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | head -n1 | tr -d ' ":,\n' | cut -c10-)
         if test $1 = 'ip' ; then
             echo $IP
         else
diff --git a/arvbox/lib/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
index ec02811..65c5463 100755
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@ -7,15 +7,27 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
 
     mkdir -p /var/lib/arvados/git
-    groupadd --gid $HOSTGID arvbox
+    groupadd --gid $HOSTGID --non-unique arvbox
     groupadd --gid $HOSTGID --non-unique git
     useradd --home-dir /var/lib/arvados \
             --uid $HOSTUID --gid $HOSTGID \
-            --groups docker arvbox
+            --non-unique \
+            --groups docker \
+            arvbox
     useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
     useradd --groups docker crunch
+
     chown arvbox:arvbox -R /usr/local
+
+    mkdir -p /var/lib/gems/ruby/2.1.0
+    chown arvbox:arvbox -R /var/lib/gems/ruby/2.1.0
+
     chown arvbox:arvbox -R /var/lib/nginx
+
+    # There's something weird about /var/log/nginx that prevents a non-root
+    # arvbox user from writing to it, even after the ownership has been
+    # changed.  As a workaround, delete it and recreate it.
+
     rm -r /var/log/nginx
     mkdir -p /var/log/nginx
     chown arvbox:arvbox -R /var/log/nginx
diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 56988fe..ae7acd9 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -55,10 +55,9 @@ if ! test -f /var/lib/arvados/api_database_pw ; then
 fi
 database_pw=$(cat /var/lib/arvados/api_database_pw)
 
-if ! test -f /var/lib/arvados/api_user_setup ; then
+if ! (psql -c "\du" | grep "^ arvados ") >/dev/null ; then
    psql -c "create user arvados with password '$database_pw'"
    psql -c "ALTER USER arvados CREATEDB;"
-   touch /var/lib/arvados/api_user_setup
 fi
 
 cat >config/database.yml <<EOF
diff --git a/arvbox/lib/arvbox/docker/service/docker/run b/arvbox/lib/arvbox/docker/service/docker/run
index 93834ee..83537d3 100755
--- a/arvbox/lib/arvbox/docker/service/docker/run
+++ b/arvbox/lib/arvbox/docker/service/docker/run
@@ -95,6 +95,6 @@ rm -rf /var/run/docker.pid
 read pid cmd state ppid pgrp session tty_nr tpgid rest < /proc/self/stat
 trap "kill -TERM -$pgrp; exit" EXIT TERM KILL SIGKILL SIGTERM SIGQUIT
 
-if ! docker daemon $DOCKER_DAEMON_ARGS ; then
-    docker daemon --storage-driver=overlay $DOCKER_DAEMON_ARGS
+if ! docker daemon --storage-driver=overlay $DOCKER_DAEMON_ARGS ; then
+    docker daemon $DOCKER_DAEMON_ARGS
 fi
diff --git a/arvbox/lib/arvbox/docker/service/sso/run-service b/arvbox/lib/arvbox/docker/service/sso/run-service
index ac19760..26defa7 100755
--- a/arvbox/lib/arvbox/docker/service/sso/run-service
+++ b/arvbox/lib/arvbox/docker/service/sso/run-service
@@ -38,10 +38,9 @@ if ! test -f /var/lib/arvados/sso_database_pw ; then
 fi
 database_pw=$(cat /var/lib/arvados/sso_database_pw)
 
-if ! test -f /var/lib/arvados/sso_user_setup ; then
+if ! (psql -c "\du" | grep "^ arvados_sso ") >/dev/null ; then
     psql -c "create user arvados_sso with password '$database_pw'"
     psql -c "ALTER USER arvados_sso CREATEDB;"
-    touch /var/lib/arvados/sso_user_setup
 fi
 
 cat >config/database.yml <<EOF

commit 91b7d5d373a317e341054a256aed46800c1eb918
Author: Tom Clegg <tom at curoverse.com>
Date:   Wed Jan 6 20:56:41 2016 -0500

    8080: Fix up whitespace.

diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 6c09e4b..5b5bb1c 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -11,17 +11,17 @@ export RAILS_ENV=development
 run_bundler --without=development
 
 if ! test -s /var/lib/arvados/api_uuid_prefix ; then
-  ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/api_uuid_prefix
+    ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/api_uuid_prefix
 fi
 uuid_prefix=$(cat /var/lib/arvados/api_uuid_prefix)
 
 if ! test -s /var/lib/arvados/api_secret_token ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/api_secret_token
+    ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/api_secret_token
 fi
 secret_token=$(cat /var/lib/arvados/api_secret_token)
 
 if ! test -s /var/lib/arvados/blob_signing_key ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/blob_signing_key
+    ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/blob_signing_key
 fi
 blob_signing_key=$(cat /var/lib/arvados/blob_signing_key)
 
@@ -56,9 +56,9 @@ fi
 database_pw=$(cat /var/lib/arvados/api_database_pw)
 
 if ! test -f /var/lib/arvados/api_user_setup ; then
-   psql -c "create user arvados with password '$database_pw'"
-   psql -c "ALTER USER arvados CREATEDB;"
-   touch /var/lib/arvados/api_user_setup
+    psql -c "create user arvados with password '$database_pw'"
+    psql -c "ALTER USER arvados CREATEDB;"
+    touch /var/lib/arvados/api_user_setup
 fi
 
 cat >config/database.yml <<EOF
@@ -94,6 +94,6 @@ rm -rf tmp
 bundle exec rake db:migrate
 
 ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start --port=3001 \
-                  --runtime-dir=/var/lib/passenger \
-                  --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
-                  --ssl-certificate-key=/var/lib/arvados/self-signed.key
+    --runtime-dir=/var/lib/passenger \
+    --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
+    --ssl-certificate-key=/var/lib/arvados/self-signed.key

commit d1fc5ede6afc84fca17b2125a9f6a775538a1cd4
Author: Tom Clegg <tom at curoverse.com>
Date:   Wed Jan 6 20:56:03 2016 -0500

    8080: Do not override blob_signing_key (or git_repo_*) in test config.

diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 56988fe..6c09e4b 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -33,17 +33,17 @@ sso_app_secret=$(cat /var/lib/arvados/sso_app_secret)
 cat >config/application.yml <<EOF
 common:
   secret_token: $secret_token
-  blob_signing_key: $blob_signing_key
   sso_app_secret: $sso_app_secret
   sso_app_id: arvados-server
   sso_provider_url: "https://$localip:3002"
   workbench_address: "http://$localip/"
   sso_insecure: true
+development:
+  uuid_prefix: $uuid_prefix
   auto_admin_first_user: true
+  blob_signing_key: $blob_signing_key
   git_repo_ssh_base: "git@$localip:"
   git_repo_https_base: "http://$localip:9001/"
-development:
-  uuid_prefix: $uuid_prefix
 test:
   uuid_prefix: zzzzz
   git_repo_ssh_base: "git at git.zzzzz.arvadosapi.com:"

commit 0accddbffff3a0e438c2a418ba2f82522e882f30
Author: Tom Clegg <tom at curoverse.com>
Date:   Wed Jan 6 18:49:28 2016 -0500

    8080: Add fuse group, needed by services/login-sync tests.

diff --git a/arvbox/lib/arvbox/docker/Dockerfile b/arvbox/lib/arvbox/docker/Dockerfile
index 22ad5d2..0fc0247 100644
--- a/arvbox/lib/arvbox/docker/Dockerfile
+++ b/arvbox/lib/arvbox/docker/Dockerfile
@@ -29,6 +29,7 @@ RUN cd /root/runit-docker && \
 ENV LD_PRELOAD /lib/runit-docker.so
 
 ADD fuse.conf /etc/
+RUN addgroup --gid 888 fuse
 
 ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
 ADD service /etc/service

commit f794ddd776cc76fcfa918d78c94287158be3866e
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Jan 6 12:10:44 2016 -0500

    8080: Check container state before stop/rm

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index a7cc884..8e01457 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -90,9 +90,11 @@ run() {
 }
 
 stop() {
-    if docker ps -a |grep -E "\b$ARVBOX_CONTAINER\b" -q ; then
+    if docker ps -a --filter "status=running" |grep -E "$ARVBOX_CONTAINER$" -q ; then
         docker stop $ARVBOX_CONTAINER
-        docker rm -v $ARVBOX_CONTAINER
+    fi
+    if docker ps -a --filter "status=exited" |grep -E "$ARVBOX_CONTAINER$" -q ; then
+        docker rm --volumes=true $ARVBOX_CONTAINER
     fi
 }
 

commit f82f8be7ab3c1cde23f629cdff5cf71205483d04
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 16:16:58 2016 -0500

    8080: Fix greadlink test

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index 62bae22..a7cc884 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -3,7 +3,7 @@
 set -e
 
 if test -z "$ARVBOX_DOCKER" ; then
-    if $(which greadlink) >/dev/null ; then
+    if which greadlink >/dev/null ; then
         ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
     else
         ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)

commit c6a7ecdcb77ae6808a62e42b8e42fdc8d9af52ad
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 16:03:39 2016 -0500

    8080: Touch api_user_setup

diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index da2dc16..56988fe 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -55,9 +55,10 @@ if ! test -f /var/lib/arvados/api_database_pw ; then
 fi
 database_pw=$(cat /var/lib/arvados/api_database_pw)
 
-if ! test -f /var/lib/arvados/api_database_setup ; then
+if ! test -f /var/lib/arvados/api_user_setup ; then
    psql -c "create user arvados with password '$database_pw'"
    psql -c "ALTER USER arvados CREATEDB;"
+   touch /var/lib/arvados/api_user_setup
 fi
 
 cat >config/database.yml <<EOF

commit 859f5ca6abf7198d2fa3c51f16ecd372cd30fc69
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 14:13:02 2016 -0500

    8080: Change git repo https base for testing.

diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 78e709c..da2dc16 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -47,6 +47,7 @@ development:
 test:
   uuid_prefix: zzzzz
   git_repo_ssh_base: "git at git.zzzzz.arvadosapi.com:"
+  git_repo_https_base: "http://git.zzzzz.arvadosapi.com/"
 EOF
 
 if ! test -f /var/lib/arvados/api_database_pw ; then

commit 589d24cf1dde32ecdd2ccdc003bee7af809ed976
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 14:07:41 2016 -0500

    8080: Add back in passenger binary caching.  Separate "reset" and "destroy"
    commands.  Add "clone".

diff --git a/arvbox/bin/arvbox b/arvbox/bin/arvbox
index ff93ac7..62bae22 100755
--- a/arvbox/bin/arvbox
+++ b/arvbox/bin/arvbox
@@ -32,9 +32,10 @@ fi
 
 PG_DATA=$ARVBOX_DATA/postgres
 VAR_DATA=$ARVBOX_DATA/var
+PASSENGER=$ARVBOX_DATA/passenger
 GEMS=$ARVBOX_DATA/gems
 
-mkdir -p $PG_DATA $VAR_DATA $GEMS
+mkdir -p $PG_DATA $VAR_DATA $PASSENGER $GEMS
 
 run() {
     if ! test -d $ARVADOS_ROOT ; then
@@ -54,6 +55,7 @@ run() {
                --volume=$SSO_ROOT:/usr/src/sso:rw \
                --volume=$PG_DATA:/var/lib/postgresql:rw \
                --volume=$VAR_DATA:/var/lib/arvados:rw \
+               --volume=$PASSENGER:/var/lib/passenger:rw \
                --volume=$GEMS:/var/lib/gems:rw \
                --volume=/var/lib/docker \
                arvados/arvbox \
@@ -67,6 +69,7 @@ run() {
                --volume=$SSO_ROOT:/usr/src/sso:rw \
                --volume=$PG_DATA:/var/lib/postgresql:rw \
                --volume=$VAR_DATA:/var/lib/arvados:rw \
+               --volume=$PASSENGER:/var/lib/passenger:rw \
                --volume=$GEMS:/var/lib/gems:rw \
                --volume=/var/lib/docker \
                arvados/arvbox
@@ -122,7 +125,7 @@ case $1 in
         ;;
 
     ip|open)
-        IP=$(docker inspect arvbox | grep \"IPAddress\" | tr -d ' ":,\n' | cut -c10-)
+        IP=$(docker inspect $ARVBOX_CONTAINER | grep \"IPAddress\" | tr -d ' ":,\n' | cut -c10-)
         if test $1 = 'ip' ; then
             echo $IP
         else
@@ -132,7 +135,17 @@ case $1 in
 
     reset)
         if test "$2" != -f ; then
-            echo "WARNING!  This will delete all code and data inside your arvbox ($ARVBOX_DATA).  Use reset -f if you really mean it."
+            echo "WARNING!  This will delete your database, git and keep files inside your arvbox ($ARVBOX_DATA).  Use reset -f if you really mean it."
+            exit 1
+        fi
+        stop
+        rm -rf $ARVBOX_DATA/postgres
+        rm -rf $ARVBOX_DATA/var
+        ;;
+
+    destroy)
+        if test "$2" != -f ; then
+            echo "WARNING!  This will delete all code and data inside your arvbox ($ARVBOX_DATA).  Use destroy -f if you really mean it."
             exit 1
         fi
         stop
@@ -179,10 +192,20 @@ case $1 in
                "$@"
         ;;
 
+    clone)
+        if test -n "$3" ; then
+            cp -r $HOME/.arvbox/$2 $HOME/.arvbox/$3
+            echo "Created new arvbox $3"
+            echo "export ARVBOX_CONTAINER=$3"
+        else
+            echo "clone <from> <to>   clone an arvbox"
+        fi
+        ;;
+
     *)
         echo "Arvados-in-a-box"
         echo
-        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|run-tests|log|svrestart)"
+        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|destroy|run-tests|log|svrestart)"
         echo
         echo "build      build arvbox Docker image"
         echo "start|run  start $ARVBOX_CONTAINER container "
@@ -192,9 +215,11 @@ case $1 in
         echo "stop       stop arvbox container"
         echo "restart    stop, then run again"
         echo "reboot     stop, build arvbox Docker image, run"
-        echo "reset      delete all persistent data (be careful!)"
+        echo "reset      delete arvbox arvados data (be careful!)"
+        echo "destroy    delete all arvbox code and data (be careful!)"
         echo "run-tests  run run-tests.sh inside $ARVBOX_CONTAINER container"
         echo "log       <service> tail log of specified service"
         echo "svrestart <service> restart specified service inside arvbox"
+        echo "clone <from> <to>   clone an arvbox"
         ;;
 esac
diff --git a/arvbox/lib/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
index 5bd8621..78e709c 100755
--- a/arvbox/lib/arvbox/docker/service/api/run-service
+++ b/arvbox/lib/arvbox/docker/service/api/run-service
@@ -91,4 +91,7 @@ rm -rf tmp
 
 bundle exec rake db:migrate
 
-ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start -p3001 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
+ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start --port=3001 \
+                  --runtime-dir=/var/lib/passenger \
+                  --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
+                  --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/lib/arvbox/docker/service/sso/run-service b/arvbox/lib/arvbox/docker/service/sso/run-service
index 085b79a..ac19760 100755
--- a/arvbox/lib/arvbox/docker/service/sso/run-service
+++ b/arvbox/lib/arvbox/docker/service/sso/run-service
@@ -38,9 +38,10 @@ if ! test -f /var/lib/arvados/sso_database_pw ; then
 fi
 database_pw=$(cat /var/lib/arvados/sso_database_pw)
 
-if ! test -f /var/lib/arvados/sso_database_setup ; then
+if ! test -f /var/lib/arvados/sso_user_setup ; then
     psql -c "create user arvados_sso with password '$database_pw'"
     psql -c "ALTER USER arvados_sso CREATEDB;"
+    touch /var/lib/arvados/sso_user_setup
 fi
 
 cat >config/database.yml <<EOF
@@ -85,4 +86,7 @@ rm -rf tmp
 
 bundle exec rake db:migrate
 export HOME=/var/lib/passenger
-exec bundle exec passenger start -p3002 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
+exec bundle exec passenger start --port=3002 \
+     --runtime-dir=/var/lib/passenger \
+     --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem \
+     --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run b/arvbox/lib/arvbox/docker/service/workbench/run
index 7838220..665d848 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run
+++ b/arvbox/lib/arvbox/docker/service/workbench/run
@@ -9,4 +9,5 @@ rm -rf tmp
 mkdir tmp
 chown arvbox:arvbox tmp
 
-exec bundle exec passenger start --port 80 --user arvbox
+exec bundle exec passenger start --port 80 \
+     --user arvbox --runtime-dir=/var/lib/passenger
diff --git a/arvbox/lib/arvbox/docker/service/workbench/run-service b/arvbox/lib/arvbox/docker/service/workbench/run-service
index 09f929f..359f1e9 100755
--- a/arvbox/lib/arvbox/docker/service/workbench/run-service
+++ b/arvbox/lib/arvbox/docker/service/workbench/run-service
@@ -33,4 +33,4 @@ EOF
 
 #bundle exec passenger start -p443 --ssl --ssl-certificate=self-signed.pem --ssl-certificate-key=self-signed.key
 
-bundle exec passenger start --runtime-check-only
+bundle exec passenger start --runtime-check-only --runtime-dir=/var/lib/passenger

commit 0d421679b68f9916b83393f0bb2ef777c1b42d2d
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 13:28:42 2016 -0500

    8080: Workaround for weird nginx permission problem on /var/log/nginx.

diff --git a/arvbox/lib/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
index eda4161..ec02811 100755
--- a/arvbox/lib/arvbox/docker/createusers.sh
+++ b/arvbox/lib/arvbox/docker/createusers.sh
@@ -15,4 +15,8 @@ if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
     useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
     useradd --groups docker crunch
     chown arvbox:arvbox -R /usr/local
+    chown arvbox:arvbox -R /var/lib/nginx
+    rm -r /var/log/nginx
+    mkdir -p /var/log/nginx
+    chown arvbox:arvbox -R /var/log/nginx
 fi

commit 88b19c236a525a8e1532f967674580282319f58e
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 13:03:42 2016 -0500

    8080: Rearrange directory structure to be more suitable for packaging.

diff --git a/arvbox/arvbox b/arvbox/bin/arvbox
similarity index 93%
rename from arvbox/arvbox
rename to arvbox/bin/arvbox
index 596d20b..ff93ac7 100755
--- a/arvbox/arvbox
+++ b/arvbox/bin/arvbox
@@ -2,7 +2,13 @@
 
 set -e
 
-ARVBOX_SCRIPT=$(readlink -f $(dirname $0))
+if test -z "$ARVBOX_DOCKER" ; then
+    if $(which greadlink) >/dev/null ; then
+        ARVBOX_DOCKER=$(greadlink -f $(dirname $0)/../lib/arvbox/docker)
+    else
+        ARVBOX_DOCKER=$(readlink -f $(dirname $0)/../lib/arvbox/docker)
+    fi
+fi
 
 if test -z "$ARVBOX_CONTAINER" ; then
     ARVBOX_CONTAINER=arvbox
@@ -89,8 +95,7 @@ stop() {
 
 case $1 in
     build)
-        cd $ARVBOX_SCRIPT
-        docker build -t arvados/arvbox docker
+        docker build -t arvados/arvbox $ARVBOX_DOCKER
         ;;
 
     start|run)
@@ -112,8 +117,7 @@ case $1 in
 
     reboot)
         stop
-        cd $ARVBOX_SCRIPT
-        docker build -t arvados/arvbox docker
+        docker build -t arvados/arvbox $ARVBOX_DOCKER
         run
         ;;
 
diff --git a/arvbox/docker/Dockerfile b/arvbox/lib/arvbox/docker/Dockerfile
similarity index 100%
rename from arvbox/docker/Dockerfile
rename to arvbox/lib/arvbox/docker/Dockerfile
diff --git a/arvbox/docker/common.sh b/arvbox/lib/arvbox/docker/common.sh
similarity index 100%
rename from arvbox/docker/common.sh
rename to arvbox/lib/arvbox/docker/common.sh
diff --git a/arvbox/docker/createusers.sh b/arvbox/lib/arvbox/docker/createusers.sh
similarity index 100%
rename from arvbox/docker/createusers.sh
rename to arvbox/lib/arvbox/docker/createusers.sh
diff --git a/arvbox/docker/crunch-setup.sh b/arvbox/lib/arvbox/docker/crunch-setup.sh
similarity index 100%
rename from arvbox/docker/crunch-setup.sh
rename to arvbox/lib/arvbox/docker/crunch-setup.sh
diff --git a/arvbox/docker/fuse.conf b/arvbox/lib/arvbox/docker/fuse.conf
similarity index 100%
rename from arvbox/docker/fuse.conf
rename to arvbox/lib/arvbox/docker/fuse.conf
diff --git a/arvbox/docker/gitolite-setup.sh b/arvbox/lib/arvbox/docker/gitolite-setup.sh
similarity index 100%
rename from arvbox/docker/gitolite-setup.sh
rename to arvbox/lib/arvbox/docker/gitolite-setup.sh
diff --git a/arvbox/docker/gitolite.rc b/arvbox/lib/arvbox/docker/gitolite.rc
similarity index 100%
rename from arvbox/docker/gitolite.rc
rename to arvbox/lib/arvbox/docker/gitolite.rc
diff --git a/arvbox/docker/gitssh-setup.sh b/arvbox/lib/arvbox/docker/gitssh-setup.sh
similarity index 100%
rename from arvbox/docker/gitssh-setup.sh
rename to arvbox/lib/arvbox/docker/gitssh-setup.sh
diff --git a/arvbox/docker/keep-setup.sh b/arvbox/lib/arvbox/docker/keep-setup.sh
similarity index 100%
rename from arvbox/docker/keep-setup.sh
rename to arvbox/lib/arvbox/docker/keep-setup.sh
diff --git a/arvbox/docker/runit-docker/.gitignore b/arvbox/lib/arvbox/docker/runit-docker/.gitignore
similarity index 100%
rename from arvbox/docker/runit-docker/.gitignore
rename to arvbox/lib/arvbox/docker/runit-docker/.gitignore
diff --git a/arvbox/docker/runit-docker/LICENSE b/arvbox/lib/arvbox/docker/runit-docker/LICENSE
similarity index 100%
rename from arvbox/docker/runit-docker/LICENSE
rename to arvbox/lib/arvbox/docker/runit-docker/LICENSE
diff --git a/arvbox/docker/runit-docker/Makefile b/arvbox/lib/arvbox/docker/runit-docker/Makefile
similarity index 100%
rename from arvbox/docker/runit-docker/Makefile
rename to arvbox/lib/arvbox/docker/runit-docker/Makefile
diff --git a/arvbox/docker/runit-docker/README.md b/arvbox/lib/arvbox/docker/runit-docker/README.md
similarity index 100%
rename from arvbox/docker/runit-docker/README.md
rename to arvbox/lib/arvbox/docker/runit-docker/README.md
diff --git a/arvbox/docker/runit-docker/debian/changelog b/arvbox/lib/arvbox/docker/runit-docker/debian/changelog
similarity index 100%
rename from arvbox/docker/runit-docker/debian/changelog
rename to arvbox/lib/arvbox/docker/runit-docker/debian/changelog
diff --git a/arvbox/docker/runit-docker/debian/compat b/arvbox/lib/arvbox/docker/runit-docker/debian/compat
similarity index 100%
rename from arvbox/docker/runit-docker/debian/compat
rename to arvbox/lib/arvbox/docker/runit-docker/debian/compat
diff --git a/arvbox/docker/runit-docker/debian/control b/arvbox/lib/arvbox/docker/runit-docker/debian/control
similarity index 100%
rename from arvbox/docker/runit-docker/debian/control
rename to arvbox/lib/arvbox/docker/runit-docker/debian/control
diff --git a/arvbox/docker/runit-docker/debian/copyright b/arvbox/lib/arvbox/docker/runit-docker/debian/copyright
similarity index 100%
rename from arvbox/docker/runit-docker/debian/copyright
rename to arvbox/lib/arvbox/docker/runit-docker/debian/copyright
diff --git a/arvbox/docker/runit-docker/debian/docs b/arvbox/lib/arvbox/docker/runit-docker/debian/docs
similarity index 100%
rename from arvbox/docker/runit-docker/debian/docs
rename to arvbox/lib/arvbox/docker/runit-docker/debian/docs
diff --git a/arvbox/docker/runit-docker/debian/rules b/arvbox/lib/arvbox/docker/runit-docker/debian/rules
similarity index 100%
rename from arvbox/docker/runit-docker/debian/rules
rename to arvbox/lib/arvbox/docker/runit-docker/debian/rules
diff --git a/arvbox/docker/runit-docker/debian/source/format b/arvbox/lib/arvbox/docker/runit-docker/debian/source/format
similarity index 100%
rename from arvbox/docker/runit-docker/debian/source/format
rename to arvbox/lib/arvbox/docker/runit-docker/debian/source/format
diff --git a/arvbox/docker/runit-docker/runit-docker b/arvbox/lib/arvbox/docker/runit-docker/runit-docker
similarity index 100%
rename from arvbox/docker/runit-docker/runit-docker
rename to arvbox/lib/arvbox/docker/runit-docker/runit-docker
diff --git a/arvbox/docker/runit-docker/runit-docker.c b/arvbox/lib/arvbox/docker/runit-docker/runit-docker.c
similarity index 100%
rename from arvbox/docker/runit-docker/runit-docker.c
rename to arvbox/lib/arvbox/docker/runit-docker/runit-docker.c
diff --git a/arvbox/docker/service/workbench/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/api/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/workbench/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/api/log/main/.gitstub
diff --git a/arvbox/docker/service/workbench/log/run b/arvbox/lib/arvbox/docker/service/api/log/run
similarity index 100%
rename from arvbox/docker/service/workbench/log/run
rename to arvbox/lib/arvbox/docker/service/api/log/run
diff --git a/arvbox/docker/service/vm/run b/arvbox/lib/arvbox/docker/service/api/run
similarity index 100%
rename from arvbox/docker/service/vm/run
rename to arvbox/lib/arvbox/docker/service/api/run
diff --git a/arvbox/docker/service/api/run-service b/arvbox/lib/arvbox/docker/service/api/run-service
similarity index 100%
rename from arvbox/docker/service/api/run-service
rename to arvbox/lib/arvbox/docker/service/api/run-service
diff --git a/arvbox/docker/service/vm/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/crunch0/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/vm/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/crunch0/log/main/.gitstub
diff --git a/arvbox/docker/service/vm/log/run b/arvbox/lib/arvbox/docker/service/crunch0/log/run
similarity index 100%
rename from arvbox/docker/service/vm/log/run
rename to arvbox/lib/arvbox/docker/service/crunch0/log/run
diff --git a/arvbox/docker/service/sso/run b/arvbox/lib/arvbox/docker/service/crunch0/run
similarity index 100%
rename from arvbox/docker/service/sso/run
rename to arvbox/lib/arvbox/docker/service/crunch0/run
diff --git a/arvbox/docker/service/crunch0/run-service b/arvbox/lib/arvbox/docker/service/crunch0/run-service
similarity index 100%
rename from arvbox/docker/service/crunch0/run-service
rename to arvbox/lib/arvbox/docker/service/crunch0/run-service
diff --git a/arvbox/docker/service/sso/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/crunch1/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/sso/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/crunch1/log/main/.gitstub
diff --git a/arvbox/docker/service/sso/log/run b/arvbox/lib/arvbox/docker/service/crunch1/log/run
similarity index 100%
rename from arvbox/docker/service/sso/log/run
rename to arvbox/lib/arvbox/docker/service/crunch1/log/run
diff --git a/arvbox/docker/service/ready/run b/arvbox/lib/arvbox/docker/service/crunch1/run
similarity index 100%
rename from arvbox/docker/service/ready/run
rename to arvbox/lib/arvbox/docker/service/crunch1/run
diff --git a/arvbox/docker/service/crunch1/run-service b/arvbox/lib/arvbox/docker/service/crunch1/run-service
similarity index 100%
rename from arvbox/docker/service/crunch1/run-service
rename to arvbox/lib/arvbox/docker/service/crunch1/run-service
diff --git a/arvbox/docker/service/ssh/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/doc/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/ssh/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/doc/log/main/.gitstub
diff --git a/arvbox/docker/service/ssh/log/run b/arvbox/lib/arvbox/docker/service/doc/log/run
similarity index 100%
rename from arvbox/docker/service/ssh/log/run
rename to arvbox/lib/arvbox/docker/service/doc/log/run
diff --git a/arvbox/docker/service/keepweb/run b/arvbox/lib/arvbox/docker/service/doc/run
similarity index 100%
rename from arvbox/docker/service/keepweb/run
rename to arvbox/lib/arvbox/docker/service/doc/run
diff --git a/arvbox/docker/service/doc/run-service b/arvbox/lib/arvbox/docker/service/doc/run-service
similarity index 100%
rename from arvbox/docker/service/doc/run-service
rename to arvbox/lib/arvbox/docker/service/doc/run-service
diff --git a/arvbox/docker/service/sdk/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/docker/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/sdk/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/docker/log/main/.gitstub
diff --git a/arvbox/docker/service/sdk/log/run b/arvbox/lib/arvbox/docker/service/docker/log/run
similarity index 100%
rename from arvbox/docker/service/sdk/log/run
rename to arvbox/lib/arvbox/docker/service/docker/log/run
diff --git a/arvbox/docker/service/docker/run b/arvbox/lib/arvbox/docker/service/docker/run
similarity index 100%
rename from arvbox/docker/service/docker/run
rename to arvbox/lib/arvbox/docker/service/docker/run
diff --git a/arvbox/docker/service/postgres/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/git/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/postgres/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/git/log/main/.gitstub
diff --git a/arvbox/docker/service/postgres/log/run b/arvbox/lib/arvbox/docker/service/git/log/run
similarity index 100%
rename from arvbox/docker/service/postgres/log/run
rename to arvbox/lib/arvbox/docker/service/git/log/run
diff --git a/arvbox/docker/service/keepproxy/run b/arvbox/lib/arvbox/docker/service/git/run
similarity index 100%
rename from arvbox/docker/service/keepproxy/run
rename to arvbox/lib/arvbox/docker/service/git/run
diff --git a/arvbox/docker/service/git/run-service b/arvbox/lib/arvbox/docker/service/git/run-service
similarity index 100%
rename from arvbox/docker/service/git/run-service
rename to arvbox/lib/arvbox/docker/service/git/run-service
diff --git a/arvbox/docker/service/keepweb/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/githttp/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/keepweb/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/githttp/log/main/.gitstub
diff --git a/arvbox/docker/service/keepweb/log/run b/arvbox/lib/arvbox/docker/service/githttp/log/run
similarity index 100%
rename from arvbox/docker/service/keepweb/log/run
rename to arvbox/lib/arvbox/docker/service/githttp/log/run
diff --git a/arvbox/docker/service/keep1/run b/arvbox/lib/arvbox/docker/service/githttp/run
similarity index 100%
rename from arvbox/docker/service/keep1/run
rename to arvbox/lib/arvbox/docker/service/githttp/run
diff --git a/arvbox/docker/service/githttp/run-service b/arvbox/lib/arvbox/docker/service/githttp/run-service
similarity index 100%
rename from arvbox/docker/service/githttp/run-service
rename to arvbox/lib/arvbox/docker/service/githttp/run-service
diff --git a/arvbox/docker/service/keepproxy/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keep0/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/keepproxy/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keep0/log/main/.gitstub
diff --git a/arvbox/docker/service/keepproxy/log/run b/arvbox/lib/arvbox/docker/service/keep0/log/run
similarity index 100%
rename from arvbox/docker/service/keepproxy/log/run
rename to arvbox/lib/arvbox/docker/service/keep0/log/run
diff --git a/arvbox/docker/service/keep0/run b/arvbox/lib/arvbox/docker/service/keep0/run
similarity index 100%
rename from arvbox/docker/service/keep0/run
rename to arvbox/lib/arvbox/docker/service/keep0/run
diff --git a/arvbox/docker/service/keep0/run-service b/arvbox/lib/arvbox/docker/service/keep0/run-service
similarity index 100%
rename from arvbox/docker/service/keep0/run-service
rename to arvbox/lib/arvbox/docker/service/keep0/run-service
diff --git a/arvbox/docker/service/keep1/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keep1/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/keep1/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keep1/log/main/.gitstub
diff --git a/arvbox/docker/service/keep1/log/run b/arvbox/lib/arvbox/docker/service/keep1/log/run
similarity index 100%
rename from arvbox/docker/service/keep1/log/run
rename to arvbox/lib/arvbox/docker/service/keep1/log/run
diff --git a/arvbox/docker/service/githttp/run b/arvbox/lib/arvbox/docker/service/keep1/run
similarity index 100%
rename from arvbox/docker/service/githttp/run
rename to arvbox/lib/arvbox/docker/service/keep1/run
diff --git a/arvbox/docker/service/keep1/run-service b/arvbox/lib/arvbox/docker/service/keep1/run-service
similarity index 100%
rename from arvbox/docker/service/keep1/run-service
rename to arvbox/lib/arvbox/docker/service/keep1/run-service
diff --git a/arvbox/docker/service/keep0/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keepproxy/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/keep0/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keepproxy/log/main/.gitstub
diff --git a/arvbox/docker/service/keep0/log/run b/arvbox/lib/arvbox/docker/service/keepproxy/log/run
similarity index 100%
rename from arvbox/docker/service/keep0/log/run
rename to arvbox/lib/arvbox/docker/service/keepproxy/log/run
diff --git a/arvbox/docker/service/git/run b/arvbox/lib/arvbox/docker/service/keepproxy/run
similarity index 100%
rename from arvbox/docker/service/git/run
rename to arvbox/lib/arvbox/docker/service/keepproxy/run
diff --git a/arvbox/docker/service/keepproxy/run-service b/arvbox/lib/arvbox/docker/service/keepproxy/run-service
similarity index 100%
rename from arvbox/docker/service/keepproxy/run-service
rename to arvbox/lib/arvbox/docker/service/keepproxy/run-service
diff --git a/arvbox/docker/service/githttp/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/keepweb/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/githttp/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/keepweb/log/main/.gitstub
diff --git a/arvbox/docker/service/githttp/log/run b/arvbox/lib/arvbox/docker/service/keepweb/log/run
similarity index 100%
rename from arvbox/docker/service/githttp/log/run
rename to arvbox/lib/arvbox/docker/service/keepweb/log/run
diff --git a/arvbox/docker/service/doc/run b/arvbox/lib/arvbox/docker/service/keepweb/run
similarity index 100%
rename from arvbox/docker/service/doc/run
rename to arvbox/lib/arvbox/docker/service/keepweb/run
diff --git a/arvbox/docker/service/keepweb/run-service b/arvbox/lib/arvbox/docker/service/keepweb/run-service
similarity index 100%
rename from arvbox/docker/service/keepweb/run-service
rename to arvbox/lib/arvbox/docker/service/keepweb/run-service
diff --git a/arvbox/docker/service/logger b/arvbox/lib/arvbox/docker/service/logger
similarity index 100%
rename from arvbox/docker/service/logger
rename to arvbox/lib/arvbox/docker/service/logger
diff --git a/arvbox/docker/service/git/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/postgres/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/git/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/postgres/log/main/.gitstub
diff --git a/arvbox/docker/service/git/log/run b/arvbox/lib/arvbox/docker/service/postgres/log/run
similarity index 100%
rename from arvbox/docker/service/git/log/run
rename to arvbox/lib/arvbox/docker/service/postgres/log/run
diff --git a/arvbox/docker/service/postgres/run b/arvbox/lib/arvbox/docker/service/postgres/run
similarity index 100%
rename from arvbox/docker/service/postgres/run
rename to arvbox/lib/arvbox/docker/service/postgres/run
diff --git a/arvbox/docker/service/postgres/run-service b/arvbox/lib/arvbox/docker/service/postgres/run-service
similarity index 100%
rename from arvbox/docker/service/postgres/run-service
rename to arvbox/lib/arvbox/docker/service/postgres/run-service
diff --git a/arvbox/docker/service/crunch1/run b/arvbox/lib/arvbox/docker/service/ready/run
similarity index 100%
rename from arvbox/docker/service/crunch1/run
rename to arvbox/lib/arvbox/docker/service/ready/run
diff --git a/arvbox/docker/service/ready/run-service b/arvbox/lib/arvbox/docker/service/ready/run-service
similarity index 100%
rename from arvbox/docker/service/ready/run-service
rename to arvbox/lib/arvbox/docker/service/ready/run-service
diff --git a/arvbox/docker/service/runsu.sh b/arvbox/lib/arvbox/docker/service/runsu.sh
similarity index 100%
rename from arvbox/docker/service/runsu.sh
rename to arvbox/lib/arvbox/docker/service/runsu.sh
diff --git a/arvbox/docker/service/docker/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/sdk/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/docker/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/sdk/log/main/.gitstub
diff --git a/arvbox/docker/service/docker/log/run b/arvbox/lib/arvbox/docker/service/sdk/log/run
similarity index 100%
rename from arvbox/docker/service/docker/log/run
rename to arvbox/lib/arvbox/docker/service/sdk/log/run
diff --git a/arvbox/docker/service/sdk/run b/arvbox/lib/arvbox/docker/service/sdk/run
similarity index 100%
rename from arvbox/docker/service/sdk/run
rename to arvbox/lib/arvbox/docker/service/sdk/run
diff --git a/arvbox/docker/service/sdk/run-service b/arvbox/lib/arvbox/docker/service/sdk/run-service
similarity index 100%
rename from arvbox/docker/service/sdk/run-service
rename to arvbox/lib/arvbox/docker/service/sdk/run-service
diff --git a/arvbox/docker/service/doc/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/ssh/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/doc/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/ssh/log/main/.gitstub
diff --git a/arvbox/docker/service/doc/log/run b/arvbox/lib/arvbox/docker/service/ssh/log/run
similarity index 100%
rename from arvbox/docker/service/doc/log/run
rename to arvbox/lib/arvbox/docker/service/ssh/log/run
diff --git a/arvbox/docker/service/ssh/run b/arvbox/lib/arvbox/docker/service/ssh/run
similarity index 100%
rename from arvbox/docker/service/ssh/run
rename to arvbox/lib/arvbox/docker/service/ssh/run
diff --git a/arvbox/docker/service/crunch1/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/sso/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/crunch1/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/sso/log/main/.gitstub
diff --git a/arvbox/docker/service/crunch1/log/run b/arvbox/lib/arvbox/docker/service/sso/log/run
similarity index 100%
rename from arvbox/docker/service/crunch1/log/run
rename to arvbox/lib/arvbox/docker/service/sso/log/run
diff --git a/arvbox/docker/service/crunch0/run b/arvbox/lib/arvbox/docker/service/sso/run
similarity index 100%
rename from arvbox/docker/service/crunch0/run
rename to arvbox/lib/arvbox/docker/service/sso/run
diff --git a/arvbox/docker/service/sso/run-service b/arvbox/lib/arvbox/docker/service/sso/run-service
similarity index 100%
rename from arvbox/docker/service/sso/run-service
rename to arvbox/lib/arvbox/docker/service/sso/run-service
diff --git a/arvbox/docker/service/crunch0/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/vm/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/crunch0/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/vm/log/main/.gitstub
diff --git a/arvbox/docker/service/crunch0/log/run b/arvbox/lib/arvbox/docker/service/vm/log/run
similarity index 100%
rename from arvbox/docker/service/crunch0/log/run
rename to arvbox/lib/arvbox/docker/service/vm/log/run
diff --git a/arvbox/docker/service/api/run b/arvbox/lib/arvbox/docker/service/vm/run
similarity index 100%
rename from arvbox/docker/service/api/run
rename to arvbox/lib/arvbox/docker/service/vm/run
diff --git a/arvbox/docker/service/vm/run-service b/arvbox/lib/arvbox/docker/service/vm/run-service
similarity index 100%
rename from arvbox/docker/service/vm/run-service
rename to arvbox/lib/arvbox/docker/service/vm/run-service
diff --git a/arvbox/docker/service/api/log/main/.gitstub b/arvbox/lib/arvbox/docker/service/workbench/log/main/.gitstub
similarity index 100%
rename from arvbox/docker/service/api/log/main/.gitstub
rename to arvbox/lib/arvbox/docker/service/workbench/log/main/.gitstub
diff --git a/arvbox/docker/service/api/log/run b/arvbox/lib/arvbox/docker/service/workbench/log/run
similarity index 100%
rename from arvbox/docker/service/api/log/run
rename to arvbox/lib/arvbox/docker/service/workbench/log/run
diff --git a/arvbox/docker/service/workbench/run b/arvbox/lib/arvbox/docker/service/workbench/run
similarity index 100%
rename from arvbox/docker/service/workbench/run
rename to arvbox/lib/arvbox/docker/service/workbench/run
diff --git a/arvbox/docker/service/workbench/run-service b/arvbox/lib/arvbox/docker/service/workbench/run-service
similarity index 100%
rename from arvbox/docker/service/workbench/run-service
rename to arvbox/lib/arvbox/docker/service/workbench/run-service
diff --git a/arvbox/docker/tests-service/docker b/arvbox/lib/arvbox/docker/tests-service/docker
similarity index 100%
rename from arvbox/docker/tests-service/docker
rename to arvbox/lib/arvbox/docker/tests-service/docker
diff --git a/arvbox/docker/tests-service/logger b/arvbox/lib/arvbox/docker/tests-service/logger
similarity index 100%
rename from arvbox/docker/tests-service/logger
rename to arvbox/lib/arvbox/docker/tests-service/logger
diff --git a/arvbox/docker/tests-service/postgres b/arvbox/lib/arvbox/docker/tests-service/postgres
similarity index 100%
rename from arvbox/docker/tests-service/postgres
rename to arvbox/lib/arvbox/docker/tests-service/postgres
diff --git a/arvbox/docker/tests-service/runsu.sh b/arvbox/lib/arvbox/docker/tests-service/runsu.sh
similarity index 100%
rename from arvbox/docker/tests-service/runsu.sh
rename to arvbox/lib/arvbox/docker/tests-service/runsu.sh

commit 9b59c468d0776e6a7c35b19ed5d0b8f877572c7c
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Jan 5 12:04:01 2016 -0500

    8080: Now runs most services as regular use instead of root.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index f6e95cb..596d20b 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -24,12 +24,11 @@ if test -z "$SSO_ROOT" ; then
     SSO_ROOT=$ARVBOX_DATA/sso-devise-omniauth-provider
 fi
 
-PASSENGER=$ARVBOX_DATA/passenger
 PG_DATA=$ARVBOX_DATA/postgres
 VAR_DATA=$ARVBOX_DATA/var
 GEMS=$ARVBOX_DATA/gems
 
-mkdir -p $PASSENGER $PG_DATA $VAR_DATA $GEMS
+mkdir -p $PG_DATA $VAR_DATA $GEMS
 
 run() {
     if ! test -d $ARVADOS_ROOT ; then
@@ -49,7 +48,6 @@ run() {
                --volume=$SSO_ROOT:/usr/src/sso:rw \
                --volume=$PG_DATA:/var/lib/postgresql:rw \
                --volume=$VAR_DATA:/var/lib/arvados:rw \
-               --volume=$PASSENGER:/var/lib/passenger:rw \
                --volume=$GEMS:/var/lib/gems:rw \
                --volume=/var/lib/docker \
                arvados/arvbox \
@@ -63,7 +61,6 @@ run() {
                --volume=$SSO_ROOT:/usr/src/sso:rw \
                --volume=$PG_DATA:/var/lib/postgresql:rw \
                --volume=$VAR_DATA:/var/lib/arvados:rw \
-               --volume=$PASSENGER:/var/lib/passenger:rw \
                --volume=$GEMS:/var/lib/gems:rw \
                --volume=/var/lib/docker \
                arvados/arvbox
@@ -86,7 +83,7 @@ run() {
 stop() {
     if docker ps -a |grep -E "\b$ARVBOX_CONTAINER\b" -q ; then
         docker stop $ARVBOX_CONTAINER
-        docker rm $ARVBOX_CONTAINER
+        docker rm -v $ARVBOX_CONTAINER
     fi
 }
 
@@ -135,13 +132,13 @@ case $1 in
             exit 1
         fi
         stop
-        sudo rm -rf $ARVBOX_DATA
+        rm -rf $ARVBOX_DATA
         ;;
 
     log|svrestart)
         if test -n "$2" ; then
             if test "$1" = log ; then
-                docker exec -ti $ARVBOX_CONTAINER tail -n40 /etc/service/$2/log/main/current
+                docker exec -ti $ARVBOX_CONTAINER tail -n100 /etc/service/$2/log/main/current
             fi
             if test "$1" = svrestart ; then
                 docker exec -ti $ARVBOX_CONTAINER sv restart $2
@@ -164,14 +161,17 @@ case $1 in
         run testing
 
         shift
-        docker exec -ti $ARVBOX_CONTAINER /usr/src/arvados-dev/jenkins/run-tests.sh \
+        docker exec -ti \
+               $ARVBOX_CONTAINER \
+               /etc/tests-service/runsu.sh \
+               /usr/src/arvados-dev/jenkins/run-tests.sh \
                --leave-temp \
                WORKSPACE=/usr/src/arvados \
                VENVDIR=/var/lib/arvados/tests-venv \
                VENV3DIR=/var/lib/arvados/tests-venv3 \
                GOPATH=/var/lib/arvados/tests-gostuff \
-               GEMHOME=/var/lib/gems \
-               GEM_HOME=/var/lib/gems \
+               GEMHOME=/var/lib/gems/ruby/2.1.0 \
+               GEM_HOME=/var/lib/gems/ruby/2.1.0 \
                "$@"
         ;;
 
diff --git a/arvbox/docker/Dockerfile b/arvbox/docker/Dockerfile
index a9c3321..22ad5d2 100644
--- a/arvbox/docker/Dockerfile
+++ b/arvbox/docker/Dockerfile
@@ -29,12 +29,8 @@ RUN cd /root/runit-docker && \
 ENV LD_PRELOAD /lib/runit-docker.so
 
 ADD fuse.conf /etc/
-RUN useradd crunch && \
-    addgroup crunch docker && \
-    mkdir -p /var/lib/arvados/git && \
-    useradd --home-dir /var/lib/arvados/git git
 
-ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh /root/
+ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh createusers.sh /usr/local/lib/arvbox/
 ADD service /etc/service
 ADD tests-service /etc/tests-service
 
diff --git a/arvbox/docker/common.sh b/arvbox/docker/common.sh
index 3bf3293..bc328f7 100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
@@ -8,8 +8,8 @@ run_bundler() {
     else
         frozen=""
     fi
-    if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment $frozen "$@" ; then
-        flock /var/lib/arvados/gems.lock bundle install --no-deployment $frozen "$@"
+    if ! flock /var/lib/arvados/gems.lock bundle install --path $GEM_HOME --local --no-deployment $frozen "$@" ; then
+        flock /var/lib/arvados/gems.lock bundle install --path $GEM_HOME --no-deployment $frozen "$@"
     fi
 }
 
diff --git a/arvbox/docker/createusers.sh b/arvbox/docker/createusers.sh
new file mode 100755
index 0000000..eda4161
--- /dev/null
+++ b/arvbox/docker/createusers.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+set -e
+
+if ! grep "^arvbox:" /etc/passwd >/dev/null 2>/dev/null ; then
+    HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
+    HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
+
+    mkdir -p /var/lib/arvados/git
+    groupadd --gid $HOSTGID arvbox
+    groupadd --gid $HOSTGID --non-unique git
+    useradd --home-dir /var/lib/arvados \
+            --uid $HOSTUID --gid $HOSTGID \
+            --groups docker arvbox
+    useradd --home-dir /var/lib/arvados/git --uid $HOSTUID --gid $HOSTGID --non-unique git
+    useradd --groups docker crunch
+    chown arvbox:arvbox -R /usr/local
+fi
diff --git a/arvbox/docker/crunch-setup.sh b/arvbox/docker/crunch-setup.sh
index 4b70250..c52b034 100755
--- a/arvbox/docker/crunch-setup.sh
+++ b/arvbox/docker/crunch-setup.sh
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/gostuff
 cd /var/lib/arvados/gostuff
diff --git a/arvbox/docker/keep-setup.sh b/arvbox/docker/keep-setup.sh
index a4f8832..529360e 100755
--- a/arvbox/docker/keep-setup.sh
+++ b/arvbox/docker/keep-setup.sh
@@ -4,7 +4,7 @@ exec 2>&1
 sleep 2
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/gostuff
 cd /var/lib/arvados/gostuff
diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run
deleted file mode 100755
index 68019e7..0000000
--- a/arvbox/docker/service/api/run
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-cd /usr/src/arvados/services/api
-export RAILS_ENV=development
-
-run_bundler --without=development
-
-if ! test -s /var/lib/arvados/api_uuid_prefix ; then
-  ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/api_uuid_prefix
-fi
-uuid_prefix=$(cat /var/lib/arvados/api_uuid_prefix)
-
-if ! test -s /var/lib/arvados/api_secret_token ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/api_secret_token
-fi
-secret_token=$(cat /var/lib/arvados/api_secret_token)
-
-if ! test -s /var/lib/arvados/blob_signing_key ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/blob_signing_key
-fi
-blob_signing_key=$(cat /var/lib/arvados/blob_signing_key)
-
-# self signed key will be created by SSO server script.
-test -s /var/lib/arvados/self-signed.key
-
-sso_app_secret=$(cat /var/lib/arvados/sso_app_secret)
-
-cat >config/application.yml <<EOF
-common:
-  secret_token: $secret_token
-  blob_signing_key: $blob_signing_key
-  sso_app_secret: $sso_app_secret
-  sso_app_id: arvados-server
-  sso_provider_url: "https://$localip:3002"
-  workbench_address: "http://$localip/"
-  sso_insecure: true
-  auto_admin_first_user: true
-  git_repo_ssh_base: "git@$localip:"
-  git_repo_https_base: "http://$localip:9001/"
-development:
-  uuid_prefix: $uuid_prefix
-test:
-  uuid_prefix: zzzzz
-  git_repo_ssh_base: "git at git.zzzzz.arvadosapi.com:"
-EOF
-
-if ! test -f /var/lib/arvados/api_database_pw ; then
-    ruby -e 'puts rand(2**128).to_s(36)' > /var/lib/arvados/api_database_pw
-fi
-database_pw=$(cat /var/lib/arvados/api_database_pw)
-
-if ! test -f /var/lib/arvados/api_database_setup ; then
-   su postgres -c "psql -c \"create user arvados with password '$database_pw'\""
-   su postgres -c "psql -c \"ALTER USER arvados CREATEDB;\""
-fi
-
-cat >config/database.yml <<EOF
-development:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_development
-  username: arvados
-  password: $database_pw
-  host: localhost
-  template: template0
-test:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_test
-  username: arvados
-  password: $database_pw
-  host: localhost
-  template: template0
-EOF
-
-if ! test -f /var/lib/arvados/api_database_setup ; then
-   bundle exec rake db:setup
-   touch /var/lib/arvados/api_database_setup
-fi
-
-if ! test -s /var/lib/arvados/superuser_token ; then
-    bundle exec ./script/create_superuser_token.rb > /var/lib/arvados/superuser_token
-fi
-
-rm -rf tmp
-
-bundle exec rake db:migrate
-ARVADOS_WEBSOCKETS=1 bundle exec passenger start -p3001 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/api/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run-service
similarity index 87%
copy from arvbox/docker/service/api/run
copy to arvbox/docker/service/api/run-service
index 68019e7..5bd8621 100755
--- a/arvbox/docker/service/api/run
+++ b/arvbox/docker/service/api/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/arvados/services/api
 export RAILS_ENV=development
@@ -55,8 +55,8 @@ fi
 database_pw=$(cat /var/lib/arvados/api_database_pw)
 
 if ! test -f /var/lib/arvados/api_database_setup ; then
-   su postgres -c "psql -c \"create user arvados with password '$database_pw'\""
-   su postgres -c "psql -c \"ALTER USER arvados CREATEDB;\""
+   psql -c "create user arvados with password '$database_pw'"
+   psql -c "ALTER USER arvados CREATEDB;"
 fi
 
 cat >config/database.yml <<EOF
@@ -90,4 +90,5 @@ fi
 rm -rf tmp
 
 bundle exec rake db:migrate
-ARVADOS_WEBSOCKETS=1 bundle exec passenger start -p3001 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
+
+ARVADOS_WEBSOCKETS=1 exec bundle exec passenger start -p3001 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/docker/service/crunch0/run b/arvbox/docker/service/crunch0/run
deleted file mode 100755
index dd864a0..0000000
--- a/arvbox/docker/service/crunch0/run
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec /root/crunch-setup.sh crunch0
diff --git a/arvbox/docker/service/crunch0/run b/arvbox/docker/service/crunch0/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/crunch0/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/crunch0/run-service b/arvbox/docker/service/crunch0/run-service
new file mode 100755
index 0000000..fa3a73a
--- /dev/null
+++ b/arvbox/docker/service/crunch0/run-service
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/lib/arvbox/crunch-setup.sh crunch0
diff --git a/arvbox/docker/service/crunch1/run b/arvbox/docker/service/crunch1/run
deleted file mode 100755
index d7583e5..0000000
--- a/arvbox/docker/service/crunch1/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-sleep 1
-exec /root/crunch-setup.sh crunch1
diff --git a/arvbox/docker/service/crunch1/run b/arvbox/docker/service/crunch1/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/crunch1/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/crunch1/run-service b/arvbox/docker/service/crunch1/run-service
new file mode 100755
index 0000000..6430e9c
--- /dev/null
+++ b/arvbox/docker/service/crunch1/run-service
@@ -0,0 +1,3 @@
+#!/bin/sh
+sleep 1
+exec /usr/local/lib/arvbox/crunch-setup.sh crunch1
diff --git a/arvbox/docker/service/doc/run b/arvbox/docker/service/doc/run
deleted file mode 100755
index e12fdb4..0000000
--- a/arvbox/docker/service/doc/run
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-cd /usr/src/arvados/doc
-run_bundler --without=development
-bundle exec rake generate baseurl=http://$localip:8000 arvados_api_host=$localip:3001 arvados_workbench_host=http://$localip
-exec bundle exec rake run
diff --git a/arvbox/docker/service/doc/run b/arvbox/docker/service/doc/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/doc/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/doc/run b/arvbox/docker/service/doc/run-service
similarity index 87%
copy from arvbox/docker/service/doc/run
copy to arvbox/docker/service/doc/run-service
index e12fdb4..bb0f0e4 100755
--- a/arvbox/docker/service/doc/run
+++ b/arvbox/docker/service/doc/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/arvados/doc
 run_bundler --without=development
diff --git a/arvbox/docker/service/git/run b/arvbox/docker/service/git/run
deleted file mode 100755
index c87c25b..0000000
--- a/arvbox/docker/service/git/run
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-mkdir -p /var/lib/arvados/git
-
-export ARVADOS_API_HOST=$localip:3001
-export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
-
-if ! test -f /var/lib/arvados/gitolite-setup ; then
-   cp -r /root/gitolite-setup.sh /root/gitssh-setup.sh /root/gitolite.rc /var/lib/arvados/git/
-
-   chown -R git:git ~git
-
-   su git -c "/var/lib/arvados/git/gitssh-setup.sh"
-   su git -c "/var/lib/arvados/git/gitolite-setup.sh"
-
-   touch /var/lib/arvados/gitolite-setup
-else
-    chown -R git:git ~git
-    su git -c "/var/lib/arvados/git/gitssh-setup.sh"
-fi
-
-prefix=$(arv --format=uuid user current | cut -d- -f1)
-
-if ! test -s /var/lib/arvados/arvados-git-uuid ; then
-    repo_uuid=$(arv --format=uuid repository create --repository "{\"owner_uuid\":\"$prefix-tpzed-000000000000000\", \"name\":\"arvados\"}")
-    echo $repo_uuid > /var/lib/arvados/arvados-git-uuid
-fi
-
-repo_uuid=$(cat /var/lib/arvados/arvados-git-uuid)
-
-if ! test -s /var/lib/arvados/arvados-git-link-uuid ; then
-    all_users_group_uuid="$prefix-j7d0g-fffffffffffffff"
-
-    set +e
-    read -rd $'\000' newlink <<EOF
-{
- "tail_uuid":"$all_users_group_uuid",
- "head_uuid":"$repo_uuid",
- "link_class":"permission",
- "name":"can_read"
-}
-EOF
-    set -e
-    link_uuid=$(arv --format=uuid link create --link "$newlink")
-    echo $link_uuid > /var/lib/arvados/arvados-git-link-uuid
-fi
-
-if ! test -d /var/lib/arvados/git/repositories/$repo_uuid.git ; then
-    git clone --bare /usr/src/arvados /var/lib/arvados/git/repositories/$repo_uuid.git
-else
-    git --git-dir=/var/lib/arvados/git/repositories/$repo_uuid.git fetch -f /usr/src/arvados master:master
-fi
-
-cd /usr/src/arvados/services/api
-export RAILS_ENV=development
-
-git_user_key=$(cat ~git/.ssh/id_rsa.pub)
-
-cat > config/arvados-clients.yml <<EOF
-development:
-  gitolite_url: /var/lib/arvados/git/repositories/gitolite-admin.git
-  gitolite_tmp: /var/lib/arvados/git
-  arvados_api_host: $localip:3001
-  arvados_api_token: "$ARVADOS_API_TOKEN"
-  arvados_api_host_insecure: true
-  gitolite_arvados_git_user_key: "$git_user_key"
-EOF
-
-while true ; do
-    su git -c "bundle exec script/arvados-git-sync.rb development"
-    sleep 120
-done
diff --git a/arvbox/docker/service/git/run b/arvbox/docker/service/git/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/git/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/git/run b/arvbox/docker/service/git/run-service
similarity index 89%
copy from arvbox/docker/service/git/run
copy to arvbox/docker/service/git/run-service
index c87c25b..4f08040 100755
--- a/arvbox/docker/service/git/run
+++ b/arvbox/docker/service/git/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/git
 
@@ -12,7 +12,7 @@ export ARVADOS_API_HOST_INSECURE=1
 export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
 if ! test -f /var/lib/arvados/gitolite-setup ; then
-   cp -r /root/gitolite-setup.sh /root/gitssh-setup.sh /root/gitolite.rc /var/lib/arvados/git/
+   cp -r /usr/local/lib/arvbox/gitolite-setup.sh /usr/local/lib/arvbox/gitssh-setup.sh /usr/local/lib/arvbox/gitolite.rc /var/lib/arvados/git/
 
    chown -R git:git ~git
 
@@ -73,6 +73,6 @@ development:
 EOF
 
 while true ; do
-    su git -c "bundle exec script/arvados-git-sync.rb development"
+    bundle exec script/arvados-git-sync.rb development
     sleep 120
 done
diff --git a/arvbox/docker/service/githttp/run b/arvbox/docker/service/githttp/run
deleted file mode 100755
index 390727d..0000000
--- a/arvbox/docker/service/githttp/run
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-mkdir -p /var/lib/arvados/gostuff
-cd /var/lib/arvados/gostuff
-
-export GOPATH=$PWD
-mkdir -p "$GOPATH/src/git.curoverse.com"
-ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/arv-git-httpd"
-install bin/arv-git-httpd /usr/local/bin
-
-export ARVADOS_API_HOST=$localip:3001
-export ARVADOS_API_HOST_INSECURE=1
-export GITOLITE_HTTP_HOME=/var/lib/arvados/git
-export GL_BYPASS_ACCESS_CHECKS=1
-export PATH="$PATH:/var/lib/arvados/git/bin"
-cd ~git
-exec chpst -u git:git /usr/local/bin/arv-git-httpd -address=:9001 -git-command=/var/lib/arvados/git/gitolite/src/gitolite-shell -repo-root=/var/lib/arvados/git/repositories 2>&1
diff --git a/arvbox/docker/service/githttp/run b/arvbox/docker/service/githttp/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/githttp/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/githttp/run b/arvbox/docker/service/githttp/run-service
similarity index 73%
copy from arvbox/docker/service/githttp/run
copy to arvbox/docker/service/githttp/run-service
index 390727d..7e4f1de 100755
--- a/arvbox/docker/service/githttp/run
+++ b/arvbox/docker/service/githttp/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/gostuff
 cd /var/lib/arvados/gostuff
@@ -20,4 +20,4 @@ export GITOLITE_HTTP_HOME=/var/lib/arvados/git
 export GL_BYPASS_ACCESS_CHECKS=1
 export PATH="$PATH:/var/lib/arvados/git/bin"
 cd ~git
-exec chpst -u git:git /usr/local/bin/arv-git-httpd -address=:9001 -git-command=/var/lib/arvados/git/gitolite/src/gitolite-shell -repo-root=/var/lib/arvados/git/repositories 2>&1
+/usr/local/bin/arv-git-httpd -address=:9001 -git-command=/var/lib/arvados/git/gitolite/src/gitolite-shell -repo-root=/var/lib/arvados/git/repositories 2>&1
diff --git a/arvbox/docker/service/keep0/run b/arvbox/docker/service/keep0/run
deleted file mode 100755
index aa5b69c..0000000
--- a/arvbox/docker/service/keep0/run
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec /root/keep-setup.sh keep0 25107
\ No newline at end of file
diff --git a/arvbox/docker/service/keep0/run b/arvbox/docker/service/keep0/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/keep0/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/keep0/run-service b/arvbox/docker/service/keep0/run-service
new file mode 100755
index 0000000..7f87b88
--- /dev/null
+++ b/arvbox/docker/service/keep0/run-service
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /usr/local/lib/arvbox/keep-setup.sh keep0 25107
diff --git a/arvbox/docker/service/keep1/run b/arvbox/docker/service/keep1/run
deleted file mode 100755
index 8b0d907..0000000
--- a/arvbox/docker/service/keep1/run
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-sleep 1
-exec /root/keep-setup.sh keep1 25108
diff --git a/arvbox/docker/service/keep1/run b/arvbox/docker/service/keep1/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/keep1/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/keep1/run-service b/arvbox/docker/service/keep1/run-service
new file mode 100755
index 0000000..a44c8dd
--- /dev/null
+++ b/arvbox/docker/service/keep1/run-service
@@ -0,0 +1,3 @@
+#!/bin/sh
+sleep 1
+exec /usr/local/lib/arvbox/keep-setup.sh keep1 25108
diff --git a/arvbox/docker/service/keepproxy/run b/arvbox/docker/service/keepproxy/run
deleted file mode 100755
index fe52d6d..0000000
--- a/arvbox/docker/service/keepproxy/run
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-exec 2>&1
-sleep 2
-set -eux
-
-. /root/common.sh
-
-mkdir -p /var/lib/arvados/gostuff
-cd /var/lib/arvados/gostuff
-
-export GOPATH=$PWD
-mkdir -p "$GOPATH/src/git.curoverse.com"
-ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/keepproxy"
-install bin/keepproxy /usr/local/bin
-
-export ARVADOS_API_HOST=$localip:3001
-export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
-
-if test -s /var/lib/arvados/keepproxy-uuid ; then
-    keep_uuid=$(cat /var/lib/arvados/keepproxy-uuid)
-    set +e
-    read -rd $'\000' keepservice <<EOF
-{
- "service_host":"$localip",
- "service_port":25100,
- "service_type":"proxy"
-}
-EOF
-   set -e
-   arv keep_service update --uuid $keep_uuid --keep-service "$keepservice"
-else
-    set +e
-    read -rd $'\000' keepservice <<EOF
-{
- "service_host":"$localip",
- "service_port":25100,
- "service_ssl_flag":false,
- "service_type":"proxy"
-}
-EOF
-    set -e
-    UUID=$(arv --format=uuid keep_service create --keep-service "$keepservice")
-    echo $UUID > /var/lib/arvados/keepproxy-uuid
-fi
-
-exec /usr/local/bin/keepproxy -listen=":25100"
diff --git a/arvbox/docker/service/keepproxy/run b/arvbox/docker/service/keepproxy/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/keepproxy/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/keepproxy/run b/arvbox/docker/service/keepproxy/run-service
similarity index 97%
copy from arvbox/docker/service/keepproxy/run
copy to arvbox/docker/service/keepproxy/run-service
index fe52d6d..87b46d9 100755
--- a/arvbox/docker/service/keepproxy/run
+++ b/arvbox/docker/service/keepproxy/run-service
@@ -4,7 +4,7 @@ exec 2>&1
 sleep 2
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/gostuff
 cd /var/lib/arvados/gostuff
diff --git a/arvbox/docker/service/keepweb/run b/arvbox/docker/service/keepweb/run
deleted file mode 100755
index ad808fe..0000000
--- a/arvbox/docker/service/keepweb/run
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-mkdir -p /var/lib/arvados/gostuff
-cd /var/lib/arvados/gostuff
-
-export GOPATH=$PWD
-mkdir -p "$GOPATH/src/git.curoverse.com"
-ln -sfn "/usr/src/arvados" "$GOPATH/src/git.curoverse.com/arvados.git"
-go get -t "git.curoverse.com/arvados.git/services/keep-web"
-install bin/keep-web /usr/local/bin
-
-export ARVADOS_API_HOST=$localip:3001
-export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
-
-exec /usr/local/bin/keep-web -trust-all-content -listen=":25099"
diff --git a/arvbox/docker/service/keepweb/run b/arvbox/docker/service/keepweb/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/keepweb/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/keepweb/run b/arvbox/docker/service/keepweb/run-service
similarity index 93%
copy from arvbox/docker/service/keepweb/run
copy to arvbox/docker/service/keepweb/run-service
index ad808fe..38c31f0 100755
--- a/arvbox/docker/service/keepweb/run
+++ b/arvbox/docker/service/keepweb/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p /var/lib/arvados/gostuff
 cd /var/lib/arvados/gostuff
diff --git a/arvbox/docker/service/postgres/run b/arvbox/docker/service/postgres/run
index 2b7c497..cf8250c 100755
--- a/arvbox/docker/service/postgres/run
+++ b/arvbox/docker/service/postgres/run
@@ -1,13 +1,11 @@
 #!/bin/sh
 
-exec 2>&1
-set -eux
+HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
+HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
 
-chown postgres:postgres -R /var/lib/postgresql
-if ! test -d /var/lib/postgresql/9.4/main ; then
-   su postgres -c "/usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main"
-fi
-mkdir -p /var/run/postgresql/9.4-main.pg_stat_tmp
-chown postgres:postgres -R /var/run/postgresql
+chown -R $HOSTUID:$HOSTGID /var/lib/postgresql
+chown -R $HOSTUID:$HOSTGID /var/run/postgresql
+chown -R $HOSTUID:$HOSTGID /etc/postgresql
+chown -R $HOSTUID:$HOSTGID /etc/ssl/private
 
-exec su postgres -c "/usr/lib/postgresql/9.4/bin/postgres -D /var/lib/postgresql/9.4/main -c config_file=/etc/postgresql/9.4/main/postgresql.conf"
+exec chpst -u:$HOSTUID:$HOSTGID $0-service
diff --git a/arvbox/docker/service/postgres/run-service b/arvbox/docker/service/postgres/run-service
new file mode 100755
index 0000000..6f72ba6
--- /dev/null
+++ b/arvbox/docker/service/postgres/run-service
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+exec 2>&1
+set -eux
+
+if ! test -d /var/lib/postgresql/9.4/main ; then
+    /usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main
+    sh -c "while ! createdb ; do sleep 1 ; done" &
+fi
+mkdir -p /var/run/postgresql/9.4-main.pg_stat_tmp
+
+rm -f /var/lib/postgresql/9.4/main/postmaster.pid
+
+exec /usr/lib/postgresql/9.4/bin/postgres -D /var/lib/postgresql/9.4/main -c config_file=/etc/postgresql/9.4/main/postgresql.conf
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
deleted file mode 100755
index 41732fd..0000000
--- a/arvbox/docker/service/ready/run
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-
-. /root/common.sh
-
-set -eu
-
-if ! [[ -d /root/ready ]] ; then
-   echo
-   echo "Arvados-in-a-box starting"
-   echo
-   echo "Note: if this is a fresh arvbox installation, it may take 10-15 minutes to download and"
-   echo "install dependencies.  Use \"arvbox log\" to monitor the progress of specific services."
-   echo
-   mkdir -p /root/ready
-fi
-
-sleep 2
-
-declare -A services
-services=(
-  [workbench]=80
-  [api]=3001
-  [sso]=3002
-  [githttp]=9001
-  [keepweb]=25099
-  [keepproxy]=25100
-  [keep0]=25107
-  [keep1]=25108
-  [ssh]=22
-  [doc]=8000
-)
-
-waiting=""
-
-. /root/common.sh
-
-for s in "${!services[@]}"
-do
-  if ! [[ -f /root/ready/$s ]] ; then
-    if nc -z $localip ${services[$s]} ; then
-      echo "$s is ready at $localip:${services[$s]}"
-      touch /root/ready/$s
-    else
-      waiting="$waiting $s"
-    fi
-  fi
-done
-
-if ! docker version >/dev/null 2>/dev/null ; then
-  waiting="$waiting docker"
-fi
-
-if ! which arv >/dev/null ; then
-  waiting="$waiting ruby_sdk"
-fi
-
-if ! which arv-get >/dev/null ; then
-  waiting="$waiting python_sdk"
-fi
-
-if ! [[ -z "$waiting" ]] ; then
-    if ps x | grep -v grep | grep "bundle install" > /dev/null; then
-        gemcount=$(ls /var/lib/gems/gems 2>/dev/null | wc -l)
-
-        gemlockcount=0
-        for l in /usr/src/arvados/services/api/Gemfile.lock \
-                     /usr/src/arvados/apps/workbench/Gemfile.lock \
-                     /usr/src/sso/Gemfile.lock ; do
-            gc=$(cat $l \
-                        | grep -vE "(GEM|PLATFORMS|DEPENDENCIES|$^|remote:|specs:)" \
-                        | sed 's/^ *//' | sed 's/(.*)//' | sed 's/ *$//' | sort | uniq | wc -l)
-            gemlockcount=$(($gemlockcount + $gc))
-        done
-        waiting="$waiting (installing ruby gems $gemcount/$gemlockcount)"
-    fi
-
-    if ps x | grep -v grep | grep "c++.*/var/lib/passenger" > /dev/null ; then
-        waiting="$waiting (compiling passenger)"
-    fi
-
-    if ps x | grep -v grep | grep "pip install" > /dev/null; then
-        waiting="$waiting (installing python packages)"
-    fi
-    echo "    Waiting for$waiting ..."
-    exit 1
-fi
-
-echo
-echo "Your Arvados-in-a-box is ready!"
-echo "Workbench is running at http://$localip"
-
-rm -r /root/ready
-
-sv stop ready >/dev/null
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/ready/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run-service
similarity index 82%
copy from arvbox/docker/service/ready/run
copy to arvbox/docker/service/ready/run-service
index 41732fd..e99570b 100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run-service
@@ -1,17 +1,17 @@
 #!/bin/bash
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 set -eu
 
-if ! [[ -d /root/ready ]] ; then
+if ! [[ -d /tmp/arvbox-ready ]] ; then
    echo
    echo "Arvados-in-a-box starting"
    echo
    echo "Note: if this is a fresh arvbox installation, it may take 10-15 minutes to download and"
    echo "install dependencies.  Use \"arvbox log\" to monitor the progress of specific services."
    echo
-   mkdir -p /root/ready
+   mkdir -p /tmp/arvbox-ready
 fi
 
 sleep 2
@@ -32,14 +32,14 @@ services=(
 
 waiting=""
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 for s in "${!services[@]}"
 do
-  if ! [[ -f /root/ready/$s ]] ; then
+  if ! [[ -f /tmp/arvbox-ready/$s ]] ; then
     if nc -z $localip ${services[$s]} ; then
       echo "$s is ready at $localip:${services[$s]}"
-      touch /root/ready/$s
+      touch /tmp/arvbox-ready/$s
     else
       waiting="$waiting $s"
     fi
@@ -51,16 +51,14 @@ if ! docker version >/dev/null 2>/dev/null ; then
 fi
 
 if ! which arv >/dev/null ; then
-  waiting="$waiting ruby_sdk"
-fi
-
-if ! which arv-get >/dev/null ; then
-  waiting="$waiting python_sdk"
+  waiting="$waiting sdk"
+elif ! which arv-get >/dev/null ; then
+  waiting="$waiting sdk"
 fi
 
 if ! [[ -z "$waiting" ]] ; then
     if ps x | grep -v grep | grep "bundle install" > /dev/null; then
-        gemcount=$(ls /var/lib/gems/gems 2>/dev/null | wc -l)
+        gemcount=$(ls /var/lib/gems/ruby/2.1.0/gems 2>/dev/null | wc -l)
 
         gemlockcount=0
         for l in /usr/src/arvados/services/api/Gemfile.lock \
@@ -89,6 +87,6 @@ echo
 echo "Your Arvados-in-a-box is ready!"
 echo "Workbench is running at http://$localip"
 
-rm -r /root/ready
+rm -r /tmp/arvbox-ready
 
 sv stop ready >/dev/null
diff --git a/arvbox/docker/service/runsu.sh b/arvbox/docker/service/runsu.sh
new file mode 100755
index 0000000..329067f
--- /dev/null
+++ b/arvbox/docker/service/runsu.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+HOSTUID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f4)
+HOSTGID=$(ls -nd /usr/src/arvados | sed 's/ */ /' | cut -d' ' -f5)
+
+flock /var/lib/arvados/createusers.lock /usr/local/lib/arvbox/createusers.sh
+
+export HOME=/var/lib/arvados
+
+if test -z "$1" ; then
+    exec su arvbox -c -- "exec $0-service"
+else
+    exec su arvbox --shell /bin/bash -- $@
+fi
diff --git a/arvbox/docker/service/sdk/run b/arvbox/docker/service/sdk/run
index e5e8880..e6c844d 100755
--- a/arvbox/docker/service/sdk/run
+++ b/arvbox/docker/service/sdk/run
@@ -1,27 +1,5 @@
-#!/bin/bash
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-mkdir -p ~/.pip /var/lib/arvados/pip
-cat > ~/.pip/pip.conf <<EOF
-[global]
-download_cache = /var/lib/arvados/pip
-EOF
-
-cd /usr/src/arvados/sdk/cli
-run_bundler --binstubs=$PWD/binstubs
-ln -sf /usr/src/arvados/sdk/cli/binstubs/arv /usr/bin/arv
-
-
-cd /usr/src/arvados/sdk/python
-python setup.py sdist
-pip_install $(ls dist/arvados-python-client-*.tar.gz | tail -n1)
-
-cd /usr/src/arvados/services/fuse
-python setup.py sdist
-pip_install $(ls dist/arvados_fuse-*.tar.gz | tail -n1)
+#!/bin/sh
+set -e
 
+/etc/service/runsu.sh $0-service
 sv stop sdk
diff --git a/arvbox/docker/service/sdk/run b/arvbox/docker/service/sdk/run-service
similarity index 82%
copy from arvbox/docker/service/sdk/run
copy to arvbox/docker/service/sdk/run-service
index e5e8880..fd376ba 100755
--- a/arvbox/docker/service/sdk/run
+++ b/arvbox/docker/service/sdk/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 mkdir -p ~/.pip /var/lib/arvados/pip
 cat > ~/.pip/pip.conf <<EOF
@@ -13,8 +13,7 @@ EOF
 
 cd /usr/src/arvados/sdk/cli
 run_bundler --binstubs=$PWD/binstubs
-ln -sf /usr/src/arvados/sdk/cli/binstubs/arv /usr/bin/arv
-
+ln -sf /usr/src/arvados/sdk/cli/binstubs/arv /usr/local/bin/arv
 
 cd /usr/src/arvados/sdk/python
 python setup.py sdist
@@ -23,5 +22,3 @@ pip_install $(ls dist/arvados-python-client-*.tar.gz | tail -n1)
 cd /usr/src/arvados/services/fuse
 python setup.py sdist
 pip_install $(ls dist/arvados_fuse-*.tar.gz | tail -n1)
-
-sv stop sdk
diff --git a/arvbox/docker/service/sso/run b/arvbox/docker/service/sso/run
deleted file mode 100755
index 73f6df5..0000000
--- a/arvbox/docker/service/sso/run
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-. /root/common.sh
-
-cd /usr/src/sso
-export RAILS_ENV=development
-export GEM_HOME=/var/lib/gems
-
-run_bundler --without=development
-
-if ! test -s /var/lib/arvados/sso_uuid_prefix ; then
-  ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/sso_uuid_prefix
-fi
-uuid_prefix=$(cat /var/lib/arvados/sso_uuid_prefix)
-
-if ! test -s /var/lib/arvados/sso_secret_token ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/sso_secret_token
-fi
-secret_token=$(cat /var/lib/arvados/sso_secret_token)
-
-if ! test -s /var/lib/arvados/self-signed.key ; then
-  openssl req -new -x509 -nodes -out /var/lib/arvados/self-signed.pem -keyout /var/lib/arvados/self-signed.key -days 365 -subj '/CN=localhost'
-fi
-
-cat >config/application.yml <<EOF
-common:
-  uuid_prefix: $uuid_prefix
-  secret_token: $secret_token
-  default_link_url: "http://$localip"
-  allow_account_registration: true
-EOF
-
-if ! test -f /var/lib/arvados/sso_database_pw ; then
-    ruby -e 'puts rand(2**128).to_s(36)' > /var/lib/arvados/sso_database_pw
-fi
-database_pw=$(cat /var/lib/arvados/sso_database_pw)
-
-if ! test -f /var/lib/arvados/sso_database_setup ; then
-    su postgres -c "psql -c \"create user arvados_sso with password '$database_pw'\""
-    su postgres -c "psql -c \"ALTER USER arvados_sso CREATEDB;\""
-fi
-
-cat >config/database.yml <<EOF
-development:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_sso_development
-  username: arvados_sso
-  password: $database_pw
-  host: localhost
-  template: template0
-test:
-  adapter: postgresql
-  encoding: utf8
-  database: arvados_sso_test
-  username: arvados_sso
-  password: $database_pw
-  host: localhost
-  template: template0
-EOF
-
-if ! test -f /var/lib/arvados/sso_database_setup ; then
-   bundle exec rake db:setup
-
-   if ! test -s /var/lib/arvados/sso_app_secret ; then
-       ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/sso_app_secret
-   fi
-   app_secret=$(cat /var/lib/arvados/sso_app_secret)
-
-   bundle exec rails console <<EOF
-c = Client.new
-c.name = "joshid"
-c.app_id = "arvados-server"
-c.app_secret = "$app_secret"
-c.save!
-EOF
-
-   touch /var/lib/arvados/sso_database_setup
-fi
-
-rm -rf tmp
-
-bundle exec rake db:migrate
-bundle exec passenger start -p3002 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/docker/service/sso/run b/arvbox/docker/service/sso/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/sso/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/sso/run b/arvbox/docker/service/sso/run-service
similarity index 85%
copy from arvbox/docker/service/sso/run
copy to arvbox/docker/service/sso/run-service
index 73f6df5..085b79a 100755
--- a/arvbox/docker/service/sso/run
+++ b/arvbox/docker/service/sso/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/sso
 export RAILS_ENV=development
@@ -39,8 +39,8 @@ fi
 database_pw=$(cat /var/lib/arvados/sso_database_pw)
 
 if ! test -f /var/lib/arvados/sso_database_setup ; then
-    su postgres -c "psql -c \"create user arvados_sso with password '$database_pw'\""
-    su postgres -c "psql -c \"ALTER USER arvados_sso CREATEDB;\""
+    psql -c "create user arvados_sso with password '$database_pw'"
+    psql -c "ALTER USER arvados_sso CREATEDB;"
 fi
 
 cat >config/database.yml <<EOF
@@ -84,4 +84,5 @@ fi
 rm -rf tmp
 
 bundle exec rake db:migrate
-bundle exec passenger start -p3002 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
+export HOME=/var/lib/passenger
+exec bundle exec passenger start -p3002 --ssl --ssl-certificate=/var/lib/arvados/self-signed.pem --ssl-certificate-key=/var/lib/arvados/self-signed.key
diff --git a/arvbox/docker/service/vm/run b/arvbox/docker/service/vm/run
deleted file mode 100755
index 807d976..0000000
--- a/arvbox/docker/service/vm/run
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-exec 2>&1
-sleep 2
-set -eux
-
-. /root/common.sh
-
-git config --system "credential.http://$localip:9001/.username" none
-git config --system "credential.http://$localip:9001/.helper" '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'
-
-export ARVADOS_API_HOST=$localip:3001
-export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
-
-if test -s /var/lib/arvados/vm-uuid ; then
-    ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)
-    set +e
-    read -rd $'\000' vm <<EOF
-{
- "hostname":"$localip"
-}
-EOF
-    set -e
-    arv virtual_machine update --uuid $ARVADOS_VIRTUAL_MACHINE_UUID --virtual-machine "$vm"
-else
-    set +e
-    read -rd $'\000' vm <<EOF
-{
- "hostname":"$localip"
-}
-EOF
-    set -e
-    ARVADOS_VIRTUAL_MACHINE_UUID=$(arv --format=uuid virtual_machine create --virtual-machine "$vm")
-    echo $ARVADOS_VIRTUAL_MACHINE_UUID > /var/lib/arvados/vm-uuid
-fi
-
-export ARVADOS_VIRTUAL_MACHINE_UUID
-
-cd /usr/src/arvados/services/login-sync
-run_bundler
-
-while true ; do
-      bundle exec arvados-login-sync
-      sleep 120
-done
diff --git a/arvbox/docker/service/vm/run b/arvbox/docker/service/vm/run
new file mode 120000
index 0000000..ef446b5
--- /dev/null
+++ b/arvbox/docker/service/vm/run
@@ -0,0 +1 @@
+../runsu.sh
\ No newline at end of file
diff --git a/arvbox/docker/service/vm/run b/arvbox/docker/service/vm/run-service
similarity index 97%
copy from arvbox/docker/service/vm/run
copy to arvbox/docker/service/vm/run-service
index 807d976..f6844d8 100755
--- a/arvbox/docker/service/vm/run
+++ b/arvbox/docker/service/vm/run-service
@@ -4,7 +4,7 @@ exec 2>&1
 sleep 2
 set -eux
 
-. /root/common.sh
+. /usr/local/lib/arvbox/common.sh
 
 git config --system "credential.http://$localip:9001/.username" none
 git config --system "credential.http://$localip:9001/.helper" '!cred(){ cat >/dev/null; if [ "$1" = get ]; then echo password=$ARVADOS_API_TOKEN; fi; };cred'
diff --git a/arvbox/docker/service/workbench/run b/arvbox/docker/service/workbench/run
index ccdbc54..7838220 100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run
@@ -1,37 +1,12 @@
 #!/bin/sh
+set -e
 
-exec 2>&1
-set -eux
-
-. /root/common.sh
+/etc/service/runsu.sh $0-service
 
 cd /usr/src/arvados/apps/workbench
-export RAILS_ENV=development
-export GEM_HOME=/var/lib/gems
-
-run_bundler --without=development
-
-if ! test -s /var/lib/arvados/workbench_secret_token ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/workbench_secret_token
-fi
-secret_token=$(cat /var/lib/arvados/workbench_secret_token)
-
-if ! test -s self-signed.key ; then
-  openssl req -new -x509 -nodes -out self-signed.pem -keyout self-signed.key -days 365 -subj '/CN=localhost'
-fi
-
-cat >config/application.yml <<EOF
-common:
-  secret_token: $secret_token
-  arvados_login_base: https://$localip:3001/login
-  arvados_v1_base: https://$localip:3001/arvados/v1
-  arvados_insecure_https: true
-  keep_web_download_url: http://$localip:25099/c=%{uuid_or_pdh}
-  keep_web_url: http://$localip:25099/c=%{uuid_or_pdh}
-  arvados_docsite: http://$localip:8000/
-EOF
 
 rm -rf tmp
+mkdir tmp
+chown arvbox:arvbox tmp
 
-#bundle exec passenger start -p443 --ssl --ssl-certificate=self-signed.pem --ssl-certificate-key=self-signed.key
-bundle exec passenger start -p80
+exec bundle exec passenger start --port 80 --user arvbox
diff --git a/arvbox/docker/service/workbench/run b/arvbox/docker/service/workbench/run-service
similarity index 92%
copy from arvbox/docker/service/workbench/run
copy to arvbox/docker/service/workbench/run-service
index ccdbc54..09f929f 100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run-service
@@ -3,7 +3,7 @@
 exec 2>&1
 set -eux
 
-. /root/common.sh
+.  /usr/local/lib/arvbox/common.sh
 
 cd /usr/src/arvados/apps/workbench
 export RAILS_ENV=development
@@ -31,7 +31,6 @@ common:
   arvados_docsite: http://$localip:8000/
 EOF
 
-rm -rf tmp
-
 #bundle exec passenger start -p443 --ssl --ssl-certificate=self-signed.pem --ssl-certificate-key=self-signed.key
-bundle exec passenger start -p80
+
+bundle exec passenger start --runtime-check-only
diff --git a/arvbox/docker/tests-service/docker b/arvbox/docker/tests-service/docker
new file mode 120000
index 0000000..9374f25
--- /dev/null
+++ b/arvbox/docker/tests-service/docker
@@ -0,0 +1 @@
+../service/docker
\ No newline at end of file
diff --git a/arvbox/docker/tests-service/docker/log/run b/arvbox/docker/tests-service/docker/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/docker/tests-service/docker/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/docker/tests-service/docker/run b/arvbox/docker/tests-service/docker/run
deleted file mode 100755
index 99540e6..0000000
--- a/arvbox/docker/tests-service/docker/run
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/bash
-
-# Taken from https://github.com/jpetazzo/dind
-
-exec 2>&1
-
-#!/bin/bash
-
-# Ensure that all nodes in /dev/mapper correspond to mapped devices currently loaded by the device-mapper kernel driver
-dmsetup mknodes
-
-# First, make sure that cgroups are mounted correctly.
-CGROUP=/sys/fs/cgroup
-: {LOG:=stdio}
-
-[ -d $CGROUP ] ||
-	mkdir $CGROUP
-
-mountpoint -q $CGROUP ||
-	mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP || {
-		echo "Could not make a tmpfs mount. Did you use --privileged?"
-		exit 1
-	}
-
-if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security
-then
-    mount -t securityfs none /sys/kernel/security || {
-        echo "Could not mount /sys/kernel/security."
-        echo "AppArmor detection and --privileged mode might break."
-    }
-fi
-
-# Mount the cgroup hierarchies exactly as they are in the parent system.
-for SUBSYS in $(cut -d: -f2 /proc/1/cgroup)
-do
-        [ -d $CGROUP/$SUBSYS ] || mkdir $CGROUP/$SUBSYS
-        mountpoint -q $CGROUP/$SUBSYS ||
-                mount -n -t cgroup -o $SUBSYS cgroup $CGROUP/$SUBSYS
-
-        # The two following sections address a bug which manifests itself
-        # by a cryptic "lxc-start: no ns_cgroup option specified" when
-        # trying to start containers withina container.
-        # The bug seems to appear when the cgroup hierarchies are not
-        # mounted on the exact same directories in the host, and in the
-        # container.
-
-        # Named, control-less cgroups are mounted with "-o name=foo"
-        # (and appear as such under /proc/<pid>/cgroup) but are usually
-        # mounted on a directory named "foo" (without the "name=" prefix).
-        # Systemd and OpenRC (and possibly others) both create such a
-        # cgroup. To avoid the aforementioned bug, we symlink "foo" to
-        # "name=foo". This shouldn't have any adverse effect.
-        echo $SUBSYS | grep -q ^name= && {
-                NAME=$(echo $SUBSYS | sed s/^name=//)
-                ln -s $SUBSYS $CGROUP/$NAME
-        }
-
-        # Likewise, on at least one system, it has been reported that
-        # systemd would mount the CPU and CPU accounting controllers
-        # (respectively "cpu" and "cpuacct") with "-o cpuacct,cpu"
-        # but on a directory called "cpu,cpuacct" (note the inversion
-        # in the order of the groups). This tries to work around it.
-        [ $SUBSYS = cpuacct,cpu ] && ln -s $SUBSYS $CGROUP/cpu,cpuacct
-done
-
-# Note: as I write those lines, the LXC userland tools cannot setup
-# a "sub-container" properly if the "devices" cgroup is not in its
-# own hierarchy. Let's detect this and issue a warning.
-grep -q :devices: /proc/1/cgroup ||
-	echo "WARNING: the 'devices' cgroup should be in its own hierarchy."
-grep -qw devices /proc/1/cgroup ||
-	echo "WARNING: it looks like the 'devices' cgroup is not mounted."
-
-# Now, close extraneous file descriptors.
-pushd /proc/self/fd >/dev/null
-for FD in *
-do
-	case "$FD" in
-	# Keep stdin/stdout/stderr
-	[012])
-		;;
-	# Nuke everything else
-	*)
-		eval exec "$FD>&-"
-		;;
-	esac
-done
-popd >/dev/null
-
-
-# If a pidfile is still around (for example after a container restart),
-# delete it so that docker can start.
-rm -rf /var/run/docker.pid
-
-exec docker daemon --storage-driver=overlay $DOCKER_DAEMON_ARGS
diff --git a/arvbox/docker/tests-service/logger b/arvbox/docker/tests-service/logger
deleted file mode 100755
index a79a518..0000000
--- a/arvbox/docker/tests-service/logger
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec svlogd -tt ./main
diff --git a/arvbox/docker/tests-service/logger b/arvbox/docker/tests-service/logger
new file mode 120000
index 0000000..b30194b
--- /dev/null
+++ b/arvbox/docker/tests-service/logger
@@ -0,0 +1 @@
+../service/logger
\ No newline at end of file
diff --git a/arvbox/docker/tests-service/postgres b/arvbox/docker/tests-service/postgres
new file mode 120000
index 0000000..9b2d8a0
--- /dev/null
+++ b/arvbox/docker/tests-service/postgres
@@ -0,0 +1 @@
+../service/postgres
\ No newline at end of file
diff --git a/arvbox/docker/tests-service/postgres/log/main/.gitstub b/arvbox/docker/tests-service/postgres/log/main/.gitstub
deleted file mode 100644
index e69de29..0000000
diff --git a/arvbox/docker/tests-service/postgres/log/run b/arvbox/docker/tests-service/postgres/log/run
deleted file mode 120000
index f99cc1d..0000000
--- a/arvbox/docker/tests-service/postgres/log/run
+++ /dev/null
@@ -1 +0,0 @@
-../../logger
\ No newline at end of file
diff --git a/arvbox/docker/tests-service/postgres/run b/arvbox/docker/tests-service/postgres/run
deleted file mode 100755
index 2b7c497..0000000
--- a/arvbox/docker/tests-service/postgres/run
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-exec 2>&1
-set -eux
-
-chown postgres:postgres -R /var/lib/postgresql
-if ! test -d /var/lib/postgresql/9.4/main ; then
-   su postgres -c "/usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main"
-fi
-mkdir -p /var/run/postgresql/9.4-main.pg_stat_tmp
-chown postgres:postgres -R /var/run/postgresql
-
-exec su postgres -c "/usr/lib/postgresql/9.4/bin/postgres -D /var/lib/postgresql/9.4/main -c config_file=/etc/postgresql/9.4/main/postgresql.conf"
diff --git a/arvbox/docker/tests-service/runsu.sh b/arvbox/docker/tests-service/runsu.sh
new file mode 120000
index 0000000..22030b0
--- /dev/null
+++ b/arvbox/docker/tests-service/runsu.sh
@@ -0,0 +1 @@
+../service/runsu.sh
\ No newline at end of file

commit 7dae80945a055453fea5ec85a3c4b1ca160b5c17
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 16:18:39 2016 -0500

    8080: Fix arvados_docsite in workbench to point to local docsite.

diff --git a/arvbox/docker/service/workbench/run b/arvbox/docker/service/workbench/run
index 1bbb5e7..ccdbc54 100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run
@@ -28,6 +28,7 @@ common:
   arvados_insecure_https: true
   keep_web_download_url: http://$localip:25099/c=%{uuid_or_pdh}
   keep_web_url: http://$localip:25099/c=%{uuid_or_pdh}
+  arvados_docsite: http://$localip:8000/
 EOF
 
 rm -rf tmp

commit f11b245d56c69fd127cf9340bbb5392ed6e48bf4
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 16:13:48 2016 -0500

    8080: Add Arvados documentation server.

diff --git a/arvbox/docker/service/doc/log/main/.gitstub b/arvbox/docker/service/doc/log/main/.gitstub
new file mode 100644
index 0000000..e69de29
diff --git a/arvbox/docker/service/doc/log/run b/arvbox/docker/service/doc/log/run
new file mode 120000
index 0000000..f99cc1d
--- /dev/null
+++ b/arvbox/docker/service/doc/log/run
@@ -0,0 +1 @@
+../../logger
\ No newline at end of file
diff --git a/arvbox/docker/service/doc/run b/arvbox/docker/service/doc/run
new file mode 100755
index 0000000..e12fdb4
--- /dev/null
+++ b/arvbox/docker/service/doc/run
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+exec 2>&1
+set -eux
+
+. /root/common.sh
+
+cd /usr/src/arvados/doc
+run_bundler --without=development
+bundle exec rake generate baseurl=http://$localip:8000 arvados_api_host=$localip:3001 arvados_workbench_host=http://$localip
+exec bundle exec rake run
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
index 0908f01..41732fd 100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run
@@ -27,6 +27,7 @@ services=(
   [keep0]=25107
   [keep1]=25108
   [ssh]=22
+  [doc]=8000
 )
 
 waiting=""

commit 3932ff785ee96479493d07c9949ed9562242a5f2
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 15:59:49 2016 -0500

    8080: Install xvfb, iceweasel & phantomjs to be able to run workbench tests.

diff --git a/arvbox/docker/Dockerfile b/arvbox/docker/Dockerfile
index 85acd0f..a9c3321 100644
--- a/arvbox/docker/Dockerfile
+++ b/arvbox/docker/Dockerfile
@@ -10,10 +10,16 @@ RUN apt-get update && \
     pkg-config libattr1-dev python-llfuse python-pycurl \
     libwww-perl libio-socket-ssl-perl libcrypt-ssleay-perl \
     libjson-perl python-virtualenv python3-virtualenv nginx \
-    gitolite3 lsof
+    gitolite3 lsof python-epydoc linkchecker xvfb iceweasel graphviz
 
 RUN curl -sSL https://get.docker.com/ | sh
 
+RUN set -e && \
+ PJS=phantomjs-1.9.7-linux-x86_64 && \
+ curl -L -o/tmp/$PJS.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/$PJS.tar.bz2 && \
+ tar -C /usr/local -xjf /tmp/$PJS.tar.bz2 && \
+ ln -s ../$PJS/bin/phantomjs /usr/local/bin/
+
 ADD runit-docker /root/runit-docker
 
 RUN cd /root/runit-docker && \

commit 80da6be45102cbd2a312dff4f5203964ef0f55b0
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 15:04:45 2016 -0500

    8080: Fixes api server tests.

diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run
index 419235d..68019e7 100755
--- a/arvbox/docker/service/api/run
+++ b/arvbox/docker/service/api/run
@@ -37,7 +37,7 @@ common:
   sso_app_secret: $sso_app_secret
   sso_app_id: arvados-server
   sso_provider_url: "https://$localip:3002"
-  workbench_address: "http://$localip"
+  workbench_address: "http://$localip/"
   sso_insecure: true
   auto_admin_first_user: true
   git_repo_ssh_base: "git@$localip:"

commit 91cc6e31cf0ad3cc43a45eb2dc7d30c2ae6158d7
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 14:26:30 2016 -0500

    8080: Test configuration uses "zzzzz" prefix, which fixes almost all the failing
    tests.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index ac1e604..f6e95cb 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -79,9 +79,7 @@ run() {
         done < $FF
         rm $FF
         echo
-        echo "You the Arvados source code is checked out at $ARVADOS_ROOT"
-        echo "Use '$0 reboot' to restart the container"
-        echo "or '$0 svrestart' to recompile/reconfigure/restart individual services."
+        echo "The Arvados source code is checked out at: $ARVADOS_ROOT"
     fi
 }
 
@@ -110,6 +108,11 @@ case $1 in
         stop
         ;;
 
+    restart)
+        stop
+        run
+        ;;
+
     reboot)
         stop
         cd $ARVBOX_SCRIPT
@@ -182,9 +185,10 @@ case $1 in
         echo "open       open arvbox workbench in a web browser"
         echo "shell      enter arvbox shell"
         echo "ip         print arvbox ip address"
-        echo "stop       stop arvbox"
-        echo "reboot     stop arvbox, build image, run"
-        echo "reset      delete persistent data (be careful!)"
+        echo "stop       stop arvbox container"
+        echo "restart    stop, then run again"
+        echo "reboot     stop, build arvbox Docker image, run"
+        echo "reset      delete all persistent data (be careful!)"
         echo "run-tests  run run-tests.sh inside $ARVBOX_CONTAINER container"
         echo "log       <service> tail log of specified service"
         echo "svrestart <service> restart specified service inside arvbox"
diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run
index 5c80964..419235d 100755
--- a/arvbox/docker/service/api/run
+++ b/arvbox/docker/service/api/run
@@ -32,7 +32,6 @@ sso_app_secret=$(cat /var/lib/arvados/sso_app_secret)
 
 cat >config/application.yml <<EOF
 common:
-  uuid_prefix: $uuid_prefix
   secret_token: $secret_token
   blob_signing_key: $blob_signing_key
   sso_app_secret: $sso_app_secret
@@ -43,6 +42,11 @@ common:
   auto_admin_first_user: true
   git_repo_ssh_base: "git@$localip:"
   git_repo_https_base: "http://$localip:9001/"
+development:
+  uuid_prefix: $uuid_prefix
+test:
+  uuid_prefix: zzzzz
+  git_repo_ssh_base: "git at git.zzzzz.arvadosapi.com:"
 EOF
 
 if ! test -f /var/lib/arvados/api_database_pw ; then

commit bfa7362c90e3bf5f42ac30612c0ec04ed9deb0d6
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 13:58:52 2016 -0500

    8080: Fix GEM_HOME

diff --git a/arvbox/arvbox b/arvbox/arvbox
index b5f1e5a..ac1e604 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -103,7 +103,7 @@ case $1 in
         ;;
 
     sh*)
-        docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM GEM_HOME=/var/lib/arvados/gems /bin/bash
+        docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM GEM_HOME=/var/lib/gems /bin/bash
         ;;
 
     stop)
@@ -167,8 +167,8 @@ case $1 in
                VENVDIR=/var/lib/arvados/tests-venv \
                VENV3DIR=/var/lib/arvados/tests-venv3 \
                GOPATH=/var/lib/arvados/tests-gostuff \
-               GEMHOME=/var/lib/arvados/gems \
-               GEM_HOME=/var/lib/arvados/gems \
+               GEMHOME=/var/lib/gems \
+               GEM_HOME=/var/lib/gems \
                "$@"
         ;;
 

commit 434c954c45ce545a92fc5326ae1f3d91b117e869
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 13:43:58 2016 -0500

    8080: Add note about where arvados git is checked out.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index c06dbcd..b5f1e5a 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -78,6 +78,10 @@ run() {
             fi
         done < $FF
         rm $FF
+        echo
+        echo "You the Arvados source code is checked out at $ARVADOS_ROOT"
+        echo "Use '$0 reboot' to restart the container"
+        echo "or '$0 svrestart' to recompile/reconfigure/restart individual services."
     fi
 }
 

commit e9e9a304e6bde8db0348a4cc6190d79d11241a1a
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 13:33:22 2016 -0500

    8080: log and svrestart print out available services

diff --git a/arvbox/arvbox b/arvbox/arvbox
index f953bc1..c06dbcd 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -113,11 +113,6 @@ case $1 in
         run
         ;;
 
-    svrestart)
-        docker exec -ti $ARVBOX_CONTAINER sv restart $2
-        docker exec -ti $ARVBOX_CONTAINER sv restart ready
-        ;;
-
     ip|open)
         IP=$(docker inspect arvbox | grep \"IPAddress\" | tr -d ' ":,\n' | cut -c10-)
         if test $1 = 'ip' ; then
@@ -136,8 +131,20 @@ case $1 in
         sudo rm -rf $ARVBOX_DATA
         ;;
 
-    log)
-        docker exec -ti $ARVBOX_CONTAINER tail -n40 /etc/service/$2/log/main/current
+    log|svrestart)
+        if test -n "$2" ; then
+            if test "$1" = log ; then
+                docker exec -ti $ARVBOX_CONTAINER tail -n40 /etc/service/$2/log/main/current
+            fi
+            if test "$1" = svrestart ; then
+                docker exec -ti $ARVBOX_CONTAINER sv restart $2
+                docker exec -ti $ARVBOX_CONTAINER sv restart ready
+            fi
+        else
+            echo "Usage: $0 $1 <service>"
+            echo "Available services:"
+            docker exec -ti $ARVBOX_CONTAINER ls /etc/service
+        fi
         ;;
 
     run-tests)
@@ -164,7 +171,7 @@ case $1 in
     *)
         echo "Arvados-in-a-box"
         echo
-        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|log|svrestart|tests)"
+        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|run-tests|log|svrestart)"
         echo
         echo "build      build arvbox Docker image"
         echo "start|run  start $ARVBOX_CONTAINER container "
@@ -173,9 +180,9 @@ case $1 in
         echo "ip         print arvbox ip address"
         echo "stop       stop arvbox"
         echo "reboot     stop arvbox, build image, run"
-        echo "reset      delete persistent data (careful!)"
-        echo "log <component>       tail log of specified service"
-        echo "svrestart <component> restart specified service inside arvbox"
+        echo "reset      delete persistent data (be careful!)"
         echo "run-tests  run run-tests.sh inside $ARVBOX_CONTAINER container"
+        echo "log       <service> tail log of specified service"
+        echo "svrestart <service> restart specified service inside arvbox"
         ;;
 esac

commit c66016db77c59b3e5e5d459bb80d670e8ab075e4
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 10:42:10 2016 -0500

    8080: Count gems for status reporting.  Store gems in a different place.  Store
    database password and rewrite database.yml on startup.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index ee8910c..f953bc1 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -27,8 +27,9 @@ fi
 PASSENGER=$ARVBOX_DATA/passenger
 PG_DATA=$ARVBOX_DATA/postgres
 VAR_DATA=$ARVBOX_DATA/var
+GEMS=$ARVBOX_DATA/gems
 
-mkdir -p $PASSENGER $PG_DATA $VAR_DATA
+mkdir -p $PASSENGER $PG_DATA $VAR_DATA $GEMS
 
 run() {
     if ! test -d $ARVADOS_ROOT ; then
@@ -49,6 +50,7 @@ run() {
                --volume=$PG_DATA:/var/lib/postgresql:rw \
                --volume=$VAR_DATA:/var/lib/arvados:rw \
                --volume=$PASSENGER:/var/lib/passenger:rw \
+               --volume=$GEMS:/var/lib/gems:rw \
                --volume=/var/lib/docker \
                arvados/arvbox \
                runsvdir /etc/tests-service
@@ -62,6 +64,7 @@ run() {
                --volume=$PG_DATA:/var/lib/postgresql:rw \
                --volume=$VAR_DATA:/var/lib/arvados:rw \
                --volume=$PASSENGER:/var/lib/passenger:rw \
+               --volume=$GEMS:/var/lib/gems:rw \
                --volume=/var/lib/docker \
                arvados/arvbox
         FF=/tmp/arvbox-fifo-$$
@@ -105,7 +108,7 @@ case $1 in
 
     reboot)
         stop
-        cd $ARVBOX
+        cd $ARVBOX_SCRIPT
         docker build -t arvados/arvbox docker
         run
         ;;
diff --git a/arvbox/docker/common.sh b/arvbox/docker/common.sh
index ffed7fd..3bf3293 100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
@@ -1,6 +1,6 @@
 localip=$(ip addr show eth0 |grep "inet " | sed 's/ *inet \([^/]*\).*/\1/')
-export GEM_HOME=/var/lib/arvados/gems
-export GEM_PATH=/var/lib/arvados/gems
+export GEM_HOME=/var/lib/gems
+export GEM_PATH=/var/lib/gems
 
 run_bundler() {
     if test -f Gemfile.lock ; then
diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run
index d290420..5c80964 100755
--- a/arvbox/docker/service/api/run
+++ b/arvbox/docker/service/api/run
@@ -45,11 +45,17 @@ common:
   git_repo_https_base: "http://$localip:9001/"
 EOF
 
+if ! test -f /var/lib/arvados/api_database_pw ; then
+    ruby -e 'puts rand(2**128).to_s(36)' > /var/lib/arvados/api_database_pw
+fi
+database_pw=$(cat /var/lib/arvados/api_database_pw)
+
 if ! test -f /var/lib/arvados/api_database_setup ; then
-   database_pw=$(ruby -e 'puts rand(2**128).to_s(36)')
    su postgres -c "psql -c \"create user arvados with password '$database_pw'\""
    su postgres -c "psql -c \"ALTER USER arvados CREATEDB;\""
-   cat >config/database.yml <<EOF
+fi
+
+cat >config/database.yml <<EOF
 development:
   adapter: postgresql
   encoding: utf8
@@ -67,6 +73,8 @@ test:
   host: localhost
   template: template0
 EOF
+
+if ! test -f /var/lib/arvados/api_database_setup ; then
    bundle exec rake db:setup
    touch /var/lib/arvados/api_database_setup
 fi
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
index 2b117b9..0908f01 100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run
@@ -59,8 +59,24 @@ fi
 
 if ! [[ -z "$waiting" ]] ; then
     if ps x | grep -v grep | grep "bundle install" > /dev/null; then
-        waiting="$waiting (installing ruby gems)"
+        gemcount=$(ls /var/lib/gems/gems 2>/dev/null | wc -l)
+
+        gemlockcount=0
+        for l in /usr/src/arvados/services/api/Gemfile.lock \
+                     /usr/src/arvados/apps/workbench/Gemfile.lock \
+                     /usr/src/sso/Gemfile.lock ; do
+            gc=$(cat $l \
+                        | grep -vE "(GEM|PLATFORMS|DEPENDENCIES|$^|remote:|specs:)" \
+                        | sed 's/^ *//' | sed 's/(.*)//' | sed 's/ *$//' | sort | uniq | wc -l)
+            gemlockcount=$(($gemlockcount + $gc))
+        done
+        waiting="$waiting (installing ruby gems $gemcount/$gemlockcount)"
+    fi
+
+    if ps x | grep -v grep | grep "c++.*/var/lib/passenger" > /dev/null ; then
+        waiting="$waiting (compiling passenger)"
     fi
+
     if ps x | grep -v grep | grep "pip install" > /dev/null; then
         waiting="$waiting (installing python packages)"
     fi
diff --git a/arvbox/docker/service/sso/run b/arvbox/docker/service/sso/run
index 718c526..73f6df5 100755
--- a/arvbox/docker/service/sso/run
+++ b/arvbox/docker/service/sso/run
@@ -7,7 +7,7 @@ set -eux
 
 cd /usr/src/sso
 export RAILS_ENV=development
-export GEM_HOME=/var/lib/arvados/gems
+export GEM_HOME=/var/lib/gems
 
 run_bundler --without=development
 
@@ -33,11 +33,17 @@ common:
   allow_account_registration: true
 EOF
 
+if ! test -f /var/lib/arvados/sso_database_pw ; then
+    ruby -e 'puts rand(2**128).to_s(36)' > /var/lib/arvados/sso_database_pw
+fi
+database_pw=$(cat /var/lib/arvados/sso_database_pw)
+
 if ! test -f /var/lib/arvados/sso_database_setup ; then
-   database_pw=$(ruby -e 'puts rand(2**128).to_s(36)')
-   su postgres -c "psql -c \"create user arvados_sso with password '$database_pw'\""
-   su postgres -c "psql -c \"ALTER USER arvados_sso CREATEDB;\""
-   cat >config/database.yml <<EOF
+    su postgres -c "psql -c \"create user arvados_sso with password '$database_pw'\""
+    su postgres -c "psql -c \"ALTER USER arvados_sso CREATEDB;\""
+fi
+
+cat >config/database.yml <<EOF
 development:
   adapter: postgresql
   encoding: utf8
@@ -55,6 +61,8 @@ test:
   host: localhost
   template: template0
 EOF
+
+if ! test -f /var/lib/arvados/sso_database_setup ; then
    bundle exec rake db:setup
 
    if ! test -s /var/lib/arvados/sso_app_secret ; then
diff --git a/arvbox/docker/service/workbench/run b/arvbox/docker/service/workbench/run
index ea7d242..1bbb5e7 100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run
@@ -7,7 +7,7 @@ set -eux
 
 cd /usr/src/arvados/apps/workbench
 export RAILS_ENV=development
-export GEM_HOME=/var/lib/arvados/gems
+export GEM_HOME=/var/lib/gems
 
 run_bundler --without=development
 
diff --git a/arvbox/docker/tests-service/docker/log/run b/arvbox/docker/tests-service/docker/log/run
new file mode 120000
index 0000000..f99cc1d
--- /dev/null
+++ b/arvbox/docker/tests-service/docker/log/run
@@ -0,0 +1 @@
+../../logger
\ No newline at end of file
diff --git a/arvbox/docker/tests-service/docker/run b/arvbox/docker/tests-service/docker/run
new file mode 100755
index 0000000..99540e6
--- /dev/null
+++ b/arvbox/docker/tests-service/docker/run
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+# Taken from https://github.com/jpetazzo/dind
+
+exec 2>&1
+
+#!/bin/bash
+
+# Ensure that all nodes in /dev/mapper correspond to mapped devices currently loaded by the device-mapper kernel driver
+dmsetup mknodes
+
+# First, make sure that cgroups are mounted correctly.
+CGROUP=/sys/fs/cgroup
+: {LOG:=stdio}
+
+[ -d $CGROUP ] ||
+	mkdir $CGROUP
+
+mountpoint -q $CGROUP ||
+	mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP || {
+		echo "Could not make a tmpfs mount. Did you use --privileged?"
+		exit 1
+	}
+
+if [ -d /sys/kernel/security ] && ! mountpoint -q /sys/kernel/security
+then
+    mount -t securityfs none /sys/kernel/security || {
+        echo "Could not mount /sys/kernel/security."
+        echo "AppArmor detection and --privileged mode might break."
+    }
+fi
+
+# Mount the cgroup hierarchies exactly as they are in the parent system.
+for SUBSYS in $(cut -d: -f2 /proc/1/cgroup)
+do
+        [ -d $CGROUP/$SUBSYS ] || mkdir $CGROUP/$SUBSYS
+        mountpoint -q $CGROUP/$SUBSYS ||
+                mount -n -t cgroup -o $SUBSYS cgroup $CGROUP/$SUBSYS
+
+        # The two following sections address a bug which manifests itself
+        # by a cryptic "lxc-start: no ns_cgroup option specified" when
+        # trying to start containers withina container.
+        # The bug seems to appear when the cgroup hierarchies are not
+        # mounted on the exact same directories in the host, and in the
+        # container.
+
+        # Named, control-less cgroups are mounted with "-o name=foo"
+        # (and appear as such under /proc/<pid>/cgroup) but are usually
+        # mounted on a directory named "foo" (without the "name=" prefix).
+        # Systemd and OpenRC (and possibly others) both create such a
+        # cgroup. To avoid the aforementioned bug, we symlink "foo" to
+        # "name=foo". This shouldn't have any adverse effect.
+        echo $SUBSYS | grep -q ^name= && {
+                NAME=$(echo $SUBSYS | sed s/^name=//)
+                ln -s $SUBSYS $CGROUP/$NAME
+        }
+
+        # Likewise, on at least one system, it has been reported that
+        # systemd would mount the CPU and CPU accounting controllers
+        # (respectively "cpu" and "cpuacct") with "-o cpuacct,cpu"
+        # but on a directory called "cpu,cpuacct" (note the inversion
+        # in the order of the groups). This tries to work around it.
+        [ $SUBSYS = cpuacct,cpu ] && ln -s $SUBSYS $CGROUP/cpu,cpuacct
+done
+
+# Note: as I write those lines, the LXC userland tools cannot setup
+# a "sub-container" properly if the "devices" cgroup is not in its
+# own hierarchy. Let's detect this and issue a warning.
+grep -q :devices: /proc/1/cgroup ||
+	echo "WARNING: the 'devices' cgroup should be in its own hierarchy."
+grep -qw devices /proc/1/cgroup ||
+	echo "WARNING: it looks like the 'devices' cgroup is not mounted."
+
+# Now, close extraneous file descriptors.
+pushd /proc/self/fd >/dev/null
+for FD in *
+do
+	case "$FD" in
+	# Keep stdin/stdout/stderr
+	[012])
+		;;
+	# Nuke everything else
+	*)
+		eval exec "$FD>&-"
+		;;
+	esac
+done
+popd >/dev/null
+
+
+# If a pidfile is still around (for example after a container restart),
+# delete it so that docker can start.
+rm -rf /var/run/docker.pid
+
+exec docker daemon --storage-driver=overlay $DOCKER_DAEMON_ARGS
diff --git a/arvbox/docker/tests-service/logger b/arvbox/docker/tests-service/logger
new file mode 100755
index 0000000..a79a518
--- /dev/null
+++ b/arvbox/docker/tests-service/logger
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec svlogd -tt ./main

commit 1f01b5bfd46cf5eb6ff06d84fd3515c9d8c5d6ef
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Mon Jan 4 09:45:05 2016 -0500

    8080: Move arvados and arvados-dev checkouts to ~/.arvbox.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index b0c1f52..ee8910c 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -2,33 +2,33 @@
 
 set -e
 
-ARVBOX=$(readlink -f $(dirname $0))
+ARVBOX_SCRIPT=$(readlink -f $(dirname $0))
 
-if test -z "$ARVADOS_ROOT" ; then
-    ARVADOS_ROOT=$ARVBOX/arvados
+if test -z "$ARVBOX_CONTAINER" ; then
+    ARVBOX_CONTAINER=arvbox
 fi
 
-if test -z "$ARVADOS_DEV_ROOT" ; then
-    ARVADOS_DEV_ROOT=$ARVBOX/arvados-dev
+if test -z "$ARVBOX_DATA" ; then
+    ARVBOX_DATA=$HOME/.arvbox/$ARVBOX_CONTAINER
 fi
 
-if test -z "$SSO_ROOT" ; then
-    SSO_ROOT=$ARVBOX/sso-devise-omniauth-provider
+if test -z "$ARVADOS_ROOT" ; then
+    ARVADOS_ROOT=$ARVBOX_DATA/arvados
 fi
 
-if test -z "$ARVBOX_CONTAINER" ; then
-    ARVBOX_CONTAINER=arvbox
+if test -z "$ARVADOS_DEV_ROOT" ; then
+    ARVADOS_DEV_ROOT=$ARVBOX_DATA/arvados-dev
 fi
 
-if test -z "$ARVBOX_DATA" ; then
-    ARVBOX_DATA=$HOME/.arvbox/$ARVBOX_CONTAINER
+if test -z "$SSO_ROOT" ; then
+    SSO_ROOT=$ARVBOX_DATA/sso-devise-omniauth-provider
 fi
 
 PASSENGER=$ARVBOX_DATA/passenger
 PG_DATA=$ARVBOX_DATA/postgres
-ARV_DATA=$ARVBOX_DATA/var
+VAR_DATA=$ARVBOX_DATA/var
 
-mkdir -p $PASSENGER $PG_DATA $ARV_DATA
+mkdir -p $PASSENGER $PG_DATA $VAR_DATA
 
 run() {
     if ! test -d $ARVADOS_ROOT ; then
@@ -47,7 +47,7 @@ run() {
                --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
                --volume=$SSO_ROOT:/usr/src/sso:rw \
                --volume=$PG_DATA:/var/lib/postgresql:rw \
-               --volume=$ARV_DATA:/var/lib/arvados:rw \
+               --volume=$VAR_DATA:/var/lib/arvados:rw \
                --volume=$PASSENGER:/var/lib/passenger:rw \
                --volume=/var/lib/docker \
                arvados/arvbox \
@@ -60,7 +60,7 @@ run() {
                --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
                --volume=$SSO_ROOT:/usr/src/sso:rw \
                --volume=$PG_DATA:/var/lib/postgresql:rw \
-               --volume=$ARV_DATA:/var/lib/arvados:rw \
+               --volume=$VAR_DATA:/var/lib/arvados:rw \
                --volume=$PASSENGER:/var/lib/passenger:rw \
                --volume=/var/lib/docker \
                arvados/arvbox
@@ -87,7 +87,7 @@ stop() {
 
 case $1 in
     build)
-        cd $ARVBOX
+        cd $ARVBOX_SCRIPT
         docker build -t arvados/arvbox docker
         ;;
 
@@ -126,12 +126,11 @@ case $1 in
 
     reset)
         if test "$2" != -f ; then
-            echo "WARNING!  This will delete all data inside your arvbox ($PG_DATA and $ARV_DATA).  Use reset -f if you really mean it."
+            echo "WARNING!  This will delete all code and data inside your arvbox ($ARVBOX_DATA).  Use reset -f if you really mean it."
             exit 1
         fi
         stop
-        sudo rm -rf $PG_DATA
-        sudo rm -rf $ARV_DATA
+        sudo rm -rf $ARVBOX_DATA
         ;;
 
     log)

commit 05348254357bd32e126e7a7ee0e8cfc5bb87cc5f
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 30 16:57:38 2015 -0500

    Use default docker driver with overlayfs as fallback.

diff --git a/arvbox/docker/service/docker/run b/arvbox/docker/service/docker/run
index 99540e6..93834ee 100755
--- a/arvbox/docker/service/docker/run
+++ b/arvbox/docker/service/docker/run
@@ -92,4 +92,9 @@ popd >/dev/null
 # delete it so that docker can start.
 rm -rf /var/run/docker.pid
 
-exec docker daemon --storage-driver=overlay $DOCKER_DAEMON_ARGS
+read pid cmd state ppid pgrp session tty_nr tpgid rest < /proc/self/stat
+trap "kill -TERM -$pgrp; exit" EXIT TERM KILL SIGKILL SIGTERM SIGQUIT
+
+if ! docker daemon $DOCKER_DAEMON_ARGS ; then
+    docker daemon --storage-driver=overlay $DOCKER_DAEMON_ARGS
+fi

commit 01cf08200a38f781a62283ebb6099f46a5bf13ef
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 30 16:34:14 2015 -0500

    --frozen based on whether there is Gemfile.lock

diff --git a/arvbox/docker/common.sh b/arvbox/docker/common.sh
index 80fbac3..ffed7fd 100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
@@ -3,8 +3,13 @@ export GEM_HOME=/var/lib/arvados/gems
 export GEM_PATH=/var/lib/arvados/gems
 
 run_bundler() {
-    if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment --frozen "$@" ; then
-        flock /var/lib/arvados/gems.lock bundle install --no-deployment --frozen "$@"
+    if test -f Gemfile.lock ; then
+        frozen=--frozen
+    else
+        frozen=""
+    fi
+    if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment $frozen "$@" ; then
+        flock /var/lib/arvados/gems.lock bundle install --no-deployment $frozen "$@"
     fi
 }
 

commit db8892cca34b4fcc62c3352d1a8bd828abaa0a3d
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 30 16:06:23 2015 -0500

    8080: Remove call to bundle install outside if statement.

diff --git a/arvbox/docker/common.sh b/arvbox/docker/common.sh
index 37bbf8e..80fbac3 100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
@@ -3,7 +3,6 @@ export GEM_HOME=/var/lib/arvados/gems
 export GEM_PATH=/var/lib/arvados/gems
 
 run_bundler() {
-    flock /var/lib/arvados/gems.lock bundle install --local --no-deployment --frozen "$@"
     if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment --frozen "$@" ; then
         flock /var/lib/arvados/gems.lock bundle install --no-deployment --frozen "$@"
     fi

commit e6b3ab8f24716b8bc8f09fcd3bcbbfa2c154d330
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Tue Dec 29 16:48:28 2015 -0500

    8080: Set GEM_HOME in arvbox shell

diff --git a/arvbox/arvbox b/arvbox/arvbox
index ed31d9b..b0c1f52 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -96,7 +96,7 @@ case $1 in
         ;;
 
     sh*)
-        docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM /bin/bash
+        docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM GEM_HOME=/var/lib/arvados/gems /bin/bash
         ;;
 
     stop)

commit 1fd2d0cc54423adb0e0fd3676af15a7ace42f468
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Sun Dec 27 16:53:28 2015 -0500

    8080: Easier support for multiple containers.  Rename tests -> run-tests.  Refactor run()

diff --git a/arvbox/arvbox b/arvbox/arvbox
index 931a248..ed31d9b 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -16,14 +16,14 @@ if test -z "$SSO_ROOT" ; then
     SSO_ROOT=$ARVBOX/sso-devise-omniauth-provider
 fi
 
-if test -z "$ARVBOX_DATA" ; then
-    ARVBOX_DATA=$HOME/.arvbox
-fi
-
 if test -z "$ARVBOX_CONTAINER" ; then
     ARVBOX_CONTAINER=arvbox
 fi
 
+if test -z "$ARVBOX_DATA" ; then
+    ARVBOX_DATA=$HOME/.arvbox/$ARVBOX_CONTAINER
+fi
+
 PASSENGER=$ARVBOX_DATA/passenger
 PG_DATA=$ARVBOX_DATA/postgres
 ARV_DATA=$ARVBOX_DATA/var
@@ -38,33 +38,48 @@ run() {
         git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
     fi
 
-    docker run \
-           --detach \
-           --name=$ARVBOX_CONTAINER \
-           --privileged \
-           --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-           --volume=$SSO_ROOT:/usr/src/sso:rw \
-           --volume=$PG_DATA:/var/lib/postgresql:rw \
-           --volume=$ARV_DATA:/var/lib/arvados:rw \
-           --volume=$PASSENGER:/var/lib/passenger:rw \
-           --volume=/var/lib/docker \
-           arvados/arvbox
-
-    FF=/tmp/arvbox-fifo-$$
-    mkfifo $FF
-    docker logs -f $ARVBOX_CONTAINER > $FF &
-    LOGPID=$!
-    while read line ; do
-        echo $line
-        if echo $line | grep "Workbench is running at" >/dev/null ; then
-            kill $LOGPID
-        fi
-    done < $FF
-    rm $FF
+    if test "$1" = testing ; then
+        docker run \
+               --detach \
+               --name=$ARVBOX_CONTAINER \
+               --privileged \
+               --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+               --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
+               --volume=$SSO_ROOT:/usr/src/sso:rw \
+               --volume=$PG_DATA:/var/lib/postgresql:rw \
+               --volume=$ARV_DATA:/var/lib/arvados:rw \
+               --volume=$PASSENGER:/var/lib/passenger:rw \
+               --volume=/var/lib/docker \
+               arvados/arvbox \
+               runsvdir /etc/tests-service
+    else
+        docker run \
+               --detach \
+               --name=$ARVBOX_CONTAINER \
+               --privileged \
+               --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+               --volume=$SSO_ROOT:/usr/src/sso:rw \
+               --volume=$PG_DATA:/var/lib/postgresql:rw \
+               --volume=$ARV_DATA:/var/lib/arvados:rw \
+               --volume=$PASSENGER:/var/lib/passenger:rw \
+               --volume=/var/lib/docker \
+               arvados/arvbox
+        FF=/tmp/arvbox-fifo-$$
+        mkfifo $FF
+        docker logs -f $ARVBOX_CONTAINER > $FF &
+        LOGPID=$!
+        while read line ; do
+            echo $line
+            if echo $line | grep "Workbench is running at" >/dev/null ; then
+                kill $LOGPID
+            fi
+        done < $FF
+        rm $FF
+    fi
 }
 
 stop() {
-    if docker ps |grep -E "\b$ARVBOX_CONTAINER\b" -q ; then
+    if docker ps -a |grep -E "\b$ARVBOX_CONTAINER\b" -q ; then
         docker stop $ARVBOX_CONTAINER
         docker rm $ARVBOX_CONTAINER
     fi
@@ -123,26 +138,14 @@ case $1 in
         docker exec -ti $ARVBOX_CONTAINER tail -n40 /etc/service/$2/log/main/current
         ;;
 
-    tests)
+    run-tests)
         stop
 
         if ! test -d $ARVADOS_DEV_ROOT ; then
             git clone https://github.com/curoverse/arvados-dev.git $ARVADOS_DEV_ROOT
         fi
 
-        docker run \
-               --detach \
-               --name=$ARVBOX_CONTAINER \
-               --privileged \
-               --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-               --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
-               --volume=$SSO_ROOT:/usr/src/sso:rw \
-               --volume=$PG_DATA:/var/lib/postgresql:rw \
-               --volume=$ARV_DATA:/var/lib/arvados:rw \
-               --volume=$PASSENGER:/var/lib/passenger:rw \
-               --volume=/var/lib/docker \
-               arvados/arvbox \
-               runsvdir /etc/tests-service
+        run testing
 
         shift
         docker exec -ti $ARVBOX_CONTAINER /usr/src/arvados-dev/jenkins/run-tests.sh \
@@ -154,11 +157,8 @@ case $1 in
                GEMHOME=/var/lib/arvados/gems \
                GEM_HOME=/var/lib/arvados/gems \
                "$@"
-        docker stop $ARVBOX_CONTAINER
-        docker rm $ARVBOX_CONTAINER
         ;;
 
-
     *)
         echo "Arvados-in-a-box"
         echo
@@ -174,6 +174,6 @@ case $1 in
         echo "reset      delete persistent data (careful!)"
         echo "log <component>       tail log of specified service"
         echo "svrestart <component> restart specified service inside arvbox"
-        echo "tests      run run-tests.sh inside $ARVBOX_CONTAINER container"
+        echo "run-tests  run run-tests.sh inside $ARVBOX_CONTAINER container"
         ;;
 esac

commit 7c7c2f10db25a1af16a523677444c802c66c807b
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Thu Dec 24 14:59:11 2015 -0500

    8080: Don't do "bundle package" (breaks arvbox gem sharing).

diff --git a/jenkins/run-tests.sh b/jenkins/run-tests.sh
index a7b5fda..e50d485 100755
--- a/jenkins/run-tests.sh
+++ b/jenkins/run-tests.sh
@@ -589,7 +589,6 @@ bundle_install_trylocal() {
             echo "(Running bundle install again, without --local.)"
             bundle install --no-deployment
         fi
-        bundle package --all
     )
 }
 

commit e2bffcc799a671160c682131799c5b15e0a154d8
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 17:59:03 2015 -0500

    Adjust workbench secret token path.

diff --git a/arvbox/docker/service/workbench/run b/arvbox/docker/service/workbench/run
index a08136c..ea7d242 100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run
@@ -11,10 +11,10 @@ export GEM_HOME=/var/lib/arvados/gems
 
 run_bundler --without=development
 
-if ! test -s secret_token ; then
-  ruby -e 'puts rand(2**400).to_s(36)' > secret_token
+if ! test -s /var/lib/arvados/workbench_secret_token ; then
+  ruby -e 'puts rand(2**400).to_s(36)' > /var/lib/arvados/workbench_secret_token
 fi
-secret_token=$(cat secret_token)
+secret_token=$(cat /var/lib/arvados/workbench_secret_token)
 
 if ! test -s self-signed.key ; then
   openssl req -new -x509 -nodes -out self-signed.pem -keyout self-signed.key -days 365 -subj '/CN=localhost'

commit 2bcee7c582ec07011c4e097703d4d56358ce15de
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 17:56:04 2015 -0500

    8080: Set GEM_HOME as well as GEMHOME.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index 22973ac..931a248 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -152,6 +152,7 @@ case $1 in
                VENV3DIR=/var/lib/arvados/tests-venv3 \
                GOPATH=/var/lib/arvados/tests-gostuff \
                GEMHOME=/var/lib/arvados/gems \
+               GEM_HOME=/var/lib/arvados/gems \
                "$@"
         docker stop $ARVBOX_CONTAINER
         docker rm $ARVBOX_CONTAINER

commit 46dca4e67a3068571e8787fd43bde3520cf8c71b
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 17:33:52 2015 -0500

    Use locally cached gems and python packages.

diff --git a/arvbox/docker/common.sh b/arvbox/docker/common.sh
index 20d164c..37bbf8e 100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
@@ -1,8 +1,29 @@
 localip=$(ip addr show eth0 |grep "inet " | sed 's/ *inet \([^/]*\).*/\1/')
 export GEM_HOME=/var/lib/arvados/gems
+export GEM_PATH=/var/lib/arvados/gems
 
 run_bundler() {
-    if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment "$@" ; then
-        flock /var/lib/arvados/gems.lock bundle install --no-deployment "$@"
+    flock /var/lib/arvados/gems.lock bundle install --local --no-deployment --frozen "$@"
+    if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment --frozen "$@" ; then
+        flock /var/lib/arvados/gems.lock bundle install --no-deployment --frozen "$@"
+    fi
+}
+
+pip_install() {
+    pushd /var/lib/arvados/pip
+    for p in $(ls http*.tar.gz) ; do
+        if test -f $p ; then
+            ln -sf $p $(echo $p | sed 's/.*%2F\(.*\)/\1/')
+        fi
+    done
+    for p in $(ls http*.whl) ; do
+        if test -f $p ; then
+            ln -sf $p $(echo $p | sed 's/.*%2F\(.*\)/\1/')
+        fi
+    done
+    popd
+
+    if ! pip install --no-index --find-links /var/lib/arvados/pip $1 ; then
+        pip install $1
     fi
 }
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
index 60ac664..2b117b9 100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run
@@ -49,6 +49,14 @@ if ! docker version >/dev/null 2>/dev/null ; then
   waiting="$waiting docker"
 fi
 
+if ! which arv >/dev/null ; then
+  waiting="$waiting ruby_sdk"
+fi
+
+if ! which arv-get >/dev/null ; then
+  waiting="$waiting python_sdk"
+fi
+
 if ! [[ -z "$waiting" ]] ; then
     if ps x | grep -v grep | grep "bundle install" > /dev/null; then
         waiting="$waiting (installing ruby gems)"
diff --git a/arvbox/docker/service/sdk/run b/arvbox/docker/service/sdk/run
index 10df374..e5e8880 100755
--- a/arvbox/docker/service/sdk/run
+++ b/arvbox/docker/service/sdk/run
@@ -1,8 +1,10 @@
-#!/bin/sh
+#!/bin/bash
 
 exec 2>&1
 set -eux
 
+. /root/common.sh
+
 mkdir -p ~/.pip /var/lib/arvados/pip
 cat > ~/.pip/pip.conf <<EOF
 [global]
@@ -10,15 +12,16 @@ download_cache = /var/lib/arvados/pip
 EOF
 
 cd /usr/src/arvados/sdk/cli
-bundle install --binstubs=binstubs
+run_bundler --binstubs=$PWD/binstubs
 ln -sf /usr/src/arvados/sdk/cli/binstubs/arv /usr/bin/arv
 
+
 cd /usr/src/arvados/sdk/python
 python setup.py sdist
-pip install $(ls dist/arvados-python-client-*.tar.gz | tail -n1)
+pip_install $(ls dist/arvados-python-client-*.tar.gz | tail -n1)
 
 cd /usr/src/arvados/services/fuse
 python setup.py sdist
-pip install $(ls dist/arvados_fuse-*.tar.gz | tail -n1)
+pip_install $(ls dist/arvados_fuse-*.tar.gz | tail -n1)
 
 sv stop sdk

commit e5a6bdc1950973910e748f2ccc655741d3a73604
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 15:59:08 2015 -0500

    8080: Use shared gems directory, use flock so that only one bundler process updates
    it at once.  Use same container for tests or demo run.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index 357cefc..22973ac 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -23,9 +23,6 @@ fi
 if test -z "$ARVBOX_CONTAINER" ; then
     ARVBOX_CONTAINER=arvbox
 fi
-if test -z "$ARVBOX_TEST_CONTAINER" ; then
-    ARVBOX_TEST_CONTAINER=arvbox-tests
-fi
 
 PASSENGER=$ARVBOX_DATA/passenger
 PG_DATA=$ARVBOX_DATA/postgres
@@ -84,7 +81,7 @@ case $1 in
         ;;
 
     sh*)
-        docker exec -ti $ARVBOX_CONTAINER /bin/bash
+        docker exec -ti $ARVBOX_CONTAINER /usr/bin/env TERM=$TERM /bin/bash
         ;;
 
     stop)
@@ -127,47 +124,44 @@ case $1 in
         ;;
 
     tests)
+        stop
+
         if ! test -d $ARVADOS_DEV_ROOT ; then
             git clone https://github.com/curoverse/arvados-dev.git $ARVADOS_DEV_ROOT
         fi
 
-        if docker ps |grep -E "\b$ARVBOX_TEST_CONTAINER\b" -q ; then
-            docker start $ARVBOX_TEST_CONTAINER
-        else
-            docker run \
-                   --detach \
-                   --name=$ARVBOX_TEST_CONTAINER \
-                   --privileged \
-                   --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-                   --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
-                   --volume=$SSO_ROOT:/usr/src/sso:rw \
-                   --volume=$PG_DATA:/var/lib/postgresql:rw \
-                   --volume=$ARV_DATA:/var/lib/arvados:rw \
-                   --volume=$PASSENGER:/var/lib/passenger:rw \
-                   --volume=/var/lib/docker \
-                   arvados/arvbox \
-                   runsvdir /etc/tests-service
-        fi
+        docker run \
+               --detach \
+               --name=$ARVBOX_CONTAINER \
+               --privileged \
+               --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+               --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
+               --volume=$SSO_ROOT:/usr/src/sso:rw \
+               --volume=$PG_DATA:/var/lib/postgresql:rw \
+               --volume=$ARV_DATA:/var/lib/arvados:rw \
+               --volume=$PASSENGER:/var/lib/passenger:rw \
+               --volume=/var/lib/docker \
+               arvados/arvbox \
+               runsvdir /etc/tests-service
+
         shift
-        docker exec -ti $ARVBOX_TEST_CONTAINER /usr/src/arvados-dev/jenkins/run-tests.sh \
+        docker exec -ti $ARVBOX_CONTAINER /usr/src/arvados-dev/jenkins/run-tests.sh \
                --leave-temp \
                WORKSPACE=/usr/src/arvados \
                VENVDIR=/var/lib/arvados/tests-venv \
                VENV3DIR=/var/lib/arvados/tests-venv3 \
                GOPATH=/var/lib/arvados/tests-gostuff \
+               GEMHOME=/var/lib/arvados/gems \
                "$@"
-        docker stop $ARVBOX_TEST_CONTAINER
-        ;;
-
-    stop-tests)
-        docker rm $ARVBOX_TEST_CONTAINER
+        docker stop $ARVBOX_CONTAINER
+        docker rm $ARVBOX_CONTAINER
         ;;
 
 
     *)
         echo "Arvados-in-a-box"
         echo
-        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|log|svrestart|tests|stop-tests)"
+        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|log|svrestart|tests)"
         echo
         echo "build      build arvbox Docker image"
         echo "start|run  start $ARVBOX_CONTAINER container "
@@ -179,7 +173,6 @@ case $1 in
         echo "reset      delete persistent data (careful!)"
         echo "log <component>       tail log of specified service"
         echo "svrestart <component> restart specified service inside arvbox"
-        echo "tests      run run-tests.sh inside $ARVBOX_TEST_CONTAINER container"
-        echo "stop-tests stop $ARVBOX_TEST_CONTAINER container"
+        echo "tests      run run-tests.sh inside $ARVBOX_CONTAINER container"
         ;;
 esac
diff --git a/arvbox/docker/common.sh b/arvbox/docker/common.sh
index 16297ba..20d164c 100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
@@ -1 +1,8 @@
 localip=$(ip addr show eth0 |grep "inet " | sed 's/ *inet \([^/]*\).*/\1/')
+export GEM_HOME=/var/lib/arvados/gems
+
+run_bundler() {
+    if ! flock /var/lib/arvados/gems.lock bundle install --local --no-deployment "$@" ; then
+        flock /var/lib/arvados/gems.lock bundle install --no-deployment "$@"
+    fi
+}
diff --git a/arvbox/docker/service/api/run b/arvbox/docker/service/api/run
index 935c93c..d290420 100755
--- a/arvbox/docker/service/api/run
+++ b/arvbox/docker/service/api/run
@@ -8,7 +8,7 @@ set -eux
 cd /usr/src/arvados/services/api
 export RAILS_ENV=development
 
-bundle install --without=development --path=vendor
+run_bundler --without=development
 
 if ! test -s /var/lib/arvados/api_uuid_prefix ; then
   ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/api_uuid_prefix
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
index 17cc0eb..60ac664 100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run
@@ -50,8 +50,14 @@ if ! docker version >/dev/null 2>/dev/null ; then
 fi
 
 if ! [[ -z "$waiting" ]] ; then
-  echo "    Waiting for$waiting ..."
-  exit 1
+    if ps x | grep -v grep | grep "bundle install" > /dev/null; then
+        waiting="$waiting (installing ruby gems)"
+    fi
+    if ps x | grep -v grep | grep "pip install" > /dev/null; then
+        waiting="$waiting (installing python packages)"
+    fi
+    echo "    Waiting for$waiting ..."
+    exit 1
 fi
 
 echo
diff --git a/arvbox/docker/service/sso/run b/arvbox/docker/service/sso/run
index 953ea95..718c526 100755
--- a/arvbox/docker/service/sso/run
+++ b/arvbox/docker/service/sso/run
@@ -7,8 +7,9 @@ set -eux
 
 cd /usr/src/sso
 export RAILS_ENV=development
+export GEM_HOME=/var/lib/arvados/gems
 
-bundle install --without=development --path=vendor
+run_bundler --without=development
 
 if ! test -s /var/lib/arvados/sso_uuid_prefix ; then
   ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/sso_uuid_prefix
diff --git a/arvbox/docker/service/vm/run b/arvbox/docker/service/vm/run
index 0bdd8ea..807d976 100755
--- a/arvbox/docker/service/vm/run
+++ b/arvbox/docker/service/vm/run
@@ -38,7 +38,7 @@ fi
 export ARVADOS_VIRTUAL_MACHINE_UUID
 
 cd /usr/src/arvados/services/login-sync
-bundle install
+run_bundler
 
 while true ; do
       bundle exec arvados-login-sync
diff --git a/arvbox/docker/service/workbench/run b/arvbox/docker/service/workbench/run
index 50f5b26..a08136c 100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run
@@ -7,8 +7,9 @@ set -eux
 
 cd /usr/src/arvados/apps/workbench
 export RAILS_ENV=development
+export GEM_HOME=/var/lib/arvados/gems
 
-bundle install --without=development --path=vendor
+run_bundler --without=development
 
 if ! test -s secret_token ; then
   ruby -e 'puts rand(2**400).to_s(36)' > secret_token

commit 0df06e7b8af5ebfa6675fc84f2d3bd81a1b0d7a8
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 13:34:25 2015 -0500

    Added readme.  Fixed keep-setup.sh.  Add note that first time takes a long time.

diff --git a/arvbox/.gitignore b/arvbox/.gitignore
deleted file mode 100644
index a79dc86..0000000
--- a/arvbox/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-arvados/
-arvados-dev/
-sso-devise-omniauth-provider/
-passenger/
-postgres/
-var/
-*~
diff --git a/arvbox/README b/arvbox/README
new file mode 100644
index 0000000..f6b7267
--- /dev/null
+++ b/arvbox/README
@@ -0,0 +1,18 @@
+Arvados-in-a-box
+
+Development and demonstration environment for Arvados.
+
+Usage:
+
+$ ./arvbox reboot
+
+Notes:
+
+Services are designed to install and auto-configure on start or restart.  For
+example, the service script for keepstore always compiles keepstore from source
+and registers the daemon with the API server.
+
+Services are run with process supervision, so a service which exits will be
+restarted.  Dependencies between services are handled by repeatedly trying and
+failing the service script until dependencies are fulfilled (by other service
+scripts) enabling the service script to complete.
diff --git a/arvbox/docker/keep-setup.sh b/arvbox/docker/keep-setup.sh
index c321070..a4f8832 100755
--- a/arvbox/docker/keep-setup.sh
+++ b/arvbox/docker/keep-setup.sh
@@ -50,6 +50,6 @@ fi
 exec /usr/local/bin/keepstore \
      -listen=:$2 \
      -enforce-permissions=true \
-     -blob-signing-key-file=/usr/src/arvados/services/api/blob_signing_key \
+     -blob-signing-key-file=/var/lib/arvados/blob_signing_key \
      -max-buffers=20 \
      -volume=/var/lib/arvados/keep
diff --git a/arvbox/docker/service/ready/run b/arvbox/docker/service/ready/run
index 8e03e3e..17cc0eb 100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run
@@ -8,6 +8,9 @@ if ! [[ -d /root/ready ]] ; then
    echo
    echo "Arvados-in-a-box starting"
    echo
+   echo "Note: if this is a fresh arvbox installation, it may take 10-15 minutes to download and"
+   echo "install dependencies.  Use \"arvbox log\" to monitor the progress of specific services."
+   echo
    mkdir -p /root/ready
 fi
 
@@ -57,4 +60,4 @@ echo "Workbench is running at http://$localip"
 
 rm -r /root/ready
 
-sv stop ready >/dev/null
\ No newline at end of file
+sv stop ready >/dev/null

commit 367e48543244672e1656e50848bed6f99dc393dc
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 13:22:29 2015 -0500

    8080: Missing postgres

diff --git a/arvbox/arvbox b/arvbox/arvbox
index 737f800..357cefc 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -1,8 +1,8 @@
 #!/bin/sh
 
-ARVBOX=$(readlink -f $(dirname $0))
-
+set -e
 
+ARVBOX=$(readlink -f $(dirname $0))
 
 if test -z "$ARVADOS_ROOT" ; then
     ARVADOS_ROOT=$ARVBOX/arvados
@@ -34,6 +34,13 @@ ARV_DATA=$ARVBOX_DATA/var
 mkdir -p $PASSENGER $PG_DATA $ARV_DATA
 
 run() {
+    if ! test -d $ARVADOS_ROOT ; then
+        git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
+    fi
+    if ! test -d $SSO_ROOT ; then
+        git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
+    fi
+
     docker run \
            --detach \
            --name=$ARVBOX_CONTAINER \
@@ -60,8 +67,10 @@ run() {
 }
 
 stop() {
+    if docker ps |grep -E "\b$ARVBOX_CONTAINER\b" -q ; then
         docker stop $ARVBOX_CONTAINER
         docker rm $ARVBOX_CONTAINER
+    fi
 }
 
 case $1 in
@@ -71,13 +80,6 @@ case $1 in
         ;;
 
     start|run)
-        if ! test -d $ARVADOS_ROOT ; then
-            git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
-        fi
-        if ! test -d $SSO_ROOT ; then
-            git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
-        fi
-
         run
         ;;
 
diff --git a/arvbox/docker/service/postgres/log/main/.gitstub b/arvbox/docker/service/postgres/log/main/.gitstub
new file mode 100644
index 0000000..e69de29
diff --git a/arvbox/docker/service/postgres/log/run b/arvbox/docker/service/postgres/log/run
new file mode 120000
index 0000000..f99cc1d
--- /dev/null
+++ b/arvbox/docker/service/postgres/log/run
@@ -0,0 +1 @@
+../../logger
\ No newline at end of file
diff --git a/arvbox/docker/service/postgres/run b/arvbox/docker/service/postgres/run
new file mode 100755
index 0000000..2b7c497
--- /dev/null
+++ b/arvbox/docker/service/postgres/run
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+exec 2>&1
+set -eux
+
+chown postgres:postgres -R /var/lib/postgresql
+if ! test -d /var/lib/postgresql/9.4/main ; then
+   su postgres -c "/usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main"
+fi
+mkdir -p /var/run/postgresql/9.4-main.pg_stat_tmp
+chown postgres:postgres -R /var/run/postgresql
+
+exec su postgres -c "/usr/lib/postgresql/9.4/bin/postgres -D /var/lib/postgresql/9.4/main -c config_file=/etc/postgresql/9.4/main/postgresql.conf"

commit 867a4c46855eaaf4b018da59c973806dbb4c7e04
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 13:03:08 2015 -0500

    Update documentation, and use ~/.arvbox as default data dir.

diff --git a/arvbox/arvbox b/arvbox/arvbox
index 44bde6f..737f800 100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
@@ -2,6 +2,8 @@
 
 ARVBOX=$(readlink -f $(dirname $0))
 
+
+
 if test -z "$ARVADOS_ROOT" ; then
     ARVADOS_ROOT=$ARVBOX/arvados
 fi
@@ -15,7 +17,7 @@ if test -z "$SSO_ROOT" ; then
 fi
 
 if test -z "$ARVBOX_DATA" ; then
-    ARVBOX_DATA=$ARVBOX
+    ARVBOX_DATA=$HOME/.arvbox
 fi
 
 if test -z "$ARVBOX_CONTAINER" ; then
@@ -94,8 +96,8 @@ case $1 in
         run
         ;;
 
-    sv|service)
-        docker exec -ti $ARVBOX_CONTAINER sv $2 $3
+    svrestart)
+        docker exec -ti $ARVBOX_CONTAINER sv restart $2
         docker exec -ti $ARVBOX_CONTAINER sv restart ready
         ;;
 
@@ -163,15 +165,19 @@ case $1 in
     *)
         echo "Arvados-in-a-box"
         echo
-        echo "$0 (build|start|run|stop|shell|stop|ip|open|resetdb|log)"
+        echo "$0 (build|start|run|open|shell|ip|stop|reboot|reset|log|svrestart|tests|stop-tests)"
         echo
         echo "build      build arvbox Docker image"
-        echo "start|run  start arvbox"
-        echo "stop       stop arvbo"
+        echo "start|run  start $ARVBOX_CONTAINER container "
+        echo "open       open arvbox workbench in a web browser"
         echo "shell      enter arvbox shell"
         echo "ip         print arvbox ip address"
-        echo "open       open arvbox workbench in a web browser"
-        echo "resetdb    delete persistent data (be careful!)"
-        echo "log <component> tail log of specified service"
+        echo "stop       stop arvbox"
+        echo "reboot     stop arvbox, build image, run"
+        echo "reset      delete persistent data (careful!)"
+        echo "log <component>       tail log of specified service"
+        echo "svrestart <component> restart specified service inside arvbox"
+        echo "tests      run run-tests.sh inside $ARVBOX_TEST_CONTAINER container"
+        echo "stop-tests stop $ARVBOX_TEST_CONTAINER container"
         ;;
 esac

commit c99df01959c27fc140e0124c509380a81948847b
Merge: bbed885 3e62819
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 12:55:36 2015 -0500

    Add 'arvbox/' from commit '3e62819af509f174087c3cebbccb97f3851e6919'
    
    git-subtree-dir: arvbox
    git-subtree-mainline: bbed885afb9007c5d81ff55af70e8d7be92f8f37
    git-subtree-split: 3e62819af509f174087c3cebbccb97f3851e6919

diff --cc arvbox/.gitignore
index 0000000,a79dc86..a79dc86
mode 000000,100644..100644
--- a/arvbox/.gitignore
+++ b/arvbox/.gitignore
diff --cc arvbox/arvbox
index 0000000,44bde6f..44bde6f
mode 000000,100755..100755
--- a/arvbox/arvbox
+++ b/arvbox/arvbox
diff --cc arvbox/docker/Dockerfile
index 0000000,85acd0f..85acd0f
mode 000000,100644..100644
--- a/arvbox/docker/Dockerfile
+++ b/arvbox/docker/Dockerfile
diff --cc arvbox/docker/common.sh
index 0000000,16297ba..16297ba
mode 000000,100644..100644
--- a/arvbox/docker/common.sh
+++ b/arvbox/docker/common.sh
diff --cc arvbox/docker/crunch-setup.sh
index 0000000,4b70250..4b70250
mode 000000,100755..100755
--- a/arvbox/docker/crunch-setup.sh
+++ b/arvbox/docker/crunch-setup.sh
diff --cc arvbox/docker/fuse.conf
index 0000000,a439ab8..a439ab8
mode 000000,100644..100644
--- a/arvbox/docker/fuse.conf
+++ b/arvbox/docker/fuse.conf
diff --cc arvbox/docker/gitolite-setup.sh
index 0000000,9a2ff9e..9a2ff9e
mode 000000,100755..100755
--- a/arvbox/docker/gitolite-setup.sh
+++ b/arvbox/docker/gitolite-setup.sh
diff --cc arvbox/docker/gitolite.rc
index 0000000,b735870..b735870
mode 000000,100644..100644
--- a/arvbox/docker/gitolite.rc
+++ b/arvbox/docker/gitolite.rc
diff --cc arvbox/docker/gitssh-setup.sh
index 0000000,aad7dd4..aad7dd4
mode 000000,100755..100755
--- a/arvbox/docker/gitssh-setup.sh
+++ b/arvbox/docker/gitssh-setup.sh
diff --cc arvbox/docker/keep-setup.sh
index 0000000,c321070..c321070
mode 000000,100755..100755
--- a/arvbox/docker/keep-setup.sh
+++ b/arvbox/docker/keep-setup.sh
diff --cc arvbox/docker/runit-docker/.gitignore
index 0000000,bbf313b..bbf313b
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/.gitignore
+++ b/arvbox/docker/runit-docker/.gitignore
diff --cc arvbox/docker/runit-docker/LICENSE
index 0000000,d158667..d158667
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/LICENSE
+++ b/arvbox/docker/runit-docker/LICENSE
diff --cc arvbox/docker/runit-docker/Makefile
index 0000000,9a28963..9a28963
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/Makefile
+++ b/arvbox/docker/runit-docker/Makefile
diff --cc arvbox/docker/runit-docker/README.md
index 0000000,1bcb8cc..1bcb8cc
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/README.md
+++ b/arvbox/docker/runit-docker/README.md
diff --cc arvbox/docker/runit-docker/debian/changelog
index 0000000,7d8689f..7d8689f
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/debian/changelog
+++ b/arvbox/docker/runit-docker/debian/changelog
diff --cc arvbox/docker/runit-docker/debian/compat
index 0000000,ec63514..ec63514
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/debian/compat
+++ b/arvbox/docker/runit-docker/debian/compat
diff --cc arvbox/docker/runit-docker/debian/control
index 0000000,4060915..4060915
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/debian/control
+++ b/arvbox/docker/runit-docker/debian/control
diff --cc arvbox/docker/runit-docker/debian/copyright
index 0000000,8679a6a..8679a6a
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/debian/copyright
+++ b/arvbox/docker/runit-docker/debian/copyright
diff --cc arvbox/docker/runit-docker/debian/docs
index 0000000,b43bf86..b43bf86
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/debian/docs
+++ b/arvbox/docker/runit-docker/debian/docs
diff --cc arvbox/docker/runit-docker/debian/rules
index 0000000,ce15cce..ce15cce
mode 000000,100755..100755
--- a/arvbox/docker/runit-docker/debian/rules
+++ b/arvbox/docker/runit-docker/debian/rules
diff --cc arvbox/docker/runit-docker/debian/source/format
index 0000000,163aaf8..163aaf8
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/debian/source/format
+++ b/arvbox/docker/runit-docker/debian/source/format
diff --cc arvbox/docker/runit-docker/runit-docker
index 0000000,fdbaad5..fdbaad5
mode 000000,100755..100755
--- a/arvbox/docker/runit-docker/runit-docker
+++ b/arvbox/docker/runit-docker/runit-docker
diff --cc arvbox/docker/runit-docker/runit-docker.c
index 0000000,825a35f..825a35f
mode 000000,100644..100644
--- a/arvbox/docker/runit-docker/runit-docker.c
+++ b/arvbox/docker/runit-docker/runit-docker.c
diff --cc arvbox/docker/service/api/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/api/log/main/.gitstub
+++ b/arvbox/docker/service/api/log/main/.gitstub
diff --cc arvbox/docker/service/api/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/api/log/run
+++ b/arvbox/docker/service/api/log/run
diff --cc arvbox/docker/service/api/run
index 0000000,935c93c..935c93c
mode 000000,100755..100755
--- a/arvbox/docker/service/api/run
+++ b/arvbox/docker/service/api/run
diff --cc arvbox/docker/service/crunch0/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/crunch0/log/main/.gitstub
+++ b/arvbox/docker/service/crunch0/log/main/.gitstub
diff --cc arvbox/docker/service/crunch0/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/crunch0/log/run
+++ b/arvbox/docker/service/crunch0/log/run
diff --cc arvbox/docker/service/crunch0/run
index 0000000,dd864a0..dd864a0
mode 000000,100755..100755
--- a/arvbox/docker/service/crunch0/run
+++ b/arvbox/docker/service/crunch0/run
diff --cc arvbox/docker/service/crunch1/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/crunch1/log/main/.gitstub
+++ b/arvbox/docker/service/crunch1/log/main/.gitstub
diff --cc arvbox/docker/service/crunch1/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/crunch1/log/run
+++ b/arvbox/docker/service/crunch1/log/run
diff --cc arvbox/docker/service/crunch1/run
index 0000000,d7583e5..d7583e5
mode 000000,100755..100755
--- a/arvbox/docker/service/crunch1/run
+++ b/arvbox/docker/service/crunch1/run
diff --cc arvbox/docker/service/docker/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/docker/log/main/.gitstub
+++ b/arvbox/docker/service/docker/log/main/.gitstub
diff --cc arvbox/docker/service/docker/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/docker/log/run
+++ b/arvbox/docker/service/docker/log/run
diff --cc arvbox/docker/service/docker/run
index 0000000,99540e6..99540e6
mode 000000,100755..100755
--- a/arvbox/docker/service/docker/run
+++ b/arvbox/docker/service/docker/run
diff --cc arvbox/docker/service/git/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/git/log/main/.gitstub
+++ b/arvbox/docker/service/git/log/main/.gitstub
diff --cc arvbox/docker/service/git/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/git/log/run
+++ b/arvbox/docker/service/git/log/run
diff --cc arvbox/docker/service/git/run
index 0000000,c87c25b..c87c25b
mode 000000,100755..100755
--- a/arvbox/docker/service/git/run
+++ b/arvbox/docker/service/git/run
diff --cc arvbox/docker/service/githttp/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/githttp/log/main/.gitstub
+++ b/arvbox/docker/service/githttp/log/main/.gitstub
diff --cc arvbox/docker/service/githttp/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/githttp/log/run
+++ b/arvbox/docker/service/githttp/log/run
diff --cc arvbox/docker/service/githttp/run
index 0000000,390727d..390727d
mode 000000,100755..100755
--- a/arvbox/docker/service/githttp/run
+++ b/arvbox/docker/service/githttp/run
diff --cc arvbox/docker/service/keep0/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/keep0/log/main/.gitstub
+++ b/arvbox/docker/service/keep0/log/main/.gitstub
diff --cc arvbox/docker/service/keep0/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/keep0/log/run
+++ b/arvbox/docker/service/keep0/log/run
diff --cc arvbox/docker/service/keep0/run
index 0000000,aa5b69c..aa5b69c
mode 000000,100755..100755
--- a/arvbox/docker/service/keep0/run
+++ b/arvbox/docker/service/keep0/run
diff --cc arvbox/docker/service/keep1/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/keep1/log/main/.gitstub
+++ b/arvbox/docker/service/keep1/log/main/.gitstub
diff --cc arvbox/docker/service/keep1/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/keep1/log/run
+++ b/arvbox/docker/service/keep1/log/run
diff --cc arvbox/docker/service/keep1/run
index 0000000,8b0d907..8b0d907
mode 000000,100755..100755
--- a/arvbox/docker/service/keep1/run
+++ b/arvbox/docker/service/keep1/run
diff --cc arvbox/docker/service/keepproxy/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/keepproxy/log/main/.gitstub
+++ b/arvbox/docker/service/keepproxy/log/main/.gitstub
diff --cc arvbox/docker/service/keepproxy/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/keepproxy/log/run
+++ b/arvbox/docker/service/keepproxy/log/run
diff --cc arvbox/docker/service/keepproxy/run
index 0000000,fe52d6d..fe52d6d
mode 000000,100755..100755
--- a/arvbox/docker/service/keepproxy/run
+++ b/arvbox/docker/service/keepproxy/run
diff --cc arvbox/docker/service/keepweb/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/keepweb/log/main/.gitstub
+++ b/arvbox/docker/service/keepweb/log/main/.gitstub
diff --cc arvbox/docker/service/keepweb/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/keepweb/log/run
+++ b/arvbox/docker/service/keepweb/log/run
diff --cc arvbox/docker/service/keepweb/run
index 0000000,ad808fe..ad808fe
mode 000000,100755..100755
--- a/arvbox/docker/service/keepweb/run
+++ b/arvbox/docker/service/keepweb/run
diff --cc arvbox/docker/service/logger
index 0000000,a79a518..a79a518
mode 000000,100755..100755
--- a/arvbox/docker/service/logger
+++ b/arvbox/docker/service/logger
diff --cc arvbox/docker/service/ready/run
index 0000000,8e03e3e..8e03e3e
mode 000000,100755..100755
--- a/arvbox/docker/service/ready/run
+++ b/arvbox/docker/service/ready/run
diff --cc arvbox/docker/service/sdk/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/sdk/log/main/.gitstub
+++ b/arvbox/docker/service/sdk/log/main/.gitstub
diff --cc arvbox/docker/service/sdk/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/sdk/log/run
+++ b/arvbox/docker/service/sdk/log/run
diff --cc arvbox/docker/service/sdk/run
index 0000000,10df374..10df374
mode 000000,100755..100755
--- a/arvbox/docker/service/sdk/run
+++ b/arvbox/docker/service/sdk/run
diff --cc arvbox/docker/service/ssh/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/ssh/log/main/.gitstub
+++ b/arvbox/docker/service/ssh/log/main/.gitstub
diff --cc arvbox/docker/service/ssh/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/ssh/log/run
+++ b/arvbox/docker/service/ssh/log/run
diff --cc arvbox/docker/service/ssh/run
index 0000000,0db3ffa..0db3ffa
mode 000000,100755..100755
--- a/arvbox/docker/service/ssh/run
+++ b/arvbox/docker/service/ssh/run
diff --cc arvbox/docker/service/sso/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/sso/log/main/.gitstub
+++ b/arvbox/docker/service/sso/log/main/.gitstub
diff --cc arvbox/docker/service/sso/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/sso/log/run
+++ b/arvbox/docker/service/sso/log/run
diff --cc arvbox/docker/service/sso/run
index 0000000,953ea95..953ea95
mode 000000,100755..100755
--- a/arvbox/docker/service/sso/run
+++ b/arvbox/docker/service/sso/run
diff --cc arvbox/docker/service/vm/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/vm/log/main/.gitstub
+++ b/arvbox/docker/service/vm/log/main/.gitstub
diff --cc arvbox/docker/service/vm/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/vm/log/run
+++ b/arvbox/docker/service/vm/log/run
diff --cc arvbox/docker/service/vm/run
index 0000000,0bdd8ea..0bdd8ea
mode 000000,100755..100755
--- a/arvbox/docker/service/vm/run
+++ b/arvbox/docker/service/vm/run
diff --cc arvbox/docker/service/workbench/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/service/workbench/log/main/.gitstub
+++ b/arvbox/docker/service/workbench/log/main/.gitstub
diff --cc arvbox/docker/service/workbench/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/service/workbench/log/run
+++ b/arvbox/docker/service/workbench/log/run
diff --cc arvbox/docker/service/workbench/run
index 0000000,50f5b26..50f5b26
mode 000000,100755..100755
--- a/arvbox/docker/service/workbench/run
+++ b/arvbox/docker/service/workbench/run
diff --cc arvbox/docker/tests-service/postgres/log/main/.gitstub
index 0000000,e69de29..e69de29
mode 000000,100644..100644
--- a/arvbox/docker/tests-service/postgres/log/main/.gitstub
+++ b/arvbox/docker/tests-service/postgres/log/main/.gitstub
diff --cc arvbox/docker/tests-service/postgres/log/run
index 0000000,f99cc1d..f99cc1d
mode 000000,120000..120000
--- a/arvbox/docker/tests-service/postgres/log/run
+++ b/arvbox/docker/tests-service/postgres/log/run
diff --cc arvbox/docker/tests-service/postgres/run
index 0000000,2b7c497..2b7c497
mode 000000,100755..100755
--- a/arvbox/docker/tests-service/postgres/run
+++ b/arvbox/docker/tests-service/postgres/run

commit 3e62819af509f174087c3cebbccb97f3851e6919
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 12:52:28 2015 -0500

    Can also run run-tests (but many tests fail).

diff --git a/arvbox b/arvbox
index 98e4838..44bde6f 100755
--- a/arvbox
+++ b/arvbox
@@ -147,10 +147,10 @@ case $1 in
         shift
         docker exec -ti $ARVBOX_TEST_CONTAINER /usr/src/arvados-dev/jenkins/run-tests.sh \
                --leave-temp \
-               WORKSPACE=/usr/src/arvados
-               VENVDIR=/var/lib/arvados/tests/venv \
-               VENV3DIR=/var/lib/arvados/tests/venv3 \
-               GOPATH=/var/lib/arvados/tests/gostuff \
+               WORKSPACE=/usr/src/arvados \
+               VENVDIR=/var/lib/arvados/tests-venv \
+               VENV3DIR=/var/lib/arvados/tests-venv3 \
+               GOPATH=/var/lib/arvados/tests-gostuff \
                "$@"
         docker stop $ARVBOX_TEST_CONTAINER
         ;;
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d004952..85acd0f 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,6 +1,7 @@
 FROM debian:8
 
-RUN apt-get update && apt-get -y -q install \
+RUN apt-get update && \
+    DEBIAN_FRONTEND=noninteractive apt-get -yq install \
     postgresql-9.4 git gcc golang-go runit \
     ruby rake bundler curl libpq-dev \
     libcurl4-openssl-dev libssl-dev zlib1g-dev libpcre3-dev \
@@ -9,12 +10,11 @@ RUN apt-get update && apt-get -y -q install \
     pkg-config libattr1-dev python-llfuse python-pycurl \
     libwww-perl libio-socket-ssl-perl libcrypt-ssleay-perl \
     libjson-perl python-virtualenv python3-virtualenv nginx \
-    gitolite3
+    gitolite3 lsof
 
 RUN curl -sSL https://get.docker.com/ | sh
 
 ADD runit-docker /root/runit-docker
-ADD gitolite /root/gitolite
 
 RUN cd /root/runit-docker && \
     make && \
diff --git a/docker/gitssh-setup.sh b/docker/gitssh-setup.sh
index 41c280d..aad7dd4 100755
--- a/docker/gitssh-setup.sh
+++ b/docker/gitssh-setup.sh
@@ -11,7 +11,9 @@ if ! test -s .ssh/id_rsa ; then
     ssh-keygen -t rsa -P '' -f .ssh/id_rsa
 fi
 
-ssh-keygen -f "/var/lib/arvados/git/.ssh/known_hosts" -R localhost
+if test -s /var/lib/arvados/git/.ssh/known_hosts ; then
+    ssh-keygen -f "/var/lib/arvados/git/.ssh/known_hosts" -R localhost
+fi
 
 if ! test -s .ssh/authorized_keys ; then
     cp .ssh/id_rsa.pub .ssh/authorized_keys
diff --git a/docker/service/git/run b/docker/service/git/run
index 6e79f26..c87c25b 100755
--- a/docker/service/git/run
+++ b/docker/service/git/run
@@ -9,11 +9,10 @@ mkdir -p /var/lib/arvados/git
 
 export ARVADOS_API_HOST=$localip:3001
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/api_superuser_token)
+export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
 if ! test -f /var/lib/arvados/gitolite-setup ; then
-   cp -r /root/gitolite /var/lib/arvados/git/
-   cp -r /root/gitolite /root/gitolite-setup.sh /root/gitssh-setup.sh /root/gitolite.rc /var/lib/arvados/git/
+   cp -r /root/gitolite-setup.sh /root/gitssh-setup.sh /root/gitolite.rc /var/lib/arvados/git/
 
    chown -R git:git ~git
 
@@ -26,6 +25,8 @@ else
     su git -c "/var/lib/arvados/git/gitssh-setup.sh"
 fi
 
+prefix=$(arv --format=uuid user current | cut -d- -f1)
+
 if ! test -s /var/lib/arvados/arvados-git-uuid ; then
     repo_uuid=$(arv --format=uuid repository create --repository "{\"owner_uuid\":\"$prefix-tpzed-000000000000000\", \"name\":\"arvados\"}")
     echo $repo_uuid > /var/lib/arvados/arvados-git-uuid
@@ -34,7 +35,6 @@ fi
 repo_uuid=$(cat /var/lib/arvados/arvados-git-uuid)
 
 if ! test -s /var/lib/arvados/arvados-git-link-uuid ; then
-    prefix=$(arv --format=uuid user current | cut -d- -f1)
     all_users_group_uuid="$prefix-j7d0g-fffffffffffffff"
 
     set +e
diff --git a/docker/service/keepweb/run b/docker/service/keepweb/run
index e549087..ad808fe 100755
--- a/docker/service/keepweb/run
+++ b/docker/service/keepweb/run
@@ -16,6 +16,6 @@ install bin/keep-web /usr/local/bin
 
 export ARVADOS_API_HOST=$localip:3001
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/api_superuser_token)
+export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
 exec /usr/local/bin/keep-web -trust-all-content -listen=":25099"
diff --git a/docker/service/vm/run b/docker/service/vm/run
index 0c13547..0bdd8ea 100755
--- a/docker/service/vm/run
+++ b/docker/service/vm/run
@@ -11,7 +11,7 @@ git config --system "credential.http://$localip:9001/.helper" '!cred(){ cat >/de
 
 export ARVADOS_API_HOST=$localip:3001
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/api_superuser_token)
+export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
 if test -s /var/lib/arvados/vm-uuid ; then
     ARVADOS_VIRTUAL_MACHINE_UUID=$(cat /var/lib/arvados/vm-uuid)

commit 5240eb2532921c731553615c1bb96463b82cfb4b
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 11:08:15 2015 -0500

    Use debian gitolite3 package instead of bundling our own.

diff --git a/.gitignore b/.gitignore
index a45f4ab..a79dc86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 arvados/
+arvados-dev/
 sso-devise-omniauth-provider/
 passenger/
 postgres/
 var/
-*~
\ No newline at end of file
+*~
diff --git a/arvbox b/arvbox
index 42fa3a9..98e4838 100755
--- a/arvbox
+++ b/arvbox
@@ -6,6 +6,10 @@ if test -z "$ARVADOS_ROOT" ; then
     ARVADOS_ROOT=$ARVBOX/arvados
 fi
 
+if test -z "$ARVADOS_DEV_ROOT" ; then
+    ARVADOS_DEV_ROOT=$ARVBOX/arvados-dev
+fi
+
 if test -z "$SSO_ROOT" ; then
     SSO_ROOT=$ARVBOX/sso-devise-omniauth-provider
 fi
@@ -17,6 +21,9 @@ fi
 if test -z "$ARVBOX_CONTAINER" ; then
     ARVBOX_CONTAINER=arvbox
 fi
+if test -z "$ARVBOX_TEST_CONTAINER" ; then
+    ARVBOX_TEST_CONTAINER=arvbox-tests
+fi
 
 PASSENGER=$ARVBOX_DATA/passenger
 PG_DATA=$ARVBOX_DATA/postgres
@@ -115,6 +122,44 @@ case $1 in
         docker exec -ti $ARVBOX_CONTAINER tail -n40 /etc/service/$2/log/main/current
         ;;
 
+    tests)
+        if ! test -d $ARVADOS_DEV_ROOT ; then
+            git clone https://github.com/curoverse/arvados-dev.git $ARVADOS_DEV_ROOT
+        fi
+
+        if docker ps |grep -E "\b$ARVBOX_TEST_CONTAINER\b" -q ; then
+            docker start $ARVBOX_TEST_CONTAINER
+        else
+            docker run \
+                   --detach \
+                   --name=$ARVBOX_TEST_CONTAINER \
+                   --privileged \
+                   --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+                   --volume=$ARVADOS_DEV_ROOT:/usr/src/arvados-dev:rw \
+                   --volume=$SSO_ROOT:/usr/src/sso:rw \
+                   --volume=$PG_DATA:/var/lib/postgresql:rw \
+                   --volume=$ARV_DATA:/var/lib/arvados:rw \
+                   --volume=$PASSENGER:/var/lib/passenger:rw \
+                   --volume=/var/lib/docker \
+                   arvados/arvbox \
+                   runsvdir /etc/tests-service
+        fi
+        shift
+        docker exec -ti $ARVBOX_TEST_CONTAINER /usr/src/arvados-dev/jenkins/run-tests.sh \
+               --leave-temp \
+               WORKSPACE=/usr/src/arvados
+               VENVDIR=/var/lib/arvados/tests/venv \
+               VENV3DIR=/var/lib/arvados/tests/venv3 \
+               GOPATH=/var/lib/arvados/tests/gostuff \
+               "$@"
+        docker stop $ARVBOX_TEST_CONTAINER
+        ;;
+
+    stop-tests)
+        docker rm $ARVBOX_TEST_CONTAINER
+        ;;
+
+
     *)
         echo "Arvados-in-a-box"
         echo
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 60a6823..d004952 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -8,7 +8,8 @@ RUN apt-get update && apt-get -y -q install \
     libpython-dev fuse libfuse-dev python-pip \
     pkg-config libattr1-dev python-llfuse python-pycurl \
     libwww-perl libio-socket-ssl-perl libcrypt-ssleay-perl \
-    libjson-perl
+    libjson-perl python-virtualenv python3-virtualenv nginx \
+    gitolite3
 
 RUN curl -sSL https://get.docker.com/ | sh
 
@@ -29,6 +30,7 @@ RUN useradd crunch && \
 
 ADD crunch-setup.sh gitolite-setup.sh gitolite.rc gitssh-setup.sh keep-setup.sh common.sh /root/
 ADD service /etc/service
+ADD tests-service /etc/tests-service
 
 # Start the supervisor.
 CMD ["runsvdir", "/etc/service"]
diff --git a/docker/gitolite-setup.sh b/docker/gitolite-setup.sh
index 203fbec..9a2ff9e 100755
--- a/docker/gitolite-setup.sh
+++ b/docker/gitolite-setup.sh
@@ -4,9 +4,7 @@ set -e
 
 cd ~
 
-mkdir -p bin
-gitolite/install -ln ~git/bin
-bin/gitolite setup -pk .ssh/id_rsa.pub
+gitolite setup -pk .ssh/id_rsa.pub
 
 if ! test -d gitolite-admin ; then
     git clone git at localhost:gitolite-admin
diff --git a/docker/gitolite/CHANGELOG b/docker/gitolite/CHANGELOG
deleted file mode 100644
index 98e0174..0000000
--- a/docker/gitolite/CHANGELOG
+++ /dev/null
@@ -1,221 +0,0 @@
-2015-11-01  v3.6.4  a ref-create bug in wild repos was fixed
-
-                    some contrib code related to AD integration, and to
-                    redmine user aliases
-
-                    teach Alias.pm a few new tricks
-
-                    remove a race condition in 'create' command that affected
-                    the 'default roles' setting
-
-                    make 'who-pushed' more efficient (local push logs, and
-                    'tip search')
-
-                    'gitolite query-rc' learns '-d' ('--dump') option
-
-2015-04-26  v3.6.3  allow limited use of 'git config' using the new 'config'
-                    command
-
-                    accept openssh 6.8's new fingerprint output format
-
-                    (finally!) allow limited symlinks within ~/repositories;
-                    see commit 8e36230 for details
-
-                    perms command now lists available roles
-
-                    minor backward compat breakage: 'perms -l repo' no longer
-                    works; see 'perms -h' for new usage
-
-                    allow gitolite-shell to be used as $SHELL (experts only;
-                    no support, no docs; see commit 9cd1e37 for details)
-
-                    help with 'git push --signed' using a post-receive hook to
-                    adopt push certs into 'refs/push-certs'; for details see
-                    contrib/hooks/repo-specific/save-push-signatures
-
-                    new 'transparent proxy' feature for git repos; see
-                    src/lib/Gitolite/Triggers/TProxy.pm for details
-
-2014-11-10  v3.6.2  disable ../ everywhere (see mailing list thread for
-                    details)
-
-                    VREF/NAME_NC -- like VREF/NAME but for new commits only.
-                    Details within src/VREF/NAME_NC.
-
-                    allow gitolite.conf to be tested locally; details within
-                    contrib/utils/gitolite-local
-
-2014-06-22  v3.6.1  experimental rc format convertor for "<= 3.3" users who
-                    have already upgraded the *code* to ">= v3.4".  Program is
-                    in contrib/utils.
-
-                    giving shell access to a few users got a lot easier (see
-                    comments in the rc file).
-
-                    allow logging to syslog as well (see comments in the rc
-                    file)
-
-                    new 'motd' command
-
-                    redis caching redone and now in core; see
-                    http://gitolite.com/gitolite/cache.html
-
-2014-05-09  v3.6    (cool stuff) the access command can now help you debug
-                    your rules / understand how a specific access decision was
-                    arrived at.
-
-                    mirroring: since mirroring is asynchronous (by default
-                    anyway), when a 'git push --mirror' fails, you may not
-                    know it unless you look in the log file on the server.
-                    Now gitolite captures the info and -- if the word 'fatal'
-                    appears anywhere within it, it saves the entire output and
-                    prints it to STDERR for anyone who reads or writes the
-                    repo on the *master* server, until the error condition
-                    clears up.
-
-                    mirroring: allow 'nosync' slaves -- no attempt to
-                    automatically push to these slaves will be made.  Instead,
-                    you have to manually (or via cron, etc) trigger pushes.
-
-                    (backward compat breakage) the old v2 syntax for
-                    specifying gitweb owner and description is no longer
-                    supported.
-
-                    macros now allow strings as arguments (thanks to Jason
-                    Donenfeld for the idea/problem).
-
-                    the 'info' command can print in JSON format if asked to.
-
-                    repo-specific hooks: now you can specify more than one,
-                    and gitolite runs all of them in sequence.
-
-                    new trigger 'expand-deny-messages' to show more details
-                    when access is denied.
-
-                    git-annex support is finally in master, yaaay!
-
-                    new 'readme' command, modelled after 'desc'.  Apparently
-                    gitweb can use a README.html file in the *bare* repo
-                    directory -- who knew!
-
-2013-10-14  v3.5.3  catch undefined groupnames (when possible)
-
-                    mirroring: async push to slaves
-
-                    (some portability fixes)
-
-                    (a couple of contrib scripts - querying IPA based LDAP
-                    servers for group membership, and user key management)
-
-                    allow groups in subconf files (this *may* slow down
-                    compilation in extreme cases)
-
-                    make adding repo-specific hooks easier (see cust.mkd or
-                    cust.html online for docs)
-
-                    smart http now supports git 1.8.2 and above (which changed
-                    the protocol requirements a wee bit)
-
-2013-07-10  v3.5.2  allow ENV vars to be set from repo options, for use in
-                    triggers and hooks
-
-                    bug-fix: the new set-default-roles feature was being
-                    invoked on every run of "perms" and overriding it!
-
-2013-03-24  v3.5    (2 minor backward compat breakages)
-                    1.  'DEFAULT_ROLE_PERMS' replaced by per repo
-                        'default.roles' option
-                    2.  'gitolite list-memberships' now requires a '-r' or a
-                        '-u' flag
-
-                    new 'gitolite owns' command (thanks to Kevin Pulo)
-
-2013-03-05  v3.4    new rc file format makes it much easier to enable specific
-                    features
-
-2012-12-29  v3.3    bug fix: gl-perms propagation to slaves broke sometime
-                    after v3.2 (so if you're only picking up tagged releases
-                    you're OK)
-
-                    the "D" command now allows rm/unlock to be totally
-                    disabled
-
-                    new trigger: update-gitweb-daemon-from-options; another
-                    way to update gitweb and daemon access lists
-
-                    new 'create' command for explicit wild repo creation, and
-                    new AutoCreate trigger to control auto-creation
-
-                    allow simple macros in conf file
-
-2012-11-14  v3.2    major efficiency boost for large setups
-
-                    optional support for multi-line pubkeys; see
-                    src/triggers/post-compile/ssh-authkeys-split
-
-                    bug fix for not creating gl-conf when repo para has only
-                    config lines and no access rules
-
-                    new 'bg' trigger command to put long jobs started from a
-                    trigger into background
-
-                    %GL_REPO and %GL_CREATOR now work for 'option's also
-
-                    test suite now much more BSD friendly
-
-2012-10-05  v3.1    (security) fix path traversal on wild repos
-
-                    new %GL_CREATOR variable for git-config lines
-
-                    rsync command to create and send bundles automagically
-
-                    migrated 'who-pushed'
-
-                    logical expressions on refexes!!!
-
-2012-06-27  v3.04   documentation graduated and moved out of parents house :)
-
-                    new trigger for 'repo specific umask'
-
-                    new 'list-dangling-repos' command
-
-                    new LOCAL_CODE rc var; allow admin specified programs to
-                    override system-installed ones
-
-                    new 'upstream' trigger-cum-command to maintain local
-                    copies of external repos
-
-                    new 'sudo' command
-
-                    minor backward compat breakage in 'gitolite query-rc'
-
-                    'perms' command can now create repo if needed
-
-                    migrated 'symbolic-ref' command
-
-                    'gitolite setup --hooks-only'
-
-2012-05-23  v3.03   fix major bug that allowed an admin to get a shell
-
-2012-05-20  v3.02   packaging instructions fixed up and smoke tested
-
-                    make it easier to give some users a full shell
-
-                    allow aliasing a repo to another name
-
-                    simulate POST_CREATE for new normal (non-wild) repos
-
-                    (just for kicks) a VREF that allows for voting on changes
-                    to a branch
-
-                    bug fix: smart http was not running PRE_ and POST_GIT
-                    triggers
-
-                    htpasswd migrated
-
-2012-04-29  v3.01   mostly BSD and Solaris compat
-                    also fork command added
-
-2012-04-18  v3.0    first release to "master"
-                    This is a compete rewrite of gitolite; please see
-                    documentation before upgrading.
diff --git a/docker/gitolite/CONTRIBUTING b/docker/gitolite/CONTRIBUTING
deleted file mode 100644
index 11009ba..0000000
--- a/docker/gitolite/CONTRIBUTING
+++ /dev/null
@@ -1,24 +0,0 @@
-Go to http://gitolite.com/gitolite/index.html#contact for information on
-contacting me, the mailing list, and IRC channel.  *Unless you are reporting
-what you think is a security issue, I prefer you send to the mailing list,
-not to me directly.*
-
-Please DO NOT send messages via github's "issues" system, linkedin
-comments/discussion, stackoverflow questions, google+, and any other Web 3.0
-"coolness". (The issues system does have an email interface, but it is not a
-substitute for email. I can't cc anyone else when I want to, for instance.
-Well I can, but any response the original requester then makes using the
-website will not get cc-d to the person I cc-d).
-
-Please send patches *via email*, not as github pull requests. Again, if you
-think it's a security issue, send it directly to my gmail address, but
-otherwise please send it to the mailing list, so others can see it and comment
-on it.
-
-The preferred format is the files created by git-format-patch, as attachments.
-However, if your repo has a public clone URL, you can make a new branch just
-for this fix, and send the repo URL and branch name to the mailing list.
-
-(If you do send me a github pull request, I may take it if it's a trivial
-patch, but otherwise I'll ask you to close the pull request, then read
-this URL for how to send me the patch.)
diff --git a/docker/gitolite/COPYING b/docker/gitolite/COPYING
deleted file mode 100644
index 7d5393a..0000000
--- a/docker/gitolite/COPYING
+++ /dev/null
@@ -1,278 +0,0 @@
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                    GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                            NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
diff --git a/docker/gitolite/README.markdown b/docker/gitolite/README.markdown
deleted file mode 100644
index a211fab..0000000
--- a/docker/gitolite/README.markdown
+++ /dev/null
@@ -1,231 +0,0 @@
-Gitolite README
-===============
-
-## about this README
-
-**(Github-users: click the "wiki" link before sending me anything via github.)**
-
-**This is a minimal README for gitolite**, so you can quickly get started with:
-
-*   installing gitolite on a fresh userid on a Unix(-like) machine
-*   learning enough to do some basic access control
-
-**For anything more, you need to look at the complete documentation, at:
-<http://gitolite.com/gitolite>**.  Please go there for what/why/how, concepts,
-background, troubleshooting, more details on what is covered here, advanced
-features not covered here, migration from older gitolite, and many more
-topics.
-
-<!-- --------------------------------------------------------------------- -->
-
-## Assumptions
-
-*   You are familiar with:
-    *   OS: at least one Unix-like OS
-    *   ssh: ssh, ssh keys, ssh authorized keys file
-    *   git: basic use of git, bare and non-bare remotes
-
-*   You are setting up a fresh, ssh-based, installation of gitolite on a Unix
-    machine of some sort.
-
-*   You have root access, or someone has created a userid called "git" for you
-    to use and given you a password for it.  This is a brand new userid (or
-    you have deleted everything but `.bashrc` and similar files to make it
-    look like one!)
-
-*   If your server is not connected to the internet, you know how to clone the
-    gitolite source code by using some in-between server or "git bundle".
-
-<!-- --------------------------------------------------------------------- -->
-
-## Installation and setup
-
-### server requirements
-
-*   any unix system
-*   sh
-*   git 1.6.6 or later
-*   perl 5.8.8 or later
-*   openssh 5.0 or later
-*   a dedicated userid to host the repos (in this document, we assume it is
-    "git", but it can be anything; substitute accordingly)
-*   this user id does NOT currently have any ssh pubkey-based access
-    *   ideally, this user id has shell access ONLY by "su - git" from some
-        other userid on the same server (this ensure minimal confusion for ssh
-        newbies!)
-
-### steps to install
-
-First, prepare the ssh key:
-
-*   login to "git" on the server
-*   make sure `~/.ssh/authorized_keys` is empty or non-existent
-*   make sure your ssh public key from your workstation has been copied as
-    $HOME/YourName.pub
-
-Next, install gitolite by running these commands:
-
-    git clone git://github.com/sitaramc/gitolite
-    mkdir -p $HOME/bin
-    gitolite/install -to $HOME/bin
-
-Finally, setup gitolite with yourself as the administrator:
-
-    gitolite setup -pk YourName.pub
-
-If the last command doesn't run perhaps "bin" is not in your "PATH". You can
-either add it, or just run:
-
-    $HOME/bin/gitolite setup -pk YourName.pub
-
-If you get any other errors please refer to the online documentation whose URL
-was given at the top of this file.
-
-## adding users and repos
-
-*Do NOT add new repos or users manually on the server.*  Gitolite users,
-repos, and access rules are maintained by making changes to a special repo
-called "gitolite-admin" and *pushing* those changes to the server.
-
-To administer your gitolite installation, start by doing this on your
-workstation (if you have not already done so):
-
-    git clone git at host:gitolite-admin
-
->   -------------------------------------------------------------------------
-
->   **NOTE: if you are asked for a password, something went wrong.**.  Go hit
->   the link for the complete documentation earlier in this file.
-
->   -------------------------------------------------------------------------
-
-Now if you "cd gitolite-admin", you will see two subdirectories in it: "conf"
-and "keydir".
-
-To add new users alice, bob, and carol, obtain their public keys and add them
-to "keydir" as alice.pub, bob.pub, and carol.pub respectively.
-
-To add a new repo "foo" and give different levels of access to these
-users, edit the file "conf/gitolite.conf" and add lines like this:
-
-    repo foo
-        RW+         =   alice
-        RW          =   bob
-        R           =   carol
-
-Once you have made these changes, do something like this:
-
-    git add conf
-    git add keydir
-    git commit -m "added foo, gave access to alice, bob, carol"
-    git push
-
-When the push completes, gitolite will add the new users to
-`~/.ssh/authorized_keys` on the server, as well as create a new, empty, repo
-called "foo".
-
-## help for your users
-
-Once a user has sent you their public key and you have added them as
-specified above and given them access, you have to tell them what URL to
-access their repos at.  This is usually "git clone git at host:reponame"; see
-man git-clone for other forms.
-
-**NOTE**: again, if they are asked for a password, something is wrong.
-
-If they need to know what repos they have access to, they just have to run
-"ssh git at host info".
-
-## access rule examples
-
-Gitolite's access rules are very powerful.  The simplest use was already
-shown above.  Here is a slightly more detailed example:
-
-    repo foo
-        RW+                     =   alice
-        -   master              =   bob
-        -   refs/tags/v[0-9]    =   bob
-        RW                      =   bob
-        RW  refs/tags/v[0-9]    =   carol
-        R                       =   dave
-
-Here's what these example rules say:
-
-  * alice can do anything to any branch or tag -- create, push,
-    delete, rewind/overwrite etc.
-
-  * bob can create or fast-forward push any branch whose name does
-    not start with "master" and create any tag whose name does not
-    start with "v"+digit.
-
-  * carol can create tags whose names start with "v"+digit.
-
-  * dave can clone/fetch.
-
-Please see the main documentation linked above for all the gory details, as
-well as more features and examples.
-
-## groups
-
-Gitolite allows you to group users or repos for convenience.  Here's an
-example that creates two groups of users:
-
-    @staff      =   alice bob carol
-    @interns    =   ashok
-
-    repo secret
-        RW      =   @staff
-
-    repo foss
-        RW+     =   @staff
-        RW      =   @interns
-
-Group lists accumulate.  The following two lines have the same effect as
-the earlier definition of @staff above:
-
-    @staff      =   alice bob
-    @staff      =   carol
-
-You can also use group names in other group names:
-
-    @all-devs   =   @staff @interns
-
-Finally, @all is a special group name that is often convenient to use if
-you really mean "all repos" or "all users".
-
-## commands
-
-Users can run certain commands remotely, using ssh.  Running
-
-    ssh git at host help
-
-prints a list of available commands.
-
-The most commonly used command is "info".  All commands respond to a
-single argument of "-h" with suitable information.
-
-If you have shell on the server, you have a lot more commands available to
-you; try running "gitolite help".
-
-<!-- --------------------------------------------------------------------- -->
-
-## LICENSE
-
-# contact and support
-
-Please see <http://gitolite.com/gitolite/#contact> for mailing list and IRC
-info.
-
-# license
-
-The gitolite software is copyright Sitaram Chamarty and is licensed under the
-GPL v2; please see the file called COPYING in the source distribution.
-
-Please see <http://gitolite.com/gitolite/#license> for more.
-
->   -------------------------------------------------------------------------
-
->   **NOTE**: GIT is a trademark of Software Freedom Conservancy and my use of
->   "Gitolite" is under license.
-
->   -------------------------------------------------------------------------
diff --git a/docker/gitolite/check-g2-compat b/docker/gitolite/check-g2-compat
deleted file mode 100755
index 508c6fd..0000000
--- a/docker/gitolite/check-g2-compat
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/perl
-
-use Cwd;
-
-my $h  = $ENV{HOME};
-my $rc = "$h/.gitolite.rc";
-my %count;
-
-intro();
-
-msg( FATAL => "no rc file found; do you even *have* g2 running?" ) if not -f $rc;
-do $rc;
-unless ( $return = do $rc ) {
-    msg( FATAL => "couldn't parse $rc: $@" ) if $@;
-    msg( FATAL   => "couldn't do $rc: $!" ) unless defined $return;
-    msg( WARNING => "couldn't run $rc" )    unless $return;
-}
-
-print "checking rc file...\n";
-rc_basic();
-rest_of_rc();
-print "\n";
-
-print "checking conf file(s)...\n";
-conf();
-print "\n";
-
-print "checking repos...\n";
-repo();
-print "\n";
-
-print "...all done...\n";
-
-# ----------------------------------------------------------------------
-
-sub intro {
-    msg( INFO => "This program only checks for uses that make the new g3 completely unusable" );
-    msg( ''   => "or that might end up giving *more* access to someone if migrated as-is." );
-    msg( ''   => "It does NOT attempt to catch all the differences described in the docs." );
-    msg( '', '' );
-    msg( INFO => "'see docs' usually means the pre-migration checklist in" );
-    msg( '',  => "'g2migr.html'; to get there, start from the main migration" );
-    msg( '',  => "page at http://gitolite.com/gitolite/migr.html" );
-    msg( '', '' );
-}
-
-sub rc_basic {
-    msg( FATAL => "GL_ADMINDIR in the wrong place -- aborting; see docs" ) if $GL_ADMINDIR ne "$h/.gitolite";
-    msg( NOTE => "GL_ADMINDIR is in the right place; assuming you did not mess with" );
-    msg( '', "GL_CONF, GL_LOGT, GL_KEYDIR, and GL_CONF_COMPILED" );
-    msg( FATAL => "REPO_BASE in the wrong place -- aborting; see docs" ) if $REPO_BASE ne "$h/repositories" and $REPO_BASE ne "repositories";
-# ( abs or rel both ok)
-}
-
-sub rest_of_rc {
-    msg( SEVERE  => "GIT_PATH found; see docs" )                          if $GIT_PATH;
-    msg( SEVERE  => "GL_ALL_INCLUDES_SPECIAL found; see docs" )           if $GL_ALL_INCLUDES_SPECIAL;
-    msg( SEVERE  => "GL_NO_CREATE_REPOS not yet implemented" )            if $GL_NO_CREATE_REPOS;
-    msg( SEVERE  => "rsync not yet implemented" )                         if $RSYNC_BASE;
-    msg( WARNING => "ADMIN_POST_UPDATE_CHAINS_TO found; see docs" )       if $ADMIN_POST_UPDATE_CHAINS_TO;
-    msg( WARNING => "GL_NO_DAEMON_NO_GITWEB found; see docs" )            if $GL_NO_DAEMON_NO_GITWEB;
-    msg( WARNING => "GL_NO_SETUP_AUTHKEYS found; see docs" )              if $GL_NO_SETUP_AUTHKEYS;
-    msg( WARNING => "UPDATE_CHAINS_TO found; see docs" )                  if $UPDATE_CHAINS_TO;
-    msg( WARNING => "GL_ADC_PATH found; see docs" )                       if $GL_ADC_PATH;
-    msg( WARNING => "non-default GL_WILDREPOS_PERM_CATS found" ) if $GL_WILDREPOS_PERM_CATS ne 'READERS WRITERS';
-}
-
-sub conf {
-    chdir($h);
-    chdir($GL_ADMINDIR);
-
-    my $conf = `find . -name "*.conf" | xargs cat`;
-    msg( "SEVERE", "NAME rules; see docs" )                    if $conf =~ m(NAME/);
-    msg( "SEVERE", "subconf command in admin repo; see docs" ) if $conf =~ m(NAME/conf/fragments);
-    msg( "SEVERE", "mirroring used; see docs" )                if $conf =~ m(config +gitolite\.mirror\.);
-}
-
-sub repo {
-    chdir($h);
-    chdir($REPO_BASE);
-    my @creater = `find . -name gl-creater`;
-    if (@creater) {
-        msg( WARNING => "found " . scalar(@creater) . " gl-creater files; see docs" );
-    }
-
-    my @perms = `find . -name gl-perms | xargs egrep -l -w R\\|RW`;
-    if (@perms) {
-        msg( WARNING => "found " . scalar(@perms) . " gl-perms files with R or RW; see docs" );
-    }
-}
-
-sub msg {
-    my ( $type, $text ) = @_;
-    print "$type" if $type;
-    print "\t$text\n";
-    exit 1 if $type eq 'FATAL';
-
-    $count{$type}++ if $type;
-}
diff --git a/docker/gitolite/contrib/commands/ukm b/docker/gitolite/contrib/commands/ukm
deleted file mode 100755
index 8a2d361..0000000
--- a/docker/gitolite/contrib/commands/ukm
+++ /dev/null
@@ -1,732 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Easy;
-
-=for usage
-Usage for this command is not that simple. Please read the full
-documentation in
-https://github.com/sitaramc/gitolite-doc/blob/master/contrib/ukm.mkd
-or online at http://gitolite.com/gitolite/ukm.html.
-=cut
-
-usage() if @ARGV and $ARGV[0] eq '-h';
-
-# Terms used in this file.
-# pubkeypath: the (relative) filename of a public key starting from
-#   gitolite-admin/keydir. Examples: alice.pub, foo/bar/alice.pub,
-#   alice at home.pub, foo/alice at laptop.pub. You get more examples, if you
-#   replace "alice" by "bob at example.com".
-# userid: computed from a pubkeypath by removing any directory
-#   part, the '.pub' extension and the "old-style" @NAME classifier.
-#   The userid identifies a user in the gitolite.conf file.
-# keyid: an identifier for a key given on the command line.
-#   If the script is called by one of the super_key_managers, then the
-#   keyid is the pubkeypath without the '.pub' extension. Otherwise it
-#   is the userid for a guest.
-#   The keyid is normalized to lowercase letters.
-
-my $rb = $rc{GL_REPO_BASE};
-my $ab = $rc{GL_ADMIN_BASE};
-
-# This will be the subdirectory under "keydir" in which the guest
-# keys will be stored. To prevent denial of service, this directory
-# should better start with 'zzz'.
-# The actual value can be set through the GUEST_DIRECTORY resource.
-# WARNING: If this value is changed you must understand the consequences.
-#          There will be no support if guestkeys_dir is anything else than
-#          'zzz/guests'.
-my $guestkeys_dir = 'zzz/guests';
-
-# A guest key cannot have arbitrary names (keyid). Only keys that do *not*
-# match $forbidden_guest_pattern are allowed. Super-key-managers can add
-# any keyid.
-
-# This is the directory for additional keys of a self key manager.
-my $selfkeys_dir = 'zzz/self';
-# There is no flexibility for selfkeys. One must specify a keyid that
-# matches the regular expression '^@[a-z0-9]+$'. Note that all keyids
-# are transformed to lowercase before checking.
-my $required_self_pattern = qr([a-z0-9]+);
-my $selfkey_management = 0; # disable selfkey managment
-
-# For guest key managers the keyid must pass two tests.
-#   1) It must match the $required_guest_pattern regular expression.
-#   2) It must not match the $forbidden_guest_pattern regular expression.
-# Default for $forbidden_guest_pattern is qr(.), i.e., every keyid is
-# forbidden, or in other words, only the gitolite-admin can manage keys.
-# Default for $required_guest_pattern is such that the keyid must look
-# like an email address, i.e. must have exactly one @ and at least one
-# dot after the @.
-# Just setting 'ukm' => 1 in .gitolite.rc only allows the super-key-managers
-# (i.e., only the gitolite admin(s)) to manage keys.
-my $required_guest_pattern =
-    qr(^[0-9a-z][-0-9a-z._+]*@[-0-9a-z._+]+[.][-0-9a-z._+]+$);
-my $forbidden_guest_pattern = qr(.);
-
-die "The command 'ukm' is not enabled.\n" if ! $rc{'COMMANDS'}{'ukm'};
-
-my $km = $rc{'UKM_CONFIG'};
-if(ref($km) eq 'HASH') {
-    # If not set we only allow keyids that look like emails
-    my $rgp = $rc{'UKM_CONFIG'}{'REQUIRED_GUEST_PATTERN'} || '';
-    $required_guest_pattern = qr(^($rgp)$) if $rgp;
-    $forbidden_guest_pattern = $rc{'UKM_CONFIG'}{'FORBIDDEN_GUEST_PATTERN'}
-                            || $forbidden_guest_pattern;
-    $selfkey_management = $rc{'UKM_CONFIG'}{'SELFKEY_MANAGEMENT'} || 0;
-}
-
-# get the actual userid
-my $gl_user = $ENV{GL_USER};
-my $super_key_manager = is_admin(); # or maybe is_super_admin() ?
-
-# save arguments for later
-my $operation = shift || 'list';
-my $keyid     = shift || '';
-$keyid = lc $keyid; # normalize to lowercase ids
-
-my ($zop, $zfp, $zselector, $zuser) = get_pending($gl_user);
-# The following will only be true if a selfkey manager logs in to
-# perform a pending operation.
-my $pending_self = ($zop ne '');
-
-die "You are not a key manager.\n"
-    unless $super_key_manager || $pending_self
-           || in_group('guest-key-managers')
-           || in_group('self-key-managers');
-
-# Let's deal with the pending user first. The only allowed operations
-# that are to confirm the add operation with the random code
-# that must be provided via stdin or to undo a pending del operation.
-if ($pending_self) {
-    pending_user($gl_user, $zop, $zfp, $zselector, $zuser);
-    exit;
-}
-
-my @available_operations = ('list','add','del');
-die "unknown ukm subcommand: $operation\n"
-    unless grep {$operation eq $_} @available_operations;
-
-# get to the keydir
-_chdir("$ab/keydir");
-
-# Note that the program warns if it finds a fingerprint that maps to
-# different userids.
-my %userids = (); # mapping from fingerprint to userid
-my %fingerprints = (); # mapping from pubkeypath to fingerprint
-my %pubkeypaths = (); # mapping from userid to pubkeypaths
-                      # note that the result is a list of pubkeypaths
-
-# Guest keys are managed by people in the @guest-key-managers group.
-# They can only add/del keys in the $guestkeys_dir directory. In fact,
-# the guest key manager $gl_user has only access to keys inside
-# %guest_pubkeypaths.
-my %guest_pubkeypaths = (); # mapping from userid to pubkeypath for $gl_user
-
-# Self keys are managed by people in the @self-key-managers group.
-# They can only add/del keys in the $selfkeys_dir directory. In fact,
-# the self key manager $gl_user has only access to keys inside
-# %self_pubkeypaths.
-my %self_pubkeypaths = ();
-
-# These are the keys that are managed by a super key manager.
-my @all_pubkeypaths = `find . -type f -name "*.pub" 2>/dev/null | sort`;
-
-for my $pubkeypath (@all_pubkeypaths) {
-    chomp($pubkeypath);
-    my $fp = fingerprint($pubkeypath);
-    $fingerprints{$pubkeypath} = $fp;
-    my $userid = get_userid($pubkeypath);
-    my ($zop, $zfp, $zselector, $zuser) = get_pending($userid);
-    $userid = $zuser if $zop;
-    if (! defined $userids{$fp}) {
-        $userids{$fp} = $userid;
-    } else {
-        warn "key $fp is used for different user ids\n"
-            unless $userids{$fp} eq $userid;
-    }
-    push @{$pubkeypaths{$userid}}, $pubkeypath;
-    if ($pubkeypath =~ m|^./$guestkeys_dir/([^/]+)/[^/]+\.pub$|) {
-        push @{$guest_pubkeypaths{$userid}}, $pubkeypath if $gl_user eq $1;
-    }
-    if ($pubkeypath =~ m|^./$selfkeys_dir/([^/]+)/[^/]+\.pub$|) {
-        push @{$self_pubkeypaths{$userid}}, $pubkeypath if $gl_user eq $1;
-    }
-}
-
-###################################################################
-# do stuff according to the operation
-###################################################################
-
-if ( $operation eq 'list' ) {
-    list_pubkeys();
-    print "\n\n";
-    exit;
-}
-
-die "keyid required\n" unless $keyid;
-die "Not allowed to use '..' in keyid.\n" if $keyid =~ /\.\./;
-
-if ( $operation eq 'add' ) {
-    if ($super_key_manager) {
-        add_pubkey($gl_user, "$keyid.pub", safe_stdin());
-    } elsif (selfselector($keyid)) {
-        add_self($gl_user, $keyid, safe_stdin());
-    } else {
-        # assert ingroup('guest-key-managers');
-        add_guest($gl_user, $keyid, safe_stdin());
-    }
-} elsif ( $operation eq 'del' ) {
-    if ($super_key_manager) {
-        del_super($gl_user, "$keyid.pub");
-    } elsif (selfselector($keyid)) {
-        del_self($gl_user, $keyid);
-    } else {
-        # assert ingroup('guest-key-managers');
-        del_guest($gl_user, $keyid);
-    }
-}
-
-exit;
-
-
-###################################################################
-# only function definitions are following
-###################################################################
-
-# make a temp clone and switch to it
-our $TEMPDIR;
-BEGIN { $TEMPDIR = `mktemp -d -t tmp.XXXXXXXXXX`; chomp($TEMPDIR) }
-END { my $err = $?; `/bin/rm -rf $TEMPDIR`; $? = $err; }
-
-sub cd_temp_clone {
-    chomp($TEMPDIR);
-    hushed_git( "clone", "$rb/gitolite-admin.git", "$TEMPDIR/gitolite-admin" );
-    chdir("$TEMPDIR/gitolite-admin");
-    my $ip = $ENV{SSH_CONNECTION};
-    $ip =~ s/ .*//;
-    my ($zop, $zfp, $zselector, $zuser) = get_pending($ENV{GL_USER});
-    my $email = $zuser;
-    $email .= '@' . $ip  unless $email =~ m(@);
-    my $name = $zop ? "\@$zselector" : $zuser;
-    # Record the keymanager in the gitolite-admin repo as author of the change.
-    hushed_git( "config", "user.email", "$email" );
-    hushed_git( "config", "user.name",  "'$name from $ip'" );
-}
-
-# compute the fingerprint from the full path of a pubkey file
-sub fingerprint {
-    my $fp = `ssh-keygen -l -f $_[0]`;
-    die "does not seem to be a valid pubkey\n"
-        unless $fp =~ /(([0-9a-f]+:)+[0-9a-f]+) /i;
-    return $1;
-}
-
-
-# Read one line from STDIN and return it.
-#  If no data is available on STDIN after one second, the empty string
-# is returned.
-# If there is more than one line or there was an error in reading, the
-# function dies.
-sub safe_stdin {
-    use IO::Select;
-    my $s=IO::Select->new(); $s->add(\*STDIN);
-    return '' unless $s->can_read(1);
-    my $data;
-    my $ret = read STDIN, $data, 4096;
-    # current pubkeys are approx 400 bytes so we go a little overboard
-    die "could not read pubkey data" . ( defined($ret) ? "" : ": $!" ) . "\n"
-        unless $ret;
-    die "pubkey data seems to have more than one line\n" if $data =~ /\n./;
-    return $data;
-}
-
-# call git, be quiet
-sub hushed_git {
-    system("git " . join(" ", @_) . ">/dev/null 2>/dev/null");
-}
-
-# Extract the userid from the full path of the pubkey file (relative
-# to keydir/ and including the '.pub' extension.
-sub get_userid {
-    my ($u) = @_; # filename of pubkey relative to keydir/.
-    $u =~ s(.*/)();                # foo/bar/baz.pub -> baz.pub
-    $u =~ s/(\@[^.]+)?\.pub$//;    # baz.pub, baz at home.pub -> baz
-    return $u;
-}
-
-# Extract the @selector part from the full path of the pubkey file
-# (relative to keydir/ and including the '.pub' extension).
-# If there is no @selector part, the empty string is returned.
-# We also correctly extract the selector part from pending keys.
-sub get_selector {
-    my ($u) = @_; # filename of pubkey relative to keydir/.
-    $u =~ s(.*/)();                # foo/bar/baz.pub -> baz.pub
-    $u =~ s(\.pub$)();             # baz at home.pub -> baz at home
-    return $1 if $u =~ m/.\@($required_self_pattern)$/; # baz at home -> home
-    my ($zop, $zfp, $zselector, $zuser) = get_pending($u);
-    # If $u was not a pending key, then $zselector is the empty string.
-    return $zselector;
-}
-
-# Extract fingerprint, operation, selector, and true userid from a
-# pending userid.
-sub get_pending {
-    my ($gl_user) = @_;
-    return ($1, $2, $3, $4)
-       if ($gl_user=~/^zzz-(...)-([0-9a-f]{32})-($required_self_pattern)-(.*)/);
-    return ('', '', '', $gl_user)
-}
-
-# multiple / and are simplified to one / and the path is made relative
-sub sanitize_pubkeypath {
-    my ($pubkeypath) = @_;
-    $pubkeypath =~ s|//|/|g; # normalize path
-    $pubkeypath =~ s,\./,,g; # remove './' from path
-    return './'.$pubkeypath; # Don't allow absolute paths.
-}
-
-# This function is only relavant for guest key managers.
-# It returns true if the pattern is OK and false otherwise.
-sub required_guest_keyid {
-    my ($_) = @_;
-    /$required_guest_pattern/ and ! /$forbidden_guest_pattern/;
-}
-
-# The function takes a $keyid as input and returns the keyid with the
-# initial @ stripped if everything is fine. It aborts with an error if
-# selfkey management is not enabled or the function is called for a
-# non-self-key-manager.
-# If the required selfkey pattern is not matched, it returns an empty string.
-# Thus the function can be used to check whether a given keyid is a
-# proper selfkeyid.
-sub selfselector {
-    my ($keyid) = @_;
-    return '' unless $keyid =~ m(^\@($required_self_pattern)$);
-    $keyid = $1;
-    die "selfkey management is not enabled\n" unless $selfkey_management;
-    die "You are not a selfkey manager.\n" if ! in_group('self-key-managers');
-    return $keyid;
-}
-
-# Return the number of characters reserved for the userid field.
-sub userid_width {
-    my ($paths) = @_;
-    my (%pkpaths) = %{$paths};
-    my (@userid_lengths) = sort {$a <=> $b} (map {length($_)} keys %pkpaths);
-    @userid_lengths ? $userid_lengths[-1] : 0;
-}
-
-# List the keys given by a reference to a hash.
-# The regular expression $re is used to remove the initial part of the
-# keyid and replace it by what is matched inside the parentheses.
-# $format and $width are used for pretty printing
-sub list_keys {
-    my ($paths, $tokeyid, $format, $width) = @_;
-    my (%pkpaths) = %{$paths};
-    for my $userid (sort keys %pkpaths) {
-        for my $pubkeypath (sort @{$pkpaths{$userid}}) {
-            my $fp = $fingerprints{$pubkeypath};
-            my $userid = $userids{$fp};
-            my $keyid = &{$tokeyid}($pubkeypath);
-            printf $format,$fp,$userid,$width+1-length($userid),"",$keyid
-                if ($super_key_manager
-                    || required_guest_keyid($keyid)
-                    || $keyid=~m(^\@));
-        }
-    }
-}
-
-# Turn a pubkeypath into a keyid for super-key-managers, guest-keys,
-# and self-keys.
-sub superkeyid {
-    my ($keyid) = @_;
-    $keyid =~ s(\.pub$)();
-    $keyid =~ s(^\./)();
-    return $keyid;
-}
-
-sub guestkeyid {
-    my ($keyid) = @_;
-    $keyid =~ s(\.pub$)();
-    $keyid =~ s(^.*/)();
-    return $keyid;
-}
-
-sub selfkeyid {
-    my ($keyid) = @_;
-    $keyid =~ s(\.pub$)();
-    $keyid =~ s(^.*/)();
-    my ($zop, $zfp, $zselector, $zuser) = get_pending($keyid);
-    return "\@$zselector (pending $zop)" if $zop;
-    $keyid =~ s(.*@)(@);
-    return $keyid;
-}
-
-###################################################################
-
-# List public keys managed by the respective user.
-# The fingerprints, userids and keyids are printed.
-# keyids are shown in a form that can be used for add and del
-# subcommands. 
-sub list_pubkeys {
-    print "Hello $gl_user, you manage the following keys:\n";
-    my $format = "%-47s %s%*s%s\n";
-    my $width = 0;
-    if ($super_key_manager) {
-        $width = userid_width(\%pubkeypaths);
-        $width = 6 if $width < 6; # length("userid")==6
-        printf $format, "fingerprint", "userid", ($width-5), "", "keyid";
-        list_keys(\%pubkeypaths, , \&superkeyid, $format, $width);
-    } else {
-        my $widths = $selfkey_management?userid_width(\%self_pubkeypaths):0;
-        my $widthg = userid_width(\%guest_pubkeypaths);
-        $width = $widths > $widthg ? $widths : $widthg; # maximum width
-        return unless $width; # there are no keys
-        $width = 6 if $width < 6; # length("userid")==6
-        printf $format, "fingerprint", "userid", ($width-5), "", "keyid";
-        list_keys(\%self_pubkeypaths, \&selfkeyid, $format, $width)
-            if $selfkey_management;
-        list_keys(\%guest_pubkeypaths, \&guestkeyid,  $format, $width);
-    }
-}
-
-
-###################################################################
-
-# Add a public key for the user $gl_user.
-# $pubkeypath is the place where the new key will be stored.
-# If the file or its fingerprint already exists, the operation is
-# rejected.
-sub add_pubkey {
-    my ( $gl_user, $pubkeypath, $keymaterial ) = @_;
-    if(! $keymaterial) {
-        print STDERR "Please supply the new key on STDIN.\n";
-        print STDERR "Try something like this:\n";
-        print STDERR "cat FOO.pub | ssh GIT\@GITOLITESERVER ukm add KEYID\n";
-        die "missing public key data\n";
-    }
-    # clean pubkeypath a bit
-    $pubkeypath = sanitize_pubkeypath($pubkeypath);
-    # Check that there is not yet something there already.
-    die "cannot override existing key\n" if $fingerprints{$pubkeypath};
-
-    my $userid = get_userid($pubkeypath);
-    # Super key managers shouldn't be able to add a that leads to
-    # either an empty userid or to a userid that starts with @.
-    #
-    # To avoid confusion, all keyids for super key managers must be in
-    # a full path format. Having a public key of the form
-    # gitolite-admin/keydir/@foo.pub might be confusing and might lead
-    # to other problems elsewhere.
-    die "cannot add key that starts with \@\n" if (!$userid) || $userid=~/^@/;
-
-    cd_temp_clone();
-    _chdir("keydir");
-    $pubkeypath =~ m((.*)/); # get the directory part
-    _mkdir($1);
-    _print($pubkeypath, $keymaterial);
-    my $fp = fingerprint($pubkeypath);
-
-    # Maybe we are adding a selfkey.
-    my ($zop, $zfp, $zselector, $zuser) = get_pending($userid);
-    my $user = $zop ? "$zuser\@$zselector" : $userid;
-    $userid = $zuser;
-    # Check that there isn't a key with the same fingerprint under a
-    # different userid.
-    if (defined $userids{$fp}) {
-        if ($userid ne $userids{$fp}) {
-            print STDERR "Found  $fp $userids{$fp}\n" if $super_key_manager;
-            print STDERR "Same key is already available under another userid.\n";
-            die "cannot add key\n";
-        } elsif ($zop) {
-            # Because of the way a key is confirmed with ukm, it is
-            # impossible to confirm the initial key of the user as a
-            # new selfkey. (It will lead to the function list_pubkeys
-            # instead of pending_user_add, because the gl_user will
-            # not be that of a pending user.) To avoid confusion, we,
-            # therefore, forbid to add the user's initial key
-            # altogether.
-            # In fact, we here also forbid to add any key for that
-            # user that is already in the system.
-            die "You cannot add a key that already belongs to you.\n";
-        }
-    } else {# this fingerprint does not yet exist
-        my @paths = @{$pubkeypaths{$userid}} if defined $pubkeypaths{$userid};
-        if (@paths) {# there are already keys for $userid
-            if (grep {$pubkeypath eq $_} @paths) {
-                print STDERR "The keyid is already present. Nothing changed.\n";
-            } elsif ($super_key_manager) {
-                # It's OK to add new selfkeys, but here we are in the case
-                # of adding multiple keys for guests. That is forbidden.
-                print STDERR "Adding new public key for $userid.\n";
-            } elsif ($pubkeypath =~ m(^\./$guestkeys_dir/)) {
-                # Arriving here means we are about to add a *new*
-                # guest key, because the fingerprint is not yet
-                # existing. This would be for an already existing
-                # userid (added by another guest key manager). Since
-                # that effectively means to (silently) add an
-                # additional key for an existing user, it must be
-                # forbidden.
-                die "cannot add another public key for an existing user\n";
-            }
-        }
-    }
-    exit if (`git status -s` eq ''); # OK to add identical keys twice
-    hushed_git( "add", "." ) and die "git add failed\n";
-    hushed_git( "commit", "-m", "'ukm add $gl_user $userid\n\n$fp'" )
-        and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-# Guest key managers should not be allowed to add directories or
-# multiple keys via the @domain mechanism, since this might allow
-# another guest key manager to give an attacker access to another
-# user's repositories.
-#
-# Example: Alice adds bob.pub for bob at example.org. David adds eve.pub
-# (where only Eve but not Bob has the private key) under the keyid
-# bob at example.org@foo. This basically gives Eve the same rights as
-# Bob.
-sub add_guest {
-    my ( $gl_user, $keyid, $keymaterial ) = @_;
-    die "keyid not allowed: '$keyid'\n"
-        if $keyid =~ m(@.*@) or $keyid =~ m(/) or !required_guest_keyid($keyid);
-    add_pubkey($gl_user, "$guestkeys_dir/$gl_user/$keyid.pub", $keymaterial);
-}
-
-# Add a new selfkey for user $gl_user.
-sub add_self {
-    my ( $gl_user, $keyid, $keymaterial ) = @_;
-    my $selector = "";
-    $selector = selfselector($keyid); # might return empty string
-    die "keyid not allowed: $keyid\n" unless $selector;
-
-    # Check that the new selector is not already in use even not in a
-    # pending state.
-    die "keyid already in use: $keyid\n"
-        if grep {selfkeyid($_)=~/^\@$selector( .*)?$/} @{$self_pubkeypaths{$gl_user}};
-    # generate new pubkey create fingerprint
-    system("ssh-keygen -N '' -q -f \"$TEMPDIR/session\" -C $gl_user");
-    my $sessionfp = fingerprint("$TEMPDIR/session.pub");
-    $sessionfp =~ s/://g;
-    my $user = "zzz-add-$sessionfp-$selector-$gl_user";
-    add_pubkey($gl_user, "$selfkeys_dir/$gl_user/$user.pub", $keymaterial);
-    print `cat "$TEMPDIR/session.pub"`;
-}
-
-###################################################################
-
-
-# Delete a key of user $gl_user.
-sub del_pubkey {
-    my ($gl_user, $pubkeypath) = @_;
-    $pubkeypath = sanitize_pubkeypath($pubkeypath);
-    my $fp = $fingerprints{$pubkeypath};
-    die "key not found\n" unless $fp;
-    cd_temp_clone();
-    chdir("keydir");
-    hushed_git( "rm", "$pubkeypath" ) and die "git rm failed\n";
-    my $userid = get_userid($pubkeypath);
-    hushed_git( "commit", "-m", "'ukm del $gl_user $userid\n\n$fp'" )
-        and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-# $gl_user is a super key manager. This function aborts if the
-# superkey manager tries to remove his last key.
-sub del_super {
-    my ($gl_user, $pubkeypath) = @_;
-    $pubkeypath = sanitize_pubkeypath($pubkeypath);
-    die "You are not managing the key $keyid.\n"
-        unless grep {$_ eq $pubkeypath} @all_pubkeypaths;
-    my $userid = get_userid($pubkeypath);
-    if ($gl_user eq $userid) {
-        my @paths = @{$pubkeypaths{$userid}};
-        die "You cannot delete your last key.\n"
-            if scalar(grep {$userid eq get_userid($_)} @paths)<2;
-    }
-    del_pubkey($gl_user, $pubkeypath);
-}
-
-sub del_guest {
-    my ($gl_user, $keyid) = @_;
-    my $pubkeypath = sanitize_pubkeypath("$guestkeys_dir/$gl_user/$keyid.pub");
-    my $userid = get_userid($pubkeypath);
-    # Check whether $gl_user actually manages $keyid.
-    my @paths = ();
-    @paths = @{$guest_pubkeypaths{$userid}}
-        if defined $guest_pubkeypaths{$userid};
-    die "You are not managing the key $keyid.\n"
-        unless grep {$_ eq $pubkeypath} @paths;
-    del_pubkey($gl_user, $pubkeypath);
-}
-
-# Delete a selfkey of $gl_user. The first delete is a preparation of
-# the deletion and only a second call will actually delete the key. If
-# the second call is done with the key that is scheduled for deletion,
-# it is basically undoing the previous del call. This last case is
-# handled in function pending_user_del.
-sub del_self {
-    my ($gl_user, $keyid) = @_;
-    my $selector = selfselector($keyid); # might return empty string
-    die "keyid not allowed: '$keyid'\n" unless $selector;
-
-    # Does $gl_user actually manage that keyid?
-    # All (non-pending) selfkeys have an @selector part in their pubkeypath.
-    my @paths = @{$self_pubkeypaths{$gl_user}};
-    die "You are not managing the key $keyid.\n"
-        unless grep {$selector eq get_selector($_)} @paths;
-
-    cd_temp_clone();
-    _chdir("keydir");
-    my $fp = '';
-    # Is it the first or the second del call? It's the second call, if
-    # there is a scheduled-for-deletion or scheduled-for-addition
-    # selfkey which has the given keyid as a selector part.
-    @paths = grep {
-        my ($zop, $zfp, $zselector, $zuser) = get_pending(get_userid($_));
-        $zselector eq $selector
-    } @paths;
-    if (@paths) {# start actual deletion of the key (second call)
-        my $pubkeypath = $paths[0];
-        $fp = fingerprint($pubkeypath);
-        my ($zop, $zf, $zs, $zu) = get_pending(get_userid($pubkeypath));
-        $zop = $zop eq 'add' ? 'undo-add' : 'confirm-del';
-        hushed_git("rm", "$pubkeypath") and die "git rm failed\n";
-        hushed_git("commit", "-m", "'ukm $zop $gl_user\@$selector\n\n$fp'")
-            and die "git commit failed\n";
-        system("gitolite push >/dev/null 2>/dev/null")
-            and die "git push failed\n";
-        print STDERR "pending keyid deleted: \@$selector\n";
-        return;
-    }
-    my $oldpubkeypath = "$selfkeys_dir/$gl_user/$gl_user\@$selector.pub";
-    # generate new pubkey and create fingerprint to get a random number
-    system("ssh-keygen -N '' -q -f \"$TEMPDIR/session\" -C $gl_user");
-    my $sessionfp = fingerprint("$TEMPDIR/session.pub");
-    $sessionfp =~ s/://g;
-    my $user = "zzz-del-$sessionfp-$selector-$gl_user";
-    my $newpubkeypath = "$selfkeys_dir/$gl_user/$user.pub";
-
-    # A key for gitolite access that is in authorized_keys and not
-    # existing in the expected place under keydir/ should actually not
-    # happen, but one never knows.
-    die "key not available\n" unless -r $oldpubkeypath;
-
-    # For some strange reason the target key already exists.
-    die "cannot override existing key\n" if -e $newpubkeypath;
-
-    $fp = fingerprint($oldpubkeypath);
-    print STDERR "prepare deletion of key \@$selector\n";
-    hushed_git("mv", "$oldpubkeypath", "$newpubkeypath")
-        and die "git mv failed\n";
-    hushed_git("commit", "-m", "'ukm prepare-del $gl_user\@$selector\n\n$fp'")
-        and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null")
-        and die "git push failed\n";
-}
-
-###################################################################
-# Adding a selfkey should be done as follows.
-#
-#   cat newkey.pub | ssh git at host ukm add @selector > session
-#   cat session | ssh -i newkey git at host ukm
-#
-# The provided random data will come from a newly generated ssh key
-# whose fingerprint will be stored in $gl_user. So we compute the
-# fingerprint of the data that is given to us. If it doesn't match the
-# fingerprint, then something went wrong and the confirm operation is
-# forbidden, in fact, the pending key will be removed from the system.
-sub pending_user_add {
-    my ($gl_user, $zfp, $zselector, $zuser) = @_;
-    my $oldpubkeypath = "$selfkeys_dir/$zuser/$gl_user.pub";
-    my $newpubkeypath = "$selfkeys_dir/$zuser/$zuser\@$zselector.pub";
-
-    # A key for gitolite access that is in authorized_keys and not
-    # existing in the expected place under keydir/ should actually not
-    # happen, but one never knows.
-    die "key not available\n" unless -r $oldpubkeypath;
-
-    my $keymaterial = safe_stdin();
-    # If there is no keymaterial (which corresponds to a session key
-    # for the confirm-add operation), logging in to this key, removes
-    # it from the system.
-    my $session_key_not_provided = '';
-    if (!$keymaterial) {
-        $session_key_not_provided = "missing session key";
-    } else {
-        _print("$TEMPDIR/session.pub", $keymaterial);
-        my $sessionfp = fingerprint("$TEMPDIR/session.pub");
-        $sessionfp =~ s/://g;
-        $session_key_not_provided = "session key not accepted"
-            unless ($zfp eq $sessionfp)
-    }
-    my $fp = fingerprint($oldpubkeypath);
-    if ($session_key_not_provided) {
-        print STDERR "$session_key_not_provided\n";
-        print STDERR "pending keyid deleted: \@$zselector\n";
-        hushed_git("rm", "$oldpubkeypath") and die "git rm failed\n";
-        hushed_git("commit", "-m", "'ukm del $zuser\@$zselector\n\n$fp'")
-            and die "git commit failed\n";
-        system("gitolite push >/dev/null 2>/dev/null")
-            and die "git push failed\n";
-        return;
-    }
-
-    # For some strange reason the target key already exists.
-    die "cannot override existing key\n" if -e $newpubkeypath;
-
-    print STDERR "pending keyid added: \@$zselector\n";
-    hushed_git("mv", "$oldpubkeypath", "$newpubkeypath")
-        and die "git mv failed\n";
-    hushed_git("commit", "-m", "'ukm confirm-add $zuser\@$zselector\n\n$fp'")
-        and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null")
-        and die "git push failed\n";
-}
-
-# To delete a key, one must first bring the key into a pending state
-# and then truely delete it with another key. In case, the login
-# happens with the pending key (implemented below), it means that the
-# delete operation has to be undone.
-sub pending_user_del {
-    my ($gl_user, $zfp, $zselector, $zuser) = @_;
-    my $oldpubkeypath = "$selfkeys_dir/$zuser/$gl_user.pub";
-    my $newpubkeypath = "$selfkeys_dir/$zuser/$zuser\@$zselector.pub";
-    print STDERR "undo pending deletion of keyid \@$zselector\n";
-    # A key for gitolite access that is in authorized_keys and not
-    # existing in the expected place under keydir/ should actually not
-    # happen, but one never knows.
-    die "key not available\n" unless -r $oldpubkeypath;
-    # For some strange reason the target key already exists.
-    die "cannot override existing key\n" if -e $newpubkeypath;
-    my $fp = fingerprint($oldpubkeypath);
-    hushed_git("mv", "$oldpubkeypath", "$newpubkeypath")
-        and die "git mv failed\n";
-    hushed_git("commit", "-m", "'ukm undo-del $zuser\@$zselector\n\n$fp'")
-        and die "git commit failed\n";
-}
-
-# A user whose key is in pending state cannot do much. In fact,
-# logging in as such a user simply takes back the "bringing into
-# pending state", i.e. a key scheduled for adding is remove and a key
-# scheduled for deletion is brought back into its properly added state.
-sub pending_user {
-    my ($gl_user, $zop, $zfp, $zselector, $zuser) = @_;
-    cd_temp_clone();
-    _chdir("keydir");
-    if ($zop eq 'add') {
-        pending_user_add($gl_user, $zfp, $zselector, $zuser);
-    } elsif ($zop eq 'del') {
-        pending_user_del($gl_user, $zfp, $zselector, $zuser);
-    } else {
-        die "unknown operation\n";
-    }
-    system("gitolite push >/dev/null 2>/dev/null")
-        and die "git push failed\n";
-}
diff --git a/docker/gitolite/contrib/hooks/repo-specific/save-push-signatures b/docker/gitolite/contrib/hooks/repo-specific/save-push-signatures
deleted file mode 100755
index 2470491..0000000
--- a/docker/gitolite/contrib/hooks/repo-specific/save-push-signatures
+++ /dev/null
@@ -1,188 +0,0 @@
-#!/bin/sh
-
-# ----------------------------------------------------------------------
-# post-receive hook to adopt push certs into 'refs/push-certs'
-
-# Collects the cert blob on push and saves it, then, if a certain number of
-# signed pushes have been seen, processes all the "saved" blobs in one go,
-# adding them to the special ref 'refs/push-certs'.  This is done in a way
-# that allows searching for all the certs pertaining to one specific branch
-# (thanks to Junio Hamano for this idea plus general brainstorming).
-
-# The "collection" happens only if $GIT_PUSH_CERT_NONCE_STATUS = OK; again,
-# thanks to Junio for pointing this out; see [1]
-#
-# [1]: https://groups.google.com/forum/#!topic/gitolite/7cSrU6JorEY
-
-# WARNINGS:
-#   Does not check that GIT_PUSH_CERT_STATUS = "G".  If you want to check that
-#   and FAIL the push, you'll have to write a simple pre-receive hook
-#   (post-receive is not the place for that; see 'man githooks').
-#
-#   Gitolite users: failing the hook cannot be done as a VREF because git does
-#   not set those environment variables in the update hook.  You'll have to
-#   write a trivial pre-receive hook and add that in.
-
-# Relevant gitolite doc links:
-#   repo-specific environment variables
-#       http://gitolite.com/gitolite/dev-notes.html#rsev
-#   repo-specific hooks
-#       http://gitolite.com/gitolite/non-core.html#rsh
-#       http://gitolite.com/gitolite/cookbook.html#v3.6-variation-repo-specific-hooks
-
-# Environment:
-#   GIT_PUSH_CERT_NONCE_STATUS should be "OK" (as mentioned above)
-#
-#   GL_OPTIONS_GPC_PENDING (optional; defaults to 1).  This is the number of
-#   git push certs that should be waiting in order to trigger the post
-#   processing.  You can set it within gitolite like so:
-#
-#       repo foo bar    # or maybe just 'repo @all'
-#           option ENV.GPC_PENDING = 5
-
-# Setup:
-#   Set up this code as a post-receive hook for whatever repos you need to.
-#   Then arrange to have the environment variable GL_OPTION_GPC_PENDING set to
-#   some number, as shown above.  (This is only required if you need it to be
-#   greater than 1.)  It could of course be different for different repos.
-#   Also see "Invocation" section below.
-
-# Invocation:
-#   Normally via git (see 'man githooks'), once it is setup as a post-receive
-#   hook.
-#
-#   However, if you set the "pending" limit high, and want to periodically
-#   "clean up" pending certs without necessarily waiting for the counter to
-#   trip, do the following (untested):
-#
-#       RB=$(gitolite query-rc GL_REPO_BASE)
-#       for r in $(gitolite list-phy-repos)
-#       do
-#           cd $RB/$repo.git
-#           unset GL_OPTIONS_GPC_PENDING    # if it is set higher up
-#           hooks/post-receive post_process
-#       done
-#
-#   That will take care of it.
-
-# Using without gitolite:
-#   Just set GL_OPTIONS_GPC_PENDING within the script (maybe read it from git
-#   config).  Everything else is independent of gitolite.
-
-# ----------------------------------------------------------------------
-# make it work on BSD also (but NOT YET TESTED on FreeBSD!)
-uname_s=`uname -s`
-if [ "$uname_s" = "Linux" ]
-then
-    _lock() { flock "$@"; }
-else
-    _lock() { lockf -k "$@"; }
-    # I'm assuming other BSDs also have this; I only have FreeBSD.
-fi
-
-# ----------------------------------------------------------------------
-# standard stuff
-die() { echo "$@" >&2; exit 1; }
-warn() { echo "$@" >&2; }
-
-# ----------------------------------------------------------------------
-# if there are no arguments, we're running as a "post-receive" hook
-if [ -z "$1" ]
-then
-    # ignore if it may be a replay attack
-    [ "$GIT_PUSH_CERT_NONCE_STATUS" = "OK" ] || exit 1
-    # I don't think "exit 1" does anything in a post-receive anyway, so that's
-    # just a symbolic gesture!
-
-    # note the lock file used
-    _lock .gpc.lock $0 cat_blob
-
-    # if you want to initiate the post-processing ONLY from outside (for
-    # example via cron), comment out the next line.
-    exec $0 post_process
-fi
-
-# ----------------------------------------------------------------------
-# the 'post_process' part; see "Invocation" section in the doc at the top
-if [ "$1" = "post_process" ]
-then
-    # this is the same lock file as above
-    _lock .gpc.lock $0 count_and_rotate $$
-
-    [ -d git-push-certs.$$ ] || exit 0
-
-    # but this is a different one
-    _lock .gpc.ref.lock $0 update_ref $$
-
-    exit 0
-fi
-
-# ----------------------------------------------------------------------
-# other values for "$1" are internal use only
-
-if [ "$1" = "cat_blob" ]
-then
-    mkdir -p git-push-certs
-    git cat-file blob $GIT_PUSH_CERT > git-push-certs/$GIT_PUSH_CERT
-    echo $GIT_PUSH_CERT >> git-push-certs/.blob.list
-fi
-
-if [ "$1" = "count_and_rotate" ]
-then
-    count=$(ls git-push-certs | wc -l)
-    if test $count -ge ${GL_OPTIONS_GPC_PENDING:-1}
-    then
-        # rotate the directory
-        mv git-push-certs git-push-certs.$2
-    fi
-fi
-
-if [ "$1" = "update_ref" ]
-then
-    # use a different index file for all this
-    GIT_INDEX_FILE=push_certs_index; export GIT_INDEX_FILE
-
-    # prepare the special ref to receive commits
-    PUSH_CERTS=refs/push-certs
-    if git rev-parse -q --verify $PUSH_CERTS >/dev/null
-    then
-        git read-tree $PUSH_CERTS
-    else
-        git read-tree --empty
-        T=$(git write-tree)
-        C=$(echo 'start' | git commit-tree $T)
-        git update-ref $PUSH_CERTS $C
-    fi
-
-    # for each cert blob...
-    for b in `cat git-push-certs.$2/.blob.list`
-    do
-        cf=git-push-certs.$2/$b
-
-        # it's highly unlikely that the blob got GC-ed already but write it
-        # back anyway, just in case
-        B=$(git hash-object -w $cf)
-
-        # bit of a sanity check
-        [ "$B" = "$b" ] || warn "this should not happen: $B is not equal to $b"
-
-        # for each ref described within the cert, update the index
-        for ref in `cat $cf | egrep '^[a-f0-9]+ [a-f0-9]+ refs/' | cut -f3 -d' '`
-        do
-            git update-index --add --cacheinfo 100644,$b,$ref
-            # we're using the ref name as a "fake" filename, so people can,
-            # for example, 'git log refs/push-certs -- refs/heads/master', to
-            # see all the push certs pertaining to the master branch.  This
-            # idea came from Junio Hamano, the git maintainer (I certainly
-            # don't deal with git plumbing enough to have thought of it!)
-        done
-
-        T=$(git write-tree)
-        C=$( git commit-tree -p $PUSH_CERTS $T < $cf )
-        git update-ref $PUSH_CERTS $C
-
-        rm -f $cf
-    done
-    rm -f git-push-certs.$2/.blob.list
-    rmdir git-push-certs.$2
-fi
diff --git a/docker/gitolite/contrib/lib/Apache/gitolite.conf b/docker/gitolite/contrib/lib/Apache/gitolite.conf
deleted file mode 100644
index 87ba843..0000000
--- a/docker/gitolite/contrib/lib/Apache/gitolite.conf
+++ /dev/null
@@ -1,47 +0,0 @@
-# Apache Gitolite smart-http install Active Directory Authentication
-
-# Author: Jonathan Gray
-
-# It is assumed you already have mod_ssl, mod_ldap, & mod_authnz configured for apache
-# It is also assumed you are disabling http on port 80 and requiring the use of https on port 443
-
-# Boiler plate configuration from the smart-http deployment documentation script
-# Adjust paths if you use something other than the default
-SetEnv GIT_PROJECT_ROOT /var/www/gitolite-home/repositories
-ScriptAlias /git/ /var/www/gitolite-home/gitolite-source/src/gitolite-shell/
-ScriptAlias /gitmob/ /var/www/gitolite-home/gitolite-source/src/gitolite-shell/
-SetEnv GITOLITE_HTTP_HOME /var/www/gitolite-home
-SetEnv GIT_HTTP_EXPORT_ALL
- 
-# Setup LDAP trusted root certificate from your domain
-LDAPTrustedGlobalCert CA_BASE64 /etc/httpd/conf.d/domain.ca.cer
-
-# In case you havn't setup proper SSL certificates in ssl.conf, go ahead and do it here to save headache later with git
-SSLCertificateFile /etc/httpd/conf.d/gitolite.server.crt
-SSLCertificateKeyFile /etc/httpd/conf.d/gitolite.server.key
-SSLCertificateChainFile /etc/httpd/conf.d/DigiCertCA.crt
- 
-<Location /git>
-        Order deny,allow
-	# In case you want to restrict access to a given ip/subnet
-        #Allow from my.ip.range/cidr
-        #Deny from All
-        AuthType Basic
-        AuthName "Git"
-        AuthBasicProvider ldap
-        AuthUserFile /dev/null
-        AuthzLDAPAuthoritative on
-        AuthLDAPURL ldaps://AD.DC1.local:3269 AD.DC2.local:3269 AD.DC3.local:3269/?sAMAccountName?sub
-        AuthLDAPBindDN git at domain.local
-        AuthLDAPBindPassword super.secret.password
-        AuthLDAPGroupAttributeIsDN on
- 
-	# You must use one of the two following approaches to handle authentication via active directory
-	
-        # Require membership in the gitolite users group in AD
-        # The ldap-filter option is used to handle nested groups on the AD server rather than multiple calls to traverse from apache
-        # Require ldap-filter memberof:1.2.840.113556.1.4.1941:=cn=Gitolite Users,ou=Security Groups,dc=domain,dc=local
-
-	# Alternatively, require a valid user account only since you're going to control authorization in gitolite anyway
-	Require valid-user
-</Location>
diff --git a/docker/gitolite/contrib/lib/Gitolite/Triggers/RedmineUserAlias.pm b/docker/gitolite/contrib/lib/Gitolite/Triggers/RedmineUserAlias.pm
deleted file mode 100644
index 8fde513..0000000
--- a/docker/gitolite/contrib/lib/Gitolite/Triggers/RedmineUserAlias.pm
+++ /dev/null
@@ -1,55 +0,0 @@
-package Gitolite::Triggers::RedmineUserAlias;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-# aliasing a redmine username to a more user-friendly one
-# ----------------------------------------------------------------------
-
-=for usage
-
-Why:
-
-    Redmine creates users like "redmine_alice_123"; we want the users to just
-    see "alice" instead of that.
-
-Assumption:
-
-*   Redmine does not allow duplicates in the middle bit; i.e., you can't
-    create redmine_alice_123 and redmine_alice_456 also.
-
-How:
-
-*   add this code as lib/Gitolite/Triggers/RedmineUserAlias.pm to your
-    site-local code directory; see this link for how:
-
-        http://gitolite.com/gitolite/non-core.html#ncloc
-
-*   add the following to the rc file, just before the ENABLE section (don't
-    forget the trailing comma):
-
-        INPUT   =>  [ 'RedmineUserAlias::input' ],
-
-Notes:
-
-*   http mode has not been tested and will not be.  If someone has the time to
-    test it and make it work please let me know.
-
-*   not tested with mirroring.
-
-Quote:
-
-*   "All that for what is effectively one line of code.  I need a life".
-
-=cut
-
-sub input {
-    $ARGV[0] or _die "no username???";
-    $ARGV[0] =~ s/^redmine_(\S+)_\d+$/$1/;
-}
-
-1;
diff --git a/docker/gitolite/contrib/t/ukm.t b/docker/gitolite/contrib/t/ukm.t
deleted file mode 100644
index da4fc0b..0000000
--- a/docker/gitolite/contrib/t/ukm.t
+++ /dev/null
@@ -1,447 +0,0 @@
-#!/usr/bin/perl
-
-# Call like this:
-# TSH_VERBOSE=1 TSH_ERREXIT=1 HARNESS_ACTIVE=1 GITOLITE_TEST=y prove t/ukm.t
-
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Common;
-use Gitolite::Test;
-
-# basic tests using ssh
-# ----------------------------------------------------------------------
-
-my $bd = `gitolite query-rc -n GL_BINDIR`;
-my $h  = $ENV{HOME};
-my $ab = `gitolite query-rc -n GL_ADMIN_BASE`;
-my $pd = "$bd/../t/keys"; # source for pubkeys
-umask 0077;
-
-_mkdir( "$h/.ssh", 0700 ) if not -d "$h/.ssh";
-
-try "plan 204";
-
-
-# Reset everything.
-# Only admin and u1, u2, and u3 keys are available initially
-# Keys u4, u5, and u6 are used as guests later.
-# For easy access, we put the keys into ~/.ssh/, though.
-try "
-    rm -f $h/.ssh/authorized_keys; ok or die 1
-    cp $pd/u[1-6]* $h/.ssh; ok or die 2
-    cp $pd/admin*  $h/.ssh; ok or die 3
-    cp $pd/config  $h/.ssh; ok or die 4
-        cat $h/.ssh/config
-        perl s/%USER/$ENV{USER}/
-        put $h/.ssh/config
-    mkdir             $ab/keydir; ok or die 5
-    cp $pd/u[1-3].pub $ab/keydir; ok or die 6
-    cp $pd/admin.pub  $ab/keydir; ok or die 7
-";
-
-# Put the keys into ~/.ssh/authorized_keys
-system("gitolite ../triggers/post-compile/ssh-authkeys");
-
-# enable user key management in a simple form.
-# Guest key managers can add keyids looking like email addresses, but
-# cannot add emails containing example.com or hemmecke.org.
-system("sed -i \"s/.*ENABLE =>.*/'UKM_CONFIG'=>{'FORBIDDEN_GUEST_PATTERN'=>'example.com|hemmecke.org'}, ENABLE => ['ukm',/\" $h/.gitolite.rc");
-
-# super-key-managers can add/del any key
-# super-key-managers should in fact agree with people having write
-# access to gitolite-admin repo.
-# guest-key-managers can add/del guest keys
-confreset; confadd '
-    @guest-key-managers = u2 u3
-    @creators = u2 u3
-    repo pub/CREATOR/..*
-        C   =   @creators
-        RW+ =   CREATOR
-        RW  =   WRITERS
-        R   =   READERS
-';
-
-# Populate the gitolite-admin/keydir in the same way as it was used for
-# the initialization of .ssh/authorized_keys above.
-try "
-    mkdir             keydir; ok or die 8
-    cp $pd/u[1-3].pub keydir; ok or die 9;
-    cp $pd/admin.pub  keydir; ok or die 10;
-    git add conf keydir; ok
-    git commit -m ukm; ok; /master.* ukm/
-";
-
-# Activate new config data.
-try "PUSH admin; ok; gsh; /master -> master/; !/FATAL/" or die text();
-
-# Check whether the above setup yields the expected behavior for ukm.
-# The admin is super-key-manager, thus can manage every key.
-try "
-    ssh admin ukm; ok; /Hello admin, you manage the following keys:/
-                       / admin +admin/
-                       / u1 +u1/
-                       / u2 +u2/
-                       / u3 +u3/
-";
-
-# u1 isn't a key manager, so shouldn't be above to manage keys.
-try "ssh u1 ukm; !ok; /FATAL: You are not a key manager./";
-
-# u2 and u3 are guest key managers, but don't yet manage any key.
-try "ssh u2 ukm; ok"; cmp "Hello u2, you manage the following keys:\n\n\n";
-try "ssh u3 ukm; ok"; cmp "Hello u3, you manage the following keys:\n\n\n";
-
-
-###################################################################
-# Unknows subkommands abort ukm.
-try "ssh u2 ukm fake; !ok; /FATAL: unknown ukm subcommand: fake/";
-
-
-###################################################################
-# Addition of keys.
-
-# If no data is provided on stdin, we don't block, but rather timeout
-# after one second and abort the program.
-try "ssh u2 ukm add u4\@example.org; !ok; /FATAL: missing public key data/";
-
-# If no keyid is given, we cannot add a key.
-try "ssh u2 ukm add; !ok; /FATAL: keyid required/";
-
-try "
-    DEF ADD = cat $pd/%1.pub|ssh %2 ukm add %3
-    DEF ADDOK = ADD %1 %2 %3; ok
-    DEF ADDNOK = ADD %1 %2 %3; !ok
-    DEF FP = ADDNOK u4 u2 %1
-    DEF FORBIDDEN_PATTERN = FP %1; /FATAL: keyid not allowed:/
-";
-
-# Neither a guest key manager nor a super key manager can add keys that have
-# double dot in their keyid. This is hardcoded to forbid paths with .. in it.
-try "
-    ADDNOK u4 u2    u4\@hemmecke..org; /Not allowed to use '..' in keyid./
-    ADDNOK u4 admin u4\@hemmecke..org; /Not allowed to use '..' in keyid./
-    ADDNOK u4 admin ./../.myshrc;      /Not allowed to use '..' in keyid./
-";
-
-# guest-key-managers can only add keys that look like emails.
-try "
-    FORBIDDEN_PATTERN u4
-    FORBIDDEN_PATTERN u4\@example
-    FORBIDDEN_PATTERN u4\@foo\@example.org
-
-    # No support for 'old style' multiple keys.
-    FORBIDDEN_PATTERN u4\@example.org\@foo
-
-    # No path delimiter in keyid
-    FORBIDDEN_PATTERN foo/u4\@example.org
-
-    # Certain specific domains listed in FORBIDDEN_GUEST_PATTERN are forbidden.
-    # Note that also u4\@example-com would be rejected, because MYDOMAIN
-    # contains a regular expression --> I don't care.
-    FORBIDDEN_PATTERN u4\@example.com
-    FORBIDDEN_PATTERN u4\@hemmecke.org
-";
-
-# Accept one guest key.
-try "ADDOK u4 u2 u4\@example.org";
-try "ssh u2 ukm; ok; /Hello u2, you manage the following keys:/
-                     / u4\@example.org *u4\@example.org/";
-
-# Various ways how a key must be rejected.
-try "
-    # Cannot add the same key again.
-    ADDNOK u4 u2 u4\@example.org; /FATAL: cannot override existing key/
-
-    # u2 can also not add u4.pub under another keyid
-    ADDNOK u4 u2 u4\@example.net; /FATAL: cannot add key/
-         /Same key is already available under another userid./
-
-    # u2 can also not add another key under the same keyid.
-    ADDNOK u5 u2 u4\@example.org; /FATAL: cannot override existing key/
-
-    # Also u3 cannot not add another key under the same keyid.
-    ADDNOK u5 u3 u4\@example.org
-         /FATAL: cannot add another public key for an existing user/
-
-    # And u3 cannot not add u4.pub under another keyid.
-    ADDNOK u4 u3 u4\@example.net; /FATAL: cannot add key/
-         /Same key is already available under another userid./
-
-    # Not even the admin can add the same key u4 under a different userid.
-    ADDNOK u4 admin u4\@example.net; /FATAL: cannot add key/
-         /Same key is already available under another userid./
-         /Found  .* u4\@example.org/
-
-    # Super key managers cannot add keys that start with @.
-    # We don't care about @ in the dirname, though.
-    ADDNOK u4 admin foo/\@ex.net; /FATAL: cannot add key that starts with \@/
-    ADDNOK u4 admin foo/\@ex;     /FATAL: cannot add key that starts with \@/
-    ADDNOK u4 admin     \@ex.net; /FATAL: cannot add key that starts with \@/
-    ADDNOK u4 admin     \@ex;     /FATAL: cannot add key that starts with \@/
-";
-
-# But u3 can add u4.pub under the same keyid.
-try "ADDOK u4 u3 u4\@example.org";
-
-try "ssh u3 ukm; ok; /Hello u3, you manage the following keys:/
-                     / u4\@example.org *u4\@example.org/";
-
-# The admin can add multiple keys for the same userid.
-try "
-    ADDOK u5 admin u4\@example.org
-    ADDOK u5 admin u4\@example.org\@home
-    ADDOK u5 admin laptop/u4\@example.org
-    ADDOK u5 admin laptop/u4\@example.org\@home
-";
-
-# And admin can also do this for other guest key managers. Note,
-# however, that the gitolite-admin must be told where the
-# GUEST_DIRECTORY is. But he/she could find out by cloning the
-# gitolite-admin repository and adding the same key directly.
-try "
-    ADDOK u5 admin zzz/guests/u2/u4\@example.org\@foo
-    ADDOK u6 admin zzz/guests/u3/u6\@example.org
-";
-
-try "ssh admin ukm; ok"; cmp "Hello admin, you manage the following keys:
-fingerprint                                     userid         keyid
-a4:d1:11:1d:25:5c:55:9b:5f:91:37:0e:44:a5:a5:f2 admin          admin
-00:2c:1f:dd:a3:76:5a:1e:c4:3c:01:15:65:19:a5:2e u1             u1
-69:6f:b5:8a:f5:7b:d8:40:ce:94:09:a2:b8:95:79:5b u2             u2
-26:4b:20:24:98:a4:e4:a5:b9:97:76:9a:15:92:27:2d u3             u3
-78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org laptop/u4\@example.org
-78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org laptop/u4\@example.org\@home
-78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org u4\@example.org
-78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org u4\@example.org\@home
-8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org zzz/guests/u2/u4\@example.org
-78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org zzz/guests/u2/u4\@example.org\@foo
-8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org zzz/guests/u3/u4\@example.org
-fc:0f:eb:52:7a:d2:35:da:89:96:f5:15:0e:85:46:e7 u6\@example.org zzz/guests/u3/u6\@example.org
-\n\n";
-
-# Now, u2 has two keys in his directory, but u2 can manage only one of
-# them, since the one added by the admin has two @ in it. Thus the key
-# added by admin is invisible to u2.
-try "ssh u2 ukm; ok"; cmp "Hello u2, you manage the following keys:
-fingerprint                                     userid         keyid
-8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org u4\@example.org
-\n\n";
-
-# Since admin added key u6 at example.org to the directory of u2, u2 is
-# also able to see it and, in fact, to manage it.
-try "ssh u3 ukm; ok"; cmp "Hello u3, you manage the following keys:
-fingerprint                                     userid         keyid
-8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org u4\@example.org
-fc:0f:eb:52:7a:d2:35:da:89:96:f5:15:0e:85:46:e7 u6\@example.org u6\@example.org
-\n\n";
-
-###################################################################
-# Deletion of keys.
-try "
-    DEF DEL = ssh %1 ukm del %2
-    DEF DELOK  = DEL %1 %2; ok
-    DEF DELNOK = DEL %1 %2; !ok
-    DEF DELNOMGR = DELNOK %1 %2; /FATAL: You are not managing the key /
-";
-
-# Deletion requires a keyid.
-try "ssh u3 ukm del; !ok; /FATAL: keyid required/";
-
-# u3 can, of course, not remove any unmanaged key.
-try "DELNOMGR u3 u2";
-
-# But u3 can delete u4 at example.org and u6 at example.org. This will, of course,
-# not remove the key u4 at example.org that u2 manages.
-try "
-    DELOK u3 u4\@example.org
-    DELOK u3 u6\@example.org
-";
-
-# After having deleted u4 at example.org, u3 cannot remove it again,
-# even though, u2 still manages that key.
-try "DELNOMGR u3 u4\@example.org";
-
-# Of course a super-key-manager can remove any (existing) key.
-try "
-    DELOK  admin zzz/guests/u2/u4\@example.org
-    DELNOK admin zzz/guests/u2/u4\@example.org
-        /FATAL: You are not managing the key zzz/guests/u2/u4\@example.org./
-    DELNOK admin zzz/guests/u2/u4\@example.org\@x
-        /FATAL: You are not managing the key zzz/guests/u2/u4\@example.org./
-    DELOK  admin zzz/guests/u2/u4\@example.org\@foo
-";
-
-# As the admin could do that via pushing to the gitolite-admin manually,
-# it's also allowed to delete even non-guest keys.
-try "DELOK admin u3";
-
-# Let's clean the environment again.
-try "
-    DELOK admin laptop/u4\@example.org\@home
-    DELOK admin laptop/u4\@example.org
-    DELOK admin        u4\@example.org\@home
-    DELOK admin        u4\@example.org
-    ADDOK u3 admin u3
- ";
-
-# Currently the admin has just one key. It cannot be removed.
-# But after adding another key, deletion should work fine.
-try "
-    DELNOK admin admin; /FATAL: You cannot delete your last key./
-    ADDOK u6 admin second/admin; /Adding new public key for admin./
-    DELOK admin admin
-    DELNOK u6 admin; /FATAL: You are not managing the key admin./
-    DELNOK u6 second/admin; /FATAL: You cannot delete your last key./
-    ADDOK admin u6 admin; /Adding new public key for admin./
-    DELOK u6 second/admin
-";
-
-###################################################################
-# Selfkey management.
-
-# If self key management is not switched on in the .gitolite.rc file,
-# it's not allowed at all.
-try "ssh u2 ukm add \@second; !ok; /FATAL: selfkey management is not enabled/";
-
-# Let's enable it.
-system("sed -i \"/'UKM_CONFIG'=>/s/=>{/=>{'SELFKEY_MANAGEMENT'=>1,/\" $h/.gitolite.rc");
-
-# And add self-key-managers to gitolite.conf
-# chdir("../gitolite-admin") or die "in `pwd`, could not cd ../g-a";
-try "glt pull admin origin master; ok";
-put "|cut -c5- > conf/gitolite.conf", '
-    repo gitolite-admin
-        RW+ = admin
-    repo testing
-        RW+ = @all
-    @guest-key-managers = u2 u3
-    @self-key-managers = u1 u2
-    @creators = u2 u3
-    repo pub/CREATOR/..*
-        C   =   @creators
-        RW+ =   CREATOR
-        RW  =   WRITERS
-        R   =   READERS
-';
-try "
-    git add conf keydir; ok
-    git commit -m selfkey; ok; /master.* selfkey/
-";
-try "PUSH admin; ok; gsh; /master -> master/; !/FATAL/" or die text();
-
-# Now we can start with the tests.
-
-# Only self key managers are allowed to use selfkey management.
-# See variable @self-key-managers.
-try "ssh u3 ukm add \@second; !ok; /FATAL: You are not a selfkey manager./";
-
-# Cannot add keyid that are not alphanumeric.
-try "ssh u1 ukm add \@second-key; !ok; /FATAL: keyid not allowed:/";
-
-# Add a second key for u1, but leave it pending by not feeding in the
-# session key. The new user can login, but he/she lives under a quite
-# random gl_user name and thus is pretty much excluded from everything
-# except permissions given to @all. If this new id calls ukm without
-# providing the session key, this (pending) key is automatically
-# removed from the system.
-# If a certain keyid is in the system, then it cannot be added again.
-try "
-    ADDOK u4 u1 \@second
-    ssh admin ukm; ok; /u1     zzz/self/u1/zzz-add-[a-z0-9]{32}-second-u1/
-    ssh u1    ukm; ok; /u1     \@second .pending add./
-    ADDNOK u4 u1 \@second; /FATAL: keyid already in use: \@second/
-    ssh u4    ukm; ok; /pending keyid deleted: \@second/
-    ssh admin ukm; ok; !/zzz/; !/second/
-";
-
-# Not providing a proper ssh public key will abort. Providing a good
-# ssh public key, which is not a session key makes the key invalid.
-# The key will, therefore, be deleted by this operation.
-try "
-    ADDOK u4 u1 \@second
-    echo fake|ssh u4 ukm; !ok; /FATAL: does not seem to be a valid pubkey/
-    cat $pd/u5.pub | ssh u4 ukm; ok;
-        /session key not accepted/
-        /pending keyid deleted: \@second/
-";
-
-# True addition of a new selfkey is done via piping it to a second ssh
-# call that uses the new key to call ukm. Note that the first ssh must
-# have completed its job before the second ssh is able to successfully
-# log in. This can be done via sleep or via redirecting to a file and
-# then reading from it.
-try "
-    # ADDOK u4 u1 \@second | (sleep 2; ssh u4 ukm); ok
-    ADD u4 u1 \@second > session; ok
-    cat session | ssh u4 ukm; ok;  /pending keyid added: \@second/
-";
-
-# u1 cannot add his/her initial key, since that key can never be
-# confirmed via ukm, so it is forbidden altogether. In fact, u1 is not
-# allowed to add any key twice.
-try "
-    ADDNOK u1 u1 \@first
-       /FATAL: You cannot add a key that already belongs to you./
-    ADDNOK u4 u1 \@first
-       /FATAL: You cannot add a key that already belongs to you./
-";
-
-# u1 also can add more keys, but not under an existing keyid. That can
-# be done by any of his/her identities (here we choose u4).
-try "
-    ADDNOK u5 u1 \@second; /FATAL: keyid already in use: \@second/
-    ADD u5 u4 \@third > session; ok
-    cat session | ssh u5 ukm; ok;  /pending keyid added: \@third/
-";
-
-# u2 cannot add the same key, but is allowed to use the same name (@third).
-try "
-    ADDNOK u5 u2 \@third; /FATAL: cannot add key/
-        /Same key is already available under another userid./
-    ADD u6 u2 \@third > session; ok
-    cat session | ssh u6 ukm; ok;  /pending keyid added: \@third/
-";
-
-# u6 can schedule his/her own key for deletion, but cannot actually
-# remove it. Trying to do so results in bringing back the key. Actual
-# deletion must be confirmed by another key.
-try "
-    ssh u6 ukm del \@third; /prepare deletion of key \@third/
-    ssh u2 ukm; ok; /u2     \@third .pending del./
-    ssh u6 ukm; ok; /undo pending deletion of keyid \@third/
-    ssh u6 ukm del \@third; /prepare deletion of key \@third/
-    ssh u2 ukm del \@third; ok;  /pending keyid deleted: \@third/
-";
-
-# While in pending-deletion state, it's forbidden to add another key
-# with the same keyid. It's also forbidden to add a key with the same
-# fingerprint as the to-be-deleted key).
-# A new key under another keyid, is OK.
-try "
-    ssh u1 ukm del \@third; /prepare deletion of key \@third/
-    ADDNOK u4 u1 \@third; /FATAL: keyid already in use: \@third/
-    ADDNOK u5 u1 \@fourth;
-        /FATAL: You cannot add a key that already belongs to you./
-    ADD u6 u1 \@fourth > session; ok
-    ssh u1 ukm; ok;
-        /u1     \@second/
-        /u1     \@fourth .pending add./
-        /u1     \@third .pending del./
-";
-# We can remove a pending-for-addition key (@fourth) by logging in
-# with a non-pending key. Trying to do anything with key u5 (@third)
-# will just bring it back to its normal state, but not change the
-# state of any other key. As already shown above, using u6 (@fourth)
-# without a proper session key, would remove it from the system.
-# Here we want to demonstrate that key u1 can delete u6 immediately.
-try "ssh u1 ukm del \@fourth; /pending keyid deleted: \@fourth/";
-
-# The pending-for-deletion key @third can also be removed via the u4
-# (@second) key.
-try "ssh u4 ukm del \@third; ok; /pending keyid deleted: \@third/";
-
-# Non-existing selfkeys cannot be deleted.
-try "ssh u4 ukm del \@x; !ok; /FATAL: You are not managing the key \@x./";
diff --git a/docker/gitolite/contrib/triggers/file_mirror b/docker/gitolite/contrib/triggers/file_mirror
deleted file mode 100755
index e3d083b..0000000
--- a/docker/gitolite/contrib/triggers/file_mirror
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# Use an external (non-gitolite) mirror to backup gitolite repos.  They will
-# be automatically kept uptodate as people push to your gitolite server.  If
-# your server should die and you create a new one, you can quickly and easily
-# get everything back from the external mirror with a few simple commands.
-
-#       -------------------------------------------------------------
-#       SEE WARNINGS/CAVEATS AND INSTRUCTIONS AT THE END OF THIS FILE
-#       -------------------------------------------------------------
-
-# ----------------------------------------------------------------------
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-my ( $trigger, $repo, $dummy, $op ) = @ARGV;
-exit 0 unless $trigger eq 'POST_GIT' or $trigger eq 'POST_CREATE';
-exit 0 if     $trigger eq 'POST_GIT' and $op ne 'W';
-
-chdir("$rc{GL_REPO_BASE}/$repo.git") or _die "chdir failed: $!\n";
-
-my %config = config( $repo, "gitolite-options\\.mirror\\.extslave" );
-for my $slave ( values %config ) {
-    _do($slave);
-
-    # processing one slave is sufficient for restoring!
-    last if $trigger eq 'POST_CREATE';
-}
-
-# in shell, that would be something like:
-#   gitolite git-config -r $repo gitolite-options\\.mirror\\.extslave | cut -f3 | while read slave
-#   do
-#       ...
-
-# ----------------------------------------------------------------------
-
-sub _do {
-    my $url = shift;
-
-    if ( $trigger eq 'POST_CREATE' ) {
-        # brand new repo just created; needs to be populated from mirror
-
-        # For your urls you will need a way to somehow query the server and
-        # ask if the repo is present; it's upto you how you do it.
-        my $path = $url;
-        $path =~ s(^file://)();
-        return unless -d $path;
-
-        # now fetch.  Maybe we can put a "-q" in there?
-        system( "git", "fetch", $url, "+refs/*:refs/*" );
-
-    } elsif ( $trigger eq 'POST_GIT' ) {
-        # someone just pushed; we need to update our mirrors
-
-        # need to create the repo on the mirror.  Again, it's upto you how you
-        # make sure there's a repo on the mirror that can receive the push.
-        make_repo($url);    # in case it doesn't already exist
-
-        # now push
-        system( "git", "push", "--mirror", $url );
-    }
-}
-
-sub make_repo {
-    my $url = shift;
-    # in this example, the URL is 'file:///...'; for other urls, presumably
-    # the url tells you enough about how to *create* a repo.
-
-    my $path = $url;
-    $path =~ s(^file://)();
-    return if -d $path;
-    system( "git", "init", "--bare", $path );
-}
-
-__END__
-
-WARNINGS
---------
-
-1.  THIS IS SAMPLE CODE.  You will AT LEAST have to customise the _do() and
-    make_repo() functions above based on what your remote URLs are.  For
-    example, I don't even know how to create a repo from the command line if
-    your external store is, say, github!
-
-2.  THIS DOES NOT WORK FOR WILD REPOs.  It can be made to work, with a few
-    extra steps to backup and restore the "gl-perms" and "gl-creator" files.
-
-    "Left as an exercise for the reader!"
-
-DESIGN NOTES
-------------
-
-This is really just a combination of "upstream" (see src/triggers/upstream)
-and mirroring (gitolite mirroring does allow a slave to be non-gitolite, as
-long as the ssh stuff is done the same way).
-
-The main difference is that gitolite mirroring expects peers to all talk ssh,
-whereas this method lets you use other protocols.  Specifically, since this
-whole thing was started off by someone wanting to put his repos on s3
-(apparently jgit can talk to s3 directly), you can modify the two functions to
-deal with whatever remote server you have.
-
-LANGUAGE
---------
-
-This doesn't have to be in perl.  Shell equivalent for the only gitolite
-specific code is supplied; the rest of the code is fairly straightforward.
-
-SETUP
------
-
-1.  Put this code into your LOCAL_CODE directory under "triggers"; see
-    non-core.html for details.
-
-2.  Add these lines to your rc file, just before the ENABLE line.  (I'm
-    assuming a v3.4 or later installation here).
-
-        POST_CREATE => [ 'file_mirror' ],
-        POST_GIT => [ 'file_mirror' ],
-
-3.  Backup your rc file, since you may have other changes in it that you'll
-    want to preserve.
-
-4.  Do something like this in your gitolite.conf file:
-
-        repo @all
-            option mirror.extslave-1    =   file:///tmp/he1/%GL_REPO.git
-            option mirror.extslave-2    =   file:///tmp/he2/%GL_REPO.git
-
-    As you can see, since this is just for demo/test, we're using a couple of
-    temp directories to serve as our "remotes" using the file:// protocol.
-
-5.  Do a one-time manual sync of all the repos (subsequent syncs happen on
-    each push):
-
-        gitolite list-phy-repos | xargs -I xx gitolite trigger POST_GIT xx admin W
-
-    (This is a little trick we're playing on the trigger stuff, but it should
-    work fine.  Just make sure that, if you have other things in your POST_GIT
-    trigger list, they're not affected in some way.  'gitolite query-rc
-    POST_GIT' will tell you what else you have.)
-
-That takes care of the "setup" and "regular backup".
-
-RESTORE
--------
-
-1.  Install gitolite normally.  You'll get the usual two repos.
-
-2.  Restore the previously backed up rc file to replace the default one that
-    gitolite created.  At the very least, the rc file should have the
-    POST_CREATE and POST_GIT entries.
-
-        ---------------------------------------------------------
-        IF YOU FORGET THIS STEP, NASTY THINGS WILL HAPPEN TO YOU!
-        ---------------------------------------------------------
-
-3.  Clone the admin repo from one of your backup servers to some temp dir.  In
-    our example,
-
-        git clone /tmp/he1/gitolite-admin.git old-ga
-
-4.  'cd' to that clone and force push to your *new* admin repo:
-
-        cd old-ga
-        git push -f admin:gitolite-admin
-
-That's it.  As each repo gets created by the admin push, they'll get populated
-by the backed up stuff due to the POST_CREATE trigger.
diff --git a/docker/gitolite/contrib/utils/ad_groups.sh b/docker/gitolite/contrib/utils/ad_groups.sh
deleted file mode 100755
index cc86692..0000000
--- a/docker/gitolite/contrib/utils/ad_groups.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-# author derived from: damien.nozay at gmail.com
-# author: Jonathan Gray
-
-# Given a username,
-# Provides a space-separated list of groups that the user is a member of.
-#
-# see http://gitolite.com/gitolite/conf.html#ldap
-# GROUPLIST_PGM => /path/to/ldap_groups.sh
-
-# Be sure to add your domain CA to the trusted certificates in /etc/openldap/ldap.conf using the TLS_CACERT option or you'll get certificate validation errors
-
-ldaphost='ldap://AD.DC1.local:3268,ldap://AD.DC2.local:3268,ldap://AD.DC3.local:3268'
-ldapuser='git at domain.local'
-ldappass='super.secret.password'
-binddn='dc=domain,dc=local'
-username=$1;
-
-# I don't assume your users share a common OU, so I search the entire domain
-ldap_groups() {
-        # Go fetch the full user CN as it could be anywhere inside the DN
-        usercn=$(
-                ldapsearch -ZZ -H ${ldaphost} -D ${ldapuser} -w ${ldappass} -b ${binddn} -LLL -o ldif-wrap=no "(sAMAccountName=${username})" \
-                | grep "^dn:" \
-                | perl -pe 's|dn: (.*?)|\1|'
-        )
-
-        # Using a proprietary AD extension, let the AD Controller resolve all nested group memberships
-        # http://ddkonline.blogspot.com/2010/05/how-to-recursively-get-group-membership.html
-        # Also, substitute spaces in AD group names for '_' since gitolite expects a space separated list
-        echo $(
-                ldapsearch -ZZ -H ${ldaphost} -D ${ldapuser} -w ${ldappass} -b ${binddn} -LLL -o ldif-wrap=no "(member:1.2.840.113556.1.4.1941:=${usercn})" \
-                | grep "^dn:" \
-                | perl -pe 's|dn: CN=(.*?),.*|\1|' \
-                | sed 's/ /_/g'
-        )
-}
-
-ldap_groups $@
diff --git a/docker/gitolite/contrib/utils/gitolite-local b/docker/gitolite/contrib/utils/gitolite-local
deleted file mode 100755
index 5faf0c7..0000000
--- a/docker/gitolite/contrib/utils/gitolite-local
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/bin/bash
-
-# ----------------------------------------------------------------------
-# change these lines to suit
-testconf=$HOME/GITOLITE-TESTCONF
-gitolite_url=git://github.com/sitaramc/gitolite
-    # change it to something local for frequent use
-    # gitolite_url=file:///tmp/gitolite.git
-
-# ----------------------------------------------------------------------
-# Usage: gitolite-local <options>
-#
-# Test your gitolite.conf rule lists on your LOCAL machine (without even
-# pushing to the server!)
-#
-# (one-time)
-#
-#   1.  put this code somewhere in your $PATH if you wish
-#   2.  edit the line near the top of the script if you want to use some other
-#       directory than the default, for "testconf".
-#   2.  prepare the "testconf" directory by running:
-#           gitolite-local prep
-#
-# (lather, rinse, repeat)
-#
-#   1.  edit the conf (see notes below for more)
-#           gitolite-local edit
-#   2.  compile the conf
-#           gitolite-local compile
-#   3.  check permissions using "info" command:
-#           gitolite-local info USERNAME
-#   4.  check permissions using "access" command:
-#           gitolite-local access <options for gitolite access command>
-#   5.  clone, fetch, and push if you like!
-#           gitolite-local clone <username> <reponame> <other options for clone>
-#           gitolite-local fetch <username> <options for fetch>
-#           gitolite-local push  <username> <options for push>
-#
-# note on editing the conf: you don't have to use the edit command; you can
-# also directly edit '.gitolite/conf/gitolite.conf' in the 'testconf'
-# directory.  You'll need to do that if your gitolite conf consists of more
-# than just one file (like if you have includes, etc.)
-#
-# note on the clone command: most of the options won't work for clone, unless
-# git is ok with them being placed *after* the repo name.
-
-# ----------------------------------------------------------------------
-die() { echo "$@" >&2; exit 1; }
-usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
-[ -z "$1" ] && usage
-
-# ----------------------------------------------------------------------
-if [ $1 == prep ]
-then
-    set -e
-
-    [ -d $testconf ] && die "directory '$testconf' already exists"
-
-    mkdir $testconf
-    cd $testconf
-
-    export HOME=$PWD
-
-    echo getting gitolite source...
-    git clone $gitolite_url gitolite
-    echo
-
-    echo installing gitolite...
-    gitolite/install >/dev/null
-    echo
-
-    echo setting up gitolite...
-    export PATH=$PWD/gitolite/src:$PATH
-    gitolite setup -a admin
-    echo
-
-    exit 0
-fi
-
-od=$PWD
-cd $testconf
-export HOME=$PWD
-export PATH=$PWD/gitolite/src:$PATH
-
-if [ $1 = edit ]
-then
-    editor=${EDITOR:-vim}
-    $editor .gitolite/conf/gitolite.conf
-elif [ $1 = compile ]
-then
-    gitolite compile
-elif [ $1 = compile+ ]
-then
-    gitolite compile\; gitolite trigger POST_COMPILE
-elif [ $1 = info ]
-then
-    shift
-    user=$1
-    shift
-
-    GL_USER=$user gitolite info "$@"
-elif [ $1 = access ]
-then
-    shift
-
-    gitolite access "$@"
-elif [ $1 = clone ]
-then
-    shift
-    export G3T_USER=$1
-    shift
-
-    cd $od
-    export GL_BINDIR=$HOME/gitolite/t
-        # or you could do it the long way, using 'gitolite query-rc GL_BINDIR'
-    repo=$1; shift
-    git clone --upload-pack=$GL_BINDIR/gitolite-upload-pack file:///$repo "$@"
-elif [ $1 = fetch ]
-then
-    shift
-    export G3T_USER=$1
-    shift
-
-    cd $od
-    export GL_BINDIR=$HOME/gitolite/t
-    git fetch --upload-pack=$GL_BINDIR/gitolite-upload-pack "$@"
-elif [ $1 = push ]
-then
-    shift
-    export G3T_USER=$1
-    shift
-
-    cd $od
-    export GL_BINDIR=$HOME/gitolite/t
-    git push --receive-pack=$GL_BINDIR/gitolite-receive-pack "$@"
-fi
diff --git a/docker/gitolite/contrib/utils/ipa_groups.pl b/docker/gitolite/contrib/utils/ipa_groups.pl
deleted file mode 100755
index 9cffa40..0000000
--- a/docker/gitolite/contrib/utils/ipa_groups.pl
+++ /dev/null
@@ -1,229 +0,0 @@
-#!/usr/bin/env perl
-#
-# ipa_groups.pl
-#
-# See perldoc for usage
-#
-use Net::LDAP;
-use Net::LDAP::Control::Paged;
-use Net::LDAP::Constant qw(LDAP_CONTROL_PAGED);
-use strict;
-use warnings;
-
-my $usage = <<EOD;
-Usage: $0 \$uid
-This script returns a list of groups that \$uid is a member of
-EOD
-
-my $uid = shift or die $usage;
-
-## CONFIG SECTION
-
-# If you want to do plain-text LDAP, then set ldap_opts to an empty hash and
-# then set protocols of ldap_hosts to ldap://
-my @ldap_hosts = [
-  'ldaps://auth-ldap-001.prod.example.net',
-  'ldaps://auth-ldap-002.prod.example.net',
-];
-my %ldap_opts = (
-    verify => 'require',
-    cafile => '/etc/pki/tls/certs/prod.example.net_CA.crt'
-);
-
-# Base DN to search
-my $base_dn = 'dc=prod,dc=example,dc=net';
-
-# User for binding to LDAP server with
-my $user = 'uid=svc_gitolite_bind,cn=sysaccounts,cn=etc,dc=prod,dc=example,dc=net';
-my $pass = 'reallysecurepasswordstringhere';
-
-## Below variables should not need to be changed under normal circumstances
-
-# OU where groups are located. Anything return that is not within this OU is
-# removed from results. This OU is static on FreeIPA so will only need updating
-# if you want to support other LDAP servers. This is a regex so can be set to
-# anything you want (E.G '.*').
-my $groups_ou = qr/cn=groups,cn=accounts,${base_dn}$/;
-
-# strip path - if you want to return the full path of the group object then set
-# this to 0
-my $strip_group_paths = 1;
-
-# Number of seconds before timeout (for each query)
-my $timeout=5;
-
-# user object class
-my $user_oclass = 'person';
-
-# group attribute
-my $group_attrib = 'memberOf';
-
-## END OF CONFIG SECTION
-
-# Catch timeouts here
-$SIG{'ALRM'} = sub {
-  die "LDAP queries timed out";
-};
-
-alarm($timeout);
-
-# try each server until timeout is reached, has very fast failover if a server
-# is totally unreachable
-my $ldap = Net::LDAP->new(@ldap_hosts, %ldap_opts) ||
-  die "Error connecting to specified servers: $@ \n";
-
-my $mesg = $ldap->bind(
-    dn       => $user,
-    password => $pass
-);
-
-if ($mesg->code()) {
-  die ("error:",      $mesg->code(),"\n",
-       "error name: ",$mesg->error_name(),"\n",
-       "error text: ",$mesg->error_text(),"\n");
-}
-
-# How many LDAP query results to grab for each paged round
-# Set to under 1000 to limit load on LDAP server
-my $page = Net::LDAP::Control::Paged->new(size => 500);
-
-# @queries is an array or array references. We initially fill it up with one
-# arrayref (The first LDAP search) and then add more during the execution.
-# First start by resolving the group.
-my @queries = [ ( base    => $base_dn,
-                  filter  => "(&(objectClass=${user_oclass})(uid=${uid}))",
-                  control => [ $page ],
-) ];
-
-# array to store groups matching $groups_ou
-my @verified_groups;
-
-# Loop until @queries is empty...
-foreach my $queryref (@queries) {
-
-  # set cookie for paged querying
-  my $cookie;
-  alarm($timeout);
-  while (1) {
-    # Perform search
-    my $mesg = $ldap->search( @{$queryref} );
-
-    foreach my $entry ($mesg->entries) {
-      my @groups = $entry->get_value($group_attrib);
-      # find any groups matching $groups_ou  regex and push onto $verified_groups array
-      foreach my $group (@groups) {
-        if ($group =~ /$groups_ou/) {
-          push @verified_groups, $group;
-        }
-      }
-    }
-
-    # Only continue on LDAP_SUCCESS
-    $mesg->code and last;
-
-    # Get cookie from paged control
-    my($resp)  = $mesg->control(LDAP_CONTROL_PAGED) or last;
-    $cookie    = $resp->cookie or last;
-
-    # Set cookie in paged control
-    $page->cookie($cookie);
-  } # END: while(1)
-
-  # Reset the page control for the next query
-  $page->cookie(undef);
-
-  if ($cookie) {
-    # We had an abnormal exit, so let the server know we do not want any more
-    $page->cookie($cookie);
-    $page->size(0);
-    $ldap->search( @{$queryref} );
-    # Then die
-    die("LDAP query unsuccessful");
-  }
-
-} # END: foreach my $queryref (...)
-
-# we're assuming that the group object looks something like
-# cn=name,cn=groups,cn=accounts,dc=X,dc=Y and there are no ',' chars in group
-# names
-if ($strip_group_paths) {
-  for (@verified_groups) { s/^cn=([^,]+),.*$/$1/g };
-}
-
-foreach my $verified (@verified_groups) {
-  print $verified . "\n";
-}
-
-alarm(0);
-
-__END__
-
-=head1 NAME
-
-ipa_groups.pl
-
-=head2 VERSION
-
-0.1.1
-
-=head2 DESCRIPTION
-
-Connects to one or more FreeIPA-based LDAP servers in a first-reachable fashion and returns a newline separated list of groups for a given uid. Uses memberOf attribute and thus supports nested groups.
-
-=head2 AUTHOR
-
-Richard Clark <rclark at telnic.org>
-
-=head2 FreeIPA vs Generic LDAP
-
-This script uses regular LDAP, but is focussed on support for FreeIPA, where users and groups are generally contained within single OUs, and memberOf attributes within the user object are enumerated with a recursive list of groups that the user is a member of.
-
-It is mostly impossible to provide generic out of the box LDAP support due to varying schemas, supported extensions and overlays between implementations.
-
-=head2 CONFIGURATION
-
-=head3  LDAP Bind Account 
-
-To setup an LDAP bind user in FreeIPA, create a svc_gitolite_bind.ldif file along the following lines:
-
-    dn: uid=svc_gitolite_bind,cn=sysaccounts,cn=etc,dc=prod,dc=example,dc=net
-    changetype: add
-    objectclass: account
-    objectclass: simplesecurityobject
-    uid: svc_gitolite_bind
-    userPassword: reallysecurepasswordstringhere
-    passwordExpirationTime: 20150201010101Z
-    nsIdleTimeout: 0
-
-Then create the service account user, using ldapmodify authenticating as the the directory manager account (or other acccount with appropriate privileges to the sysaccounts OU):
-
-    $ ldapmodify -h auth-ldap-001.prod.example.net -Z -x -D "cn=Directory Manager" -W -f svc_gitolite_bind.ldif
-
-=head3 Required Configuration
-
-The following variables within the C<## CONFIG SECTION ##> need to be configured before the script will work.
-
-C<@ldap_hosts> - Should be set to an array of URIs or hosts to connect to. Net::LDAP will attempt to connect to each host in this list and stop on the first reachable server. The example shows TLS-supported URIs, if you want to use plain-text LDAP then set the protocol part of the URI to LDAP:// or just provide hostnames as this is the default behavior for Net::LDAP.
-
-C<%ldap_opts> - To use LDAP-over-TLS, provide the CA certificate for your LDAP servers. To use plain-text LDAP, then empty this hash of it's values or provide other valid arguments to Net::LDAP.
-
-C<%base_dn> - This can either be set to the 'true' base DN for your directory, or alternatively you can set it the the OU that your users are located in (E.G cn=users,cn=accounts,dc=prod,dc=example,dc=net).
-
-C<$user> - Provide the full Distinguished Name of your directory bind account as configured above.
-
-C<$pass> - Set to password of your directory bind account as configured above.
-
-=head3 Optional Configuration
-
-C<$groups_ou> - By default this is a regular expression matching the default groups OU. Any groups not matching this regular expression are removed from the search results. This is because FreeIPA enumerates non-user type groups (E.G system, sudoers, policy and other types) within the memberOf attribute. To change this behavior, set C<$groups_ou> to a regex matching anything you want (E.G: '.*').
-
-C<$strip_group_paths> - If this is set to perl boolean false (E.G '0') then groups will be returned in DN format. Default is true, so just the short/CN value is returned.
-
-C<$timeout> - Number of seconds to wait for an LDAP query before determining that it has failed and trying the next server in the list. This does not affect unreachable servers, which are failed immediately.
-
-C<$user_oclass> - Object class of the user to search for.
-
-C<$group_attrib> - Attribute to search for within the user object that denotes the membership of a group.
-
-=cut
-
diff --git a/docker/gitolite/contrib/utils/ldap_groups.sh b/docker/gitolite/contrib/utils/ldap_groups.sh
deleted file mode 100755
index 01bf5ee..0000000
--- a/docker/gitolite/contrib/utils/ldap_groups.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-# author: damien.nozay at gmail.com
-
-# Given a username,
-# Provides a space-separated list of groups that the user is a member of.
-#
-# see http://gitolite.com/gitolite/conf.html#ldap
-# GROUPLIST_PGM => /path/to/ldap_groups.sh
-
-ldap_groups() {
-    username=$1;
-    # this relies on openldap / pam_ldap to be configured properly on your
-    # system. my system allows anonymous search.
-    echo $(
-        ldapsearch -x -LLL "(&(objectClass=posixGroup)(memberUid=${username}))" cn \
-        | grep "^cn" \
-        | cut -d' ' -f2
-    );
-}
-
-ldap_groups $@
diff --git a/docker/gitolite/contrib/utils/rc-format-v3.4 b/docker/gitolite/contrib/utils/rc-format-v3.4
deleted file mode 100755
index 1a11737..0000000
--- a/docker/gitolite/contrib/utils/rc-format-v3.4
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/bin/perl
-
-# help with rc file format change at v3.4 -- help upgrade v3 rc files from
-# v3.3 and below to the new v3.4 and above format
-
-# once you upgrade gitolite past 3.4, you may want to use the new rc file
-# format, because it's really much nicer (just to recap: the old format will
-# still work, in fact internally the new format gets converted to the old
-# format before actually being used.  However, the new format makes it much
-# easier to enable and disable features).
-
-# PLEASE SEE WARNINGS BELOW
-
-# this program helps you upgrade your rc file.
-
-# STEPS
-#   cd gitolite-source-repo-clone
-#   contrib/utils/upgrade-rc33 /path/to/old.gitolite.rc > new.gitolite.rc
-
-# WARNINGS
-#   make sure you also READ ALL ERROR/WARNING MESSAGES GENERATED
-#   make sure you EXAMINE THE FILE AND CHECK THAT EVERYTHING LOOKS GOOD before using it
-#   be especially careful about
-#       variables which contains single/double quotes or other special characters
-#       variables that stretch across multiple lines
-#       features which take arguments (like 'renice')
-#       new features you've enabled which don't exist in the default rc
-
-# ----------------------------------------------------------------------
-
-use strict;
-use warnings;
-use 5.10.0;
-use Cwd;
-use Data::Dumper;
-$Data::Dumper::Terse    = 1;
-$Data::Dumper::Indent   = 1;
-$Data::Dumper::Sortkeys = 1;
-
-BEGIN {
-    $ENV{HOME} = getcwd;
-    $ENV{HOME} .= "/.home.rcupgrade.$$";
-    mkdir $ENV{HOME} or die "mkdir '$ENV{HOME}': $!\n";
-}
-
-END {
-    system("rm -rf ./.home.rcupgrade.$$");
-}
-
-use lib "./src/lib";
-use Gitolite::Rc;
-{
-    no warnings 'redefine';
-    sub Gitolite::Common::gl_log { }
-}
-
-# ----------------------------------------------------------------------
-
-# everything happens inside a fresh v3.6.1+ gitolite clone; no other
-# directories are used.
-
-# the old rc file to be migrated is somewhere *else* and is supplied as a
-# command line argument.
-
-# ----------------------------------------------------------------------
-
-my $oldrc = shift or die "need old rc filename as arg-1\n";
-
-{
-
-    package rcup;
-    do $oldrc;
-}
-
-my %oldrc;
-{
-    no warnings 'once';
-    %oldrc = %rcup::RC;
-}
-
-delete $rcup::{RC};
-{
-    my @extra = sort keys %rcup::;
-    warn "**** WARNING ****\nyou have variables declared outside the %RC hash; you must handle them manually\n" if @extra;
-}
-
-# this is the new rc text being built up
-my $newrc = glrc('default-text');
-
-# ----------------------------------------------------------------------
-
-# default disable all features in newrc
-map { disable( $_, 'sq' ) } (qw(help desc info perms writable ssh-authkeys git-config daemon gitweb));
-# map { disable($_, '') } (qw(GIT_CONFIG_KEYS));
-
-set_s('HOSTNAME');
-set_s( 'UMASK',               'num' );
-set_s( 'GIT_CONFIG_KEYS',     'sq' );
-set_s( 'LOG_EXTRA',           'num' );
-set_s( 'DISPLAY_CPU_TIME',    'num' );
-set_s( 'CPU_TIME_WARN_LIMIT', 'num' );
-set_s('SITE_INFO');
-
-set_s('LOCAL_CODE');
-
-if ( $oldrc{WRITER_CAN_UPDATE_DESC} ) {
-    die "tell Sitaram he changed the default rc too much" unless $newrc =~ /rc variables used by various features$/m;
-    $newrc =~ s/(rc variables used by various features\n)/$1\n    # backward compat\n        WRITER_CAN_UPDATE_DESC      =>  1,\n/;
-
-    delete $oldrc{WRITER_CAN_UPDATE_DESC};
-}
-
-if ( $oldrc{ROLES} ) {
-    my $t = '';
-    for my $r ( sort keys %{ $oldrc{ROLES} } ) {
-        $t .= ( " " x 8 ) . $r . ( " " x ( 28 - length($r) ) ) . "=>  1,\n";
-    }
-    $newrc =~ s/(ROLES *=> *\{\n).*?\n( *\},)/$1$t$2/s;
-
-    delete $oldrc{ROLES};
-}
-
-if ( $oldrc{DEFAULT_ROLE_PERMS} ) {
-    warn "DEFAULT_ROLE_PERMS has been replaced by per repo option\nsee http://gitolite.com/gitolite/wild.html\n";
-    delete $oldrc{DEFAULT_ROLE_PERMS};
-}
-
-# the following is a bit like the reverse of what the new Rc.pm does...
-
-for my $l ( split /\n/, $Gitolite::Rc::non_core ) {
-    next if $l =~ /^ *#/ or $l !~ /\S/;
-
-    my ( $name, $where, $module ) = split ' ', $l;
-    $module = $name if $module eq '.';
-    ( $module = $name ) .= "::" . lc($where) if $module eq '::';
-
-    # if you find $module as an element of $where, enable $name
-    enable($name) if miw( $module, $where );
-}
-
-# now deal with commands
-if ( $oldrc{COMMANDS} ) {
-    for my $c ( sort keys %{ $oldrc{COMMANDS} } ) {
-        if ( $oldrc{COMMANDS}{$c} == 1 ) {
-            enable($c);
-            # we don't handle anything else right (and so far only git-annex
-            # is affected, as far as I remember)
-
-            delete $oldrc{COMMANDS}{$c};
-        }
-    }
-}
-
-print $newrc;
-
-for my $w (qw(INPUT POST_COMPILE PRE_CREATE ACCESS_1 POST_GIT PRE_GIT ACCESS_2 POST_CREATE SYNTACTIC_SUGAR)) {
-    delete $oldrc{$w} unless scalar( @{ $oldrc{$w} } );
-}
-delete $oldrc{COMMANDS} unless scalar keys %{ $oldrc{COMMANDS} };
-
-exit 0 unless %oldrc;
-
-warn "the following parts of the old rc were NOT converted:\n";
-print STDERR Dumper \%oldrc;
-
-# ----------------------------------------------------------------------
-
-# set scalars that the new file defaults to "commented out"
-sub set_s {
-    my ( $key, $type ) = @_;
-    $type ||= '';
-    return unless exists $oldrc{$key};
-
-    # special treatment for UMASK
-    $oldrc{$key} = substr( "00" . sprintf( "%o", $oldrc{$key} ), -4 ) if ( $key eq 'UMASK' );
-
-    $newrc =~ s/# $key /$key   /;    # uncomment if needed
-    if ( $type eq 'num' ) {
-        $newrc =~ s/$key ( *=> *).*/$key $1$oldrc{$key},/;
-    } elsif ( $type eq 'sq' ) {
-        $newrc =~ s/$key ( *=> *).*/$key $1'$oldrc{$key}',/;
-    } else {
-        $newrc =~ s/$key ( *=> *).*/$key $1"$oldrc{$key}",/;
-    }
-
-    delete $oldrc{$key};
-}
-
-sub disable {
-    my ( $key, $type ) = @_;
-    if ( $type eq 'sq' ) {
-        $newrc =~ s/^( *)'$key'/$1# '$key'/m;
-    } else {
-        $newrc =~ s/^( *)$key\b/$1# $key/m;
-    }
-}
-
-sub enable {
-    my $key = shift;
-    $newrc =~ s/^( *)# *'$key'/$1'$key'/m;
-    return if $newrc =~ /^ *'$key'/m;
-    $newrc =~ s/(add new commands here.*\n)/$1            '$key',\n/;
-}
-
-sub miw {
-    my ( $m, $w ) = @_;
-    return 0 unless $oldrc{$w};
-    my @in = @{ $oldrc{$w} };
-    my @out = grep { !/^$m$/ } @{ $oldrc{$w} };
-    $oldrc{$w} = \@out;
-    return not scalar(@in) == scalar(@out);
-}
diff --git a/docker/gitolite/convert-gitosis-conf b/docker/gitolite/convert-gitosis-conf
deleted file mode 100755
index 9b92f68..0000000
--- a/docker/gitolite/convert-gitosis-conf
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/perl -w
-#
-# migrate gitosis.conf to gitolite.conf format
-#
-# Based on gl-conf-convert by: Sitaram Chamarty
-# Rewritten by: Behan Webster <behanw at websterwood.com>
-#
-
-use strict;
-use warnings;
-
-if (not @ARGV and -t or @ARGV and $ARGV[0] eq '-h') {
-    print "Usage:\n    gl-conf-convert < gitosis.conf > gitolite.conf\n(please see the documentation for details)\n";
-    exit 1;
-}
-
-my @comments = ();
-my $groupname;
-my %groups;
-my $reponame;
-my %repos;
-
-while (<>)
-{
-    # not supported
-    if (/^repositories *=/ or /^map /) {
-        print STDERR "not supported: $_";
-        s/^/NOT SUPPORTED: /;
-        print;
-        next;
-    }
-
-    # normalise whitespace to help later regexes
-    chomp;
-    s/\s+/ /g;
-    s/ ?= ?/ = /;
-    s/^ //;
-    s/ $//;
-
-    if (/^\s*$/ and @comments > 1) {
-        @{$repos{$reponame}{comments}} = @comments if $reponame;
-        @{$groups{$groupname}{comments}} = @comments if $groupname;
-        @comments = ();
-    } elsif (/^\s*#/) {
-        push @comments, $_;
-    } elsif (/^\[repo\s+(.*?)\]$/) {
-        $groupname = '';
-        $reponame = $1;
-        $reponame =~ s/\.git$//;
-    } elsif (/^\[gitosis\]$/) {
-        $groupname = '';
-        $reponame = '@all';
-    } elsif (/^gitweb\s*=\s*yes/i) {
-        push @{$repos{$reponame}{R}}, 'gitweb';
-    } elsif (/^daemon\s*=\s*yes/i) {
-        push @{$repos{$reponame}{R}}, 'daemon';
-    } elsif (/^description\s*=\s*(.+?)$/) {
-        $repos{$reponame}{desc} = $1;
-    } elsif (/^owner\s*=\s*(.+?)$/) {
-        $repos{$reponame}{owner} = $1;
-    } elsif (/^\[group\s+(.*)\]$/) {
-        $reponame = '';
-        $groupname = $1;
-    } elsif (/^members\s*=\s*(.*)/) {
-        push @{$groups{$groupname}{users}}, map {s/\@([^.]+)$/_$1/g; $_} split(' ', $1);
-    } elsif (/^write?able\s*=\s*(.*)/) {
-        foreach my $repo (split(' ', $1)) {
-            $repo =~ s/\.git$//;
-            push @{$repos{$repo}{RW}}, "\@$groupname";
-        }
-    } elsif (/^readonly\s*=\s*(.*)/) {
-        foreach my $repo (split(' ', $1)) {
-            $repo =~ s/\.git$//;
-            push @{$repos{$repo}{R}}, "\@$groupname";
-        }
-    }
-}
-
-#use Data::Dumper;
-#print Dumper(\%repos);
-#print Dumper(\%groups);
-
-# Groups
-print "#\n# Groups\n#\n\n";
-foreach my $grp (sort keys %groups) {
-    next unless @{$groups{$grp}{users}};
-    printf join("\n", @{$groups{$grp}{comments}})."\n" if $groups{$grp}{comments};
-    printf "\@%-19s = %s\n", $grp, join(' ', @{$groups{$grp}{users}});
-}
-
-# Gitweb
-print "\n#\n# Gitweb\n#\n\n";
-foreach my $repo (sort keys %repos) {
-    if ($repos{$repo}{desc}) {
-        @{$repos{$repo}{R}} = grep(!/^gitweb$/, @{$repos{$repo}{R}});
-        print $repo;
-        print " \"$repos{$repo}{owner}\"" if $repos{$repo}{owner};
-        print " = \"$repos{$repo}{desc}\"\n";
-    }
-}
-
-# Repos
-print "\n#\n# Repos\n#\n";
-foreach my $repo (sort keys %repos) {
-    print "\n";
-    printf join("\n", @{$repos{$repo}{comments}})."\n" if $repos{$repo}{comments};
-    #if ($repos{$repo}{desc}) {
-    #    @{$repos{$repo}{R}} = grep(!/^gitweb$/, @{$repos{$repo}{R}});
-    #}
-    print "repo\t$repo\n";
-    foreach my $access (qw(RW+ RW R)) {
-        next unless $repos{$repo}{$access};
-        my @keys;
-        foreach my $key (@{$repos{$repo}{$access}}) {
-            if ($key =~ /^\@(.*)/) {
-                next unless defined $groups{$1} and @{$groups{$1}{users}};
-            }
-            push @keys, $key;
-        }
-        printf "\t$access\t= %s\n", join(' ', @keys) if @keys;
-    }
-    #if ($repos{$repo}{desc}) {
-    #    print $repo;
-    #    print " \"$repos{$repo}{owner}\"" if $repos{$repo}{owner};
-    #    print " = \"$repos{$repo}{desc}\"\n";
-    #}
-}
diff --git a/docker/gitolite/install b/docker/gitolite/install
deleted file mode 100755
index 98d8aee..0000000
--- a/docker/gitolite/install
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# Clearly you don't need a program to make one measly symlink, but the git
-# describe command involved in generating the VERSION string is a bit fiddly.
-
-use Getopt::Long;
-use FindBin;
-
-# meant to be run from the root of the gitolite tree, one level above 'src'
-BEGIN { $ENV{GL_BINDIR} = $FindBin::RealBin . "/src"; }
-BEGIN { $ENV{GL_LIBDIR} = "$ENV{GL_BINDIR}/lib"; }
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Common;
-
-=for usage
-Usage (from gitolite clone directory):
-
-    ./install
-        to run gitolite using an absolute or relative path, for example
-        'src/gitolite' or '/full/path/to/this/dir/src/gitolite'
-
-    ./install -ln [<dir>]
-        to symlink just the gitolite executable to some <dir> that is in
-        $PATH.  <dir> defaults to $HOME/bin if <dir> not specified.  <dir> is
-        assumed to exist; gitolite will not create it.
-
-        Please provide a full path, not a relative path.
-
-    ./install -to <dir>
-        to copy the entire 'src' directory to <dir>.  If <dir> is not in
-        $PATH, use the full path to run gitolite commands.
-
-        Please provide a full path, not a relative path.
-
-Simplest use, if $HOME/bin exists and is in $PATH, is:
-
-    git clone git://github.com/sitaramc/gitolite
-    gitolite/install -ln
-
-    # now run setup
-    gitolite setup -pk /path/to/YourName.pub
-=cut
-
-my ( $to, $ln, $help, $quiet );
-
-GetOptions(
-    'to=s' => \$to,
-    'ln:s' => \$ln,
-    'help|h'    => \$help,
-    'quiet|q'    => \$quiet,
-);
-usage() if $to and $ln or $help;
-$ln = "$ENV{HOME}/bin" if defined($ln) and not $ln;
-for my $d ($ln, $to) {
-    next unless $d;    # ignore empty values
-    unless ( $d =~ m(^/) ) {
-        print STDERR "FATAL: please use an absolute path, not a relative path\n";
-        usage();
-    }
-    if ( not -d $d ) {
-        print STDERR "FATAL: '$d' does not exist.\n";
-        usage();
-    }
-}
-
-chdir($ENV{GL_BINDIR});
-my $version = `git describe --tags --long --dirty=-dt 2>/dev/null`;
-unless ($version =~ /^v\d/) {
-    print STDERR "git describe failed; cannot deduce version number\n";
-    $version = "(unknown)";
-}
-
-if ($to) {
-    _mkdir($to);
-    system("cp -RpP * $to");
-    _print( "$to/VERSION", $version );
-} elsif ($ln) {
-    ln_sf( $ENV{GL_BINDIR}, "gitolite", $ln );
-    _print( "VERSION", $version );
-} else {
-    say "use the following full path for gitolite:";
-    say "\t$ENV{GL_BINDIR}/gitolite";
-    _print( "VERSION", $version );
-}
diff --git a/docker/gitolite/src/VREF/COUNT b/docker/gitolite/src/VREF/COUNT
deleted file mode 100755
index f4c3eae..0000000
--- a/docker/gitolite/src/VREF/COUNT
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/sh
-
-# gitolite VREF to count number of changed/new files in a push
-
-# see gitolite docs for what the first 7 arguments mean
-
-# inputs:
-#   arg-8 is a number
-#   arg-9 is optional, and can be "NEWFILES"
-# outputs (STDOUT)
-#   arg-7 if the number of changed (or new, if arg-9 supplied) files is > arg-8
-#   otherwise nothing
-# exit status:
-#   always 0
-
-die() { echo "$@" >&2; exit 1; }
-[ -z "$8" ] && die "not meant to be run manually"
-
-newsha=$3
-oldtree=$4
-newtree=$5
-refex=$7
-
-max=$8
-
-nf=
-[ "$9" = "NEWFILES" ] && nf='--diff-filter=A'
-# NO_SIGNOFF implies NEWFILES
-[ "$9" = "NO_SIGNOFF" ] && nf='--diff-filter=A'
-
-# count files against all the other commits in the system not just $oldsha
-# (why?  consider what is $oldtree when you create a new branch, or what is
-# $oldsha when you update an old feature branch from master and then push it
-count=`git log --name-only $nf --format=%n $newtree --not --all | grep . | sort -u | perl -ne '}{print "$."'`
-
-[ $count -gt $max ] && {
-    # count has been exceeded.  If $9 was NO_SIGNOFF there's still a chance
-    # for redemption -- if the top commit has a proper signed-off by line
-    [ "$9" = "NO_SIGNOFF" ] && {
-        author_email=$(git log --format=%ae -1 $newsha)
-        git cat-file -p $newsha |
-            egrep -i >/dev/null "^ *$count +new +files +signed-off by: *$author_email *$" && exit 0
-        echo $refex top commit message should include the text \'$count new files signed-off by: $author_email\'
-        exit 0
-    }
-    echo -n $refex "(too many "
-    [ -n "$nf" ] && echo -n "new " || echo -n "changed "
-    echo "files in this push)"
-}
-
-exit 0
diff --git a/docker/gitolite/src/VREF/EMAIL-CHECK b/docker/gitolite/src/VREF/EMAIL-CHECK
deleted file mode 100755
index 34c66f5..0000000
--- a/docker/gitolite/src/VREF/EMAIL-CHECK
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/perl
-
-# gitolite VREF to check if all *new* commits have author == pusher
-
-#                       THIS IS NOT READY TO USE AS IS
-#                       ------------------------------
-#           you MUST change the 'email_ok()' sub to suit *YOUR* site's
-#           gitolite username -> author email mapping!
-
-# See bottom of the program for important philosophical notes.
-
-use strict;
-use warnings;
-
-# mapping between gitolite userid and correct email address is encapsulated in
-# this subroutine; change as you like
-sub email_ok {
-    my ($author_email) = shift;
-    my $expected_email = "$ENV{GL_USER}\@atc.tcs.com";
-    return $author_email eq $expected_email;
-}
-
-my ( $ref, $old, $new ) = @ARGV;
-for my $rev (`git log --format="%ae\t%h\t%s" $new --not --all`) {
-    chomp($rev);
-    my ( $author_email, $hash, $subject ) = split /\t/, $rev;
-
-    # again, we use the trick that a vref can just choose to die instead of
-    # passing back a vref, having it checked, etc., if it's more convenient
-    die "$ENV{GL_USER}, you can't push $hash authored by $author_email\n" . "\t(subject of commit was $subject)\n"
-      unless email_ok($author_email);
-}
-
-exit 0;
-
-__END__
-
-The following discussion is for people who want to enforce this check on ALL
-their developers (i.e., not just the newbies).
-
-Doing this breaks the "D" in "DVCS", forcing all your developers to work to a
-centralised model as far as pushes are concerned.  It prevents amending
-someone else's commit and pushing (this includes rebasing, cherry-picking, and
-so on, which are all impossible now).  It also makes *any* off-line
-collabaration between two developers useless, because neither of them can push
-the result to the server.
-
-PHBs should note that validating the committer ID is NOT the same as reviewing
-the code and running QA/tests on it.  If you're not reviewing/QA-ing the code,
-it's probably worthless anyway.  Conversely, if you *are* going to review the
-code and run QA/tests anyway, then you don't really need to validate the
-author email!
-
-In a DVCS, if you *pushed* a series of commits, you have -- in some sense --
-signed off on them.  The most formal way to "sign" a series is to tack on and
-push a gpg-signed tag, although most people don't go that far.  Gitolite's log
-files are designed to preserve that accountability to *some* extent, though;
-see contrib/adc/who-pushed for an admin defined command that quickly and
-easily tells you who *pushed* a particular commit.
-
-Anyway, the point is that the only purpose of this script is to
-
-  * pander to someone who still has not grokked *D*VCS
-          OR
-  * tick off an item in some stupid PHB's checklist
-
diff --git a/docker/gitolite/src/VREF/FILETYPE b/docker/gitolite/src/VREF/FILETYPE
deleted file mode 100755
index 3f1d5f9..0000000
--- a/docker/gitolite/src/VREF/FILETYPE
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-
-# gitolite VREF to find autogenerated files
-
-# *completely* site specific; use it as an illustration of what can be done
-# with gitolite VREFs if you wish
-
-# see gitolite docs for what the first 7 arguments mean
-
-# inputs:
-#   arg-8 is currently only one possible value: AUTOGENERATED
-# outputs (STDOUT)
-#   arg-7 if any files changed in the push look like they were autogenerated
-#   otherwise nothing
-# exit status:
-#   always 0
-
-die() { echo "$@" >&2; exit 1; }
-[ -z "$8" ] && die "not meant to be run manually"
-
-newsha=$3
-oldtree=$4
-newtree=$5
-refex=$7
-
-option=$8
-
-[ "$option" = "AUTOGENERATED" ] && {
-    # currently we only look for ".java" programs with the string "Generated
-    # by the protocol buffer compiler.  DO NOT EDIT" in them.
-
-    git log --name-only $nf --format=%n $newtree --not --all |
-        grep . |
-        sort -u |
-        grep '\.java$' |
-    while read fn
-    do
-        git show "$newtree:$fn" | egrep >/dev/null \
-            'Generated by the protocol buffer compiler. +DO NOT EDIT' ||
-            continue
-
-        echo $refex
-        exit 0
-    done
-}
diff --git a/docker/gitolite/src/VREF/MAX_NEWBIN_SIZE b/docker/gitolite/src/VREF/MAX_NEWBIN_SIZE
deleted file mode 100755
index 84a9efa..0000000
--- a/docker/gitolite/src/VREF/MAX_NEWBIN_SIZE
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# gitolite VREF to check max size of new binary files
-
-# see gitolite docs for what the first 7 arguments mean
-
-# inputs:
-#   arg-8 is a number
-# outputs (STDOUT)
-#   arg-7 if any new binary files exist that are greater in size than arg-8
-#   *and* there is no "signed-off by" line for such a file in the top commit
-#   message.
-#
-#   Otherwise nothing
-# exit status:
-#   always 0
-
-die "not meant to be run manually" unless $ARGV[7];
-
-my ( $newsha, $oldtree, $newtree, $refex, $max ) = @ARGV[ 2, 3, 4, 6, 7 ];
-
-# / (.*) +\| Bin 0 -> (\d+) bytes/
-
-chomp( my $author_email = `git log --format=%ae -1 $newsha` );
-my $msg = `git cat-file -p $newsha`;
-$msg =~ s/\t/ /g;    # makes our regexes simpler
-
-for my $newbin (`git diff --stat=999,999 $oldtree $newtree | grep Bin.0.-`) {
-    next unless $newbin =~ /^ (.*) +\| +Bin 0 -> (\d+) bytes/;
-    my ( $f, $s ) = ( $1, $2 );
-    next if $s <= $max;
-
-    next if $msg =~ /^ *$f +signed-off by: *$author_email *$/mi;
-
-    print "$refex $f is larger than $max";
-}
-
-exit 0
diff --git a/docker/gitolite/src/VREF/MERGE-CHECK b/docker/gitolite/src/VREF/MERGE-CHECK
deleted file mode 100644
index 07f0351..0000000
--- a/docker/gitolite/src/VREF/MERGE-CHECK
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# gitolite VREF to check if there are any merge commits in the current push.
-
-# THIS IS DEMO CODE; please read all comments below as well as
-# doc/vref.mkd before trying to use this.
-
-# usage in conf/gitolite.conf goes like this:
-
-#       -   VREF/MERGE_CHECK/master     =   @all
-#       # reject only if the merge commit is being pushed to the master branch
-#       -   VREF/MERGE_CHECK            =   @all
-#       # reject merge commits to any branch
-
-my $ref    = $ARGV[0];
-my $oldsha = $ARGV[1];
-my $newsha = $ARGV[2];
-my $refex  = $ARGV[6];
-
-# The following code duplicates some code from parse_conf_line() and some from
-# check_ref().  This duplication is the only thing that is preventing me from
-# removing the "M" permission code from 'core' gitolite and using this
-# instead.  However, it does demonstrate how you would do this if you had to
-# create any other similar features, for example someone wanted "no non-merge
-# first-parent", which is far too specific for me to add to 'core'.
-
-# -- begin duplication --
-my $branch_refex = $ARGV[7] || '';
-if ($branch_refex) {
-    $branch_refex =~ m(^refs/) or $branch_refex =~ s(^)(refs/heads/);
-} else {
-    $branch_refex = 'refs/.*';
-}
-exit 0 unless $ref =~ /^$branch_refex/;
-# -- end duplication --
-
-# we can't run this check for tag creation or new branch creation, because
-# 'git log' does not deal well with $oldsha = '0' x 40.
-if ( $oldsha eq "0" x 40 or $newsha eq "0" x 40 ) {
-    print STDERR "ref create/delete ignored for purposes of merge-check\n";
-    exit 0;
-}
-
-my $ret = `git rev-list -n 1 --merges $oldsha..$newsha`;
-print "$refex FATAL: merge commits not allowed\n" if $ret =~ /./;
-
-exit 0;
diff --git a/docker/gitolite/src/VREF/NAME_NC b/docker/gitolite/src/VREF/NAME_NC
deleted file mode 100755
index 1a81714..0000000
--- a/docker/gitolite/src/VREF/NAME_NC
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-# ----------------------------------------------------------------------
-# VREF/NAME_NC
-#   Like VREF/NAME, but only considers "new commits" -- i.e., commits that
-#   don't already exist in the repo as part of some other ref.
-
-# ----------------------------------------------------------------------
-# WHY
-#   VREF/NAME doesn't deal well with tag creation (or new branch creation),
-#   since then all files in the project look like they are being created (due
-#   to comparison with an empty tree).
-
-#   Use this instead of VREF/NAME when you need to make that distinction.
-
-newsha=$3
-
-[ $newsha = "0000000000000000000000000000000000000000" ] && {
-    echo "we don't currently handle deletions" >&2
-    exit 1
-}
-
-git log --name-only --format=%n $newsha --not --all |
-    sort -u | grep . | sed -e 's.^.VREF/NAME_NC/.'
-
-# ----------------------------------------------------------------------
-# OTHER NOTES
-#   The built-in NAME does have a wee bit of a performance advantage.  I plan
-#   to ignore this until someone notices this enough to be a problem :)
-#
-#   I could explain it here at least, but I fear that any explanation will
-#   only add to the already rampant confusion about how VREFs work.  I'm not
-#   rocking THAT boat again, sorry!
diff --git a/docker/gitolite/src/VREF/VOTES b/docker/gitolite/src/VREF/VOTES
deleted file mode 100755
index 8dc3563..0000000
--- a/docker/gitolite/src/VREF/VOTES
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/sh
-
-# gitolite VREF to count votes before allowing pushes to certain branches.
-
-# This approximates gerrit's voting (but it is SHA based; I believe Gerrit is
-# more "changeset" based).  Here's how it works:
-
-# - A normal developer "bob" proposes changes to master by pushing a commit to
-#   "pers/bob/master", then informs the voting members by email.
-
-# - Some or all of the voting members fetch and examine the commit.  If they
-#   approve, they "vote" for the commit like so.  For example, say voting
-#   member "alice" fetched bob's proposed commit into "bob-master" on her
-#   clone, then tested or reviewed it.  She would approve it by running:
-#       git push origin bob-master:votes/alice/master
-
-# - Once enough votes have been tallied (hopefully there is normal team
-#   communication that says "hey I approved your commit", or it can be checked
-#   by 'git ls-remote origin' anyway), Bob, or any developer, can push the
-#   same commit (same SHA) to master and the push will succeed.
-
-# - Finally, a "trusted" developer can push a commit to master without
-#   worrying about the voting restriction at all.
-
-# The config for this example would look like this:
-
-#   repo foo
-#       # allow personal branches (to submit proposed changes)
-#       RW+ pers/USER/          =   @devs
-#       -   pers/               =   @all
-#
-#       # allow only voters to vote
-#       RW+ votes/USER/         =   @voters
-#       -   votes/              =   @all
-#
-#       # normal access rules go here; should allow *someone* to push master
-#       RW+                     =   @devs
-#
-#       # 2 votes required to push master, but trusted devs don't have this restriction
-#       RW+ VREF/VOTES/2/master =   @trusted-devs
-#       -   VREF/VOTES/2/master =   @devs
-
-# Note: "2 votes required to push master" means at least 2 refs matching
-# "votes/*/master" have the same SHA as the one currently being pushed.
-
-# ----------------------------------------------------------------------
-
-# see gitolite docs for what the first 7 arguments mean
-
-# inputs:
-#   arg-8 is a number; see below
-#   arg-9 is a simple branch name (i.e., "master", etc).  Currently this code
-#   does NOT do vote counting for branch names with more than one component
-#   (like foo/bar).
-# outputs (STDOUT)
-#   nothing
-# exit status:
-#   always 0
-
-die() { echo "$@" >&2; exit 1; }
-[ -z "$8" ] && die "not meant to be run manually"
-
-ref=$1
-newsha=$3
-refex=$7
-votes_needed=$8
-branch=$9
-
-# nothing to do if the branch being pushed is not "master" (using our example)
-[ "$ref" = "refs/heads/$branch" ] || exit 0
-
-# find how many votes have come in
-votes=`git for-each-ref refs/heads/votes/*/$branch | grep -c $newsha`
-
-# send back a vref if we don't have the minimum votes needed.  For trusted
-# developers this will invoke the RW+ rule and pass anyway, but for others it
-# will invoke the "-" rule and fail.
-[ $votes -ge $votes_needed ] || echo $refex "require at least $votes_needed votes to push $branch"
-
-exit 0
diff --git a/docker/gitolite/src/VREF/lock b/docker/gitolite/src/VREF/lock
deleted file mode 100755
index 0fc7681..0000000
--- a/docker/gitolite/src/VREF/lock
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Common;
-
-# gitolite VREF to lock and unlock (binary) files.  Requires companion command
-# 'lock' to be enabled; see doc/locking.mkd for details.
-
-# ----------------------------------------------------------------------
-
-# see gitolite docs for what the first 7 arguments mean
-
-die "not meant to be run manually" unless $ARGV[6];
-
-my $ff = "$ENV{GL_REPO_BASE}/$ENV{GL_REPO}.git/gl-locks";
-exit 0 unless -f $ff;
-
-our %locks;
-my $t = slurp($ff);
-eval $t;
-_die "do '$ff' failed with '$@', contact your administrator" if $@;
-
-my ( $oldtree, $newtree, $refex ) = @ARGV[ 3, 4, 6 ];
-
-for my $file (`git diff --name-only $oldtree $newtree`) {
-    chomp($file);
-
-    if ( $locks{$file} and $locks{$file}{USER} ne $ENV{GL_USER} ) {
-        print "$refex '$file' locked by '$locks{$file}{USER}'";
-        last;
-    }
-}
-
-exit 0
diff --git a/docker/gitolite/src/VREF/partial-copy b/docker/gitolite/src/VREF/partial-copy
deleted file mode 100755
index 55a7dcf..0000000
--- a/docker/gitolite/src/VREF/partial-copy
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-# push updated branches back to the "main" repo.
-
-# This must be run as the *last* VREF, though it doesn't matter what
-# permission you give to it
-
-die() { echo "$@" >&2; exit 1; }
-
-repo=$GL_REPO
-user=$GL_USER
-ref=$1          # we're running like an update hook
-old=$2
-new=$3
-
-# never send any STDOUT back, to avoid looking like a ref.  If we fail, git
-# will catch it by our exit code
-exec >&2
-
-main=`git config --file $GL_REPO_BASE/$repo.git/config --get gitolite.partialCopyOf`;
-[ -z "$main" ] && exit 0
-
-rand=$$
-export GL_BYPASS_ACCESS_CHECKS=1
-
-if [ "$new" = "0000000000000000000000000000000000000000" ]
-then
-    # special case for deleting a ref (this is why it is important to put this
-    # VREF as the last one; if we got this far he is allowed to delete it)
-    git push -f $GL_REPO_BASE/$main.git :$ref || die "FATAL: failed to delete $ref"
-
-    exit 0
-fi
-
-git push -f $GL_REPO_BASE/$main.git $new:refs/partial/br-$rand || die "FATAL: failed to send $new"
-
-cd $GL_REPO_BASE/$main.git
-git update-ref -d refs/partial/br-$rand
-git update-ref $ref $new $old || die "FATAL: update-ref for $ref failed"
-
-exit 0
diff --git a/docker/gitolite/src/VREF/refex-expr b/docker/gitolite/src/VREF/refex-expr
deleted file mode 100755
index b788dd9..0000000
--- a/docker/gitolite/src/VREF/refex-expr
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# see bottom of this file for instructons and IMPORTANT WARNINGS!
-# ----------------------------------------------------------------------
-
-my $rule = $ARGV[7];
-die "\n\nFATAL: GL_REFEX_EXPR_ doesn't exist\n(your admin probably forgot the rc file change needed for this to work)\n\n"
-  unless exists $ENV{ "GL_REFEX_EXPR_" . $rule };
-my $res = $ENV{ "GL_REFEX_EXPR_" . $rule } || 0;
-print "$ARGV[6] ($res)\n" if $res;
-
-exit 0;
-
-__END__
-
-------------------------------------------------------------------------
-IMPORTANT WARNINGS:
-  * has not been tested heavily
-      * SO PLEASE TEST YOUR SPECIFIC USE CASE THOROUGHLY!
-      * read the NOTES section below
-  * syntax and semantics are to be considered beta and may change as I find
-    better use cases
-------------------------------------------------------------------------
-
-Refex expressions, like VREFs, are best used as additional "deny" rules, to
-deny combinations that the normal ruleset cannot detect.
-
-To enable this, uncomment 'refex-expr' in the ENABLE list in the rc file.
-
-It allows you to say things like "don't allow users u3 and u4 to change the
-Makefile in the master branch" (i.e., they can change any other file in
-master, or the Makefile in any other branch, but not that specific combo).
-
-    repo foo
-        RW+                                 =   u1 u2   # line 1
-
-        RW+ master                          =   u3 u4   # line 2
-        RW+                                 =   u3 u4   # line 3
-        RW+ VREF/NAME/Makefile              =   u3 u4   # line 4
-        -   master and VREF/NAME/Makefile   =   u3 u4   # line 5
-
-Line 5 is a "refex expression".  Here are the rules:
-
-  * for each refex in the expression ("master" and "VREF/NAME/Makefile" in
-    this example), a count is kept of the number of times the EXACT refex was
-    matched and allowed in the *normal* rules (here, lines 2 and 4) during
-    this push.
-
-  * the expression is evaluated based on these counts.  0 is false, and
-    any non-zero is true (see more examples later).  The truth value of the
-    expression determines whether the refex expression matched.
-
-    You can use any logical or arithmetic expression using refexes as operands
-    and using these operators:
-
-        not and or xor + - == -lt -gt -eq -le -ge -ne
-
-    Parens are not allowed.  Precedence is as you might expect for those
-    operators.  It's actually perl that is evaluating it (you can guess what
-    the '-lt' etc., get translated to) so if in doubt, check 'man perlop'.
-
-  * the refexes that form the terms of the expression (in this case, lines 2
-    and 4) MUST come before the expression itself (i.e., line 5).
-
-  * note the words "EXACT refex was matched" above.
-
-    Let's say you add "u3" to line 1.  Then the refex expression in line 5
-    would never match for u3.  This is because line 1 prevents line 2 from
-    matching (being more general *and* appearing earlier), so the count for
-    the "master" refex would be 0.  If "master" is 0 (false), then "master and
-    <anything>" is also false.
-
-    (Same thing is you swap lines 2 and 3; i.e., put the "RW+ = ..." before
-    the "RW+ master = ...").
-
-    Put another way, the terms in the refex expression are refexes, not refs.
-    Merely pushing the master branch does not mean the count for "master"
-    increases; it has to *match* on a line that has "master" as the refex.
-
-Here are some more examples:
-
-  * user u2 is allowed to push either 'doc/' or 'src/' but not both
-
-        repo    foo
-            RW+                         =   u1 u2 u3
-
-            RW+ VREF/NAME/doc/                      =   u2
-            RW+ VREF/NAME/src/                      =   u2
-            -   VREF/NAME/doc/ and VREF/NAME/src/   =   u2
-
-  * user u3 is allowed to push at most 2 files to conf/
-
-        repo    foo
-            RW+                         =   u1 u2 u3
-
-            RW+ VREF/NAME/conf/         =   u3
-            -   VREF/NAME/conf/ -gt 2   =   u3
diff --git a/docker/gitolite/src/commands/D b/docker/gitolite/src/commands/D
deleted file mode 100755
index 016a365..0000000
--- a/docker/gitolite/src/commands/D
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/bin/sh
-
-# ----------------------------------------------------------------------
-# ADMINISTRATOR NOTES:
-# ----------------------------------------------------------------------
-
-# - set TRASH_CAN in the rc if you don't like the default.  It should be
-#   relative to GL_REPO_BASE or an absolute value.  It should also be on the
-#   same filesystem as GL_REPO_BASE, otherwise the 'mv' will take too long.
-
-# - you could set TRASH_SUFFIX also but I recomend you leave it as it is
-
-# - run a cron job to delete old repos based on age (the TRASH_SUFFIX has a
-#   timestamp); your choice how/how often you do that
-
-# - you can completely disable the 'rm' command by setting an rc variable
-#   called D_DISABLE_RM to "1".
-# ----------------------------------------------------------------------
-
-# ----------------------------------------------------------------------
-# Usage:    ssh git at host D <subcommand> <argument>
-#
-# The whimsically named "D" command deletes repos ("D" is a counterpart to the
-# "C" permission which lets you create repos.  Which also means that, just
-# like "C", it only works for wild repos).
-#
-# There are two kinds of deletions: 'rm' removes a repo completely, while
-# 'trash' moves it to a trashcan which can be recovered later (upto a time
-# limit that your admin will tell you).
-#
-# The 'rm', 'lock', and 'unlock' subcommands:
-#     Initially, all repos are "locked" against 'rm'.  The correct sequence is
-#         ssh git at host D unlock repo
-#         ssh git at host D rm repo
-#     Since the initial condition is always locked, the "lock" command is
-#     rarely used but it is there if you want it.
-#
-# The 'trash', 'list-trash', and 'restore' subcommands:
-#     You can 'trash' a repo, which moves it to a special place:
-#         ssh git at host D trash repo
-#     You can then 'list-trash'
-#         ssh git at host D list-trash
-#     which prints something like
-#         repo/2012-04-11_05:58:51
-#     allowing you to restore by saying
-#         ssh git at host D restore repo/2012-04-11_05:58:51
-
-die() { echo "$@" >&2; exit 1; }
-usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
-[ -z "$1" ] && usage
-[ "$1" = "-h" ] && usage
-[ "$1" != "list-trash" ] && [ -z "$2" ] && usage
-[ -z "$GL_USER" ] && die GL_USER not set
-
-# ----------------------------------------------------------------------
-cmd=$1
-repo=$2
-# ----------------------------------------------------------------------
-RB=`gitolite query-rc GL_REPO_BASE`;            cd $RB
-TRASH_CAN=`gitolite query-rc TRASH_CAN`;        tcan=Trash;                     TRASH_CAN=${TRASH_CAN:-$tcan}
-TRASH_SUFFIX=`gitolite query-rc TRASH_SUFFIX`;  tsuf=`date +%Y-%m-%d_%H:%M:%S`; TRASH_SUFFIX=${TRASH_SUFFIX:-$tsuf}
-# ----------------------------------------------------------------------
-
-owner_or_die() {
-    gitolite owns "$repo" || die You are not authorised
-}
-
-# ----------------------------------------------------------------------
-
-if [ "$cmd" = "rm" ]
-then
-
-    gitolite query-rc -q D_DISABLE_RM && die "sorry, 'unlock' and 'rm' are disabled"
-
-    owner_or_die
-    [ -f $repo.git/gl-rm-ok ] || die "'$repo' is locked!"
-    rm -rf $repo.git
-    echo "'$repo' is now gone!"
-
-elif [ "$cmd" = "lock" ]
-then
-
-    owner_or_die
-    rm -f $repo.git/gl-rm-ok
-    echo "'$repo' is now locked"
-
-elif [ "$cmd" = "unlock" ]
-then
-
-    gitolite query-rc -q D_DISABLE_RM && die "sorry, 'unlock' and 'rm' are disabled"
-
-    owner_or_die
-    touch $repo.git/gl-rm-ok
-    echo "'$repo' is now unlocked"
-
-elif [ "$cmd" = "trash" ]
-then
-
-    owner_or_die
-    mkdir -p $TRASH_CAN/$repo 2>/dev/null || die "failed creating directory in trashcan"
-    [ -d $TRASH_CAN/$repo/$TRASH_SUFFIX ] && die "try again in a few seconds..."
-    mv $repo.git $TRASH_CAN/$repo/$TRASH_SUFFIX
-    echo "'$repo' moved to trashcan"
-
-elif [ "$cmd" = "list-trash" ]
-then
-
-    cd $TRASH_CAN 2>/dev/null || exit 0
-    find . -name gl-creator | sort | while read t
-    do
-        owner=
-        owner=`cat "$t"`
-        [ "$owner" = "$GL_USER" ] && dirname $t
-    done | cut -c3-
-
-elif [ "$cmd" = "restore" ]
-then
-
-    owner=
-    owner=`cat $TRASH_CAN/$repo/gl-creator 2>/dev/null`
-    [ "$owner" = "$GL_USER" ] || die "'$repo' is not yours!"
-
-    cd $TRASH_CAN
-    realrepo=`dirname $repo`
-    [ -d $RB/$realrepo.git ] && die "'$realrepo' already exists"
-    mv $repo $RB/$realrepo.git
-    echo "'$repo' restored to '$realrepo'"
-
-else
-    die "unknown subcommand '$cmd'"
-fi
diff --git a/docker/gitolite/src/commands/access b/docker/gitolite/src/commands/access
deleted file mode 100755
index 1b16c72..0000000
--- a/docker/gitolite/src/commands/access
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/perl -s
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-our ( $q, $s, $h );    # quiet, show, help
-
-=for usage
-Usage:  gitolite access [-q|-s] <repo> <user> <perm> <ref>
-
-Print access rights for arguments given.  The string printed has the word
-DENIED in it if access was denied.  With '-q', returns only an exit code
-(shell truth, not perl truth -- 0 is success).  For '-s', see below.
-
-  - repo: mandatory
-  - user: mandatory
-  - perm: defauts to '+'.  Valid values: R, W, +, C, D, M
-  - ref:  defauts to 'any'.  See notes below
-
-Notes:
-  - ref: something like 'master', or 'refs/tags/v1.0', or even a VREF if you
-    know what they look like.
-
-    The 'any' ref is special -- it ignores deny rules, thus simulating
-    gitolite's behaviour during the pre-git access check (see 'deny-rules'
-    section in rules.html for details).
-
-  - batch mode: see src/triggers/post-compile/update-git-daemon-access-list
-    for a good example that shows how to test several repos in one invocation.
-    This is orders of magnitude faster than running the command multiple
-    times; you'll notice if you have more than a hundred or so repos.
-
-  - '-s' shows the rules (conf file name, line number, and rule) that were
-    considered and how they fared.
-=cut
-
-usage() if not @ARGV or $h;
-
-my ( $repo, $user, $aa, $ref ) = @ARGV;
-# default access is '+'
-$aa  ||= '+';
-# default ref is 'any'
-$ref ||= 'any';
-# fq the ref if needed
-$ref =~ s(^)(refs/heads/) if $ref and $ref ne 'any' and $ref !~ m(^(refs|VREF)/);
-_die "invalid perm" if not( $aa and $aa =~ /^(R|W|\+|C|D|M|\^C)$/ );
-_die "invalid ref name" if not( $ref and $ref =~ $REPONAME_PATT );
-
-my $ret = '';
-
-if ( $repo ne '%' and $user ne '%' ) {
-    # single repo, single user; no STDIN
-    $ret = access( $repo, $user, $aa, $ref );
-
-    show($ret) if $s;
-
-    if ( $ret =~ /DENIED/ ) {
-        print "$ret\n" unless $q;
-        exit 1;
-    }
-
-    print "$ret\n" unless $q;
-    exit 0;
-}
-
-$repo = '' if $repo eq '%';
-$user = '' if $user eq '%';
-
-_die "'-q' and '-s' meaningless in pipe mode" if $q or $s;
- at ARGV = ();
-while (<>) {
-    my @in = split;
-    my $r  = $repo || shift @in;
-    my $u  = $user || shift @in;
-    $ret = access( $r, $u, $aa, $ref );
-    print "$r\t$u\t$ret\n";
-}
-
-sub show {
-    my $ret = shift;
-    die "repo already exists; ^C won't work\n" if $ret =~ /DENIED by existence/;
-
-    my $in = $rc{RULE_TRACE} or die "this should not happen! $ret";
-
-    print STDERR "legend:";
-    print STDERR "
-    d => skipped deny rule due to ref unknown or 'any',
-    r => skipped due to refex not matching,
-    p => skipped due to perm (W, +, etc) not matching,
-    D => explicitly denied,
-    A => explicitly allowed,
-    F => denied due to fallthru (no rules matched)
-
-";
-
-    my %rule_info = read_ri($in);    # get rule info data for all traced rules
-                                     # this means conf filename, line number, and content of the line
-
-    # the rule-trace info is a set of pairs of a number plus a string.  Only
-    # the last character in a string is valid (and has meanings shown above).
-    # At the end there may be a final 'f'
-    my @in = split ' ', $in;
-    while (@in) {
-        $in = shift @in;
-        if ( $in =~ /^\d+$/ ) {
-            my $res = shift @in or die "this should not happen either!";
-            my $m = chop($res);
-            printf "  %s %20s:%-6s %s\n", $m,
-                                          $rule_info{$in}{fn},
-                                          $rule_info{$in}{ln},
-                                          $rule_info{$in}{cl};
-        } elsif ( $in eq 'F' ) {
-            printf "  %s %20s\n", $in, "(fallthru)";
-        } else {
-            die "and finally, this also should not happen!";
-        }
-    }
-    print "\n";
-}
-
-sub read_ri {
-    my %rules = map { $_ => 1 } $_[0] =~ /(\d+)/g;
-    # contains a series of rule numbers, each of which we must search in
-    # $GL_ADMIN_BASE/.gitolite/conf/rule_info
-
-    my %rule_info;
-    for ( slurp( $ENV{GL_ADMIN_BASE} . "/conf/rule_info" ) ) {
-        my ( $r, $f, $l ) = split ' ', $_;
-        next unless $rules{$r};
-        $rule_info{$r}{fn} = $f;
-        $rule_info{$r}{ln} = $l;
-        $rule_info{$r}{cl} = conf_lines( $f, $l );
-
-        # a wee bit of optimisation, in case the rule_info file is huge and
-        # what we want is up near the beginning
-        delete $rules{$r};
-        last unless %rules;
-    }
-    return %rule_info;
-}
-
-{
-    my %conf_lines;
-
-    sub conf_lines {
-        my ( $file, $line ) = @_;
-        $line--;
-
-        unless ( $conf_lines{$file} ) {
-            $conf_lines{$file} = [ slurp( $ENV{GL_ADMIN_BASE} . "/conf/$file" ) ];
-            chomp( @{ $conf_lines{$file} } );
-        }
-        return $conf_lines{$file}[$line];
-    }
-}
diff --git a/docker/gitolite/src/commands/config b/docker/gitolite/src/commands/config
deleted file mode 100755
index b996066..0000000
--- a/docker/gitolite/src/commands/config
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/perl
-use 5.10.0;
-
-# ----------------------------------------------------------------------
-# gitolite command to allow "git config" on repos (with some restrictions)
-
-# (Not to be confused with the 'git-config' command, which is used only in
-# server-side scripts, not remotely.)
-
-# setup:
-#   1.  Enable the command by adding it to the COMMANDS section in the ENABLE
-#       list in the rc file.
-#
-#   2.  Specify configs allowed to be changed by the user.  This is a space
-#       separated regex list.  For example:
-
-#           repo ...
-#               ... (various rules) ...
-#               option user-configs = hook\..* foo.bar[0-9].*
-
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-use Gitolite::Common;
-
-# ----------------------------------------------------------------------
-# usage
-
-=for usage
-Usage:    ssh git at host config <repo> [git config options]
-
-Runs "git config" in the repo.  Only the following 3 syntaxes are supported
-(see 'man git-config'):
-
-          --add name value
-      --get-all name
-    --unset-all name
-         --list
-
-Your administrator should tell you what keys are allowed for the "name".
-=cut
-
-# ----------------------------------------------------------------------
-# arg checks
-
-my %nargs = qw(
-          --add 3
-      --get-all 2
-    --unset-all 2
-         --list 1
-     );
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-
-my $repo = shift;
-
-my ($op, $key, $val) = @ARGV;
-usage() unless $op and exists $nargs{$op} and @ARGV == $nargs{$op};
-
-# ----------------------------------------------------------------------
-# authorisation checks
-
-die "sorry, you are not authorised\n" unless
-    owns($repo)
-        or
-    ( ( $op eq '--get-all' or $op eq '--list' )
-        ? can_read($repo)
-        : ( can_write($repo) and option( $repo, 'writer-is-owner' ) )
-    );
-
-# ----------------------------------------------------------------------
-# key validity checks
-
-unless ($op eq '--list') {
-    my $user_configs = option( $repo, 'user-configs' );
-    # this is a space separated list of allowed config keys
-    my @validkeys = split( ' ', ( $user_configs || '' ) );
-    my @matched = grep { $key =~ /^$_$/i } @validkeys;
-    _die "config '$key' not allowed\n" if ( @matched < 1 );
-}
-
-# ----------------------------------------------------------------------
-# go!
-
-_chdir("$rc{GL_REPO_BASE}/$repo.git");
-_system( "git", "config", @ARGV );
diff --git a/docker/gitolite/src/commands/create b/docker/gitolite/src/commands/create
deleted file mode 100755
index d35c4a8..0000000
--- a/docker/gitolite/src/commands/create
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-# Usage:    ssh git at host create <repo>
-#
-# Create wild repo.
-
-die() { echo "$@" >&2; exit 1; }
-usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
-[ -z "$1" ] && usage
-[ -z "$2" ] || usage
-[ "$1" = "-h" ] && usage
-[ -z "$GL_USER" ] && die GL_USER not set
-
-# ----------------------------------------------------------------------
-perms=$(gitolite git-config -r $1 gitolite-options.default.roles | sort | cut -f3 |
-    perl -pe 's/(\s)CREATOR(\s|$)/$1$ENV{GL_USER}$1/')
-echo "$perms" | $GL_BINDIR/commands/perms -c "$@"
diff --git a/docker/gitolite/src/commands/creator b/docker/gitolite/src/commands/creator
deleted file mode 100755
index 702df73..0000000
--- a/docker/gitolite/src/commands/creator
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-=for usage
-Usage:  gitolite creator [-n] <reponame> [<username>]
-
-Print the creator name for the repo.  A '-n' suppresses the newline.
-
-When an optional username is supplied, it checks if the user is the creator of
-the repo and returns an exit code (shell truth, 0 for success) instead of
-printing anything, which makes it possible to do this in shell:
-
-    if gitolite creator someRepo someUser
-    then
-        ...
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-my $nl = "\n";
-if ( $ARGV[0] eq '-n' ) {
-    $nl = '';
-    shift;
-}
-my $repo = shift;
-my $user = shift || '';
-
-my $creator = '';
-$creator = creator($repo) if not repo_missing($repo);
-if ($user) {
-    exit 0 if $creator eq $user;
-    exit 1;
-}
-return ( $creator eq $user ) if $user;
-print "$creator$nl";
diff --git a/docker/gitolite/src/commands/desc b/docker/gitolite/src/commands/desc
deleted file mode 100755
index 4a4bf20..0000000
--- a/docker/gitolite/src/commands/desc
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-=for usage
-Usage:    ssh git at host desc <repo>
-          ssh git at host desc <repo> <description string>
-
-Show or set description for repo.  You need to have write access to the repo
-and the 'writer-is-owner' option must be set for the repo, or it must be a
-user-created ('wild') repo and you must be the owner.
-=cut
-
-usage() if not @ARGV or @ARGV < 1 or $ARGV[0] eq '-h';
-
-my $repo = shift;
-my $text = join( " ", @ARGV );
-my $file = 'description';
-
-#<<<
-_die "you are not authorized" unless
-    ( not $text and can_read($repo) )   or
-    (     $text and owns($repo) )       or
-    (     $text and can_write($repo)    and ( $rc{WRITER_CAN_UPDATE_DESC} or option( $repo, 'writer-is-owner' ) ) );
-#>>>
-
-$text
-  ? textfile( file => $file, repo => $repo, text => $text )
-  : print textfile( file => $file, repo => $repo );
-
-__END__
-
-kernel.org needs 'desc' to be available to people who have "RW" or above, not
-just the "creator".  In fact they need it for non-wild repos so there *is* no
-creator.  To accommodate this, we created the WRITER_CAN_UPDATE_DESC rc
-variable.
-
-However, that has turned out to be a bit of a blunt instrument for people with
-different types of wild repos -- they don't want to apply this to all of them.
-It seems easier to do this as an option, so you may have it for one set of
-"repo ..." and not have it for others.  And if you want it for the whole
-system you'd just put it under "repo @all".
-
-The new 'writer-is-owner' option is meant to cover desc, readme, and any other
-repo-specific text file, so it's also a blunt instrument, though in a
-different dimension :-)
diff --git a/docker/gitolite/src/commands/fork b/docker/gitolite/src/commands/fork
deleted file mode 100755
index 49994fc..0000000
--- a/docker/gitolite/src/commands/fork
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-
-# Usage:    ssh git at host fork <repo1> <repo2>
-#
-# Forks repo1 to repo2.  You must have read permissions on repo1, and create
-# ("C") permissions for repo2, which of course must not exist.
-#
-# A fork is functionally the same as cloning repo1 to a client and pushing it
-# to a new repo2.  It's just a little more efficient, not just in network
-# traffic but because it uses git clone's "-l" option to share the object
-# store also, so it is likely to be almost instantaneous, regardless of how
-# big the repo actually is.
-
-die() { echo "$@" >&2; exit 1; }
-usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
-[ -z "$1" ] && usage
-[ "$1" = "-h" ] && usage
-[ -z "$GL_USER" ] && die GL_USER not set
-
-# ----------------------------------------------------------------------
-from=$1; shift
-to=$1; shift
-[ -z "$to" ] && usage
-
-gitolite access -q "$from" $GL_USER R any || die "'$from' does not exist or you are not allowed to read it"
-gitolite access -q "$to"   $GL_USER ^C any || die "'$to' already exists or you are not allowed to create it"
-
-# ----------------------------------------------------------------------
-# IMPORTANT NOTE: checking whether someone can create a repo is done as above.
-# However, make sure that the env var GL_USER is set, and that too to the same
-# value as arg-2 of the access command), otherwise it won't work.
-
-# Ideally, you'll leave such code to me.  There's a reason ^C is not listed in
-# the help message for 'gitolite access'.
-# ----------------------------------------------------------------------
-
-# clone $from to $to
-git clone --bare -l $GL_REPO_BASE/$from.git $GL_REPO_BASE/$to.git
-[ $? -ne 0 ] && exit 1
-
-echo "$from forked to $to" >&2
-
-# fix up creator, default role permissions (gl-perms), and hooks
-cd $GL_REPO_BASE/$to.git
-echo $GL_USER > gl-creator
-
-gitolite query-rc -q LOCAL_CODE && ln -sf `gitolite query-rc LOCAL_CODE`/hooks/common/* hooks
-ln -sf `gitolite query-rc GL_ADMIN_BASE`/hooks/common/* hooks
-
-# record where you came from
-echo "$from" > gl-forked-from
-
-# cache control, if rc says caching is on
-gitolite query-rc -q CACHE && perl -I$GL_LIBDIR -MGitolite::Cache -e "cache_control('flush', '$to')";
-
-# trigger post_create
-gitolite trigger POST_CREATE $to $GL_USER fork
diff --git a/docker/gitolite/src/commands/git-annex-shell b/docker/gitolite/src/commands/git-annex-shell
deleted file mode 100755
index 572aba6..0000000
--- a/docker/gitolite/src/commands/git-annex-shell
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/perl
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-# This command requires unrestricted arguments, so add it to the ENABLE list
-# like this:
-#   'git-annex-shell ua',
-
-# This requires git-annex version 20111016 or newer. Older versions won't
-# be secure.
-
-use strict;
-use warnings;
-
-# ignore @ARGV and look at the original unmodified command
-my $cmd = $ENV{SSH_ORIGINAL_COMMAND};
-
-# Expect commands like:
-#   git-annex-shell 'configlist' '/~/repo'
-#   git-annex-shell 'configlist' '/repo'
-#   git-annex-shell 'sendkey' '/~/repo' 'key'
-# The parameters are always single quoted, and the repo path is always
-# the second parameter.
-# Further parameters are not validated here (see below).
-die "bad git-annex-shell command: $cmd"
-  unless $cmd =~ m#^(git-annex-shell '\w+' ')/(?:\~/)?([0-9a-zA-Z][0-9a-zA-Z._\@/+-]*)('( .*|))$#;
-my $start = $1;
-my $repo  = $2;
-my $end   = $3;
-$repo =~ s/\.git$//;
-die "I dont like some of the characters in $repo\n" unless $repo =~ $Gitolite::Rc::REPONAME_PATT;
-die "I dont like absolute paths in $cmd\n" if $repo =~ /^\//;
-die "I dont like '..' paths in $cmd\n"     if $repo =~ /\.\./;
-
-# Modify $cmd, fixing up the path to the repo to include GL_REPO_BASE.
-my $newcmd = "$start$rc{GL_REPO_BASE}/$repo$end";
-
-# Rather than keeping track of which git-annex-shell commands
-# require write access and which are readonly, we tell it
-# when readonly access is needed.
-if ( can_write($repo) ) {
-} elsif ( can_read($repo) ) {
-    $ENV{GIT_ANNEX_SHELL_READONLY} = 1;
-} else {
-    die "$repo $ENV{GL_USER} DENIED\n";
-}
-# Further limit git-annex-shell to safe commands (avoid it passing
-# unknown commands on to git-shell)
-$ENV{GIT_ANNEX_SHELL_LIMITED} = 1;
-
-# Note that $newcmd does *not* get evaluated by the unix shell.
-# Instead it is passed as a single parameter to git-annex-shell for
-# it to parse and handle the command. This is why we do not need to
-# fully validate $cmd above.
-Gitolite::Common::gl_log( $ENV{SSH_ORIGINAL_COMMAND} );
-exec "git-annex-shell", "-c", $newcmd;
-
-__END__
-
-INSTRUCTIONS... (NEED TO BE VALIDATED BY SOMEONE WHO KNOWS GIT-ANNEX WELL).
-
-based on http://git-annex.branchable.com/tips/using_gitolite_with_git-annex/
-ONLY VARIATIONS FROM THAT PAGE ARE WRITTEN HERE.
-
-setup
-
-  * in the ENABLE list in the rc file, add an entry like this:
-        'git-annex-shell ua',
-
-That should be it; everything else should be as in that page.
diff --git a/docker/gitolite/src/commands/git-config b/docker/gitolite/src/commands/git-config
deleted file mode 100755
index 94211de..0000000
--- a/docker/gitolite/src/commands/git-config
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use Getopt::Long;
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-=for usage
-Usage:  gitolite git-config [-n] [-q] [-r] <repo> <key|pattern>
-
-Print git config keys and values for the given repo.  The key is either a full
-key, or, if '-r' is supplied, a regex that is applied to all available keys.
-
-    -q          exit code only (shell truth; 0 is success)
-    -n          suppress trailing newline when used as key (not pattern)
-    -r          treat key as regex pattern (unanchored)
-    -ev         print keys with empty values also (see below)
-
-Examples:
-    gitolite git-config repo gitweb.owner
-    gitolite git-config -q repo gitweb.owner
-    gitolite git-config -r repo gitweb
-
-Notes:
-
-1.  When the key is treated as a pattern, prints:
-
-        reponame<tab>key<tab>value<newline>
-
-    Otherwise the output is just the value.
-
-2.  By default, keys with empty values (specified as "" in the conf file) are
-    treated as non-existant.  Using '-ev' will print those keys also.  Note
-    that this only makes sense when the key is treated as a pattern, where
-    such keys are printed as:
-
-        reponame<tab>key<tab><newline>
-
-3.  Finally, see the advanced use section of 'gitolite access -h' -- you can
-    do something similar here also:
-
-        gitolite list-phy-repos | gitolite git-config -r % gitweb\\. | cut -f1 > ~/projects.list
-=cut
-
-usage() if not @ARGV;
-
-my ( $help, $nonl, $quiet, $regex, $ev ) = (0) x 5;
-GetOptions(
-    'n'  => \$nonl,
-    'q'  => \$quiet,
-    'r'  => \$regex,
-    'h'  => \$help,
-    'ev' => \$ev,
-) or usage();
-
-my ( $repo, $key ) = @ARGV;
-usage() unless $key;
-
-my $ret = '';
-
-if ( $repo ne '%' and $key ne '%' ) {
-    # single repo, single key; no STDIN
-    $key = "^\Q$key\E\$" unless $regex;
-
-    $ret = git_config( $repo, $key, $ev );
-
-    # if the key is not a regex, it should match at most one item
-    _die "found more than one entry for '$key'" if not $regex and scalar( keys %$ret ) > 1;
-
-    # unlike access, there's nothing to print if we don't find any matching keys
-    exit 1 unless %$ret;
-
-    if ($regex) {
-        map { print "$repo\t$_\t" . $ret->{$_} . "\n" } sort keys %$ret unless $quiet;
-    } else {
-        map { print $ret->{$_} . ( $nonl ? "" : "\n" ) } sort keys %$ret unless $quiet;
-    }
-    exit 0;
-}
-
-$repo = '' if $repo eq '%';
-$key  = '' if $key eq '%';
-
-_die "'-q' doesn't go with using a pipe" if $quiet;
- at ARGV = ();
-while (<>) {
-    my @in = split;
-    my $r  = $repo || shift @in;
-    my $k  = $key || shift @in;
-    $k = "^\Q$k\E\$" unless $regex;
-    $ret = git_config( $r, $k, $ev );
-    next unless %$ret;
-    map { print "$r\t$_\t" . $ret->{$_} . "\n" } sort keys %$ret;
-}
diff --git a/docker/gitolite/src/commands/help b/docker/gitolite/src/commands/help
deleted file mode 100755
index cf54084..0000000
--- a/docker/gitolite/src/commands/help
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-=for usage
-Usage:  ssh git at host help       # via ssh
-        gitolite help           # directly on server command line
-
-Prints a list of custom commands available at this gitolite installation.
-
-Each command has its own help, accessed by passing it '-h' again.
-=cut
-
-usage() if @ARGV;
-
-print greeting();
-
-my $user = $ENV{GL_USER} || '';
-print "list of " . ( $user ? "remote" : "gitolite" ) . " commands available:\n\n";
-
-my %list = ( list_x( $ENV{GL_BINDIR} ), list_x( $rc{LOCAL_CODE} || '' ) );
-for ( sort keys %list ) {
-    print "\t$list{$_}" if $ENV{D};
-    print "\t$_\n" if not $user or $rc{COMMANDS}{$_};
-}
-
-print "\n";
-print "$rc{SITE_INFO}\n" if $rc{SITE_INFO};
-
-exit 0;
-
-# ------------------------------------------------------------------------------
-sub list_x {
-    my $d = shift;
-    return unless $d;
-    return unless -d "$d/commands";
-    _chdir "$d/commands";
-    return map { $_ => $d } grep { -x $_ } map { chomp; s(^./)(); $_ } `find . -type f -o -type l|sort`;
-}
diff --git a/docker/gitolite/src/commands/htpasswd b/docker/gitolite/src/commands/htpasswd
deleted file mode 100755
index bbfacc7..0000000
--- a/docker/gitolite/src/commands/htpasswd
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-=for usage
-Usage:  ssh git at host htpasswd
-
-Sets your htpasswd, assuming your admin has enabled it.
-
-(Admins: You need to add HTPASSWD_FILE to the rc file, pointing to an
-existing, writable, but possibly an initially empty, file, as well as adding
-'htpasswd' to the ENABLE list).
-=cut
-
-# usage and sanity checks
-usage() if @ARGV and $ARGV[0] eq '-h';
-$ENV{GL_USER} or _die "GL_USER not set";
-my $htpasswd_file = $rc{HTPASSWD_FILE} || '';
-die "htpasswd not enabled\n" unless $htpasswd_file;
-die "$htpasswd_file doesn't exist or is not writable\n" unless -w $htpasswd_file;
-
-# prompt
-$|++;
-print <<EOFhtp;
-Please type in your new htpasswd at the prompt.  You only have to type it once.
-
-NOTE THAT THE PASSWORD WILL BE ECHOED, so please make sure no one is
-shoulder-surfing, and make sure you clear your screen as well as scrollback
-history after you're done (or close your terminal instance).
-
-EOFhtp
-print "new htpasswd: ";
-
-# get the password and run htpasswd
-my $password = <>;
-$password =~ s/[\n\r]*$//;
-die "empty passwords are not allowed\n" unless $password;
-my $res = system( "htpasswd", "-mb", $htpasswd_file, $ENV{GL_USER}, $password );
-die "htpasswd command seems to have failed with return code: $res.\n" if $res;
diff --git a/docker/gitolite/src/commands/info b/docker/gitolite/src/commands/info
deleted file mode 100755
index 5079cfa..0000000
--- a/docker/gitolite/src/commands/info
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use Getopt::Long;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-=for args
-Usage:  gitolite info [-lc] [-ld] [-json] [<repo name pattern>]
-
-List all existing repos you can access, as well as repo name patterns you can
-create repos from (if any).
-
-    '-lc'       lists creators as an additional field at the end.
-    '-ld'       lists description as an additional field at the end.
-    '-json'     produce JSON output instead of normal output
-
-The optional pattern is an unanchored regex that will limit the repos
-searched, in both cases.  It might speed up things a little if you have more
-than a few thousand repos.
-=cut
-
-# these are globals
-my ( $lc, $ld, $json, $patt ) = args();
-my %out;    # holds info to be json'd
-
-$ENV{GL_USER} or _die "GL_USER not set";
-if ($json) {
-    greeting(\%out);
-} else {
-    print greeting();
-}
-
-print_patterns();     # repos he can create for himself
-print_phy_repos();    # repos already created
-
-if ( $rc{SITE_INFO} ) {
-    $json
-      ? $out{SITE_INFO} = $rc{SITE_INFO}
-      : print "\n$rc{SITE_INFO}\n";
-}
-
-print JSON::to_json( \%out, { utf8 => 1, pretty => 1 } ) if $json;
-
-# ----------------------------------------------------------------------
-
-sub args {
-    my ( $lc, $ld, $json, $patt ) = ( '', '', '', '' );
-    my $help = '';
-
-    GetOptions(
-        'lc'   => \$lc,
-        'ld'   => \$ld,
-        'json' => \$json,
-        'h'    => \$help,
-    ) or usage();
-
-    usage() if @ARGV > 1 or $help;
-    $patt = shift @ARGV || '.';
-
-    require JSON if $json;
-
-    return ( $lc, $ld, $json, $patt );
-}
-
-sub print_patterns {
-    my ( $repos, @aa );
-
-    my $lm = \&Gitolite::Conf::Load::list_members;
-
-    # find repo patterns only, call them with ^C flag included
-    @$repos = grep { !/$REPONAME_PATT/ } map { /^@/ ? @{ $lm->($_) } : $_ } @{ lister_dispatch('list-repos')->() };
-    @aa = qw(R W ^C);
-    listem( $repos, '', '', @aa );
-    # but squelch the 'lc' and 'ld' flags for these
-}
-
-sub print_phy_repos {
-    my ( $repos, @aa );
-
-    # now get the actual repos and get R or W only
-    _chdir( $rc{GL_REPO_BASE} );
-    $repos = list_phy_repos(1);
-    @aa    = qw(R W);
-    listem( $repos, $lc, $ld, @aa );
-}
-
-sub listem {
-    my ( $repos, $lc, $ld, @aa ) = @_;
-    my @list;
-    my $mlr = 0;    # max length of reponame
-    my $mlc = 0;    # ...and creator
-    for my $repo (@$repos) {
-        next unless $repo =~ /$patt/;
-        my $creator = '';
-        my $desc    = '';
-        my $perm    = '';
-        $creator = creator($repo) if $lc;
-
-        if ($ld) {
-            # use config value first, else 'description' file as second choice
-            my $k = 'gitweb.description';
-            my $d = "$ENV{GL_REPO_BASE}/$repo.git/description";
-            $desc = git_config( $repo, $k )->{$k} || '';
-            if ( !$desc and -r $d ) {
-                $desc = slurp($d);
-                chomp($desc);
-            }
-        }
-
-        for my $aa (@aa) {
-            my $ret = access( $repo, $ENV{GL_USER}, $aa, 'any' );
-            $perm .= ( $ret =~ /DENIED/ ? "  " : " $aa" );
-        }
-        $perm =~ s/\^//;
-        next unless $perm =~ /\S/;
-
-        if ($json) {
-            $out{repos}{$repo}{creator}     = $creator if $lc;
-            $out{repos}{$repo}{description} = $desc    if $ld;
-            $out{repos}{$repo}{perms}       = _hash($perm);
-        } else {
-            $mlr = length($repo) if ( $lc or $ld ) and $mlr < length($repo);
-            $mlc = length($creator) if $lc and $ld and $mlc < length($creator);
-            push @list, [ $perm, $repo, $creator, $desc ];
-        }
-    }
-    return if $json;
-
-    my $fmt = "%s\t%-${mlr}s\t%-${mlc}s\t%s\n";
-    map { s/\t\t/\t/; s/\s*$/\n/; print } map { sprintf $fmt, @$_ } @list;
-}
-
-sub _hash {
-    my $in = shift;
-    my %out = map { $_ => 1 } ( $in =~ /(\S)/g );
-    return \%out;
-}
diff --git a/docker/gitolite/src/commands/list-dangling-repos b/docker/gitolite/src/commands/list-dangling-repos
deleted file mode 100755
index 60a3592..0000000
--- a/docker/gitolite/src/commands/list-dangling-repos
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-=for usage
-Usage:  gitolite list-dangling-repos
-
-List all existing repos that no one can access remotely any more.  They could
-be normal repos that were taken out of "repo" statements in the conf file, or
-wildcard repos whose matching "wild" pattern was taken out or changed so it no
-longer matches.
-
-I would advise caution if you use this as a basis for deleting repos from the
-file system.  A bug in this program could cause you to lose important data!
-=cut
-
-usage() if @ARGV and $ARGV[0] eq '-h';
-
-# get the two lists we need.  %repos is the list of repos in "repo" statements
-# in the conf file.  %phy_repos is the list of actual repos on disk.  Our job
-# is to cull %phy_repos of all keys that have a matching key in %repos, where
-# "matching" means "string equal" or "regex match".
-my %repos = map { chomp; $_ => 1 } `gitolite list-repos`;
-for my $r ( grep /^@/, keys %repos ) {
-    map { chomp; $repos{$_} = 1; } `gitolite list-members $r`;
-}
-my %phy_repos = map { chomp; $_ => 1 } `gitolite list-phy-repos`;
-
-# Remove exact matches.  But for repo names like "gtk+", you could have
-# collapsed this into the next step (the regex match).
-for my $pr ( keys %phy_repos ) {
-    next unless exists $repos{$pr};
-    delete $repos{$pr};
-    delete $phy_repos{$pr};
-}
-
-# Remove regex matches.
-for my $pr ( keys %phy_repos ) {
-    my $matched = 0;
-    my $pr2     = Gitolite::Conf::Load::generic_name($pr);
-    for my $r ( keys %repos ) {
-        if ( $pr =~ /^$r$/ or $pr2 =~ /^$r$/ ) {
-            $matched = 1;
-            next;
-        }
-    }
-    delete $phy_repos{$pr} if $matched;
-}
-
-# what's left in %phy_repos are dangling repos.
-print join( "\n", sort keys %phy_repos ), "\n";
diff --git a/docker/gitolite/src/commands/lock b/docker/gitolite/src/commands/lock
deleted file mode 100755
index 70c2190..0000000
--- a/docker/gitolite/src/commands/lock
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use Getopt::Long;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-# gitolite command to lock and unlock (binary) files and deal with locks.
-
-=for usage
-Usage:  ssh git at host lock -l      <repo> <file>     # lock a file
-        ssh git at host lock -u      <repo> <file>     # unlock a file
-        ssh git at host lock --break <repo> <file>     # break someone else's lock
-        ssh git at host lock -ls     <repo>            # list locked files for repo
-
-See doc/locking.mkd for other details.
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-$ENV{GL_USER} or _die "GL_USER not set";
-
-my $op = '';
-$op = 'lock'   if $ARGV[0] eq '-l';
-$op = 'unlock' if $ARGV[0] eq '-u';
-$op = 'break'  if $ARGV[0] eq '--break';
-$op = 'list'   if $ARGV[0] eq '-ls';
-usage() if not $op;
-shift;
-
-my $repo = shift;
-_die "You are not authorised" if access( $repo, $ENV{GL_USER}, 'W', 'any' ) =~ /DENIED/;
-_die "You are not authorised" if $op eq 'break' and access( $repo, $ENV{GL_USER}, '+', 'any' ) =~ /DENIED/;
-
-my $file = shift || '';
-usage() if $op ne 'list' and not $file;
-
-_chdir( $ENV{GL_REPO_BASE} );
-_chdir("$repo.git");
-
-_die "aborting, file '$file' not found in any branch" if $file and not object_exists($file);
-
-my $ff = "gl-locks";
-
-if ( $op eq 'lock' ) {
-    f_lock( $repo, $file );
-} elsif ( $op eq 'unlock' ) {
-    f_unlock( $repo, $file );
-} elsif ( $op eq 'break' ) {
-    f_break( $repo, $file );
-} elsif ( $op eq 'list' ) {
-    f_list($repo);
-}
-
-# ----------------------------------------------------------------------
-# For a given path, return 1 if object exists in any branch, 0 if not.
-# This is to prevent locking invalid objects.
-
-sub object_exists {
-    my $file = shift;
-
-    my @branches = `git for-each-ref refs/heads '--format=%(refname)'`;
-    foreach my $b (@branches) {
-        chomp($b);
-        system("git cat-file -e $b:$file 2>/dev/null") or return 1;
-        # note that with system(), the return value is "shell truth", so
-        # you check for success with "or", not "and"
-    }
-    return 0;    # report object not found
-}
-
-# ----------------------------------------------------------------------
-# everything below assumes we have already chdir'd to "$repo.git".  Also, $ff
-# is used as a global.
-
-sub f_lock {
-    my ( $repo, $file ) = @_;
-
-    my %locks = get_locks();
-    _die "'$file' locked by '$locks{$file}{USER}' since " . localtime( $locks{$file}{TIME} ) if $locks{$file}{USER};
-    $locks{$file}{USER} = $ENV{GL_USER};
-    $locks{$file}{TIME} = time;
-    put_locks(%locks);
-}
-
-sub f_unlock {
-    my ( $repo, $file ) = @_;
-
-    my %locks = get_locks();
-    _die "'$file' not locked by '$ENV{GL_USER}'" if ( $locks{$file}{USER} || '' ) ne $ENV{GL_USER};
-    delete $locks{$file};
-    put_locks(%locks);
-}
-
-sub f_break {
-    my ( $repo, $file ) = @_;
-
-    my %locks = get_locks();
-    _die "'$file' was not locked" unless $locks{$file};
-    push @{ $locks{BREAKS} }, time . " $ENV{GL_USER} $locks{$file}{USER} $locks{$file}{TIME} $file";
-    delete $locks{$file};
-    put_locks(%locks);
-}
-
-sub f_list {
-    my $repo = shift;
-
-    my %locks = get_locks();
-    print "\n# locks held:\n\n";
-    map { print "$locks{$_}{USER}\t$_\t(" . scalar( localtime( $locks{$_}{TIME} ) ) . ")\n" } grep { $_ ne 'BREAKS' } sort keys %locks;
-    print "\n# locks broken:\n\n";
-    for my $b ( @{ $locks{BREAKS} } ) {
-        my ( $when, $who, $whose, $how_old, $what ) = split ' ', $b;
-        print "$who\t$what\t(" . scalar( localtime($when) ) . ")\t(locked by $whose at " . scalar( localtime($how_old) ) . ")\n";
-    }
-}
-
-sub get_locks {
-    if ( -f $ff ) {
-        our %locks;
-
-        my $t = slurp($ff);
-        eval $t;
-        _die "do '$ff' failed with '$@', contact your administrator" if $@;
-
-        return %locks;
-    }
-    return ();
-}
-
-sub put_locks {
-    my %locks = @_;
-
-    use Data::Dumper;
-    $Data::Dumper::Indent   = 1;
-    $Data::Dumper::Sortkeys = 1;
-
-    my $dumped_data = Data::Dumper->Dump( [ \%locks ], [qw(*locks)] );
-    _print( $ff, $dumped_data );
-}
diff --git a/docker/gitolite/src/commands/mirror b/docker/gitolite/src/commands/mirror
deleted file mode 100755
index dbdc952..0000000
--- a/docker/gitolite/src/commands/mirror
+++ /dev/null
@@ -1,167 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-my $tid;
-
-BEGIN {
-    $tid = $ENV{GL_TID} || 0;
-    delete $ENV{GL_TID};
-}
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-=for usage
-Usage 1:    gitolite mirror push <slave> <repo>
-Usage 2:    ssh git at master-server mirror push <slave> <repo>
-
-Forces a push of one repo to one slave.
-
-Usage 1 is directly on the master server.  Nothing is checked; if the slave
-accepts it, the push happens, even if the slave is not in any slaves
-option.  This is how you do delayed or lagged pushes to servers that do not
-need real-time updates or have bandwidth/connectivity issues.
-
-Usage 2 can be initiated by *any* user who has *any* gitolite access to the
-master server, but it checks that the slave is in one of the slaves options
-before doing the push.
-
-MIRROR STATUS: To find the status of the last mirror push to any slave, run
-the same command except with 'status' instead of 'push'.  With usage 1, you
-can use the special name "all" to get the status of all slaves for the given
-repo.  (Admins wishing to find the status of all slaves for ALL repos will
-have to script it using the output of "gitolite list-phy-repos".)
-
-SERVER LIST: 'gitolite mirror list master <reponame>' and 'gitolite mirror
-list slaves <reponame>' will show you the name of the master server, and list
-the slave servers, for the repo.  They only work on the server command line
-(any server), but not remotely (from a normal user).
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-
-_die "HOSTNAME not set" if not $rc{HOSTNAME};
-
-my ( $cmd, $host, $repo ) = @ARGV;
-$repo =~ s/\.git$//;
-usage() if not $repo;
-
-if ( $cmd eq 'push' ) {
-    valid_slave( $host, $repo ) if exists $ENV{GL_USER};
-    # will die if host not in slaves for repo
-
-    trace( 1, "TID=$tid host=$host repo=$repo", "gitolite mirror push started" );
-    _chdir( $rc{GL_REPO_BASE} );
-    _chdir("$repo.git");
-
-    if ( -f "gl-creator" ) {
-        # try to propagate the wild repo, including creator name and gl-perms
-        my $creator = `cat gl-creator`; chomp($creator);
-        trace( 1, `cat gl-perms 2>/dev/null | ssh $host CREATOR=$creator perms -c \\'$repo\\' 2>/dev/null` );
-    }
-
-    my $errors = 0;
-    my $glss = '';
-    for (`git push --mirror $host:$repo 2>&1`) {
-        $errors = 1 if $?;
-        print STDERR "$_" if -t STDERR or exists $ENV{GL_USER};
-        $glss .= $_;
-        chomp;
-        if (/FATAL/) {
-            $errors = 1;
-            gl_log( 'mirror', $_ );
-        } else {
-            trace( 1, "mirror: $_" );
-        }
-    }
-    # save the mirror push status for this slave if the word 'fatal' is found,
-    # else remove the status file.  We don't store "success" output messages;
-    # you can always get those from the log files if you really need them.
-    if ( $glss =~ /fatal/i ) {
-        my $glss_prefix = Gitolite::Common::gen_ts() . "\t$ENV{GL_TID}\t";
-        $glss =~ s/^/$glss_prefix/gm;
-        _print("gl-slave-$host.status", $glss);
-    } else {
-        unlink "gl-slave-$host.status";
-    }
-
-    exit $errors;
-} elsif ($cmd eq 'status') {
-    valid_slave( $host, $repo ) if exists $ENV{GL_USER};
-    # will die if host not in slaves for repo
-
-    _chdir( $rc{GL_REPO_BASE} );
-    _chdir("$repo.git");
-
-    $host = '*' if $host eq 'all';
-    map { print_status($_) } sort glob("gl-slave-$host.status");
-} else {
-    # strictly speaking, we could allow some of the possible commands remotely
-    # also, at least for admins.  However, these commands are mainly intended
-    # for server-side scripting so I don't care.
-    usage() if $ENV{GL_USER};
-
-    server_side_commands(@ARGV);
-}
-
-# ----------------------------------------------------------------------
-
-sub valid_slave {
-    my ( $host, $repo ) = @_;
-    _die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
-
-    my %list = repo_slaves($repo);
-    _die "'$host' not a valid slave for '$repo'" unless $list{$host};
-}
-
-sub repo_slaves {
-    my $repo = shift;
-
-    my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves.*" );
-    my %list = map { $_ => 1 } map { split } values %$ref;
-
-    return %list;
-}
-
-sub repo_master {
-    my $repo = shift;
-
-    my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.master\$" );
-    my @list = map { split } values %$ref;
-    _die "'$repo' seems to have more than one master" if @list > 1;
-
-    return $list[0] || '';
-}
-
-sub print_status {
-    my $file = shift;
-    return unless -f $file;
-    my $slave = $1 if $file =~ /^gl-slave-(.+)\.status$/;
-    print "----------\n";
-    print "WARNING: previous mirror push to host '$slave' failed, status is:\n";
-    print slurp($file);
-    print "----------\n";
-}
-
-# ----------------------------------------------------------------------
-# server side commands.  Very little error checking.
-#   gitolite mirror list master <repo>
-#   gitolite mirror list slaves <repo>
-
-sub server_side_commands {
-    if ( $cmd eq 'list' ) {
-        if ( $host eq 'master' ) {
-            say repo_master($repo);
-        } elsif ( $host eq 'slaves' ) {
-            my %list = repo_slaves($repo);
-            say join( " ", sort keys %list );
-        } else {
-            _die "gitolite mirror list master|slaves <reponame>";
-        }
-    } else {
-        _die "invalid command";
-    }
-}
diff --git a/docker/gitolite/src/commands/motd b/docker/gitolite/src/commands/motd
deleted file mode 100755
index b56e99e..0000000
--- a/docker/gitolite/src/commands/motd
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-=for usage
-Usage:    ssh git at host motd <repo> rm
-          cat <filename> | ssh git at host motd <repo> set
-
-Remove or set the motd file for repo or the whole system.
-
-For a repo: you need to have write access to the repo and the
-'writer-is-owner' option must be set for the repo, or it must be a
-user-created ('wild') repo and you must be the owner.
-
-For the whole system: you need to be an admin (have write access to the
-gitolite-admin repo).  Use @all in place of the repo name.
-
-PLEASE NOTE that if you're using http mode, the motd will only appear for
-gitolite commands, not for normal git operations.  This in turn means that
-only the system wide motd can be seen; repo level motd's never show up.
-=cut
-
-usage() if not @ARGV or @ARGV < 1 or $ARGV[0] eq '-h';
-
-my $repo = shift;
-my $op = shift || '';
-usage() if $op ne 'rm' and $op ne 'set';
-my $file = "gl-motd";
-
-#<<<
-_die "you are not authorized" unless
-    ( $repo eq '@all' and is_admin() )      or
-    ( $repo ne '@all' and owns($repo) )     or
-    ( $repo ne '@all' and can_write($repo)  and option( $repo, 'writer-is-owner' ) );
-#>>>
-
-my @out =
-  $repo eq '@all'
-  ? ( dir => $rc{GL_ADMIN_BASE} )
-  : ( repo => $repo );
-
-if ( $op eq 'rm' ) {
-    $repo eq '@all'
-      ? unlink "$rc{GL_ADMIN_BASE}/$file"
-      : unlink "$rc{GL_REPO_BASE}/$repo.git/$file";
-} elsif ( $op eq 'set' ) {
-    textfile( file => $file, @out, prompt => '' );
-} else {
-    print textfile( file => $file, @out, );
-}
diff --git a/docker/gitolite/src/commands/option b/docker/gitolite/src/commands/option
deleted file mode 100644
index de49aab..0000000
--- a/docker/gitolite/src/commands/option
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/perl
-
-# ----------------------------------------------------------------------
-# gitolite command to allow repo "owners" to set "options" on repos
-
-# This command can be run by a user to set "options" for any repo that she
-# owns.
-#
-# However, gitolite does *not* have the concept of an incremental "compile",
-# and options are only designed to be specified in the gitolite.conf file
-# (which a user should not be able to even see!).  Therefore, we allow one
-# specific file (conf/options.conf) to be manipulated by a remote user in a
-# *controlled* fashion, and this file is "include"d in the main gitolite.conf
-# file.
-
-# WARNINGS:
-#   1.  Runs "gitolite compile" at the end.  On really huge systems (where the
-#       sum total of the conf files is in the order of tens of thousands of
-#       lines) this may take a second or two :)
-#   2.  Since "options.conf" is not part of the admin repo, you may need to
-#       back it up separately, just like you currently back up gl-creator and
-#       gl-perms files from individual repos.
-#   3.  "options.conf" is formatted very strictly because it's not meant to be
-#       human edited.  If you edit it directly on the server, be careful.
-
-# Relevant gitolite doc links:
-#   "wild" repos and "owners"
-#       http://gitolite.com/gitolite/wild.html
-#       http://gitolite.com/gitolite/wild.html#specifying-owners
-#       http://gitolite.com/gitolite/wild.html#appendix-1-owner-and-creator
-#   gitolite "options"
-#       http://gitolite.com/gitolite/options.html
-#   the "include" statement
-#       http://gitolite.com/gitolite/conf.html#include
-
-# setup:
-#   1.  Enable the command by adding it to the ENABLE list in the rc file.
-#
-#   2.  Make sure your gitolite.conf has this line at the end:
-#
-#           include "options.conf"
-#
-#       then add/commit/push.
-#
-#       Do NOT add a file called "options.conf" to your gitolite-admin repo!
-#       This means every time you compile (push the admin repo) you will get a
-#       warning about the missing file.
-#
-#       You can either "touch ~/.gitolite/conf/options.conf" on the server, or
-#       take *any* wild repo and add *any* option to create it.
-#
-#   3.  Specify options allowed to be changed by the user.  For example:
-#
-#           repo foo/..*
-#               C   =   blah blah
-#               ...other rules...
-#               option user-options = hook\..* foo bar[0-9].*
-#
-#       Users can then set any of these options, but no others.
-
-# ----------------------------------------------------------------------
-
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-use Gitolite::Common;
-
-# ----------------------------------------------------------------------
-# usage and arg checks
-
-=for usage
-Usage:    ssh git at host option <repo> add <key> <val>
-          ssh git at host option <repo> del <key>
-          ssh git at host option <repo> list
-
-Add, delete, or list options for wild repos.  Keys must match one of the
-allowed patterns; your system administrator will tell you what they are.
-
-Doesn't check things like adding a key that already exists (simply overwrites
-without warning), deleting a key that doesn't, etc.
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-
-my $OPTIONS = "$ENV{HOME}/.gitolite/conf/options.conf";
-
-my $repo = shift;
-die "sorry, you are not authorised\n" unless owns($repo);
-
-my $op = shift; usage() unless $op =~ /^(add|del|list)$/;
-my $key = shift; usage() if not $key and $op ne 'list';
-my $val = shift; usage() if not $val and $op eq 'add';
-
-_print( $OPTIONS, "" ) unless -f $OPTIONS;    # avoid error on first run
-my $options = slurp($OPTIONS);
-
-# ----------------------------------------------------------------------
-# get 'list' out of the way first
-if ( $op eq 'list' ) {
-    print "$1\t$2\n" while $options =~ /^repo $repo\n    option (\S+) = (.*)/mg;
-    exit 0;
-}
-
-# ----------------------------------------------------------------------
-# that leaves 'add' or 'del'
-
-# NOTE: sanity check on characters in key and val not needed;
-# REMOTE_COMMAND_PATT is more restrictive than UNSAFE_PATT anyway!
-
-# check if the key is allowed
-my $user_options = option( $repo, 'user-options' );
-# this is a space separated list of allowed option keys
-my @validkeys = split( ' ', ( $user_options || '' ) );
-my @matched = grep { $key =~ /^$_$/i } @validkeys;
-_die "option '$key' not allowed\n" if ( @matched < 1 );
-
-# delete anyway
-$options =~ s/^repo $repo\n    option $key = .*\n//m;
-# then re-add if needed
-$options .= "repo $repo\n    option $key = $val\n" if $op eq 'add';
-
-# ----------------------------------------------------------------------
-# save and compile
-_print( $OPTIONS, $options );
-system("gitolite compile");
diff --git a/docker/gitolite/src/commands/owns b/docker/gitolite/src/commands/owns
deleted file mode 100755
index d1d8757..0000000
--- a/docker/gitolite/src/commands/owns
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-=for usage
-Usage:  gitolite owns <reponame>
-
-Checks if $GL_USER is an owner of the repo and returns an exit code (shell
-truth, 0 for success), which makes it possible to do this in shell:
-
-    if gitolite owns someRepo
-    then
-        ...
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-my $repo = shift;
-
-exit not owns($repo);
diff --git a/docker/gitolite/src/commands/perms b/docker/gitolite/src/commands/perms
deleted file mode 100755
index 30984bf..0000000
--- a/docker/gitolite/src/commands/perms
+++ /dev/null
@@ -1,190 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Easy;
-
-=for usage
-perms -- list or set permissions for user-created ("wild") repo.
-
-Usage summary:
-    ssh git at host perms <repo> -l
-        # list current permissions on repo
-    ssh git at host perms <repo> -lr
-        # list available roles and their access rights
-
-    ssh git at host perms <repo> + <rolename> <username>
-        # change permissions: add a user to a role
-    ssh git at host perms <repo> - <rolename> <username>
-        # change permissions: remove a user from a role
-
-Examples:
-    ssh git at host perms my/repo + READERS alice
-    ssh git at host perms my/repo + WRITERS bob
-
-----
-There is also a batch mode useful for scripting and bulk loading.  Do not
-combine this with the +/- mode above.  This mode also accepts an optional "-c"
-flag to create the repo if it does not already exist (assuming $GL_USER has
-permissions to create it).
-
-Examples:
-    cat copy-of-backed-up-gl-perms | ssh git at host perms <repo>
-    cat copy-of-backed-up-gl-perms | ssh git at host perms -c <repo>
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-
-$ENV{GL_USER} or _die "GL_USER not set";
-
-my $generic_error = "repo does not exist, or you are not authorised";
-
-if ( @ARGV >= 2 and $ARGV[1] eq '-l' ) {
-    getperms($ARGV[0]);    # doesn't return
-}
-
-# auto-create the repo if -c passed and repo doesn't exist
-if ( $ARGV[0] eq '-c' ) {
-    shift;
-    my $repo = $ARGV[0] or usage();
-    _die "invalid repo '$repo'" unless $repo =~ $REPONAME_PATT;
-
-    if ( not -d "$rc{GL_REPO_BASE}/$repo.git" ) {
-        my $ret = Gitolite::Conf::Load::access( $repo, $ENV{GL_USER}, '^C', 'any' );
-        _die $generic_error if $ret =~ /DENIED/;
-
-        require Gitolite::Conf::Store;
-        Gitolite::Conf::Store->import;
-        new_wild_repo( $repo, $ENV{GL_USER}, 'perms-c' );
-        gl_log( 'create', $repo, $ENV{GL_USER}, 'perms-c' );
-    }
-}
-
-my $repo = shift;
-
-if ( @ARGV and $ARGV[0] eq '-lr' ) {
-    list_roles();
-    exit 0;
-} else {
-    setperms(@ARGV);
-}
-
-# cache control
-if ($rc{CACHE}) {
-    require Gitolite::Cache;
-    Gitolite::Cache::cache_control('flush', $repo);
-}
-
-_system( "gitolite", "trigger", "POST_CREATE", $repo, $ENV{GL_USER}, 'perms' );
-
-# ----------------------------------------------------------------------
-
-sub getperms {
-    my $repo = shift;
-    _die $generic_error if not owns($repo);
-    my $pf = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
-
-    print slurp($pf) if -f $pf;
-
-    exit 0;
-}
-
-sub setperms {
-    _die $generic_error if not owns($repo);
-    my $pf = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
-
-    if ( not @_ ) {
-        # legacy mode; pipe data in
-        print STDERR "'batch' mode started, waiting for input (run with '-h' for details).\n";
-        print STDERR "Please enter 'cancel' to abort if you did not intend to do this.\n";
-        @ARGV = ();
-        my @a;
-        while (<>) {
-            _die "CANCELLED" if /^\s*cancel\s*$/i;
-            invalid_role($1) if /(\S+)/ and not $rc{ROLES}{$1};
-            push @a, $_;
-        }
-
-        _print( $pf, @a );
-        return;
-    }
-
-    _die "Invalid syntax.  Please re-run with '-h' for detailed usage" if @_ != 3;
-    my ( $op, $role, $user ) = @_;
-    _die "Invalid syntax.  Please re-run with '-h' for detailed usage" if $op ne '+' and $op ne '-';
-    _die "Invalid user '$user'"                                        if not $user =~ $USERNAME_PATT;
-
-    my $text = '';
-    my @text = slurp($pf) if -f $pf;
-
-    my $present = grep { $_ eq "$role $user\n" } @text;
-
-    if ( $op eq '-' ) {
-        if ( not $present ) {
-            _warn "'$role $user' was not present in file";
-        } else {
-            @text = grep { $_ ne "$role $user\n" } @text;
-            _print( $pf, @text );
-        }
-    } else {
-        invalid_role($role) unless grep { $_->[3] eq $role } load_roles();
-        if ($present) {
-            _warn "'$role $user' already present in file";
-        } else {
-            push @text, "$role $user\n";
-            @text = sort @text;
-            _print( $pf, @text );
-        }
-    }
-}
-
-my @rules;
-
-sub load_roles {
-    return @rules if @rules;
-
-    require Gitolite::Conf::Load;
-    Gitolite::Conf::Load::load($repo);
-
-    my %repos = %Gitolite::Conf::Load::repos;
-    my @repo_memberships = Gitolite::Conf::Load::memberships('repo', $repo);
-
-    for my $rp (@repo_memberships) {
-        my $hr = $repos{$rp};
-        for my $r ( keys %$hr ) {
-            next unless $r =~ s/^@//;
-            next unless $rc{ROLES}{$r};
-            map { $_->[3] = $r } @{ $hr->{"\@$r"} };
-            push @rules, @{ $hr->{"\@$r"} };
-        }
-    }
-    return @rules;
-}
-
-sub invalid_role {
-    my $role = shift;
-
-    print STDERR "Invalid role '$role'; valid roles for this repo:\n";
-    open(STDOUT, '>&', \*STDERR);   # make list_roles print to STDERR
-    list_roles();
-    exit 1;
-}
-
-sub list_roles {
-
-    my @rules = sort { $a->[0] <=> $b->[0] } load_roles();
-
-    for (@rules) {
-        $_->[2] =~ s(^refs/heads/)();
-        $_->[2] = '--any--' if $_->[2] eq 'refs/.*';
-    }
-
-    my $max = 0;
-    map { $max = $_ if $_ > $max } map { length($_->[2]) } @rules;
-    printf("\t%s\t%*s\t \t%s\n", "perm",  -$max, "ref",   "role");
-    printf("\t%s\t%*s\t \t%s\n", "----",  -$max, "---",   "----");
-    printf("\t%s\t%*s\t=\t%s\n", $_->[1], -$max, $_->[2], $_->[3]) for @rules;
-}
diff --git a/docker/gitolite/src/commands/print-default-rc b/docker/gitolite/src/commands/print-default-rc
deleted file mode 100755
index 79b88c1..0000000
--- a/docker/gitolite/src/commands/print-default-rc
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-
-print glrc('default-text');
diff --git a/docker/gitolite/src/commands/push b/docker/gitolite/src/commands/push
deleted file mode 100755
index f97f730..0000000
--- a/docker/gitolite/src/commands/push
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-export GL_BYPASS_ACCESS_CHECKS=1
-
-git push "$@"
diff --git a/docker/gitolite/src/commands/readme b/docker/gitolite/src/commands/readme
deleted file mode 100755
index cd9632f..0000000
--- a/docker/gitolite/src/commands/readme
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-# README.html files work similar to "description" files. For further
-# information see
-#   https://www.kernel.org/pub/software/scm/git/docs/gitweb.html
-# under "Per-repository gitweb configuration".
-
-=for usage
-Usage:    ssh git at host readme <repo>
-          ssh git at host readme <repo> rm
-          cat <filename> | ssh git at host readme <repo> set
-
-Show, remove or set the README.html file for repo.
-
-You need to have write access to the repo and the 'writer-is-owner' option
-must be set for the repo, or it must be a user-created ('wild') repo and you
-must be the owner.
-=cut
-
-usage() if not @ARGV or @ARGV < 1 or $ARGV[0] eq '-h';
-
-my $repo = shift;
-my $op = shift || '';
-usage() if $op and $op ne 'rm' and $op ne 'set';
-my $file = 'README.html';
-
-#<<<
-_die "you are not authorized" unless
-    ( not $op and can_read($repo) )   or
-    (     $op and owns($repo) )       or
-    (     $op and can_write($repo)    and option( $repo, 'writer-is-owner' ) );
-#>>>
-
-if ( $op eq 'rm' ) {
-    unlink "$rc{GL_REPO_BASE}/$repo.git/$file";
-} elsif ( $op eq 'set' ) {
-    textfile( file => $file, repo => $repo, prompt => '' );
-} else {
-    print textfile( file => $file, repo => $repo );
-}
-
-__END__
-
-The WRITER_CAN_UPDATE_README option is gone now; it applies to all the repos
-in the system.  Much better to add 'option writer-is-owner = 1' to repos or
-repo groups that you want this to apply to.
-
-This option is meant to cover desc, readme, and any other repo-specific text
-file, so it's also a blunt instrument, though in a different dimension :-)
diff --git a/docker/gitolite/src/commands/rsync b/docker/gitolite/src/commands/rsync
deleted file mode 100755
index 1109ac4..0000000
--- a/docker/gitolite/src/commands/rsync
+++ /dev/null
@@ -1,149 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-=for admins
-
-BUNDLE SUPPORT
-
-    (1) For each repo in gitolite.conf for which you want bundle support (or
-        '@all', if you wish), add the following line:
-
-            option bundle       =   1
-
-        Or you can say:
-
-            option bundle.ttl   =   <number>
-
-        A bundle file that is more than <number> seconds old (default value
-        86400, i.e., 1 day) is recreated on the next bundle request.  Increase
-        this if your repo is not terribly active.
-
-        Note: a bundle file is also deleted and recreated if it contains a ref
-        that was then either deleted or rewound in the repo.  This is checked
-        on every invocation.
-
-    (2) Add 'rsync' to the ENABLE list in the rc file
-
-
-GENERIC RSYNC SUPPORT
-
-    TBD
-
-=cut
-
-=for usage
-rsync helper for gitolite
-
-BUNDLE SUPPORT
-
-    Admins: see src/commands/rsync for setup instructions
-
-    Users:
-        rsync -P git at host:repo.bundle .
-            # downloads a file called "<basename of repo>.bundle"; repeat as
-            # needed till the whole thing is downloaded
-        git clone repo.bundle repo
-        cd repo
-        git remote set-url origin git at host:repo
-        git fetch origin    # and maybe git pull, etc. to freshen the clone
-
-GENERIC RSYNC SUPPORT
-
-    TBD
-
-=cut
-
-usage() if not @ARGV or $ARGV[0] eq '-h';
-
-# rsync driver program.  Several things can be done later, but for now it
-# drives just the 'bundle' transfer.
-
-if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^rsync --server --sender (-[-\w=.]+ )+\. (\S+)\.bundle$/ ) {
-
-    my $repo = $2;
-    $repo =~ s/\.git$//;
-
-    # all errors have the same message to avoid leaking info
-    can_read($repo) or _die "you are not authorised";
-    my %config = config( $repo, "gitolite-options.bundle" ) or _die "you are not authorised";
-
-    my $ttl = $config{'gitolite-options.bundle.ttl'} || 86400;    # in seconds (default 1 day)
-
-    my $bundle = bundle_create( $repo, $ttl );
-
-    $ENV{SSH_ORIGINAL_COMMAND} =~ s( \S+\.bundle)( $bundle);
-    trace( 1, "rsync bundle", $ENV{SSH_ORIGINAL_COMMAND} );
-    Gitolite::Common::_system( split ' ', $ENV{SSH_ORIGINAL_COMMAND} );
-    exit 0;
-}
-
-_warn "invalid rsync command '$ENV{SSH_ORIGINAL_COMMAND}'";
-usage();
-
-# ----------------------------------------------------------------------
-# helpers
-# ----------------------------------------------------------------------
-
-sub bundle_create {
-    my ( $repo, $ttl ) = @_;
-    my $bundle = "$repo.bundle";
-    $bundle =~ s(.*/)();
-    my $recreate = 0;
-
-    my ( %b, %r );
-    if ( -f $bundle ) {
-        %b = map { chomp; reverse split; } `git ls-remote --heads --tags $bundle`;
-        %r = map { chomp; reverse split; } `git ls-remote --heads --tags .`;
-
-        for my $ref ( sort keys %b ) {
-
-            my $mtime = ( stat $bundle )[9];
-            if ( time() - $mtime > $ttl ) {
-                trace( 1, "bundle too old" );
-                $recreate++;
-                last;
-            }
-
-            if ( not $r{$ref} ) {
-                trace( 1, "ref '$ref' deleted in repo" );
-                $recreate++;
-                last;
-            }
-
-            if ( $r{$ref} eq $b{$ref} ) {
-                # same on both sides; ignore
-                delete $r{$ref};
-                delete $b{$ref};
-                next;
-            }
-
-            `git rev-list --count --left-right $b{$ref}...$r{$ref}` =~ /^(\d+)\s+(\d+)$/ or _die "git too old";
-            if ($1) {
-                trace( 1, "ref '$ref' rewound in repo" );
-                $recreate++;
-                last;
-            }
-
-        }
-
-    } else {
-        trace( 1, "no bundle found" );
-        $recreate++;
-    }
-
-    return $bundle if not $recreate;
-
-    trace( 1, "creating bundle for '$repo'" );
-    -f $bundle and ( unlink $bundle or die "a horrible death" );
-    system("git bundle create $bundle --branches --tags >&2");
-
-    return $bundle;
-}
-
-sub trace {
-    Gitolite::Common::trace(@_);
-}
diff --git a/docker/gitolite/src/commands/sshkeys-lint b/docker/gitolite/src/commands/sshkeys-lint
deleted file mode 100755
index c7f0c81..0000000
--- a/docker/gitolite/src/commands/sshkeys-lint
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# complete rewrite of the sshkeys-lint program.  Usage has changed, see
-# usage() function or run without arguments.
-
-use Getopt::Long;
-my $admin = 0;
-my $quiet = 0;
-my $help  = 0;
-GetOptions( 'admin|a=s' => \$admin, 'quiet|q' => \$quiet, 'help|h' => \$help );
-
-use Data::Dumper;
-$Data::Dumper::Deepcopy = 1;
-$|++;
-
-my $in_gl_section = 0;
-my $warnings      = 0;
-my $KEYTYPE_REGEX = qr/\b(?:ssh-(?:rsa|dss|ed25519)|ecdsa-sha2-nistp(?:256|384|521))\b/;
-
-sub dbg {
-    use Data::Dumper;
-    for my $i (@_) {
-        print STDERR "DBG: " . Dumper($i);
-    }
-}
-
-sub msg {
-    my $warning = shift;
-    return if $quiet and not $warning;
-    $warnings++ if $warning;
-    print "sshkeys-lint: " . ( $warning ? "WARNING: " : "" ) . $_ for @_;
-}
-
-usage() if $help;
-
-our @pubkeyfiles = @ARGV; @ARGV = ();
-my $kd = "$ENV{HOME}/.gitolite/keydir";
-if ( not @pubkeyfiles ) {
-    chomp( @pubkeyfiles = `find $kd -type f -name "*.pub" | sort` );
-}
-
-if ( -t STDIN ) {
-    @ARGV = ("$ENV{HOME}/.ssh/authorized_keys");
-}
-
-# ------------------------------------------------------------------------
-
-my @authkeys;
-my %seen_fprints;
-my %pkf_by_fp;
-msg 0, "==== checking authkeys file:\n";
-fill_authkeys();    # uses up STDIN
-
-if ($admin) {
-    my $fp = fprint("$admin.pub");
-    my $fpu = ( $fp && $seen_fprints{$fp}{user} || 'no access' );
-    # dbg("fpu = $fpu, admin=$admin");
-    #<<<
-    die "\t\t*** FATAL ***\n" .
-        "$admin.pub maps to $fpu, not $admin.\n" .
-        "You will not be able to access gitolite with this key.\n" .
-        "Look for the 'ssh troubleshooting' link in http://gitolite.com/gitolite/ssh.html.\n"
-    if $fpu ne "user $admin";
-    #>>>
-}
-
-msg 0, "==== checking pubkeys:\n" if @pubkeyfiles;
-for my $pkf (@pubkeyfiles) {
-    # get the short name for the pubkey file
-    ( my $pkfsn = $pkf ) =~ s(^$kd/)();
-
-    my $fp = fprint($pkf);
-    next unless $fp;
-    msg 1, "$pkfsn appears to be a COPY of $pkf_by_fp{$fp}\n" if $pkf_by_fp{$fp};
-    $pkf_by_fp{$fp} ||= $pkfsn;
-    my $fpu = ( $seen_fprints{$fp}{user} || 'no access' );
-    msg 0, "$pkfsn maps to $fpu\n";
-}
-
-if ($warnings) {
-    print "\n$warnings warnings found\n";
-}
-
-exit $warnings;
-
-# ------------------------------------------------------------------------
-sub fill_authkeys {
-    while (<>) {
-        my $seq = $.;
-        next if ak_comment($_);    # also sets/clears $in_gl_section global
-        my $fp   = fprint($_);
-        my $user = user($_);
-
-        check( $seq, $fp, $user );
-
-        $authkeys[$seq]{fprint}  = $fp;
-        $authkeys[$seq]{ustatus} = $user;
-    }
-}
-
-sub check {
-    my ( $seq, $fp, $user ) = @_;
-
-    msg 1, "line $seq, $user key found *outside* gitolite section!\n"
-      if $user =~ /^user / and not $in_gl_section;
-
-    msg 1, "line $seq, $user key found *inside* gitolite section!\n"
-      if $user !~ /^user / and $in_gl_section;
-
-    if ( $seen_fprints{$fp} ) {
-        #<<<
-        msg 1, "authkeys line $seq ($user) will be ignored by sshd; " .
-              "same key found on line " .
-              $seen_fprints{$fp}{seq} . " (" .
-              $seen_fprints{$fp}{user} . ")\n";
-        return;
-        #>>>
-    }
-
-    $seen_fprints{$fp}{seq}  = $seq;
-    $seen_fprints{$fp}{user} = $user;
-}
-
-sub user {
-    my $user = '';
-    $user ||= "user $1"         if /^command=.*gitolite-shell (.*?)"/;
-    $user ||= "unknown command" if /^command/;
-    $user ||= "shell access"    if /$KEYTYPE_REGEX/;
-
-    return $user;
-}
-
-sub ak_comment {
-    local $_ = shift;
-    $in_gl_section = 1 if /^# gitolite start/;
-    $in_gl_section = 0 if /^# gitolite end/;
-    die "gitosis?  what's that?\n" if /^#.*gitosis/;
-    return /^\s*(#|$)/;
-}
-
-sub fprint {
-    local $_ = shift;
-    my ( $fh, $tempfn, $in );
-    if ( /$KEYTYPE_REGEX/ ) {
-        # an actual key was passed.  Since ssh-keygen requires an actual file,
-        # make a temp file to take the data and pass on to ssh-keygen
-        s/^.* ($KEYTYPE_REGEX)/$1/;
-        use File::Temp qw(tempfile);
-        ( $fh, $tempfn ) = tempfile();
-        $in = $tempfn;
-        print $fh $_;
-        close $fh;
-    } else {
-        # a filename was passed
-        $in = $_;
-    }
-    # dbg("in = $in");
-    -f $in or die "file not found: $in\n";
-    open( $fh, "ssh-keygen -l -f $in |" ) or die "could not fork: $!\n";
-    my $fp = <$fh>;
-    # dbg("fp = $fp");
-    close $fh;
-    unlink $tempfn if $tempfn;
-    warn "$fp\n" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/ or $fp =~ m(SHA256:([A-Za-z0-9+/]+));
-
-    return $1;
-}
-
-# ------------------------------------------------------------------------
-sub usage {
-    print <<EOF;
-
-Usage:  gitolite sshkeys-lint [-q] [optional list of pubkey filenames]
-        (optionally, STDIN can be a pipe or redirected from a file; see below)
-
-Look for potential problems in ssh keys.
-
-sshkeys-lint expects:
-  - the contents of an authorized_keys file via STDIN, otherwise it uses
-    \$HOME/.ssh/authorized_keys
-  - one or more pubkey filenames as arguments, otherwise it uses all the keys
-    found (recursively) in \$HOME/.gitolite/keydir
-
-The '-q' option will print only warnings instead of all mappings.
-
-Note that this runs ssh-keygen -l for each line in the authkeys file and each
-pubkey in the argument list, so be wary of running it on something huge.  This
-is meant for troubleshooting.
-
-EOF
-    exit 1;
-}
diff --git a/docker/gitolite/src/commands/sskm b/docker/gitolite/src/commands/sskm
deleted file mode 100755
index fd60233..0000000
--- a/docker/gitolite/src/commands/sskm
+++ /dev/null
@@ -1,280 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-=for usage
-Usage for this command is not that simple.  Please read the full documentation
-in doc/sskm.mkd or online at http://gitolite.com/gitolite/sskm.html.
-=cut
-
-usage() if @ARGV and $ARGV[0] eq '-h';
-
-my $rb = $rc{GL_REPO_BASE};
-my $ab = $rc{GL_ADMIN_BASE};
-# get to the keydir
-_chdir("$ab/keydir");
-
-# save arguments for later
-my $operation = shift || 'list';
-my $keyid     = shift || '';
-# keyid must fit a very specific pattern
-$keyid and $keyid !~ /^@[-0-9a-z_]+$/i and die "invalid keyid $keyid\n";
-
-# get the actual userid and keytype
-my $gl_user = $ENV{GL_USER};
-my $keytype = '';
-$keytype = $1 if $gl_user =~ s/^zzz-marked-for-(...)-//;
-print STDERR "hello $gl_user, you are currently using "
-  . (
-    $keytype
-    ? "a key in the 'marked for $keytype' state\n"
-    : "a normal (\"active\") key\n"
-  );
-
-# ----
-# first collect the keys
-
-my ( @pubkeys, @marked_for_add, @marked_for_del );
-# get the list of pubkey files for this user, including pubkeys marked for
-# add/delete
-
-for my $pubkey (`find . -type f -name "*.pub" | sort`) {
-    chomp($pubkey);
-    $pubkey =~ s(^./)();    # artifact of the find command
-
-    my $user = $pubkey;
-    $user =~ s(.*/)();                # foo/bar/baz.pub -> baz.pub
-    $user =~ s/(\@[^.]+)?\.pub$//;    # baz.pub, baz at home.pub -> baz
-
-    next unless $user eq $gl_user or $user =~ /^zzz-marked-for-...-$gl_user/;
-
-    if ( $user =~ m(^zzz-marked-for-add-) ) {
-        push @marked_for_add, $pubkey;
-    } elsif ( $user =~ m(^zzz-marked-for-del-) ) {
-        push @marked_for_del, $pubkey;
-    } else {
-        push @pubkeys, $pubkey;
-    }
-}
-
-# ----
-# list mode; just do it and exit
-sub print_keylist {
-    my ( $message, @list ) = @_;
-    return unless @list;
-    print "== $message ==\n";
-    my $count = 1;
-    for (@list) {
-        my $fp = fingerprint($_);
-        s/zzz-marked(\/|-for-...-)//g;
-        print $count++ . ": $fp : $_\n";
-    }
-}
-if ( $operation eq 'list' ) {
-    print "you have the following keys:\n";
-    print_keylist( "active keys",                          @pubkeys );
-    print_keylist( "keys marked for addition/replacement", @marked_for_add );
-    print_keylist( "keys marked for deletion",             @marked_for_del );
-    print "\n\n";
-    exit;
-}
-
-# ----
-# please see docs for details on how a user interacts with this
-
-if ( $keytype eq '' ) {
-    # user logging in with a normal key
-    die "valid operations: add, del, undo-add, confirm-del\n" unless $operation =~ /^(add|del|confirm-del|undo-add)$/;
-    if ( $operation eq 'add' ) {
-        print STDERR "please supply the new key on STDIN.  (I recommend you
-        don't try to do this interactively, but use a pipe)\n";
-        kf_add( $gl_user, $keyid, safe_stdin() );
-    } elsif ( $operation eq 'del' ) {
-        kf_del( $gl_user, $keyid );
-    } elsif ( $operation eq 'confirm-del' ) {
-        die "you dont have any keys marked for deletion\n" unless @marked_for_del;
-        kf_confirm_del( $gl_user, $keyid );
-    } elsif ( $operation eq 'undo-add' ) {
-        die "you dont have any keys marked for addition\n" unless @marked_for_add;
-        kf_undo_add( $gl_user, $keyid );
-    }
-} elsif ( $keytype eq 'del' ) {
-    # user is using a key that was marked for deletion.  The only possible use
-    # for this is that she changed her mind for some reason (maybe she marked
-    # the wrong key for deletion) or is not able to get her client-side sshd
-    # to stop using this key
-    die "valid operations: undo-del\n" unless $operation eq 'undo-del';
-
-    # reinstate the key
-    kf_undo_del( $gl_user, $keyid );
-} elsif ( $keytype eq 'add' ) {
-    die "valid operations: confirm-add\n" unless $operation eq 'confirm-add';
-    # user is trying to validate a key that has been previously marked for
-    # addition.  This isn't interactive, but it *could* be... if someone asked
-    kf_confirm_add( $gl_user, $keyid );
-}
-
-exit;
-
-# ----
-
-# make a temp clone and switch to it
-our $TEMPDIR;
-BEGIN { $TEMPDIR = `mktemp -d -t tmp.XXXXXXXXXX`; }
-END { `/bin/rm -rf $TEMPDIR`; }
-
-sub cd_temp_clone {
-    chomp($TEMPDIR);
-    hushed_git( "clone", "$rb/gitolite-admin.git", "$TEMPDIR" );
-    chdir($TEMPDIR);
-    my $hostname = `hostname`; chomp($hostname);
-    hushed_git( "config", "--get", "user.email" ) and hushed_git( "config", "user.email", $ENV{USER} . "@" . $hostname );
-    hushed_git( "config", "--get", "user.name" )  and hushed_git( "config", "user.name",  "$ENV{USER} on $hostname" );
-}
-
-sub fingerprint {
-    my $fp = `ssh-keygen -l -f $_[0]`;
-    die "does not seem to be a valid pubkey\n" unless $fp =~ /(([0-9a-f]+:)+[0-9a-f]+ )/i;
-    return $1;
-}
-
-sub safe_stdin {
-    # read one line from STDIN
-    my $data;
-    my $ret = read STDIN, $data, 4096;
-    # current pubkeys are approx 400 bytes so we go a little overboard
-    die "could not read pubkey data" . ( defined($ret) ? "" : ": $!" ) . "\n" unless $ret;
-    die "pubkey data seems to have more than one line\n" if $data =~ /\n./;
-    return $data;
-}
-
-sub hushed_git {
-    local (*STDOUT) = \*STDOUT;
-    local (*STDERR) = \*STDERR;
-    open( STDOUT, ">", "/dev/null" );
-    open( STDERR, ">", "/dev/null" );
-    system( "git", @_ );
-}
-
-sub highlander {
-    # there can be only one
-    my ( $keyid, $die_if_empty, @a ) = @_;
-    # too many?
-    if ( @a > 1 ) {
-        print STDERR "
-more than one key satisfies this condition, and I can't deal with that!
-The keys are:
-
-";
-        print STDERR "\t" . join( "\n\t", @a ), "\n\n";
-        exit 1;
-    }
-    # too few?
-    die "no keys with " . ( $keyid || "empty" ) . " keyid found\n" if $die_if_empty and not @a;
-
-    return @a;
-}
-
-sub kf_add {
-    my ( $gl_user, $keyid, $keymaterial ) = @_;
-
-    # add a new "marked for addition" key for $gl_user.
-    cd_temp_clone();
-    chdir("keydir");
-
-    mkdir("zzz-marked");
-    _print( "zzz-marked/zzz-marked-for-add-$gl_user$keyid.pub", $keymaterial );
-    hushed_git( "add", "." ) and die "git add failed\n";
-    my $fp = fingerprint("zzz-marked/zzz-marked-for-add-$gl_user$keyid.pub");
-    hushed_git( "commit", "-m", "sskm: add $gl_user$keyid ($fp)" ) and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-sub kf_confirm_add {
-    my ( $gl_user, $keyid ) = @_;
-    # find entries in both @pubkeys and @marked_for_add whose basename matches $gl_user$keyid
-    my @pk  = highlander( $keyid, 0, grep { m(^(.*/)?$gl_user$keyid.pub$) } @pubkeys );
-    my @mfa = highlander( $keyid, 1, grep { m(^zzz-marked/zzz-marked-for-add-$gl_user$keyid.pub$) } @marked_for_add );
-
-    cd_temp_clone();
-    chdir("keydir");
-
-    my $fp = fingerprint( $mfa[0] );
-    if ( $pk[0] ) {
-        hushed_git( "mv", "-f", $mfa[0], $pk[0] );
-        hushed_git( "commit", "-m", "sskm: confirm-add (replace) $pk[0] ($fp)" ) and die "git commit failed\n";
-    } else {
-        hushed_git( "mv", "-f", $mfa[0], "$gl_user$keyid.pub" );
-        hushed_git( "commit", "-m", "sskm: confirm-add $gl_user$keyid ($fp)" ) and die "git commit failed\n";
-    }
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-sub kf_undo_add {
-    # XXX some code at start is shared with kf_confirm_add
-    my ( $gl_user, $keyid ) = @_;
-    my @mfa = highlander( $keyid, 1, grep { m(^zzz-marked/zzz-marked-for-add-$gl_user$keyid.pub$) } @marked_for_add );
-
-    cd_temp_clone();
-    chdir("keydir");
-
-    my $fp = fingerprint( $mfa[0] );
-    hushed_git( "rm", $mfa[0] );
-    hushed_git( "commit", "-m", "sskm: undo-add $gl_user$keyid ($fp)" ) and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-sub kf_del {
-    my ( $gl_user, $keyid ) = @_;
-
-    cd_temp_clone();
-    chdir("keydir");
-
-    mkdir("zzz-marked");
-    my @pk = highlander( $keyid, 1, grep { m(^(.*/)?$gl_user$keyid.pub$) } @pubkeys );
-
-    my $fp = fingerprint( $pk[0] );
-    hushed_git( "mv", $pk[0], "zzz-marked/zzz-marked-for-del-$gl_user$keyid.pub" ) and die "git mv failed\n";
-    hushed_git( "commit", "-m", "sskm: del $pk[0] ($fp)" ) and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-sub kf_confirm_del {
-    my ( $gl_user, $keyid ) = @_;
-    my @mfd = highlander( $keyid, 1, grep { m(^zzz-marked/zzz-marked-for-del-$gl_user$keyid.pub$) } @marked_for_del );
-
-    cd_temp_clone();
-    chdir("keydir");
-
-    my $fp = fingerprint( $mfd[0] );
-    hushed_git( "rm", $mfd[0] );
-    hushed_git( "commit", "-m", "sskm: confirm-del $gl_user$keyid ($fp)" ) and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
-
-sub kf_undo_del {
-    my ( $gl_user, $keyid ) = @_;
-
-    my @mfd = highlander( $keyid, 1, grep { m(^zzz-marked/zzz-marked-for-del-$gl_user$keyid.pub$) } @marked_for_del );
-
-    print STDERR "
-You're undeleting a key that is currently marked for deletion.
-    Hit ENTER to undelete this key
-    Hit Ctrl-C to cancel the undelete
-Please see documentation for caveats on the undelete process as well as how to
-actually delete it.
-";
-    <>;    # yeay... always wanted to do that -- throw away user input!
-
-    cd_temp_clone();
-    chdir("keydir");
-
-    my $fp = fingerprint( $mfd[0] );
-    hushed_git( "mv", "-f", $mfd[0], "$gl_user$keyid.pub" );
-    hushed_git( "commit", "-m", "sskm: undo-del $gl_user$keyid ($fp)" ) and die "git commit failed\n";
-    system("gitolite push >/dev/null 2>/dev/null") and die "git push failed\n";
-}
diff --git a/docker/gitolite/src/commands/sudo b/docker/gitolite/src/commands/sudo
deleted file mode 100755
index eeb0083..0000000
--- a/docker/gitolite/src/commands/sudo
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-# Usage:    ssh git at host sudo <user> <command> <arguments>
-#
-# Let super-user run commands as any other user.  "Super-user" is defined as
-# "have write access to the gitolite-admin repo".
-
-die() { echo "$@" >&2; exit 1; }
-usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
-[ -z "$2" ] && usage
-[ "$1" = "-h" ] && usage
-[ -z "$GL_USER" ] && die GL_USER not set
-
-gitolite access -q gitolite-admin $GL_USER W any || die "You are not authorised"
-
-user="$1"; shift
-cmd="$1"; shift
-
-# switch user
-GL_USER="$user"
-
-# figure out if the command is allowed from a remote user
-gitolite query-rc -q COMMANDS $cmd || die "Command '$cmd' not allowed"
-gitolite $cmd "$@"
diff --git a/docker/gitolite/src/commands/svnserve b/docker/gitolite/src/commands/svnserve
deleted file mode 100755
index 6e68acf..0000000
--- a/docker/gitolite/src/commands/svnserve
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-my $svnserve = $rc{SVNSERVE} || '';
-$svnserve ||= "/usr/bin/svnserve -r /var/svn/ -t --tunnel-user=%u";
-
-my $cmd = $ENV{SSH_ORIGINAL_COMMAND};
-
-die "expecting 'svnserve -t', got '$cmd'\n" unless $cmd eq 'svnserve -t';
-
-$svnserve =~ s/%u/$ENV{GL_USER}/g;
-exec $svnserve;
-die "svnserve exec failed\n";
diff --git a/docker/gitolite/src/commands/symbolic-ref b/docker/gitolite/src/commands/symbolic-ref
deleted file mode 100755
index b65c792..0000000
--- a/docker/gitolite/src/commands/symbolic-ref
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/sh
-
-# Usage:    ssh git at host symbolic-ref <repo> <arguments to git-symbolic-ref>
-#
-# allow 'git symbolic-ref' over a gitolite connection
-
-# Security: remember all arguments to commands must match a very conservative
-# pattern.  Once that is assured, the symbolic-ref command has no security
-# related side-effects, so we don't check arguments at all.
-
-# Note: because of the restriction on allowed characters in arguments, you
-# can't supply an arbitrary string to the '-m' option.  The simplest
-# work-around is-to-just-use-join-up-words-like-this if you feel the need to
-# supply a "reason" string.  In any case this is useless by default; you'd
-# have to have core.logAllRefUpdates set for it to have any meaning.
-
-die() { echo "$@" >&2; exit 1; }
-usage() { perl -lne 'print substr($_, 2) if /^# Usage/../^$/' < $0; exit 1; }
-[ -z "$1" ] && usage
-[ "$1" = "-h" ] && usage
-[ -z "$GL_USER" ] && die GL_USER not set
-
-# ----------------------------------------------------------------------
-repo=$1; shift
-repo=${repo%.git}
-gitolite access -q "$repo" $GL_USER W any || die You are not authorised
-
-# change head
-cd $GL_REPO_BASE/$repo.git
-
-git symbolic-ref "$@"
diff --git a/docker/gitolite/src/commands/who-pushed b/docker/gitolite/src/commands/who-pushed
deleted file mode 100755
index fb37607..0000000
--- a/docker/gitolite/src/commands/who-pushed
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-usage($ARGV[1]) if $ARGV[1] and $ARGV[1] =~ /^[\w-]+$/ and $ARGV[0] eq '-h';
-
-( my $logdir = $ENV{GL_LOGFILE} ) =~ s(/[^/]+$)();
-
-# deal with migrate
-my %gl_log_lines_buffer;
-my $countr = 0;
-my $countl = 0;
-migrate(@ARGV) if $ARGV[0] eq '--migrate';   # won't return; exits right there
-
-# tip search?
-my $tip_search = 0;
-if ($ARGV[0] eq '--tip') {
-    shift;
-    $tip_search = 1;
-}
-
-# the normal who-pushed
-usage() if not @ARGV or @ARGV < 2 or $ARGV[0] eq '-h';
-usage() if $ARGV[1] !~ /^[0-9a-f]+$/i;
-
-my $repo = shift;
-my $sha = shift; $sha =~ tr/A-F/a-f/;
-
-$ENV{GL_USER} and ( can_read($repo) or die "no read permissions on '$repo'" );
-
-# ----------------------------------------------------------------------
-
-my $repodir = "$ENV{GL_REPO_BASE}/$repo.git";
-chdir $repodir or die "repo '$repo' missing";
-
-my @logfiles = reverse glob("$logdir/*");
- at logfiles = ( "$repodir/gl-log" ) if -f "$repodir/gl-log";
-
-for my $logfile ( @logfiles ) {
-    @ARGV = ($logfile);
-    for my $line ( reverse grep { m(\tupdate\t($repo|$repodir)\t) } <> ) {
-        chomp($line);
-        my @fields = split /\t/, $line;
-        my ( $ts, $pid, $who, $ref, $d_old, $new ) = @fields[ 0, 1, 4, 6, 7, 8 ];
-
-        # d_old is what you display
-        my $old = $d_old;
-        $old = ""       if $d_old eq ( "0" x 40 );
-        $old = "$old.." if $old;
-
-        if ($tip_search) {
-            print "$ts $pid $who $ref $d_old $new\n" if $new =~ /^$sha/;
-        } else {
-            system("git rev-list $old$new 2>/dev/null | grep ^$sha >/dev/null && echo '$ts $pid $who $ref $d_old $new'");
-        }
-    }
-}
-
-# ----------------------------------------------------------------------
-# migration
-
-sub migrate {
-    chdir $ENV{GL_REPO_BASE};
-    my @repos = `gitolite list-phy-repos`; chomp @repos;
-
-    my $count = scalar( grep { -f "$_.git/gl-log" } @repos );
-    if ( $count and ( $_[1] || '' ) ne '--force' ) {
-        say2 "$count repo(s) already have gl-log files.  To confirm overwriting, please re-run as:";
-        say2 "\tgitolite who-pushed --migrate --force";
-        say2 "see help ('-h', '-h logfiles', or '-h migrate') for details.";
-        exit 1;
-    }
-
-    foreach my $r (@repos) {
-        _print("$r.git/gl-log", '');
-    }
-
-    my %repo_exists = map { $_ => 1 } @repos;
-    @ARGV = sort ( glob("$logdir/*") );
-    while (<>) {
-        say2 "processed '$ARGV'" if eof(ARGV);
-        next unless /\tupdate\t/;
-        my @f = split /\t/;
-        my $repo = $f[3];
-        if ($repo =~ m(^/)) {
-            $repo =~ s/^$ENV{GL_REPO_BASE}\///;
-            $repo =~ s/\.git$//;
-        }
-
-        gen_gl_log($repo, $_) if $repo_exists{$repo};
-    }
-    flush_gl_log();
-
-    exit 0;
-}
-sub gen_gl_log {
-    my ($repo, $l) = @_;
-
-    $countr++ unless $gl_log_lines_buffer{$repo};    # new repo, not yet seen
-    $countl++;
-    $gl_log_lines_buffer{$repo} .= $l;
-
-    # once we have buffered log lines for about 100 repos, or about 10,000 log
-    # lines, we flush them
-    flush_gl_log() if $countr >= 100 or $countl >= 10_000;
-}
-sub flush_gl_log {
-    while (my ($r, $l) = each %gl_log_lines_buffer) {
-        open my $fh, ">>", "$r.git/gl-log" or _die "open flush_gl_log failed: $!";
-        print $fh $l;
-        close $fh;
-    }
-    %gl_log_lines_buffer = ();
-    say2 "flushed $countl lines to $countr repos...";
-    $countr = $countl = 0;
-}
-
-__END__
-
-=for usage
-uSAge:    ssh git at host who-pushed [--tip] <repo> <SHA>
-
-Determine who pushed the given commit.  The first few hex digits of the SHA
-should suffice.  If the '--tip' option is supplied, it'll only look for the
-SHA among "tip" commits (i.e., search the "new SHA"s, without running the
-expensive 'git rev-parse' for each push).
-
-Each line of the output contains the following fields: timestamp, a
-transaction ID, username, refname, and the old and new SHAs for the ref.
-
-Note on the "transaction ID" field: if looking at the log file doesn't help
-you figure out what its purpose is, please just ignore it.
-
-TO SEE ADDITIONAL HELP, run with options "-h logfiles" or "-h migrate".
-=cut
-
-=for logfiles
-There are 2 places that gitolite logs to, based on the value give to the
-LOG_DEST rc variable.  By default, log files go to ~/.gitolite/logs, but you
-can choose to send them to syslog instead (in which case 'who-pushed' will not
-work), or to both syslog and the normal log files.
-
-In addition, gitolite can also be told to log just the "update" records to a
-special "gl-log" file in the bare repo directory.  This makes 'who-pushed'
-**much** faster (thanks to milki for the problem *and* the simple solution).
-
-'who-pushed' will look for that special file first and use only that if it is
-found.  Otherwise it will look in the normal gitolite log files, which will of
-course be much slower.
-=cut
-
-=for migrate
-If you installed gitolite before v3.6.4, and you wish to use the new, more
-efficient logging that helps who-pushed run faster, you should first update
-the rc file (see http://gitolite.com/gitolite/rc.html for notes on that) to
-specify a suitable value for LOG_DEST.
-
-After that you should probably do a one-time generation of the repo-specific
-'gl-log' files from the normal log files.  This can only be done from the
-server command line, even if the 'who-pushed' command has been enabled for
-remote access.
-
-To do this, just run 'gitolite who-pushed --migrate'.  If some of your repos
-already had gl-log files, it will warn you, and tell you how to override.
-You're only supposed to to use this *once* after upgrading to v3.6.4 and
-setting LOG_DEST in the rc file anyway.
-=cut
-
diff --git a/docker/gitolite/src/commands/writable b/docker/gitolite/src/commands/writable
deleted file mode 100755
index 3e97f0b..0000000
--- a/docker/gitolite/src/commands/writable
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Easy;
-
-=for usage
-Usage: gitolite writable <reponame>|@all on|off|status
-
-Disable/re-enable pushes to all repos or named repo.  Useful to run
-non-git-aware backups and so on.
-
-'on' enables, 'off' disables, writes (pushes) to the named repo or all repos.
-'status' returns the current status as shell truth (i.e., exit code 0 for
-writable, 1 for not writable).
-
-With 'off', any subsequent text is taken to be the message to be shown to
-users when their pushes get rejected.  If it is not supplied, it will take it
-from STDIN; this allows longer messages.
-=cut
-
-usage() if not @ARGV or @ARGV < 2 or $ARGV[0] eq '-h';
-usage() if $ARGV[1] ne 'on' and $ARGV[1] ne 'off' and $ARGV[1] ne 'status';
-
-my $repo = shift;
-my $op   = shift;    # on|off|status
-
-if ( $repo eq '@all' ) {
-    _die "you are not authorized" if $ENV{GL_USER} and not is_admin();
-} else {
-    _die "you are not authorized" if $ENV{GL_USER} and not( owns($repo) or is_admin() or ( can_write($repo) and $op eq 'status' ) );
-}
-
-my $msg = join( " ", @ARGV );
-# try STDIN only if no msg found in args *and* it's an 'off' command
-if ( not $msg and $op eq 'off' ) {
-    say2 "...please type the message to be shown to users:";
-    $msg = join( "", <> );
-}
-
-my $sf = ".gitolite.down";
-my $rb = $ENV{GL_REPO_BASE};
-
-if ( $repo eq '@all' ) {
-    target( $ENV{HOME} );
-} else {
-    target("$rb/$repo.git");
-    target( $ENV{HOME} ) if $op eq 'status';
-}
-
-exit 0;
-
-sub target {
-    my $repodir = shift;
-    if ( $op eq 'status' ) {
-        exit 1 if -e "$repodir/$sf";
-    } elsif ( $op eq 'on' ) {
-        unlink "$repodir/$sf";
-    } elsif ( $op eq 'off' ) {
-        _print( "$repodir/$sf", $msg );
-    }
-}
diff --git a/docker/gitolite/src/gitolite b/docker/gitolite/src/gitolite
deleted file mode 100755
index 4a4cbf5..0000000
--- a/docker/gitolite/src/gitolite
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/perl
-
-# all gitolite CLI tools run as sub-commands of this command
-# ----------------------------------------------------------------------
-
-=for args
-Usage:  gitolite [sub-command] [options]
-
-The following built-in subcommands are available; they should all respond to
-'-h' if you want further details on each:
-
-    setup                       1st run: initial setup; all runs: hook fixups
-    compile                     compile gitolite.conf
-
-    query-rc                    get values of rc variables
-
-    list-groups                 list all group names in conf
-    list-users                  list all users/user groups in conf
-    list-repos                  list all repos/repo groups in conf
-    list-phy-repos              list all repos actually on disk
-    list-memberships            list all groups a name is a member of
-    list-members                list all members of a group
-
-Warnings:
-  - list-users is disk bound and could take a while on sites with 1000s of repos
-  - list-memberships does not check if the name is known; unknown names come
-    back with 2 answers: the name itself and '@all'
-
-In addition, running 'gitolite help' should give you a list of custom commands
-available.  They may or may not respond to '-h', depending on how they were
-written.
-=cut
-
-# ----------------------------------------------------------------------
-
-use FindBin;
-
-BEGIN { $ENV{GL_BINDIR} = $FindBin::RealBin; }
-BEGIN { $ENV{GL_LIBDIR} = "$ENV{GL_BINDIR}/lib"; }
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-my ( $command, @args ) = @ARGV;
-gl_log( 'cli', 'gitolite', @ARGV ) if -d $rc{GL_ADMIN_BASE} and $$ == ( $ENV{GL_TID} || 0 );
-args();
-
-# the first two commands need options via @ARGV, as they have their own
-# GetOptions calls and older perls don't have 'GetOptionsFromArray'
-
-if ( $command eq 'setup' ) {
-    shift @ARGV;
-    require Gitolite::Setup;
-    Gitolite::Setup->import;
-    setup();
-
-} elsif ( $command eq 'query-rc' ) {
-    shift @ARGV;
-    query_rc();    # doesn't return
-
-# the rest don't need @ARGV per se
-
-} elsif ( $command eq 'compile' ) {
-    require Gitolite::Conf;
-    Gitolite::Conf->import;
-    compile(@args);
-
-} elsif ( $command eq 'trigger' ) {
-    trigger(@args);
-
-} elsif ( my $c = _which( "commands/$command", 'x' ) ) {
-    trace( 2, "attempting gitolite command $c" );
-    _system( $c, @args );
-
-} elsif ( $command eq 'list-phy-repos' ) {
-    _chdir( $rc{GL_REPO_BASE} );
-    print "$_\n" for ( @{ list_phy_repos(@args) } );
-
-} elsif ( $command =~ /^list-/ ) {
-    trace( 2, "attempting lister command $command" );
-    require Gitolite::Conf::Load;
-    Gitolite::Conf::Load->import;
-    my $fn = lister_dispatch($command);
-    print "$_\n" for ( @{ $fn->(@args) } );
-
-} else {
-    _die "unknown gitolite sub-command";
-}
-
-gl_log('END') if $$ == $ENV{GL_TID};
-
-exit 0;
-
-sub args {
-    usage() if not $command or $command eq '-h';
-}
-
-# ----------------------------------------------------------------------
diff --git a/docker/gitolite/src/gitolite-shell b/docker/gitolite/src/gitolite-shell
deleted file mode 100755
index d9ec01f..0000000
--- a/docker/gitolite/src/gitolite-shell
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/perl
-
-# gitolite shell, invoked from ~/.ssh/authorized_keys
-# ----------------------------------------------------------------------
-
-use FindBin;
-
-BEGIN { $ENV{GL_BINDIR} = $FindBin::RealBin; }
-BEGIN { $ENV{GL_LIBDIR} = "$ENV{GL_BINDIR}/lib"; }
-use lib $ENV{GL_LIBDIR};
-
-# set HOME
-BEGIN { $ENV{HOME} = $ENV{GITOLITE_HTTP_HOME} if $ENV{GITOLITE_HTTP_HOME}; }
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-# the main() sub expects ssh-ish things; set them up...
-my $id = '';
-if ( exists $ENV{G3T_USER} ) {
-    $id = in_file();    # file:// masquerading as ssh:// for easy testing
-} elsif ( exists $ENV{SSH_CONNECTION} ) {
-    $id = in_ssh();
-} elsif ( exists $ENV{REQUEST_URI} ) {
-    $id = in_http();
-} else {
-    _die "who the *heck* are you?";
-}
-
-# sanity...
-my $soc = $ENV{SSH_ORIGINAL_COMMAND};
-$soc =~ s/[\n\r]+/<<newline>>/g;
-_die "I don't like newlines in the command: '$soc'\n" if $ENV{SSH_ORIGINAL_COMMAND} ne $soc;
-
-# allow gitolite-shell to be used as "$SHELL".  Experts only; no support, no docs
-if (@ARGV and $ARGV[0] eq '-c') {
-    shift;
-    $ARGV[0] =~ s/^$0 // or _die "unknown git/gitolite command: '$ARGV[0]'";
-}
-
-# the INPUT trigger massages @ARGV and $ENV{SSH_ORIGINAL_COMMAND} as needed
-trigger('INPUT');
-
-main($id);
-
-gl_log('END') if $$ == $ENV{GL_TID};
-
-exit 0;
-
-# ----------------------------------------------------------------------
-
-sub in_file {
-    gl_log( 'file', "ARGV=" . join( ",", @ARGV ), "SOC=$ENV{SSH_ORIGINAL_COMMAND}" );
-
-    if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /git-\w+-pack/ ) {
-        print STDERR "TRACE: gsh(", join( ")(", @ARGV ), ")\n";
-        print STDERR "TRACE: gsh(SOC=$ENV{SSH_ORIGINAL_COMMAND})\n";
-    }
-    return 'file';
-}
-
-sub in_http {
-    http_setup_die_handler();
-
-    _die "GITOLITE_HTTP_HOME not set" unless $ENV{GITOLITE_HTTP_HOME};
-
-    _die "fallback to DAV not supported" if $ENV{REQUEST_METHOD} eq 'PROPFIND';
-
-    # fake out SSH_ORIGINAL_COMMAND and SSH_CONNECTION when called via http,
-    # so the rest of the code stays the same (except the exec at the end).
-    http_simulate_ssh_connection();
-    $ENV{SSH_ORIGINAL_COMMAND} ||= '';
-
-    $ENV{REMOTE_USER} ||= $rc{HTTP_ANON_USER};
-    @ARGV = ( $ENV{REMOTE_USER} );
-
-    my $ip;
-    ( $ip = $ENV{SSH_CONNECTION} || '(no-IP)' ) =~ s/ .*//;
-
-    gl_log( 'http', "ARGV=" . join( ",", @ARGV ), "SOC=" . ( $ENV{SSH_ORIGINAL_COMMAND} || '' ), "FROM=$ip" );
-
-    return 'http';
-}
-
-sub in_ssh {
-    my $ip;
-    ( $ip = $ENV{SSH_CONNECTION} || '(no-IP)' ) =~ s/ .*//;
-
-    gl_log( 'ssh', "ARGV=" . join( ",", @ARGV ), "SOC=" . ( $ENV{SSH_ORIGINAL_COMMAND} || '' ), "FROM=$ip" );
-
-    $ENV{SSH_ORIGINAL_COMMAND} ||= '';
-
-    return $ip;
-}
-
-# ----------------------------------------------------------------------
-
-# call this once you are sure arg-1 is the username and SSH_ORIGINAL_COMMAND
-# has been setup (even if it's not actually coming via ssh).
-sub main {
-    my $id = shift;
-
-    # set up the user
-    my $user = $ENV{GL_USER} = shift @ARGV;
-
-    # set up the repo and the attempted access
-    my ( $verb, $repo ) = parse_soc();    # returns only for git commands
-    Gitolite::Conf::Load::sanity($repo, $REPONAME_PATT);
-    $ENV{GL_REPO} = $repo;
-    my $aa = ( $verb =~ 'upload' ? 'R' : 'W' );
-
-    # set up env vars from options set for this repo
-    env_options($repo);
-
-    # auto-create?
-    if ( repo_missing($repo) and access( $repo, $user, '^C', 'any' ) !~ /DENIED/ ) {
-        require Gitolite::Conf::Store;
-        Gitolite::Conf::Store->import;
-        new_wild_repo( $repo, $user, $aa );
-        gl_log( 'create', $repo, $user, $aa );
-    }
-
-    # a ref of 'any' signifies that this is a pre-git check, where we don't
-    # yet know the ref that will be eventually pushed (and even that won't
-    # apply if it's a read operation).  See the matching code in access() for
-    # more information.
-    unless ( $ENV{GL_BYPASS_ACCESS_CHECKS} ) {
-        my $ret = access( $repo, $user, $aa, 'any' );
-        trigger( 'ACCESS_1', $repo, $user, $aa, 'any', $ret );
-        _die $ret . "\n(or you mis-spelled the reponame)" if $ret =~ /DENIED/;
-
-        gl_log( "pre_git", $repo, $user, $aa, 'any', $ret );
-    }
-
-    trigger( 'PRE_GIT', $repo, $user, $aa, 'any', $verb );
-    if ( $ENV{REQUEST_URI} ) {
-        _system( "git", "http-backend" );
-    } else {
-        my $repodir = "'$rc{GL_REPO_BASE}/$repo.git'";
-        _system( "git", "shell", "-c", "$verb $repodir" );
-    }
-    trigger( 'POST_GIT', $repo, $user, $aa, 'any', $verb );
-}
-
-# ----------------------------------------------------------------------
-
-sub parse_soc {
-    my $soc = $ENV{SSH_ORIGINAL_COMMAND};
-    $soc ||= 'info';
-
-    my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-    if ( $soc =~ m(^($git_commands) '?/?(.*?)(?:\.git(\d)?)?'?$) ) {
-        my ( $verb, $repo, $trace_level ) = ( $1, $2, $3 );
-        $ENV{D} = $trace_level if $trace_level;
-        _die "invalid repo name: '$repo'" if $repo !~ $REPONAME_PATT;
-        trace( 2, "git command", $soc );
-        return ( $verb, $repo );
-    }
-
-    # after this we should not return; caller expects us to handle it all here
-    # and exit out
-
-    my @words = split ' ', $soc;
-    if ( $rc{COMMANDS}{ $words[0] } ) {
-        if ( $rc{COMMANDS}{ $words[0] } ne 'ua' ) {
-            _die "suspicious characters loitering about '$soc'" if $soc !~ $REMOTE_COMMAND_PATT;
-            _die "no relative paths allowed anywhere!" if $soc =~ m(\.\./);
-        }
-        trace( 2, "gitolite command", $soc );
-        _system( "gitolite", @words );
-        exit 0;
-    }
-
-    _die "unknown git/gitolite command: '$soc'";
-}
-
-# ----------------------------------------------------------------------
-# helper functions for "in_http"
-
-sub http_setup_die_handler {
-
-    $SIG{__DIE__} = sub {
-        my $service = ( $ENV{SSH_ORIGINAL_COMMAND} =~ /git-receive-pack/ ? 'git-receive-pack' : 'git-upload-pack' );
-        my $message = shift; chomp($message);
-        print STDERR "$message\n";
-
-        http_print_headers($service);
-
-        # format the service response, then the message.  With initial
-        # help from Ilari and then a more detailed email from Shawn...
-        $service = "# service=$service\n"; $message = "ERR $message\n";
-        $service = sprintf( "%04X", length($service) + 4 ) . "$service";    # no CRLF on this one
-        $message = sprintf( "%04X", length($message) + 4 ) . "$message";
-
-        print $service;
-        print "0000";                                                       # flush-pkt, apparently
-        print $message;
-        print STDERR $service;
-        print STDERR $message;
-        exit 0;                                                             # if it's ok for die_webcgi in git.git/http-backend.c, it's ok for me ;-)
-      }
-}
-
-sub http_simulate_ssh_connection {
-    # these patterns indicate normal git usage; see "services[]" in
-    # http-backend.c for how I got that.  Also note that "info" is overloaded;
-    # git uses "info/refs...", while gitolite uses "info" or "info?...".  So
-    # there's a "/" after info in the list below
-    if ( $ENV{PATH_INFO} =~ m(^/(.*)/(HEAD$|info/refs$|objects/|git-(?:upload|receive)-pack$)) ) {
-        my $repo = $1;
-        my $verb = ( $ENV{REQUEST_URI} =~ /git-receive-pack/ ) ? 'git-receive-pack' : 'git-upload-pack';
-        $ENV{SSH_ORIGINAL_COMMAND} = "$verb '$repo'";
-    } else {
-        # this is one of our custom commands; could be anything really,
-        # because of the adc feature
-        my ($verb) = ( $ENV{PATH_INFO} =~ m(^/(\S+)) );
-        my $args = $ENV{QUERY_STRING};
-        $args =~ s/\+/ /g;
-        $args =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
-        $ENV{SSH_ORIGINAL_COMMAND} = $verb;
-        $ENV{SSH_ORIGINAL_COMMAND} .= " $args" if $args;
-        http_print_headers();    # in preparation for the eventual output!
-
-        # we also need to pipe STDERR out via STDOUT, else the user doesn't see those messages!
-        open(STDERR, ">&STDOUT") or _die "Can't dup STDOUT: $!";
-    }
-    $ENV{SSH_CONNECTION} = "$ENV{REMOTE_ADDR} $ENV{REMOTE_PORT} $ENV{SERVER_ADDR} $ENV{SERVER_PORT}";
-}
-
-my $http_headers_printed = 0;
-
-sub http_print_headers {
-    my ( $service, $code, $text ) = @_;
-
-    return if $http_headers_printed++;
-    $code ||= 200;
-    $text ||= "OK - gitolite";
-
-    $|++;
-    print "Status: $code $text\r\n";
-    print "Expires: Fri, 01 Jan 1980 00:00:00 GMT\r\n";
-    print "Pragma: no-cache\r\n";
-    print "Cache-Control: no-cache, max-age=0, must-revalidate\r\n";
-    if ($service) {
-        print "Content-Type: application/x-$service-advertisement\r\n";
-    } else {
-        print "Content-Type: text/plain\r\n";
-    }
-    print "\r\n";
-}
diff --git a/docker/gitolite/src/lib/Gitolite/Cache.pm b/docker/gitolite/src/lib/Gitolite/Cache.pm
deleted file mode 100644
index 351a13e..0000000
--- a/docker/gitolite/src/lib/Gitolite/Cache.pm
+++ /dev/null
@@ -1,161 +0,0 @@
-package Gitolite::Cache;
-
-# cache stuff using an external database (redis)
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  cache_control
-  cache_wrap
-);
-
-use Exporter 'import';
-
-use Gitolite::Common;
-use Gitolite::Rc;
-use Storable qw(freeze thaw);
-use Redis;
-
-my $redis;
-
-my $redis_sock = "$ENV{HOME}/.redis-gitolite.sock";
-if ( -S $redis_sock ) {
-    _connect_redis();
-} else {
-    _start_redis();
-    _connect_redis();
-
-    # this redis db is a transient, caching only, db, so let's not
-    # accidentally use any stale data when if we're just starting up
-    cache_control('stop');
-    cache_control('start');
-}
-
-# ----------------------------------------------------------------------
-
-my %wrapped;
-my $ttl = ( $rc{CACHE_TTL} || ( $rc{GROUPLIST_PGM} ? 900 : 90000 ) );
-
-sub cache_control {
-    my $op = shift;
-    if ( $op eq 'stop' ) {
-        $redis->flushall();
-    } elsif ( $op eq 'start' ) {
-        $redis->set( 'cache-up', 1 );
-    } elsif ( $op eq 'flush' ) {
-        flush_repo(@_);
-    }
-}
-
-sub cache_wrap {
-    my $sub   = shift;
-    my $tname = $sub;    # this is what will show up in the trace output
-    trace( 3, "wrapping '$sub'" );
-    $sub = ( caller 1 )[0] . "::" . $sub if $sub !~ /::/;
-    return if $wrapped{$sub}++;    # in case somehow it gets called twice for the same sub!
-
-    # collect names of wrapped subs into a redis 'set'
-    $redis->sadd( "SUBWAY", $sub );    # subway?  yeah well they wrap subs don't they?
-
-    my $cref = eval '\&' . $sub;
-    my %opt  = @_;
-        # rest of the options come in as a hash.  'list' says this functions
-        # returns a list.  'ttl' is a number to override the default ttl for
-        # the cached value.
-
-    no strict 'refs';
-    no warnings 'redefine';
-    *{$sub} = sub {                    # the wrapper function
-        my $key = join( ", ", @_ );
-        trace( 2, "$tname.args", @_ );
-
-        if ( cache_up() and defined( my $val = $redis->get("$sub: $key") ) ) {
-            # cache is up and we got a hit, return value from cache
-            if ( $opt{list} ) {
-                trace( 2, "$tname.getl", @{ thaw($val) } );
-                return @{ thaw($val) };
-            } else {
-                trace( 2, "$tname.get", $val );
-                return $val;
-            }
-        } else {
-            # cache is down or we got a miss, compute
-            my ( $r, @r );
-            if ( $opt{list} ) {
-                @r = $cref->(@_);    # provide list context
-                trace( 2, "$tname.setl", @r );
-            } else {
-                $r = $cref->(@_);    # provide scalar context
-                trace( 2, "$tname.set", $r );
-            }
-
-            # store computed value in cache if cache is up
-            if ( cache_up() ) {
-                $redis->set( "$sub: $key", ( $opt{list} ? freeze( \@r ) : $r ) );
-                $redis->expire( "$sub: $key", $opt{ttl} || $ttl );
-                trace( 2, "$tname.ttl", ( $opt{ttl} || $ttl ) );
-            }
-
-            return @r if $opt{list};
-            return $r;
-        }
-    };
-    trace( 3, "wrapped '$sub'" );
-}
-
-sub cache_up {
-    return $redis->exists('cache-up');
-}
-
-sub flush_repo {
-    my $repo = shift;
-
-    my @wrapped = $redis->smembers("SUBWAY");
-    for my $func (@wrapped) {
-        # if we wrap any more functions, make sure they're functions where the
-        # first argument is 'repo'
-        my @keys = $redis->keys("$func: $repo, *");
-        $redis->del( @keys ) if @keys;
-    }
-}
-
-# ----------------------------------------------------------------------
-
-sub _start_redis {
-    my $conf = join( "", <DATA> );
-    $conf =~ s/%HOME/$ENV{HOME}/g;
-
-    open( REDIS, "|-", "/usr/sbin/redis-server", "-" ) or die "start redis server failed: $!";
-    print REDIS $conf;
-    close REDIS;
-
-    # give it a little time to come up
-    select( undef, undef, undef, 0.2 );
-}
-
-sub _connect_redis {
-    $redis = Redis->new( sock => $redis_sock, encoding => undef ) or die "redis new failed: $!";
-    $redis->ping or die "redis ping failed: $!";
-}
-
-1;
-
-__DATA__
-# resources
-maxmemory 50MB
-port 0
-unixsocket %HOME/.redis-gitolite.sock
-unixsocketperm 700
-timeout 0
-databases 1
-
-# daemon
-daemonize yes
-pidfile %HOME/.redis-gitolite.pid
-dbfilename %HOME/.redis-gitolite.rdb
-dir %HOME
-
-# feedback
-loglevel notice
-logfile %HOME/.redis-gitolite.log
-
-# we don't save
diff --git a/docker/gitolite/src/lib/Gitolite/Common.pm b/docker/gitolite/src/lib/Gitolite/Common.pm
deleted file mode 100644
index 5d6b749..0000000
--- a/docker/gitolite/src/lib/Gitolite/Common.pm
+++ /dev/null
@@ -1,365 +0,0 @@
-package Gitolite::Common;
-
-# common (non-gitolite-specific) functions
-# ----------------------------------------------------------------------
-
-#<<<
- at EXPORT = qw(
-  print2  dbg     _mkdir  _open   ln_sf     tsh_rc      sort_u
-  say     _warn   _chdir  _print            tsh_text    list_phy_repos
-  say2    _die    _system slurp             tsh_lines
-          trace           cleanup_conf_line tsh_try
-          usage                             tsh_run
-          gen_lfn
-          gl_log
-
-          dd
-          t_start
-          t_lap
-);
-#>>>
-use Exporter 'import';
-use File::Path qw(mkpath);
-use Carp qw(carp cluck croak confess);
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub print2 {
-    local $/ = "\n";
-    print STDERR @_;
-}
-
-sub say {
-    local $/ = "\n";
-    print @_, "\n";
-}
-
-sub say2 {
-    local $/ = "\n";
-    print STDERR @_, "\n";
-}
-
-sub trace {
-    gl_log( "\t" . join( ",", @_[ 1 .. $#_ ] ) ) if $_[0] <= 1 and defined $Gitolite::Rc::rc{LOG_EXTRA};
-
-    return unless defined( $ENV{D} );
-
-    my $level = shift; return if $ENV{D} < $level;
-    my $sub = ( caller 1 )[3] || ''; $sub =~ s/.*://;
-    if ( not $sub ) {
-        $sub = (caller)[1];
-        $sub =~ s(.*/(.*))(($1));
-    }
-    $sub .= ' ' x ( 31 - length($sub) );
-    say2 "$level\t$sub\t", join( "\t", @_ );
-}
-
-sub dbg {
-    use Data::Dumper;
-    return unless defined( $ENV{D} );
-    for my $i (@_) {
-        print STDERR "DBG: " . Dumper($i);
-    }
-}
-
-sub dd {
-    local $ENV{D} = 1;
-    dbg(@_);
-}
-
-{
-    my %start_times;
-
-    eval "require Time::HiRes";
-    # we just ignore any errors from this; nothing needs to be done as long as
-    # no code *calls* either of the next two functions.
-
-    sub t_start {
-        my $name = shift || 'default';
-        $start_times{$name} = [ Time::HiRes::gettimeofday() ];
-    }
-
-    sub t_lap {
-        my $name = shift || 'default';
-        return Time::HiRes::tv_interval( $start_times{$name} );
-    }
-}
-
-sub _warn {
-    gl_log( 'warn', @_ );
-    if ( $ENV{D} and $ENV{D} >= 3 ) {
-        cluck "WARNING: ", @_, "\n";
-    } elsif ( defined( $ENV{D} ) ) {
-        carp "WARNING: ", @_, "\n";
-    } else {
-        warn "WARNING: ", @_, "\n";
-    }
-}
-$SIG{__WARN__} = \&_warn;
-
-sub _die {
-    gl_log( 'die', @_ );
-    if ( $ENV{D} and $ENV{D} >= 3 ) {
-        confess "FATAL: " . join( ",", @_ ) . "\n" if defined( $ENV{D} );
-    } elsif ( defined( $ENV{D} ) ) {
-        croak "FATAL: " . join( ",", @_ ) . "\n";
-    } else {
-        die "FATAL: " . join( ",", @_ ) . "\n";
-    }
-}
-$SIG{__DIE__} = \&_die;
-
-sub usage {
-    my $script = (caller)[1];
-    my $function = shift if @_ and $_[0] =~ /^[\w-]+$/;
-    $function ||= ( ( ( caller(1) )[3] ) || ( ( caller(0) )[3] ) );
-    $function =~ s/.*:://;
-    my $code = slurp($script);
-    $code =~ /^=for $function\b(.*?)^=cut/sm;
-    say( $1 ? $1 : "...no usage message for '$function' in $script" );
-    exit 1;
-}
-
-sub _mkdir {
-    # It's not an error if the directory exists, but it is an error if it
-    # doesn't exist and we can't create it. This includes not guaranteeing
-    # dead symlinks or if mkpath traversal is blocked by a file.
-    my $dir  = shift;
-    my $perm = shift;    # optional
-    return if -d $dir;
-    mkpath($dir);
-    chmod $perm, $dir if $perm;
-    return 1;
-}
-
-sub _chdir {
-    chdir( $_[0] || $ENV{HOME} ) or _die "chdir $_[0] failed: $!\n";
-}
-
-sub _system {
-    # run system(), catch errors.  Be verbose only if $ENV{D} exists.  If not,
-    # exit with <rc of system()> if it applies, else just "exit 1".
-    trace( 1, 'system', @_ );
-    if ( system(@_) != 0 ) {
-        trace( 1, "system() failed", @_, "-> $?" );
-        if ( $? == -1 ) {
-            die "failed to execute: $!\n" if $ENV{D};
-        } elsif ( $? & 127 ) {
-            die "child died with signal " . ( $? & 127 ) . "\n" if $ENV{D};
-        } else {
-            die "child exited with value " . ( $? >> 8 ) . "\n" if $ENV{D};
-            exit( $? >> 8 );
-        }
-        exit 1;
-    }
-}
-
-sub _open {
-    open( my $fh, $_[0], $_[1] ) or _die "open $_[1] failed: $!\n";
-    return $fh;
-}
-
-sub _print {
-    my ( $file, @text ) = @_;
-    my $fh = _open( ">", "$file.$$" );
-    print $fh @text;
-    close($fh) or _die "close $file failed: $! at ", (caller)[1], " line ", (caller)[2], "\n";
-    my $oldmode = ( ( stat $file )[2] );
-    rename "$file.$$", $file;
-    chmod $oldmode, $file if $oldmode;
-}
-
-sub slurp {
-    return unless defined wantarray;
-    local $/ = undef unless wantarray;
-    my $fh = _open( "<", $_[0] );
-    return <$fh>;
-}
-
-sub dos2unix {
-    # WARNING: when calling this, make sure you supply a list context
-    s/\r\n/\n/g for @_;
-    return @_;
-}
-
-sub ln_sf {
-    trace( 3, @_ );
-    my ( $srcdir, $glob, $dstdir ) = @_;
-    for my $hook ( glob("$srcdir/$glob") ) {
-        $hook =~ s/$srcdir\///;
-        unlink "$dstdir/$hook";
-        symlink "$srcdir/$hook", "$dstdir/$hook" or croak "could not symlink $srcdir/$hook to $dstdir\n";
-    }
-}
-
-sub sort_u {
-    my %uniq;
-    my $listref = shift;
-    return [] unless @{$listref};
-    undef @uniq{ @{$listref} };    # expect a listref
-    my @sort_u = sort keys %uniq;
-    return \@sort_u;
-}
-
-sub cleanup_conf_line {
-    my $line = shift;
-    return $line if $line =~ /^# \S+ \d+$/;
-
-    # kill comments, but take care of "#" inside *simple* strings
-    $line =~ s/^((".*?"|[^#"])*)#.*/$1/;
-    # normalise whitespace; keeps later regexes very simple
-    $line =~ s/=/ = /;
-    $line =~ s/\s+/ /g;
-    $line =~ s/^ //;
-    $line =~ s/ $//;
-    return $line;
-}
-
-{
-    my @phy_repos = ();
-
-    sub list_phy_repos {
-        # use cached value only if it exists *and* no arg was received (i.e.,
-        # receiving *any* arg invalidates cache)
-        return \@phy_repos if ( @phy_repos and not @_ );
-
-        my $cmd = 'find . ' . ($Gitolite::Rc::rc{REPO_SYMLINKS} || '') . ' -name "*.git" -prune';
-        for my $repo (`$cmd`) {
-            chomp($repo);
-            $repo =~ s/\.git$//;
-            $repo =~ s(^\./)();
-            push @phy_repos, $repo;
-        }
-        trace( 3, scalar(@phy_repos) . " physical repos found" );
-        return sort_u( \@phy_repos );
-    }
-}
-
-# generate a timestamp
-sub gen_ts {
-    my ( $s, $min, $h, $d, $m, $y ) = (localtime)[ 0 .. 5 ];
-    $y += 1900; $m++;    # usual adjustments
-    for ( $s, $min, $h, $d, $m ) {
-        $_ = "0$_" if $_ < 10;
-    }
-    my $ts = "$y-$m-$d.$h:$min:$s";
-
-    return $ts;
-}
-
-# generate a log file name
-sub gen_lfn {
-    my ( $s, $min, $h, $d, $m, $y ) = (localtime)[ 0 .. 5 ];
-    $y += 1900; $m++;    # usual adjustments
-    for ( $s, $min, $h, $d, $m ) {
-        $_ = "0$_" if $_ < 10;
-    }
-
-    my ($template) = shift;
-    # substitute template parameters and set the logfile name
-    $template =~ s/%y/$y/g;
-    $template =~ s/%m/$m/g;
-    $template =~ s/%d/$d/g;
-
-    return $template;
-}
-
-my $log_dest;
-my $syslog_opened = 0;
-END { closelog() if $syslog_opened; }
-sub gl_log {
-    # the log filename and the timestamp come from the environment.  If we get
-    # called even before they are set, we have no choice but to dump to STDERR
-    # (and probably call "logger").
-
-    # tab sep if there's more than one field
-    my $msg = join( "\t", @_ );
-    $msg =~ s/[\n\r]+/<<newline>>/g;
-
-    my $ts = gen_ts();
-    my $tid = $ENV{GL_TID} ||= $$;
-
-    $log_dest = $Gitolite::Rc::rc{LOG_DEST} || '' if not defined $log_dest;
-
-    # log (update records only) to "gl-log" in the bare repo dir; this is to
-    # make 'who-pushed' more efficient.  Since this is only for the update
-    # records, it is not a replacement for the other two types of logging.
-    if ($log_dest =~ /repo-log/ and $_[0] eq 'update') {
-        # if the log line is 'update', we're already in the bare repo dir
-        open my $lfh, ">>", "gl-log" or _die "open gl-log failed: $!";
-        print $lfh "$ts\t$tid\t$msg\n";
-        close $lfh;
-    }
-
-    # syslog
-    if ($log_dest =~ /syslog/) {            # log_dest *includes* syslog
-        if ($syslog_opened == 0) {
-            require Sys::Syslog;
-            Sys::Syslog->import(qw(:standard));
-
-            openlog("gitolite" . ( $ENV{GL_TID} ? "[$ENV{GL_TID}]" : "" ), "pid", "local0");
-            $syslog_opened = 1;
-        }
-
-        # gl_log is called either directly, or, if the rc variable LOG_EXTRA
-        # is set, from trace(1, ...).  The latter use is considered additional
-        # info for troubleshooting.  Trace prefixes a tab to the arguments
-        # before calling gl_log, to visually set off such lines in the log
-        # file.  Although syslog eats up that leading tab, we use it to decide
-        # the priority/level of the syslog message.
-        syslog( ( $msg =~ /^\t/ ? 'debug' : 'info' ), "%s", $msg);
-
-        return if $log_dest !~ /normal/;
-    }
-
-    my $fh;
-    logger_plus_stderr( "errors found before logging could be setup", "$msg" ) if not $ENV{GL_LOGFILE};
-    open my $lfh, ">>", $ENV{GL_LOGFILE}
-      or logger_plus_stderr( "errors found but logfile could not be created", "$ENV{GL_LOGFILE}: $!", "$msg" );
-    print $lfh "$ts\t$tid\t$msg\n";
-    close $lfh;
-}
-
-sub logger_plus_stderr {
-    open my $fh, "|-", "logger" or confess "it's really not my day is it...?\n";
-    for (@_) {
-        print STDERR "FATAL: $_\n";
-        print $fh "FATAL: $_\n";
-    }
-    exit 1;
-}
-
-# ----------------------------------------------------------------------
-
-# bare-minimum subset of 'Tsh' (see github.com/sitaramc/tsh)
-{
-    my ( $rc, $text );
-    sub tsh_rc   { return $rc   || 0; }
-    sub tsh_text { return $text || ''; }
-    sub tsh_lines { return split /\n/, $text; }
-
-    sub tsh_try {
-        my $cmd = shift; die "try: expects only one argument" if @_;
-        $text = `( $cmd ) 2>&1; printf RC=\$?`;
-        if ( $text =~ s/RC=(\d+)$// ) {
-            $rc = $1;
-            trace( 3, $text );
-            return ( not $rc );
-        }
-        die "couldnt find RC= in result; this should not happen:\n$text\n\n...\n";
-    }
-
-    sub tsh_run {
-        open( my $fh, "-|", @_ ) or die "popen failed: $!";
-        local $/ = undef; $text = <$fh>;
-        close $fh; warn "pclose failed: $!" if $!;
-        $rc = ( $? >> 8 );
-        trace( 3, $text );
-        return $text;
-    }
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Conf.pm b/docker/gitolite/src/lib/Gitolite/Conf.pm
deleted file mode 100644
index ce7adca..0000000
--- a/docker/gitolite/src/lib/Gitolite/Conf.pm
+++ /dev/null
@@ -1,99 +0,0 @@
-package Gitolite::Conf;
-
-# explode/parse a conf file
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  compile
-  explode
-  parse
-);
-
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Sugar;
-use Gitolite::Conf::Store;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub compile {
-    _die "'gitolite compile' does not take any arguments" if @_;
-
-    _chdir( $rc{GL_ADMIN_BASE} );
-    _chdir("conf");
-
-    parse( sugar('gitolite.conf') );
-
-    # the order matters; new repos should be created first, to give store a
-    # place to put the individual gl-conf files
-    new_repos();
-
-    # cache control
-    if ($rc{CACHE}) {
-        require Gitolite::Cache;
-        Gitolite::Cache->import(qw(cache_control));
-
-        cache_control('stop');
-    }
-
-    store();
-
-    if ($rc{CACHE}) {
-        cache_control('start');
-    }
-
-    for my $repo ( @{ $rc{NEW_REPOS_CREATED} } ) {
-        trigger( 'POST_CREATE', $repo );
-    }
-}
-
-sub parse {
-    my $lines = shift;
-    trace( 3, scalar(@$lines) . " lines incoming" );
-
-    my ( $fname, $lnum );
-    for my $line (@$lines) {
-        ( $fname, $lnum ) = ( $1, $2 ), next if $line =~ /^# (\S+) (\d+)$/;
-        # user or repo groups
-        if ( $line =~ /^(@\S+) = (.*)/ ) {
-            add_to_group( $1, split( ' ', $2 ) );
-        } elsif ( $line =~ /^repo (.*)/ ) {
-            set_repolist( split( ' ', $1 ) );
-        } elsif ( $line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/ ) {
-            my $perm  = $1;
-            my @refs  = parse_refs( $2 || '' );
-            my @users = parse_users($3);
-
-            for my $ref (@refs) {
-                for my $user (@users) {
-                    add_rule( $perm, $ref, $user, $fname, $lnum );
-                }
-            }
-        } elsif ( $line =~ /^config (.+) = ?(.*)/ ) {
-            my ( $key, $value ) = ( $1, $2 );
-            $value =~ s/^['"](.*)["']$/$1/;
-            my @validkeys = split( ' ', ( $rc{GIT_CONFIG_KEYS} || '' ) );
-            push @validkeys, "gitolite-options\\..*";
-            my @matched = grep { $key =~ /^$_$/i } @validkeys;
-            _die "git config '$key' not allowed\ncheck GIT_CONFIG_KEYS in the rc file" if ( @matched < 1 );
-            _die "bad config value '$value'" if $value =~ $UNSAFE_PATT;
-            while ( my ( $mk, $mv ) = each %{ $rc{SAFE_CONFIG} } ) {
-                $value =~ s/%$mk/$mv/g;
-            }
-            add_config( 1, $key, $value );
-        } elsif ( $line =~ /^subconf (\S+)$/ ) {
-            trace( 3, $line );
-            set_subconf($1);
-        } else {
-            _warn "syntax error, ignoring: '$line'";
-        }
-    }
-    parse_done();
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Conf/Explode.pm b/docker/gitolite/src/lib/Gitolite/Conf/Explode.pm
deleted file mode 100644
index cf89620..0000000
--- a/docker/gitolite/src/lib/Gitolite/Conf/Explode.pm
+++ /dev/null
@@ -1,118 +0,0 @@
-package Gitolite::Conf::Explode;
-
-# include/subconf processor
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  explode
-);
-
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-# 'seen' for include/subconf files
-my %included = ();
-# 'seen' for group names on LHS
-my %prefixed_groupname = ();
-
-sub explode {
-    trace( 3, @_ );
-    my ( $file, $subconf, $out ) = @_;
-
-    # seed the 'seen' list if it's empty
-    $included{ device_inode("gitolite.conf") }++ unless %included;
-
-    my $fh = _open( "<", $file );
-    while (<$fh>) {
-        my $line = cleanup_conf_line($_);
-        next unless $line =~ /\S/;
-
-        # subst %HOSTNAME word if rc defines a hostname, else leave as is
-        $line =~ s/%HOSTNAME\b/$rc{HOSTNAME}/g if $rc{HOSTNAME};
-
-        $line = prefix_groupnames( $line, $subconf ) if $subconf ne 'master';
-
-        if ( $line =~ /^(include|subconf) (?:(\S+) )?(\S.+)$/ ) {
-            incsub( $1, $2, $3, $subconf, $out );
-        } else {
-            # normal line, send it to the callback function
-            push @{$out}, "# $file $.";
-            push @{$out}, $line;
-        }
-    }
-}
-
-sub incsub {
-    my $is_subconf = ( +shift eq 'subconf' );
-    my ( $new_subconf, $include_glob, $current_subconf, $out ) = @_;
-
-    _die "subconf '$current_subconf' attempting to run 'subconf'\n" if $is_subconf and $current_subconf ne 'master';
-
-    _die "invalid include/subconf file/glob '$include_glob'"
-      unless $include_glob =~ /^"(.+)"$/
-      or $include_glob =~ /^'(.+)'$/;
-    $include_glob = $1;
-
-    trace( 3, $is_subconf, $include_glob );
-
-    for my $file ( glob($include_glob) ) {
-        _warn("included file not found: '$file'"), next unless -f $file;
-        _die "invalid include/subconf filename '$file'" unless $file =~ m(([^/]+).conf$);
-        my $basename = $1;
-
-        next if already_included($file);
-
-        if ($is_subconf) {
-            push @{$out}, "subconf " . ( $new_subconf || $basename );
-            explode( $file, ( $new_subconf || $basename ), $out );
-            push @{$out}, "subconf $current_subconf";
-        } else {
-            explode( $file, $current_subconf, $out );
-        }
-    }
-}
-
-sub prefix_groupnames {
-    my ( $line, $subconf ) = @_;
-
-    my $lhs = '';
-    # save 'foo' if it's an '@foo = list' line
-    $lhs = $1 if $line =~ /^@(\S+) = /;
-    # prefix all @groups in the line
-    $line =~ s/(^| )(@\S+)(?= |$)/ $1 . ($prefixed_groupname{$subconf}{$2} || $2) /ge;
-    # now prefix the LHS and store it if needed
-    if ($lhs) {
-        $line =~ s/^@\S+ = /"\@$subconf.$lhs = "/e;
-        $prefixed_groupname{$subconf}{"\@$lhs"} = "\@$subconf.$lhs";
-        trace( 3, "prefixed_groupname.$subconf.\@$lhs = \@$subconf.$lhs" );
-    }
-
-    return $line;
-}
-
-sub already_included {
-    my $file = shift;
-
-    my $file_id = device_inode($file);
-    return 0 unless $included{$file_id}++;
-
-    _warn("$file already included");
-    trace( 3, "$file already included" );
-    return 1;
-}
-
-sub device_inode {
-    my $file = shift;
-    trace( 3, $file, ( stat $file )[ 0, 1 ] );
-    return join( "/", ( stat $file )[ 0, 1 ] );
-}
-
-1;
-
diff --git a/docker/gitolite/src/lib/Gitolite/Conf/Load.pm b/docker/gitolite/src/lib/Gitolite/Conf/Load.pm
deleted file mode 100644
index 7728a5a..0000000
--- a/docker/gitolite/src/lib/Gitolite/Conf/Load.pm
+++ /dev/null
@@ -1,676 +0,0 @@
-package Gitolite::Conf::Load;
-
-# load conf data from stored files
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  load
-
-  access
-  git_config
-  env_options
-
-  option
-  repo_missing
-  creator
-
-  vrefs
-  lister_dispatch
-);
-
-use Exporter 'import';
-use Cwd;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-# our variables, because they get loaded by a 'do'
-our $data_version = '';
-our %repos;
-our %one_repo;
-our %groups;
-our %patterns;
-our %configs;
-our %one_config;
-our %split_conf;
-
-my $subconf = 'master';
-
-my %listers = (
-    'list-groups'      => \&list_groups,
-    'list-users'       => \&list_users,
-    'list-repos'       => \&list_repos,
-    'list-memberships' => \&list_memberships,
-    'list-members'     => \&list_members,
-);
-
-# helps maintain the "cache" in both "load_common" and "load_1"
-my $last_repo = '';
-
-# ----------------------------------------------------------------------
-
-{
-    my $loaded_repo = '';
-
-    sub load {
-        my $repo = shift or _die "load() needs a reponame";
-        trace( 3, "$repo" );
-        if ( $repo ne $loaded_repo ) {
-            load_common();
-            load_1($repo);
-            $loaded_repo = $repo;
-        }
-    }
-}
-
-sub access {
-    my ( $repo, $user, $aa, $ref ) = @_;
-    trace( 2, $repo, $user, $aa, $ref );
-    _die "invalid user '$user'" if not( $user and $user =~ $USERNAME_PATT );
-    sanity($repo);
-
-    my @rules;
-    my $deny_rules;
-
-    load($repo);
-    @rules = rules( $repo, $user );
-    $deny_rules = option( $repo, 'deny-rules' );
-
-    # sanity check the only piece the user can control
-    _die "invalid characters in ref or filename: '$ref'\n" unless $ref =~ m(^VREF/NAME/) or $ref =~ $REF_OR_FILENAME_PATT;
-    # apparently we can't always force sanity; at least what we *return*
-    # should be sane/safe.  This pattern is based on REF_OR_FILENAME_PATT.
-    ( my $safe_ref = $ref ) =~ s([^-0-9a-zA-Z._\@/+ :,])(.)g;
-    trace( 3, "safe_ref", $safe_ref ) if $ref ne $safe_ref;
-
-    # when a real repo doesn't exist, ^C is a pre-requisite for any other
-    # check to give valid results.
-    if ( $aa ne '^C' and $repo !~ /^\@/ and $repo =~ $REPONAME_PATT and repo_missing($repo) ) {
-        my $iret = access( $repo, $user, '^C', $ref );
-        $iret =~ s/\^C/$aa/;
-        return $iret if $iret =~ /DENIED/;
-    }
-    # similarly, ^C must be denied if the repo exists
-    if ( $aa eq '^C' and not repo_missing($repo) ) {
-        trace( 2, "DENIED by existence" );
-        return "$aa $safe_ref $repo $user DENIED by existence";
-    }
-
-    trace( 3, scalar(@rules) . " rules found" );
-
-    $rc{RULE_TRACE} = '';
-    for my $r (@rules) {
-        $rc{RULE_TRACE} .= " " . $r->[0] . " ";
-
-        my $perm = $r->[1];
-        my $refex = $r->[2]; $refex =~ s(/USER/)(/$user/);
-        trace( 3, "perm=$perm, refex=$refex" );
-
-        $rc{RULE_TRACE} .= "d";
-        # skip 'deny' rules if the ref is not (yet) known
-        next if $perm eq '-' and $ref eq 'any' and not $deny_rules;
-
-        $rc{RULE_TRACE} .= "r";
-        # rule matches if ref matches or ref is any (see gitolite-shell)
-        next unless $ref =~ /^$refex/ or $ref eq 'any';
-
-        $rc{RULE_TRACE} .= "D";
-        trace( 2, "DENIED by $refex" ) if $perm eq '-';
-        return "$aa $safe_ref $repo $user DENIED by $refex" if $perm eq '-';
-
-        # For repo creation, perm will be C and aa will be "^C".  For branch
-        # access, $perm can be RW\+?(C|D|CD|DC)?M?, and $aa can be W, +, C or
-        # D, or any of these followed by "M".
-
-        # We need to turn $aa into a regex that can match a suitable $perm.
-        # This is trivially true for "^C", "W" and "D", but the others (+, C,
-        # M) need some tweaking.
-
-        # first, quote the '+':
-        ( my $aaq = $aa ) =~ s/\+/\\+/;
-        # if aa is just "C", the user is trying to create a *branch* (not a
-        # *repo*), so let's make the pattern clearer to reflect that.
-        $aaq = "RW.*C" if $aaq eq "C";
-        # if the aa is, say "WM", make this "W.*M" because the perm could be
-        # 'RW+M', 'RW+CDM' etc, and they are all valid:
-        $aaq =~ s/M/.*M/;
-
-        $rc{RULE_TRACE} .= "A";
-
-        # as far as *this* ref is concerned we're ok
-        return $refex if ( $perm =~ /$aaq/ );
-
-        $rc{RULE_TRACE} .= "p";
-    }
-    $rc{RULE_TRACE} .= " F";
-
-    trace( 2, "DENIED by fallthru" );
-    return "$aa $safe_ref $repo $user DENIED by fallthru";
-}
-
-# cache control
-if ($rc{CACHE}) {
-    require Gitolite::Cache;
-    Gitolite::Cache::cache_wrap('Gitolite::Conf::Load::access');
-}
-
-sub git_config {
-    my ( $repo, $key, $empty_values_OK ) = @_;
-    $key ||= '.';
-
-    if ( repo_missing($repo) ) {
-        load_common();
-    } else {
-        load($repo);
-    }
-
-    # read comments bottom up
-    my %ret =
-      # and take the second and third elements to make up your new hash
-      map { $_->[1] => $_->[2] }
-      # keep only the ones where the second element matches your key
-      grep { $_->[1] =~ qr($key) }
-      # sort this list of listrefs by the first element in each list ref'd to
-      sort { $a->[0] <=> $b->[0] }
-      # dereference it (into a list of listrefs)
-      map { @$_ }
-      # take the value of that entry
-      map { $configs{$_} }
-      # if it has an entry in %configs
-      grep { $configs{$_} }
-      # for each "repo" that represents us
-      memberships( 'repo', $repo );
-
-    # %configs looks like this (for each 'foo' that is in memberships())
-    # 'foo' => [ [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ], [ 8, 'foo.czar', 'jule' ] ],
-    # the first map gets you the value
-    #          [ [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ], [ 8, 'foo.czar', 'jule' ] ],
-    # the deref gets you
-    #            [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ], [ 8, 'foo.czar', 'jule' ]
-    # the sort rearranges it (in this case it's already sorted but anyway...)
-    # the grep gets you this, assuming the key is foo.bar (and "." is regex ".')
-    #            [ 6, 'foo.bar', 'repo' ], [ 7, 'foodbar', 'repoD' ]
-    # and the final map does this:
-    #                 'foo.bar'=>'repo'  ,      'foodbar'=>'repoD'
-
-    # now some of these will have an empty key; we need to delete them unless
-    # we're told empty values are OK
-    unless ($empty_values_OK) {
-        my ( $k, $v );
-        while ( ( $k, $v ) = each %ret ) {
-            delete $ret{$k} if not $v;
-        }
-    }
-
-    my ( $k, $v );
-    my $creator = creator($repo);
-    while ( ( $k, $v ) = each %ret ) {
-        $v =~ s/%GL_REPO/$repo/g;
-        $v =~ s/%GL_CREATOR/$creator/g if $creator;
-        $ret{$k} = $v;
-    }
-
-    map { trace( 3, "$_", "$ret{$_}" ) } ( sort keys %ret ) if $ENV{D};
-    return \%ret;
-}
-
-sub env_options {
-    return unless -f "$rc{GL_ADMIN_BASE}/conf/gitolite.conf-compiled.pm";
-    # prevent catch-22 during initial install
-
-    my $cwd = getcwd();
-
-    my $repo = shift;
-    map { delete $ENV{$_} } grep { /^GL_OPTION_/ } keys %ENV;
-    my $h = git_config( $repo, '^gitolite-options.ENV\.' );
-    while ( my ( $k, $v ) = each %$h ) {
-        next unless $k =~ /^gitolite-options.ENV\.(\w+)$/;
-        $ENV{ "GL_OPTION_" . $1 } = $v;
-    }
-
-    chdir($cwd);
-}
-
-sub option {
-    my ( $repo, $option ) = @_;
-    $option = "gitolite-options.$option";
-    my $ret = git_config( $repo, "^\Q$option\E\$" );
-    return '' unless %$ret;
-    return $ret->{$option};
-}
-
-sub sanity {
-    my ($repo, $patt) = @_;
-    $patt ||= $REPOPATT_PATT;
-
-    _die "invalid repo '$repo'" if not( $repo and $repo =~ $patt );
-    _die "'$repo' ends with a '/'"  if $repo =~ m(/$);
-    _die "'$repo' contains '..'"    if $repo =~ $REPONAME_PATT and $repo =~ m(\.\.);
-    _die "'$repo' contains '.git/'" if $repo =~ $REPONAME_PATT and $repo =~ m(\.git/);
-}
-
-sub repo_missing {
-    my $repo = shift;
-    sanity($repo);
-
-    return not -d "$rc{GL_REPO_BASE}/$repo.git";
-}
-
-# ----------------------------------------------------------------------
-
-sub load_common {
-
-    _chdir( $rc{GL_ADMIN_BASE} );
-
-    # we take an unusual approach to caching this function!
-    # (requires that first call to load_common is before first call to load_1)
-    if ( $last_repo and $split_conf{$last_repo} ) {
-        delete $repos{$last_repo};
-        delete $configs{$last_repo};
-        return;
-    }
-
-    my $cc = "conf/gitolite.conf-compiled.pm";
-
-    _die "parse '$cc' failed: " . ( $! or $@ ) unless do $cc;
-
-    if ( data_version_mismatch() ) {
-        _system("gitolite setup");
-        _die "parse '$cc' failed: " . ( $! or $@ ) unless do $cc;
-        _die "data version update failed; this is serious" if data_version_mismatch();
-    }
-}
-
-sub load_1 {
-    my $repo = shift;
-    return if $repo =~ /^\@/;
-    trace( 3, $repo );
-
-    if ( repo_missing($repo) ) {
-        trace( 1, "repo '$repo' missing" ) if $repo =~ $REPONAME_PATT;
-        return;
-    }
-    _chdir("$rc{GL_REPO_BASE}/$repo.git");
-
-    if ( $repo eq $last_repo ) {
-        $repos{$repo} = $one_repo{$repo};
-        $configs{$repo} = $one_config{$repo} if $one_config{$repo};
-        return;
-    }
-
-    if ( -f "gl-conf" ) {
-        return if not $split_conf{$repo};
-
-        my $cc = "./gl-conf";
-        _die "parse '$cc' failed: " . ( $! or $@ ) unless do $cc;
-
-        $last_repo = $repo;
-        $repos{$repo} = $one_repo{$repo};
-        $configs{$repo} = $one_config{$repo} if $one_config{$repo};
-    } else {
-        _die "split conf set, gl-conf not present for '$repo'" if $split_conf{$repo};
-    }
-}
-
-{
-    my $lastrepo = '';
-    my $lastuser = '';
-    my @cached   = ();
-
-    sub rules {
-        my ( $repo, $user ) = @_;
-        trace( 3, $repo, $user );
-
-        return @cached if ( $lastrepo eq $repo and $lastuser eq $user and @cached );
-
-        my @rules = ();
-
-        my @repos = memberships( 'repo', $repo );
-        my @users = memberships( 'user', $user, $repo );
-        trace( 3, "memberships: " . scalar(@repos) . " repos and " . scalar(@users) . " users found" );
-
-        for my $r (@repos) {
-            for my $u (@users) {
-                push @rules, @{ $repos{$r}{$u} } if exists $repos{$r} and exists $repos{$r}{$u};
-            }
-        }
-
-        @rules = sort { $a->[0] <=> $b->[0] } @rules;
-
-        $lastrepo = $repo;
-        $lastuser = $user;
-        @cached   = @rules;
-
-        # however if the repo was missing, invalidate the cache
-        $lastrepo = '' if repo_missing($repo);
-
-        return @rules;
-    }
-
-    sub vrefs {
-        my ( $repo, $user ) = @_;
-        # fill the cache if needed
-        rules( $repo, $user ) unless ( $lastrepo eq $repo and $lastuser eq $user and @cached );
-
-        my %seen;
-        my @vrefs = grep { /^VREF\// and not $seen{$_}++ } map { $_->[2] } @cached;
-        return @vrefs;
-    }
-}
-
-sub memberships {
-    trace( 3, @_ );
-    my ( $type, $base, $repo ) = @_;
-    $repo ||= '';
-    my @ret;
-    my $base2 = '';
-
-    @ret = ( $base, '@all' );
-
-    if ( $type eq 'repo' ) {
-        # first, if a repo, say, pub/sitaram/project, has a gl-creator file
-        # that says "sitaram", find memberships for pub/CREATOR/project also
-        $base2 = generic_name($base);
-
-        # second, you need to check in %repos also
-        for my $i ( keys %repos, keys %configs ) {
-            if ( $base eq $i or $base =~ /^$i$/ or $base2 and ( $base2 eq $i or $base2 =~ /^$i$/ ) ) {
-                push @ret, $i;
-            }
-        }
-    }
-
-    push @ret, @{ $groups{$base} } if exists $groups{$base};
-    push @ret, @{ $groups{$base2} } if $base2 and exists $groups{$base2};
-    for my $i ( keys %{ $patterns{groups} } ) {
-        if ( $base =~ /^$i$/ or $base2 and ( $base2 =~ /^$i$/ ) ) {
-            push @ret, @{ $groups{$i} };
-        }
-    }
-
-    push @ret, @{ ext_grouplist($base) } if $type eq 'user' and $rc{GROUPLIST_PGM};
-
-    if ( $type eq 'user' and $repo and not repo_missing($repo) ) {
-        # find the roles this user has when accessing this repo and add those
-        # in as groupnames he is a member of.  You need the already existing
-        # memberships for this; see below this function for an example
-        push @ret, user_roles( $base, $repo, @ret );
-    }
-
-    @ret = @{ sort_u( \@ret ) };
-    trace( 3, sort @ret );
-    return @ret;
-}
-
-=for example
-
-conf/gitolite.conf:
-    @g1 = u1
-    @g2 = u1
-    # now user is a member of both g1 and g2
-
-gl-perms for repo being accessed:
-    READERS @g1
-
-This should result in @READERS being added to the memberships that u1 has
-(when accessing this repo).  So we send the current list (@g1, @g2) to
-user_roles(), otherwise it has to redo that logic.
-
-=cut
-
-sub data_version_mismatch {
-    return $data_version ne glrc('current-data-version');
-}
-
-sub user_roles {
-    my ( $user, $repo, @eg ) = @_;
-
-    # eg == existing groups (that user is already known to be a member of)
-    my %eg = map { $_ => 1 } @eg;
-
-    my %ret   = ();
-    my $f     = "$rc{GL_REPO_BASE}/$repo.git/gl-perms";
-    my @roles = ();
-    if ( -f $f ) {
-        my $fh = _open( "<", $f );
-        chomp( @roles = <$fh> );
-    }
-    push @roles, "CREATOR = " . creator($repo);
-    for (@roles) {
-        # READERS u3 u4 @g1
-        s/^\s+//; s/ +$//; s/=/ /; s/\s+/ /g; s/^\@//;
-        next if /^#/;
-        next unless /\S/;
-        my ( $role, @members ) = split;
-        # role = READERS, members = u3, u4, @g1
-        if ( $role ne 'CREATOR' and not $rc{ROLES}{$role} ) {
-            _warn "role '$role' not allowed, ignoring";
-            next;
-        }
-        for my $m (@members) {
-            if ( $m !~ $USERNAME_PATT ) {
-                _warn "ignoring '$m' in perms line";
-                next;
-            }
-            # if user eq u3/u4, or is a member of @g1, he has role READERS
-            $ret{ '@' . $role } = 1 if $m eq $user or $eg{$m};
-        }
-    }
-
-    return keys %ret;
-}
-
-sub generic_name {
-    my $base  = shift;
-    my $base2 = '';
-    my $creator;
-
-    # get the creator name.  For not-yet-born repos this is $ENV{GL_USER},
-    # which should be set in all cases that we care about, viz., where we are
-    # checking ^C permissions before new_wild_repo(), and the info command.
-    # In particular, 'gitolite access' can't be used to check ^C perms on wild
-    # repos that contain "CREATOR" if GL_USER is not set.
-    $creator = creator($base);
-
-    $base2 = $base;
-    $base2 =~ s(\b$creator\b)(CREATOR) if $creator;
-    $base2 = '' if $base2 eq $base;    # if there was no change
-
-    return $base2;
-}
-
-sub creator {
-    my $repo = shift;
-    sanity($repo);
-
-    return ( $ENV{GL_USER} || '' ) if repo_missing($repo);
-    my $f       = "$rc{GL_REPO_BASE}/$repo.git/gl-creator";
-    my $creator = '';
-    chomp( $creator = slurp($f) ) if -f $f;
-    return $creator;
-}
-
-{
-    my %cache = ();
-
-    sub ext_grouplist {
-        my $user = shift;
-        my $pgm  = $rc{GROUPLIST_PGM};
-        return [] if not $pgm;
-
-        return $cache{$user} if $cache{$user};
-        my @extgroups = map { s/^@?/@/; $_; } split ' ', `$rc{GROUPLIST_PGM} $user`;
-        return ( $cache{$user} = \@extgroups );
-    }
-}
-
-# ----------------------------------------------------------------------
-# api functions
-# ----------------------------------------------------------------------
-
-sub lister_dispatch {
-    my $command = shift;
-
-    my $fn = $listers{$command} or _die "unknown gitolite sub-command";
-    return $fn;
-}
-
-=for list_groups
-Usage:  gitolite list-groups
-
-  - lists all group names in conf
-  - no options, no flags
-=cut
-
-sub list_groups {
-    usage() if @_;
-
-    load_common();
-
-    my @g = ();
-    while ( my ( $k, $v ) = each(%groups) ) {
-        push @g, @{$v};
-    }
-    return ( sort_u( \@g ) );
-}
-
-=for list_users
-Usage:  gitolite list-users [<repo name pattern>]
-
-List all users and groups explicitly named in a rule.  User names not
-mentioned in an access rule will not show up; you have to run 'list-members'
-on each group name yourself to see them.
-
-WARNING: may be slow if you have thousands of repos.  The optional repo name
-pattern is an unanchored regex; it can speed things up if you're interested
-only in users of a matching set of repos.  This is only an optimisation, not
-an actual access list; you will still have to pipe it to 'gitolite access'
-with appropriate arguments to get an actual access list.
-=cut
-
-sub list_users {
-    my $patt = shift || '.';
-    usage() if $patt eq '-h' or @_;
-    my $count = 0;
-    my $total = 0;
-
-    load_common();
-
-    my @u = map { keys %{$_} } values %repos;
-    $total = scalar( grep { /$patt/ } keys %split_conf );
-    warn "WARNING: you have $total repos to check; this could take some time!\n" if $total > 100;
-    for my $one ( grep { /$patt/ } keys %split_conf ) {
-        load_1($one);
-        $count++; print STDERR "$count / $total\r" if not( $count % 100 ) and timer(5);
-        push @u, map { keys %{$_} } values %one_repo;
-    }
-    print STDERR "\n" if $count >= 100;
-    return ( sort_u( \@u ) );
-}
-
-=for list_repos
-Usage:  gitolite list-repos
-
-  - lists all repos/repo groups in conf
-  - no options, no flags
-=cut
-
-sub list_repos {
-    usage() if @_;
-
-    load_common();
-
-    my @r = keys %repos;
-    push @r, keys %split_conf;
-
-    return ( sort_u( \@r ) );
-}
-
-=for list_memberships
-Usage:  gitolite list-memberships -u|-r <name>
-
-List all groups a name is a member of.  One of the flags '-u' or '-r' is
-mandatory, to specify if the name is a user or a repo.
-
-For users, the output includes the result from GROUPLIST_PGM, if it is
-defined.  For repos, the output includes any repo patterns that the repo name
-matches, as well as any groups that contain those patterns.
-=cut
-
-sub list_memberships {
-    require Getopt::Long;
-
-    my ( $user, $repo, $help );
-
-    Getopt::Long::GetOptionsFromArray(
-        \@_,
-        'user|u=s' => \$user,
-        'repo|r=s' => \$repo,
-        'help|h'   => \$help,
-    );
-    usage() if $help or ( not $user and not $repo );
-
-    load_common();
-    my @m;
-
-    if ( $user and $repo ) {
-        # unsupported/undocumented except via "in_role()" in Easy.pm
-        @m = memberships( 'user', $user, $repo );
-    } elsif ($user) {
-        @m = memberships( 'user', $user );
-    } elsif ($repo) {
-        @m = memberships( 'repo', $repo );
-    }
-
-    @m = grep { $_ ne '@all' and $_ ne ( $user || $repo ) } @m;
-    return ( sort_u( \@m ) );
-}
-
-=for list_members
-Usage:  gitolite list-members <group name>
-
-  - list all members of a group
-  - takes one group name
-=cut
-
-sub list_members {
-    usage() if @_ and $_[0] eq '-h' or not @_;
-
-    my $name = shift;
-
-    load_common();
-
-    my @m = ();
-    while ( my ( $k, $v ) = each(%groups) ) {
-        for my $g ( @{$v} ) {
-            push @m, $k if $g eq $name;
-        }
-    }
-
-    return ( sort_u( \@m ) );
-}
-
-# ----------------------------------------------------------------------
-
-{
-    my $start_time = 0;
-
-    sub timer {
-        unless ($start_time) {
-            $start_time = time();
-            return 0;
-        }
-        my $elapsed = shift;
-        return 0 if time() - $start_time < $elapsed;
-        $start_time = time();
-        return 1;
-    }
-}
-
-1;
-
diff --git a/docker/gitolite/src/lib/Gitolite/Conf/Store.pm b/docker/gitolite/src/lib/Gitolite/Conf/Store.pm
deleted file mode 100644
index 5568b3f..0000000
--- a/docker/gitolite/src/lib/Gitolite/Conf/Store.pm
+++ /dev/null
@@ -1,408 +0,0 @@
-package Gitolite::Conf::Store;
-
-# receive parsed conf data and store it
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  add_to_group
-  set_repolist
-  parse_refs
-  parse_users
-  add_rule
-  add_config
-  set_subconf
-
-  expand_list
-  new_repos
-  new_repo
-  new_wild_repo
-  hook_repos
-  store
-  parse_done
-);
-
-use Exporter 'import';
-use Data::Dumper;
-$Data::Dumper::Indent   = 1;
-$Data::Dumper::Sortkeys = 1;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Hooks::Update;
-use Gitolite::Hooks::PostUpdate;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-my %repos;
-my %groups;
-my %configs;
-my %split_conf;
-
-my @repolist;    # current repo list; reset on each 'repo ...' line
-my $subconf = 'master';
-my $nextseq = 0;
-my %ignored;
-
-# ----------------------------------------------------------------------
-
-sub add_to_group {
-    my ( $lhs, @rhs ) = @_;
-    _die "bad group '$lhs'" unless $lhs =~ $REPONAME_PATT;
-    map { _die "bad expansion '$_'" unless $_ =~ $REPOPATT_PATT } @rhs;
-
-    # store the group association, but overload it to keep track of when
-    # the group was *first* created by using $subconf as the *value*
-    do { $groups{$lhs}{$_} ||= $subconf }
-      for ( expand_list(@rhs) );
-
-    # create the group hash even if empty
-    $groups{$lhs} = {} unless $groups{$lhs};
-}
-
-sub set_repolist {
-    my @in = @_;
-    @repolist = ();
-    # ...sanity checks
-    while (@in) {
-        $_ = shift @in;
-        if ( check_subconf_repo_disallowed( $subconf, $_ ) ) {
-            if ( exists $groups{$_} ) {
-                # groupname disallowed; try individual members now
-                ( my $g = $_ ) =~ s/^\@$subconf\./\@/;
-                _warn "expanding '$g'; this *may* slow down compilation";
-                unshift @in, keys %{ $groups{$_} };
-                next;
-            }
-            $ignored{$subconf}{$_} = 1;
-            next;
-        }
-
-        _warn "explicit '.git' extension ignored for $_.git" if s/\.git$//;
-        _die "bad reponame '$_'" if $_ !~ $REPOPATT_PATT;
-
-        push @repolist, $_;
-    }
-}
-
-sub parse_refs {
-    my $refs = shift;
-    my @refs; @refs = split( ' ', $refs ) if $refs;
-    @refs = expand_list(@refs);
-
-    # if no ref is given, this PERM applies to all refs
-    @refs = qw(refs/.*) unless @refs;
-
-    # fully qualify refs that dont start with "refs/" or "VREF/";
-    # prefix them with "refs/heads/"
-    @refs = map { m(^(refs|VREF)/) or s(^)(refs/heads/); $_ } @refs;
-
-    return @refs;
-}
-
-sub parse_users {
-    my $users = shift;
-    my @users = split ' ', $users;
-    do { _die "bad username '$_'" unless $_ =~ $USERNAME_PATT }
-      for @users;
-
-    return @users;
-}
-
-sub add_rule {
-    my ( $perm, $ref, $user, $fname, $lnum ) = @_;
-    _warn "doesn't make sense to supply a ref ('$ref') for 'R' rule"
-      if $perm eq 'R' and $ref ne 'refs/.*';
-    _warn "possible undeclared group '$user'"
-      if $user =~ /^@/
-      and not $groups{$user}
-      and not $rc{GROUPLIST_PGM}
-      and not special_group($user);
-    _die "bad ref '$ref'"   unless $ref =~ $REPOPATT_PATT;
-    _die "bad user '$user'" unless $user =~ $USERNAME_PATT;
-
-    $nextseq++;
-    store_rule_info( $nextseq, $fname, $lnum );
-    for my $repo (@repolist) {
-        push @{ $repos{$repo}{$user} }, [ $nextseq, $perm, $ref ];
-    }
-
-    sub special_group {
-        # ok perl doesn't really have lexical subs (at least not the older
-        # perls I want to support) but let's pretend...
-        my $g = shift;
-        $g =~ s/^\@//;
-        return 1 if $g eq 'all' or $g eq 'CREATOR';
-        return 1 if $rc{ROLES}{$g};
-        return 0;
-    }
-
-}
-
-sub add_config {
-    my ( $n, $key, $value ) = @_;
-
-    $nextseq++;
-    for my $repo (@repolist) {
-        push @{ $configs{$repo} }, [ $nextseq, $key, $value ];
-    }
-}
-
-sub set_subconf {
-    $subconf = shift;
-    _die "bad subconf '$subconf'" unless $subconf =~ /^[-\w.]+$/;
-}
-
-# ----------------------------------------------------------------------
-
-sub expand_list {
-    my @list     = @_;
-    my @new_list = ();
-
-    for my $item (@list) {
-        if ( $item =~ /^@/ and $item ne '@all' )    # nested group
-        {
-            _die "undefined group '$item'" unless $groups{$item};
-            # add those names to the list
-            push @new_list, sort keys %{ $groups{$item} };
-        } else {
-            push @new_list, $item;
-        }
-    }
-
-    return @new_list;
-}
-
-sub new_repos {
-    trace(3);
-    _chdir( $rc{GL_REPO_BASE} );
-
-    # normal repos
-    my @repos = grep { $_ =~ $REPONAME_PATT and not /^@/ } ( sort keys %repos, sort keys %configs );
-    # add in members of repo groups
-    map { push @repos, keys %{ $groups{$_} } } grep { /^@/ and $_ ne '@all' } keys %repos;
-
-    for my $repo ( @{ sort_u( \@repos ) } ) {
-        next unless $repo =~ $REPONAME_PATT;    # skip repo patterns
-        next if $repo =~ m(^\@|EXTCMD/);        # skip groups and fake repos
-
-        # use gl-conf as a sentinel
-        hook_1($repo) if -d "$repo.git" and not -f "$repo.git/gl-conf";
-
-        if ( not -d "$repo.git" ) {
-            push @{ $rc{NEW_REPOS_CREATED} }, $repo;
-            trigger( 'PRE_CREATE', $repo );
-            new_repo($repo);
-        }
-    }
-}
-
-sub new_repo {
-    my $repo = shift;
-    trace( 3, $repo );
-
-    _mkdir("$repo.git");
-    _chdir("$repo.git");
-    _system("git init --bare >&2");
-    _chdir( $rc{GL_REPO_BASE} );
-    hook_1($repo);
-}
-
-sub new_wild_repo {
-    my ( $repo, $user, $aa ) = @_;
-    _chdir( $rc{GL_REPO_BASE} );
-
-    trigger( 'PRE_CREATE', $repo, $user, $aa );
-    new_repo($repo);
-    _print( "$repo.git/gl-creator", $user );
-    trigger( 'POST_CREATE', $repo, $user, $aa );
-
-    _chdir( $rc{GL_ADMIN_BASE} );
-}
-
-sub hook_repos {
-    trace(3);
-
-    # all repos, all hooks
-    _chdir( $rc{GL_REPO_BASE} );
-    my $phy_repos = list_phy_repos(1);
-
-    for my $repo ( @{$phy_repos} ) {
-        hook_1($repo);
-    }
-}
-
-sub store {
-    trace(3);
-
-    # first write out the ones for the physical repos
-    _chdir( $rc{GL_REPO_BASE} );
-    my $phy_repos = list_phy_repos(1);
-
-    for my $repo ( @{$phy_repos} ) {
-        store_1($repo);
-    }
-
-    _chdir( $rc{GL_ADMIN_BASE} );
-    store_common();
-}
-
-sub parse_done {
-    for my $ig ( sort keys %ignored ) {
-        _warn "subconf '$ig' attempting to set access for " . join( ", ", sort keys %{ $ignored{$ig} } );
-    }
-
-    close_rule_info();
-}
-
-# ----------------------------------------------------------------------
-
-sub check_subconf_repo_disallowed {
-    # trying to set access for $repo (='foo')...
-    my ( $subconf, $repo ) = @_;
-    trace( 2, $subconf, $repo );
-
-    # processing the master config, not a subconf
-    return 0 if $subconf eq 'master';
-    # subconf is also called 'foo' (you're allowed to have a
-    # subconf that is only concerned with one repo)
-    return 0 if $subconf eq $repo;
-    # same thing in big-config-land; foo is just @foo now
-    return 0 if ( "\@$subconf" eq $repo );
-    my @matched = grep { $repo =~ /^$_$/ }
-      grep { $groups{"\@$subconf"}{$_} eq 'master' }
-      sort keys %{ $groups{"\@$subconf"} };
-    return 0 if @matched > 0;
-
-    trace( 2, "-> disallowed" );
-    return 1;
-}
-
-sub store_1 {
-    # warning: writes and *deletes* it from %repos and %configs
-    my ($repo) = shift;
-    trace( 3, $repo );
-    return unless ( $repos{$repo} or $configs{$repo} ) and -d "$repo.git";
-
-    my ( %one_repo, %one_config );
-
-    open( my $compiled_fh, ">", "$repo.git/gl-conf" ) or return;
-
-    my $dumped_data = '';
-    if ( $repos{$repo} ) {
-        $one_repo{$repo} = $repos{$repo};
-        delete $repos{$repo};
-        $dumped_data = Data::Dumper->Dump( [ \%one_repo ], [qw(*one_repo)] );
-    }
-
-    if ( $configs{$repo} ) {
-        $one_config{$repo} = $configs{$repo};
-        delete $configs{$repo};
-        $dumped_data .= Data::Dumper->Dump( [ \%one_config ], [qw(*one_config)] );
-    }
-
-    print $compiled_fh $dumped_data;
-    close $compiled_fh;
-
-    $split_conf{$repo} = 1;
-}
-
-sub store_common {
-    trace(3);
-    my $cc = "conf/gitolite.conf-compiled.pm";
-    my $compiled_fh = _open( ">", "$cc.new" );
-
-    my %patterns = ();
-
-    my $data_version = glrc('current-data-version');
-    trace( 3, "data_version = $data_version" );
-    print $compiled_fh Data::Dumper->Dump( [$data_version], [qw(*data_version)] );
-
-    my $dumped_data = Data::Dumper->Dump( [ \%repos ], [qw(*repos)] );
-    $dumped_data .= Data::Dumper->Dump( [ \%configs ], [qw(*configs)] ) if %configs;
-
-    print $compiled_fh $dumped_data;
-
-    if (%groups) {
-        my %groups = %{ inside_out( \%groups ) };
-        $dumped_data = Data::Dumper->Dump( [ \%groups ], [qw(*groups)] );
-        print $compiled_fh $dumped_data;
-
-        # save patterns in %groups for faster handling of multiple repos, such
-        # as happens in the various POST_COMPILE scripts
-        for my $k ( keys %groups ) {
-            $patterns{groups}{$k} = 1 unless $k =~ $REPONAME_PATT;
-        }
-    }
-
-    print $compiled_fh Data::Dumper->Dump( [ \%patterns ], [qw(*patterns)] ) if %patterns;
-
-    print $compiled_fh Data::Dumper->Dump( [ \%split_conf ], [qw(*split_conf)] ) if %split_conf;
-
-    close $compiled_fh or _die "close compiled-conf failed: $!\n";
-    rename "$cc.new", $cc;
-}
-
-{
-    my $hook_reset = 0;
-
-    sub hook_1 {
-        my $repo = shift;
-        trace( 3, $repo );
-
-        # reset the gitolite supplied hooks, in case someone fiddled with
-        # them, but only once per run
-        if ( not $hook_reset ) {
-            _mkdir("$rc{GL_ADMIN_BASE}/hooks/common");
-            _mkdir("$rc{GL_ADMIN_BASE}/hooks/gitolite-admin");
-            _print( "$rc{GL_ADMIN_BASE}/hooks/common/update",              update_hook() );
-            _print( "$rc{GL_ADMIN_BASE}/hooks/gitolite-admin/post-update", post_update_hook() );
-            chmod 0755, "$rc{GL_ADMIN_BASE}/hooks/common/update";
-            chmod 0755, "$rc{GL_ADMIN_BASE}/hooks/gitolite-admin/post-update";
-            $hook_reset++;
-        }
-
-        # propagate user-defined (custom) hooks to all repos
-        ln_sf( "$rc{LOCAL_CODE}/hooks/common", "*", "$repo.git/hooks" ) if $rc{LOCAL_CODE};
-
-        # override/propagate gitolite defined hooks for all repos
-        ln_sf( "$rc{GL_ADMIN_BASE}/hooks/common", "*", "$repo.git/hooks" );
-        # override/propagate gitolite defined hooks for the admin repo
-        ln_sf( "$rc{GL_ADMIN_BASE}/hooks/gitolite-admin", "*", "$repo.git/hooks" ) if $repo eq 'gitolite-admin';
-    }
-}
-
-sub inside_out {
-    my $href = shift;
-    # input conf: @aa = bb cc <newline> @bb = @aa dd
-
-    my %ret = ();
-    while ( my ( $k, $v ) = each( %{$href} ) ) {
-        # $k is '@aa', $v is a href
-        for my $k2 ( keys %{$v} ) {
-            # $k2 is bb, then cc
-            push @{ $ret{$k2} }, $k;
-        }
-    }
-    return \%ret;
-    # %groups = ( 'bb' => [ '@bb', '@aa' ], 'cc' => [ '@bb', '@aa' ], 'dd' => [ '@bb' ]);
-}
-
-{
-    my $ri_fh = '';
-
-    sub store_rule_info {
-        $ri_fh = _open( ">", $rc{GL_ADMIN_BASE} . "/conf/rule_info" ) unless $ri_fh;
-        # $nextseq, $fname, $lnum
-        print $ri_fh join( "\t", @_ ) . "\n";
-    }
-
-    sub close_rule_info {
-        close $ri_fh or die "close rule_info file failed: $!";
-    }
-}
-
-1;
-
diff --git a/docker/gitolite/src/lib/Gitolite/Conf/Sugar.pm b/docker/gitolite/src/lib/Gitolite/Conf/Sugar.pm
deleted file mode 100644
index 986494b..0000000
--- a/docker/gitolite/src/lib/Gitolite/Conf/Sugar.pm
+++ /dev/null
@@ -1,183 +0,0 @@
-# and now for something completely different...
-
-package SugarBox;
-
-sub run_sugar_script {
-    my ( $ss, $lref ) = @_;
-    do $ss if -r $ss;
-    $lref = sugar_script($lref);
-    return $lref;
-}
-
-# ----------------------------------------------------------------------
-
-package Gitolite::Conf::Sugar;
-
-# syntactic sugar for the conf file, including site-local macros
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  sugar
-);
-
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Explode;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub sugar {
-    # gets a filename, returns a listref
-
-    my @lines = ();
-    explode( shift, 'master', \@lines );
-
-    my $lines;
-    $lines = \@lines;
-
-    # run through the sugar stack one by one
-
-    # first, user supplied sugar:
-    if ( exists $rc{SYNTACTIC_SUGAR} ) {
-        if ( ref( $rc{SYNTACTIC_SUGAR} ) ne 'ARRAY' ) {
-            _warn "bad syntax for specifying sugar scripts; see docs";
-        } else {
-            for my $s ( @{ $rc{SYNTACTIC_SUGAR} } ) {
-
-                # perl-ism; apart from keeping the full path separate from the
-                # simple name, this also protects %rc from change by implicit
-                # aliasing, which would happen if you touched $s itself
-                my $sfp = _which( "syntactic-sugar/$s", 'r' );
-
-                _warn("skipped sugar script '$s'"), next if not -r $sfp;
-                $lines = SugarBox::run_sugar_script( $sfp, $lines );
-                $lines = [ grep /\S/, map { cleanup_conf_line($_) } @$lines ];
-            }
-        }
-    }
-
-    # then our stuff:
-
-    $lines = rw_cdm($lines);
-    $lines = option($lines);       # must come after rw_cdm
-    $lines = owner_desc($lines);
-    $lines = name_vref($lines);
-    $lines = role_names($lines);
-
-    return $lines;
-}
-
-sub rw_cdm {
-    my $lines = shift;
-    my @ret;
-
-    # repo foo <...> RWC = ...
-    #   ->  option CREATE_IS_C = 1
-    # (and similarly DELETE_IS_D and MERGE_CHECK)
-    # but only once per repo of course
-
-    my %seen = ();
-    for my $line (@$lines) {
-        push @ret, $line;
-        if ( $line =~ /^repo / ) {
-            %seen = ();
-        } elsif ( $line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/ ) {
-            my $perms = $1;
-            push @ret, "option DELETE_IS_D = 1" if $perms =~ /D/     and not $seen{D}++;
-            push @ret, "option CREATE_IS_C = 1" if $perms =~ /RW.*C/ and not $seen{C}++;
-            push @ret, "option MERGE_CHECK = 1" if $perms =~ /M/     and not $seen{M}++;
-        }
-    }
-    return \@ret;
-}
-
-sub option {
-    my $lines = shift;
-    my @ret;
-
-    # option foo = bar
-    #   ->  config gitolite-options.foo = bar
-
-    for my $line (@$lines) {
-        if ( $line =~ /^option (\S+) = (\S.*)/ ) {
-            push @ret, "config gitolite-options.$1 = $2";
-        } else {
-            push @ret, $line;
-        }
-    }
-    return \@ret;
-}
-
-sub owner_desc {
-    my $lines = shift;
-    my @ret;
-
-    # owner = "owner name"
-    #   ->  config gitweb.owner = owner name
-    # desc = "some long description"
-    #   ->  config gitweb.description = some long description
-    # category = "whatever..."
-    #   ->  config gitweb.category = whatever...
-
-    for my $line (@$lines) {
-        if ( $line =~ /^desc = (\S.*)/ ) {
-            push @ret, "config gitweb.description = $1";
-        } elsif ( $line =~ /^owner = (\S.*)/ ) {
-            push @ret, "config gitweb.owner = $1";
-        } elsif ( $line =~ /^category = (\S.*)/ ) {
-            push @ret, "config gitweb.category = $1";
-        } else {
-            push @ret, $line;
-        }
-    }
-    return \@ret;
-}
-
-sub name_vref {
-    my $lines = shift;
-    my @ret;
-
-    # <perm> NAME/foo = <user>
-    #   ->  <perm> VREF/NAME/foo = <user>
-
-    for my $line (@$lines) {
-        if ( $line =~ /^(-|R\S+) \S.* = \S.*/ ) {
-            $line =~ s( NAME/)( VREF/NAME/)g;
-        }
-        push @ret, $line;
-    }
-    return \@ret;
-}
-
-sub role_names {
-    my $lines = shift;
-    my @ret;
-
-    # <perm> [<ref>] = <user list containing CREATOR|READERS|WRITERS>
-    #   ->  same but with "@" prepended to rolenames
-
-    for my $line (@$lines) {
-        if ( $line =~ /^(-|C|R|RW\+?(?:C?D?|D?C?)M?) (.* )?= (.+)/ ) {
-            my ( $p, $r ) = ( $1, $2 );
-            my $u = '';
-            for ( split ' ', $3 ) {
-                $_ = "\@$_" if $_ eq 'CREATOR' or $rc{ROLES}{$_};
-                $u .= " $_";
-            }
-            $r ||= '';
-            # mind the spaces (or play safe and run cleanup_conf_line again)
-            push @ret, cleanup_conf_line("$p $r = $u");
-        } else {
-            push @ret, $line;
-        }
-    }
-    return \@ret;
-}
-
-1;
-
diff --git a/docker/gitolite/src/lib/Gitolite/Easy.pm b/docker/gitolite/src/lib/Gitolite/Easy.pm
deleted file mode 100644
index 8f530f2..0000000
--- a/docker/gitolite/src/lib/Gitolite/Easy.pm
+++ /dev/null
@@ -1,240 +0,0 @@
-package Gitolite::Easy;
-
-# easy access to gitolite from external perl programs
-# ----------------------------------------------------------------------
-# most/all functions in this module test $ENV{GL_USER}'s rights and
-# permissions so it needs to be set.
-
-# "use"-ing this module
-# ----------------------------------------------------------------------
-# Using this module from within a gitolite trigger or command is easy; you
-# just need 'use lib $ENV{GL_LIBDIR};' before the 'use Gitolite::Easy;'.
-#
-# Using it from something completely outside gitolite requires a bit more
-# work.  First, run 'gitolite query-rc -a' to find the correct values for
-# GL_BINDIR and GL_LIBDIR in your installation.  Then use this code in your
-# external program, using the paths you just found:
-#
-#   BEGIN {
-#       $ENV{HOME} = "/home/git";   # or whatever is the hosting user's $HOME
-#       $ENV{GL_BINDIR} = "/full/path/to/gitolite/src";
-#       $ENV{GL_LIBDIR} = "/full/path/to/gitolite/src/lib";
-#   }
-#   use lib $ENV{GL_LIBDIR};
-#   use Gitolite::Easy;
-
-# API documentation
-# ----------------------------------------------------------------------
-# documentation for each function is at the top of the function.
-# Documentation is NOT in pod format; just read the source with a nice syntax
-# coloring text editor and you'll be happy enough.  (I do not like POD; please
-# don't send me patches for this aspect of the module).
-
-#<<<
- at EXPORT = qw(
-  is_admin
-  is_super_admin
-  in_group
-  in_role
-
-  owns
-  can_read
-  can_write
-
-  config
-
-  textfile
-
-  %rc
-  say
-  say2
-  _die
-  _warn
-  _print
-  usage
-
-  option
-);
-#>>>
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-my $user;
-
-# ----------------------------------------------------------------------
-
-# is_admin()
-
-# return true if $ENV{GL_USER} is set and has W perms to the admin repo
-
-# shell equivalent
-#   if gitolite access -q gitolite-admin $GL_USER W; then ...
-
-sub is_admin {
-    valid_user();
-    return not( access( 'gitolite-admin', $user, 'W', 'any' ) =~ /DENIED/ );
-}
-
-# is_super_admin()
-
-# (useful only if you are using delegation)
-
-# return true if $ENV{GL_USER} is set and has W perms to any file in the admin
-# repo
-
-# shell equivalent
-#   if gitolite access -q gitolite-admin $GL_USER W VREF/NAME/; then ...
-sub is_super_admin {
-    valid_user();
-    return not( access( 'gitolite-admin', $user, 'W', 'VREF/NAME/' ) =~ /DENIED/ );
-}
-
-# in_group()
-
-# return true if $ENV{GL_USER} is set and is in the given group
-
-# shell equivalent
-#   if gitolite list-memberships $GL_USER | grep -x $GROUPNAME >/dev/null; then ...
-sub in_group {
-    valid_user();
-    my $g = shift;
-    $g =~ s/^\@?/@/;
-
-    return grep { $_ eq $g } @{ Gitolite::Conf::Load::list_memberships( '-u', $user ) };
-}
-
-# in_role()
-
-# return true if $ENV{GL_USER} is set and has the given role for the given repo
-
-# shell equivalent
-#   if gitolite list-memberships -u $GL_USER -r $GL_REPO | grep -x $ROLENAME >/dev/null; then ...
-sub in_role {
-    valid_user();
-    my $r = shift;
-    $r =~ s/^\@?/@/;
-    my $repo = shift;
-
-    return grep { $_ eq $r } @{ Gitolite::Conf::Load::list_memberships( "-u", $user, "-r", $repo ) };
-}
-
-# owns()
-
-# return true if $ENV{GL_USER} is set and is an OWNER of the given repo.
-
-# shell equivalent (assuming GL_USER is set)
-#   if gitolite owns $REPONAME; then ...
-sub owns {
-    valid_user();
-    my $r = shift;
-
-    # prevent unnecessary disclosure of repo existence info
-    return 0 if repo_missing($r);
-
-    return ( creator($r) eq $user or $rc{OWNER_ROLENAME} and in_role( $rc{OWNER_ROLENAME}, $r ) );
-}
-
-# can_read()
-# return true if $ENV{GL_USER} is set and can read the given repo
-
-# shell equivalent
-#   if gitolite access -q $REPONAME $GL_USER R; then ...
-sub can_read {
-    valid_user();
-    my $r = shift;
-    return not( access( $r, $user, 'R', 'any' ) =~ /DENIED/ );
-}
-
-# can_write()
-# return true if $ENV{GL_USER} is set and can write to the given repo.
-# Optional second argument can be '+' to check that instead of 'W'.  Optional
-# third argument can be a full ref name instead of 'any'.
-
-# shell equivalent
-#   if gitolite access -q $REPONAME $GL_USER W; then ...
-sub can_write {
-    valid_user();
-    my ( $r, $aa, $ref ) = @_;
-    $aa  ||= 'W';
-    $ref ||= 'any';
-    return not( access( $r, $user, $aa, $ref ) =~ /DENIED/ );
-}
-
-# config()
-# given a repo and a key, return a hash containing all the git config
-# variables for that repo where the section+key match the regex.  If none are
-# found, return an empty hash.  If you don't want it as a regex, use \Q
-# appropriately
-
-# shell equivalent
-#   foo=$(gitolite git-config -r $REPONAME foo\\.bar)
-sub config {
-    my $repo = shift;
-    my $key  = shift;
-
-    return () if repo_missing($repo);
-
-    my $ret = git_config( $repo, $key );
-    return %$ret;
-}
-
-# ----------------------------------------------------------------------
-
-# maintain a textfile; see comments in code for details, and calls in various
-# other programs (like 'motd', 'desc', and 'readme') for how to call
-sub textfile {
-    my %h = @_;
-    my $repodir;
-
-    # target file
-    _die "need file" unless $h{file};
-    _die "'$h{file}' contains a '/'" if $h{file} =~ m(/);
-    Gitolite::Conf::Load::sanity($h{file}, $REPONAME_PATT);
-
-    # target file's location.  This can come from one of two places: dir
-    # (which comes from our code, so does not need to be sanitised), or repo,
-    # which may come from the user
-    _die "need exactly one of repo or dir" unless $h{repo} xor $h{dir};
-    _die "'$h{dir}' does not exist" if $h{dir} and not -d $h{dir};
-    if ($h{repo}) {
-        Gitolite::Conf::Load::sanity($h{repo}, $REPONAME_PATT);
-        $h{dir} = "$rc{GL_REPO_BASE}/$h{repo}.git";
-        _die "repo '$h{repo}' does not exist" if not -d $h{dir};
-
-        my $umask = option( $h{repo}, 'umask' );
-        # note: using option() moves us to ADMIN_BASE, but we don't care here
-        umask oct($umask) if $umask;
-    }
-
-    # final full file name
-    my $f = "$h{dir}/$h{file}";
-
-    # operation
-    _die "can't have both prompt and text" if defined $h{prompt} and defined $h{text};
-    if (defined $h{prompt}) {
-        print STDERR $h{prompt};
-        my $t = join( "", <> );
-        _print($f, $t);
-    } elsif (defined $h{text}) {
-        _print($f, $h{text});
-    } else {
-        return slurp($f) if -f $f;
-    }
-
-    return '';
-}
-
-# ----------------------------------------------------------------------
-
-sub valid_user {
-    _die "GL_USER not set" unless exists $ENV{GL_USER};
-    $user = $ENV{GL_USER};
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Hooks/PostUpdate.pm b/docker/gitolite/src/lib/Gitolite/Hooks/PostUpdate.pm
deleted file mode 100644
index 2eeefcc..0000000
--- a/docker/gitolite/src/lib/Gitolite/Hooks/PostUpdate.pm
+++ /dev/null
@@ -1,74 +0,0 @@
-package Gitolite::Hooks::PostUpdate;
-
-# everything to do with the post-update hook
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  post_update
-  post_update_hook
-);
-
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub post_update {
-    trace( 3, 'post-up', @ARGV );
-    # this is the *real* post_update hook for gitolite
-
-    tsh_try("git ls-tree --name-only master");
-    _die "no files/dirs called 'hooks' or 'logs' are allowed" if tsh_text() =~ /^(hooks|logs)$/m;
-
-    my $hooks_changed = 0;
-    {
-        local $ENV{GIT_WORK_TREE} = $rc{GL_ADMIN_BASE};
-
-        tsh_try("git diff --name-only master");
-        $hooks_changed++ if tsh_text() =~ m(/hooks/common/);
-        # the leading slash ensure that this hooks/common directory is below
-        # some top level directory, not *at* the top.  That's LOCAL_CODE, and
-        # it's actual name could be anything but it doesn't matter to us.
-
-        tsh_try("git checkout -f --quiet master");
-    }
-    _system("gitolite compile");
-    _system("gitolite setup --hooks-only") if $hooks_changed;
-    _system("gitolite trigger POST_COMPILE");
-
-    exit 0;
-}
-
-{
-    my $text = '';
-
-    sub post_update_hook {
-        if ( not $text ) {
-            local $/ = undef;
-            $text = <DATA>;
-        }
-        return $text;
-    }
-}
-
-1;
-
-__DATA__
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Hooks::PostUpdate;
-
-# gitolite post-update hook (only for the admin repo)
-# ----------------------------------------------------------------------
-
-post_update();          # is not expected to return
-exit 1;                 # so if it does, something is wrong
diff --git a/docker/gitolite/src/lib/Gitolite/Hooks/Update.pm b/docker/gitolite/src/lib/Gitolite/Hooks/Update.pm
deleted file mode 100644
index 32cd6e0..0000000
--- a/docker/gitolite/src/lib/Gitolite/Hooks/Update.pm
+++ /dev/null
@@ -1,170 +0,0 @@
-package Gitolite::Hooks::Update;
-
-# everything to do with the update hook
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  update
-  update_hook
-);
-
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub update {
-    # this is the *real* update hook for gitolite
-
-    bypass() if $ENV{GL_BYPASS_ACCESS_CHECKS};
-
-    my ( $ref, $oldsha, $newsha, $oldtree, $newtree, $aa ) = args(@ARGV);
-
-    trace( 2, $ENV{GL_REPO}, $ENV{GL_USER}, $aa, @ARGV );
-
-    my $ret = access( $ENV{GL_REPO}, $ENV{GL_USER}, $aa, $ref );
-    trigger( 'ACCESS_2', $ENV{GL_REPO}, $ENV{GL_USER}, $aa, $ref, $ret, $oldsha, $newsha );
-    _die $ret if $ret =~ /DENIED/;
-
-    check_vrefs( $ref, $oldsha, $newsha, $oldtree, $newtree, $aa );
-
-    gl_log( 'update', $ENV{GL_REPO}, $ENV{GL_USER}, $aa, @ARGV, $ret );
-    exit 0;
-}
-
-sub bypass {
-    require Cwd;
-    Cwd->import;
-    gl_log( 'update', getcwd(), '(' . ( $ENV{USER} || '?' ) . ')', 'bypass', @ARGV );
-    exit 0;
-}
-
-sub check_vrefs {
-    my ( $ref, $oldsha, $newsha, $oldtree, $newtree, $aa ) = @_;
-    my $name_seen = 0;
-    my $n_vrefs   = 0;
-    for my $vref ( vrefs( $ENV{GL_REPO}, $ENV{GL_USER} ) ) {
-        $n_vrefs++;
-        if ( $vref =~ m(^VREF/NAME/) ) {
-            # this one is special; we process it right here, and only once
-            next if $name_seen++;
-
-            for my $ref ( map { chomp; s(^)(VREF/NAME/); $_; } `git diff --name-only $oldtree $newtree` ) {
-                check_vref( $aa, $ref );
-            }
-        } else {
-            my ( $dummy, $pgm, @args ) = split '/', $vref;
-            $pgm = _which( "VREF/$pgm", 'x' );
-            $pgm or _die "'$vref': helper program missing or unexecutable";
-
-            open( my $fh, "-|", $pgm, @_, $vref, @args ) or _die "'$vref': can't spawn helper program: $!";
-            while (<$fh>) {
-                # print non-vref lines and skip processing (for example,
-                # normal STDOUT by a normal update hook)
-                unless (m(^VREF/)) {
-                    print;
-                    next;
-                }
-                my ( $ref, $deny_message ) = split( ' ', $_, 2 );
-                check_vref( $aa, $ref, $deny_message );
-            }
-            close($fh) or _die $!
-              ? "Error closing sort pipe: $!"
-              : "$vref: helper program exit status $?";
-        }
-    }
-    return $n_vrefs;
-}
-
-sub check_vref {
-    my ( $aa, $ref, $deny_message ) = @_;
-
-    my $ret = access( $ENV{GL_REPO}, $ENV{GL_USER}, $aa, $ref );
-    trace( 2, "access($ENV{GL_REPO}, $ENV{GL_USER}, $aa, $ref)", "-> $ret" );
-    if ( $ret =~ /by fallthru/ ) {
-        trace( 3, "remember, fallthru is success here!" );
-        return;
-    }
-    trigger( 'ACCESS_2', $ENV{GL_REPO}, $ENV{GL_USER}, $aa, $ref, $ret );
-    _die "$ret" . ( $deny_message ? "\n$deny_message" : '' ) if $ret =~ /DENIED/;
-}
-
-{
-    my $text = '';
-
-    sub update_hook {
-        if ( not $text ) {
-            local $/ = undef;
-            $text = <DATA>;
-        }
-        return $text;
-    }
-}
-
-# ----------------------------------------------------------------------
-
-sub args {
-    my ( $ref, $oldsha, $newsha ) = @_;
-    my ( $oldtree, $newtree, $aa );
-
-    # this is special to git -- the hash of an empty tree
-    my $empty = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
-    $oldtree = $oldsha eq '0' x 40 ? $empty : $oldsha;
-    $newtree = $newsha eq '0' x 40 ? $empty : $newsha;
-
-    my $merge_base = '0' x 40;
-    # for branch create or delete, merge_base stays at '0'x40
-    chomp( $merge_base = `git merge-base $oldsha $newsha` )
-      unless $oldsha eq '0' x 40
-      or $newsha eq '0' x 40;
-
-    $aa = 'W';
-    # tag rewrite
-    $aa = '+' if $ref =~ m(refs/tags/) and $oldsha ne ( '0' x 40 );
-    # non-ff push to ref (including ref delete)
-    $aa = '+' if $oldsha ne $merge_base;
-
-    $aa = 'D' if ( option( $ENV{GL_REPO}, 'DELETE_IS_D' ) ) and $newsha eq '0' x 40;
-    $aa = 'C' if ( option( $ENV{GL_REPO}, 'CREATE_IS_C' ) ) and $oldsha eq '0' x 40;
-
-    # and now "M" commits.  All the other accesses (W, +, C, D) were mutually
-    # exclusive in some sense.  Sure a W could be a C or a + could be a D but
-    # that's by design.  A merge commit, however, could still be any of the
-    # others (except a "D").
-
-    # so we have to *append* 'M' to $aa (if the repo has MERGE_CHECK in
-    # effect and this push contains a merge inside)
-
-    if ( option( $ENV{GL_REPO}, 'MERGE_CHECK' ) ) {
-        if ( $oldsha eq '0' x 40 or $newsha eq '0' x 40 ) {
-            _warn "ref create/delete ignored for purposes of merge-check\n";
-        } else {
-            $aa .= 'M' if `git rev-list -n 1 --merges $oldsha..$newsha` =~ /./;
-        }
-    }
-
-    return ( $ref, $oldsha, $newsha, $oldtree, $newtree, $aa );
-}
-
-1;
-
-__DATA__
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Hooks::Update;
-
-# gitolite update hook
-# ----------------------------------------------------------------------
-
-update();               # is not expected to return
-exit 1;                 # so if it does, something is wrong
diff --git a/docker/gitolite/src/lib/Gitolite/Rc.pm b/docker/gitolite/src/lib/Gitolite/Rc.pm
deleted file mode 100644
index 9fd94b5..0000000
--- a/docker/gitolite/src/lib/Gitolite/Rc.pm
+++ /dev/null
@@ -1,684 +0,0 @@
-package Gitolite::Rc;
-
-# everything to do with 'rc'.  Also defines some 'constants'
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  %rc
-  glrc
-  query_rc
-  version
-  greeting
-  trigger
-  _which
-
-  $REMOTE_COMMAND_PATT
-  $REF_OR_FILENAME_PATT
-  $REPONAME_PATT
-  $REPOPATT_PATT
-  $USERNAME_PATT
-  $UNSAFE_PATT
-);
-
-use Exporter 'import';
-
-use Gitolite::Common;
-
-# ----------------------------------------------------------------------
-
-our %rc;
-our $non_core;
-
-# ----------------------------------------------------------------------
-
-# pre-populate some important rc keys
-# ----------------------------------------------------------------------
-
-$rc{GL_BINDIR} = $ENV{GL_BINDIR};
-$rc{GL_LIBDIR} = $ENV{GL_LIBDIR};
-
-# these keys could be overridden by the rc file later
-$rc{GL_REPO_BASE}  = "$ENV{HOME}/repositories";
-$rc{GL_ADMIN_BASE} = "$ENV{HOME}/.gitolite";
-$rc{LOG_TEMPLATE}  = "$ENV{HOME}/.gitolite/logs/gitolite-%y-%m.log";
-
-# variables that should probably never be changed but someone will want to, I'll bet...
-# ----------------------------------------------------------------------
-
-#<<<
-$REMOTE_COMMAND_PATT  =                qr(^[-0-9a-zA-Z._\@/+ :,\%=]*$);
-$REF_OR_FILENAME_PATT =     qr(^[0-9a-zA-Z][-0-9a-zA-Z._\@/+ :,]*$);
-$REPONAME_PATT        =  qr(^\@?[0-9a-zA-Z][-0-9a-zA-Z._\@/+]*$);
-$REPOPATT_PATT        = qr(^\@?[[0-9a-zA-Z][-0-9a-zA-Z._\@/+\\^$|()[\]*?{},]*$);
-$USERNAME_PATT        =  qr(^\@?[0-9a-zA-Z][-0-9a-zA-Z._\@+]*$);
-
-$UNSAFE_PATT          = qr([`~#\$\&()|;<>]);
-#>>>
-
-# ----------------------------------------------------------------------
-
-# find the rc file and 'do' it
-# ----------------------------------------------------------------------
-my $current_data_version = "3.2";
-
-my $rc = glrc('filename');
-if ( -r $rc and -s $rc ) {
-    do $rc or die $@;
-}
-if ( defined($GL_ADMINDIR) ) {
-    say2 "";
-    say2 "FATAL: '$rc' seems to be for older gitolite; please see\nhttp://gitolite.com/gitolite/migr.html";
-
-    exit 1;
-}
-
-# let values specified in rc file override our internal ones
-# ----------------------------------------------------------------------
- at rc{ keys %RC } = values %RC;
-
-# expand the non_core list into INPUT, PRE_GIT, etc using 'ENABLE' settings
-non_core_expand() if $rc{ENABLE};
-
-# add internal triggers
-# ----------------------------------------------------------------------
-
-# is the server/repo in a writable state (i.e., not down for maintenance etc)
-unshift @{ $rc{ACCESS_1} }, 'Writable::access_1';
-
-# (testing only) override the rc file silently
-# ----------------------------------------------------------------------
-# use an env var that is highly unlikely to appear in real life :)
-do $ENV{G3T_RC} if exists $ENV{G3T_RC} and -r $ENV{G3T_RC};
-
-# setup some perl/rc/env vars, plus umask
-# ----------------------------------------------------------------------
-
-umask ( $rc{UMASK} || 0077 );
-
-unshift @INC, "$rc{LOCAL_CODE}/lib" if $rc{LOCAL_CODE};
-
-$ENV{PATH} = "$ENV{GL_BINDIR}:$ENV{PATH}" unless $ENV{PATH} =~ /^$ENV{GL_BINDIR}:/;
-
-{
-    $rc{GL_TID} = $ENV{GL_TID} ||= $$;
-    # TID: loosely, transaction ID.  The first PID at the entry point passes
-    # it down to all its children so you can track each access, across all the
-    # various commands it spawns and actions it generates.
-
-    $rc{GL_LOGFILE} = $ENV{GL_LOGFILE} ||= gen_lfn( $rc{LOG_TEMPLATE} );
-}
-
-# these two are meant to help externally written commands (see
-# src/commands/writable for an example)
-$ENV{GL_REPO_BASE}  = $rc{GL_REPO_BASE};
-$ENV{GL_ADMIN_BASE} = $rc{GL_ADMIN_BASE};
-
-# ----------------------------------------------------------------------
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-my $glrc_default_text = '';
-{
-    local $/ = undef;
-    $glrc_default_text = <DATA>;
-}
-
-# ----------------------------------------------------------------------
-
-sub non_core_expand {
-    my %enable;
-
-    for my $e ( @{ $rc{ENABLE} } ) {
-        my ( $name, $arg ) = split ' ', $e, 2;
-        # store args as the hash value for the name
-        $enable{$name} = $arg || '';
-
-        # for now, we pretend everything is a command, because commands
-        # are the only thing that the non_core list does not contain
-        $rc{COMMANDS}{$name} = $arg || 1;
-    }
-
-    # bring in additional non-core specs from the rc file, if given
-    if ( my $nc2 = $rc{NON_CORE} ) {
-        for ( $non_core, $nc2 ) {
-            # beat 'em into shape :)
-            s/#.*//g;
-            s/[ \t]+/ /g; s/^ //mg; s/ $//mg;
-            s/\n+/\n/g;
-        }
-
-        for ( split "\n", $nc2 ) {
-            next unless /\S/;
-            my ( $name, $where, $module, $before, $name2 ) = split ' ', $_;
-            if ( not $before ) {
-                $non_core .= "$name $where $module\n";
-                next;
-            }
-            die if $before ne 'before';
-            $non_core =~ s(^(?=$name2 $where( |$)))($name $where $module\n)m;
-        }
-    }
-
-    my @data = split "\n", $non_core || '';
-    for (@data) {
-        next if /^\s*(#|$)/;
-        my ( $name, $where, $module ) = split ' ', $_;
-
-        # if it appears here, it's not a command, so delete it.  At the end of
-        # this loop, what's left in $rc{COMMANDS} will be those names in the
-        # enable list that do not appear in the non_core list.
-        delete $rc{COMMANDS}{$name};
-
-        next unless exists $enable{$name};
-
-        # module to call is name if specified as "."
-        $module = $name if $module eq ".";
-
-        # module to call is "name::pre_git" or such if specified as "::"
-        ( $module = $name ) .= "::" . lc($where) if $module eq '::';
-
-        # append arguments, if supplied
-        $module .= " $enable{$name}" if $enable{$name};
-
-        push @{ $rc{$where} }, $module;
-    }
-
-    # finally, add in commands that were declared in the non-core list
-    map { /^(\S+)/; $rc{COMMANDS}{$1} = 1 } @{ $rc{COMMAND} };
-}
-
-# exported functions
-# ----------------------------------------------------------------------
-
-sub glrc {
-    my $cmd = shift;
-    if ( $cmd eq 'default-filename' ) {
-        return "$ENV{HOME}/.gitolite.rc";
-    } elsif ( $cmd eq 'default-text' ) {
-        return $glrc_default_text if $glrc_default_text;
-        _die "rc file default text not set; this should not happen!";
-    } elsif ( $cmd eq 'filename' ) {
-        # where is the rc file?
-
-        # search $HOME first
-        return "$ENV{HOME}/.gitolite.rc" if -f "$ENV{HOME}/.gitolite.rc";
-
-        return '';
-    } elsif ( $cmd eq 'current-data-version' ) {
-        return $current_data_version;
-    } else {
-        _die "unknown argument to glrc: '$cmd'";
-    }
-}
-
-my $all   = 0;
-my $dump  = 0;
-my $nonl  = 0;
-my $quiet = 0;
-
-sub query_rc {
-
-    my @vars = args();
-
-    no strict 'refs';
-
-    if ($all) {
-        for my $e ( sort keys %rc ) {
-            print "$e=" . ( defined( $rc{$e} ) ? $rc{$e} : 'undef' ) . "\n";
-        }
-        exit 0;
-    }
-
-    if ($dump) {
-        require Data::Dumper;
-        $Data::Dumper::Sortkeys = 1;
-        print Data::Dumper::Dumper \%rc;
-        exit 0;
-    }
-
-    my $cv = \%rc;    # current "value"
-    while (@vars) {
-        my $v = shift @vars;
-
-        # dig into the rc hash, using each var as a component
-        if ( not ref($cv) ) {
-            _warn "unused arguments...";
-            last;
-        } elsif ( ref($cv) eq 'HASH' ) {
-            $cv = $cv->{$v} || '';
-        } elsif ( ref($cv) eq 'ARRAY' ) {
-            $cv = $cv->[$v] || '';
-        } else {
-            _die "dont know what to do with " . ref($cv) . " item in the rc file";
-        }
-    }
-
-    # we've run out of arguments so $cv is what we have.  If we're supposed to
-    # be quiet, we don't have to print anything so let's get that done first:
-    exit( $cv ? 0 : 1 ) if $quiet;    # shell truth
-
-    # print values (notice we ignore the '-n' option if it's a ref)
-    if ( ref($cv) eq 'HASH' ) {
-        print join( "\n", sort keys %$cv ), "\n" if %$cv;
-    } elsif ( ref($cv) eq 'ARRAY' ) {
-        print join( "\n", @$cv ), "\n" if @$cv;
-    } else {
-        print $cv . ( $nonl ? '' : "\n" ) if $cv;
-    }
-    exit( $cv ? 0 : 1 );              # shell truth
-}
-
-sub version {
-    my $version = '';
-    $version = '(unknown)';
-    for ("$ENV{GL_BINDIR}/VERSION") {
-        $version = slurp($_) if -r $_;
-    }
-    chomp($version);
-    return $version;
-}
-
-sub greeting {
-    my $json = shift;
-
-    chomp( my $hn = `hostname -s 2>/dev/null || hostname` );
-    my $gv = substr( `git --version`, 12 );
-    my $gl_user = $ENV{GL_USER} || '';
-    $gl_user = " $gl_user" if $gl_user;
-
-    if ($json) {
-        $json->{GL_USER}          = $ENV{GL_USER};
-        $json->{USER}             = ( $ENV{USER} || "httpd" ) . "\@$hn";
-        $json->{gitolite_version} = version();
-        chomp( $json->{git_version} = $gv );    # this thing has a newline at the end
-        return;
-    }
-
-    # normal output
-    return "hello$gl_user, this is " . ( $ENV{USER} || "httpd" ) . "\@$hn running gitolite3 " . version() . " on git $gv\n";
-}
-
-sub trigger {
-    my $rc_section = shift;
-
-    # if arg-2 (now arg-1, due to the 'shift' above) exists, it is a repo
-    # name, so setup env from options
-    require Gitolite::Conf::Load;
-    Gitolite::Conf::Load->import('env_options');
-    env_options( $_[0] ) if $_[0];
-
-    if ( exists $rc{$rc_section} ) {
-        if ( ref( $rc{$rc_section} ) ne 'ARRAY' ) {
-            _die "'$rc_section' section in rc file is not a perl list";
-        } else {
-            for my $s ( @{ $rc{$rc_section} } ) {
-                my ( $pgm, @args ) = split ' ', $s;
-
-                if ( my ( $module, $sub ) = ( $pgm =~ /^(.*)::(\w+)$/ ) ) {
-
-                    require Gitolite::Triggers;
-                    trace( 2, 'trigger module', $module, $sub, @args, $rc_section, @_ );
-                    Gitolite::Triggers::run( $module, $sub, @args, $rc_section, @_ );
-
-                } else {
-                    $pgm = _which( "triggers/$pgm", 'x' );
-
-                    _warn("skipped trigger '$s' (not found or not executable)"), next if not $pgm;
-                    trace( 2, 'trigger command', $s );
-                    _system( $pgm, @args, $rc_section, @_ );    # they better all return with 0 exit codes!
-                }
-            }
-        }
-        return;
-    }
-    trace( 3, "'$rc_section' not found in rc" );
-}
-
-sub _which {
-    # looks for a file in LOCAL_CODE or GL_BINDIR.  Returns whichever exists
-    # (LOCAL_CODE preferred if defined) or 0 if not found.
-    my $file = shift;
-    my $mode = shift;    # could be 'x' or 'r'
-
-    my @files = ("$rc{GL_BINDIR}/$file");
-    unshift @files, ("$rc{LOCAL_CODE}/$file") if $rc{LOCAL_CODE};
-
-    for my $f (@files) {
-        return $f if -x $f;
-        return $f if -r $f and $mode eq 'r';
-    }
-
-    return 0;
-}
-
-# ----------------------------------------------------------------------
-
-=for args
-Usage:  gitolite query-rc -a
-        gitolite query-rc -d
-        gitolite query-rc [-n] [-q] rc-variable
-
-    -a          print all variables and values (first level only)
-    -d          dump the entire rc structure
-    -n          do not append a newline if variable is scalar
-    -q          exit code only (shell truth; 0 is success)
-
-Query the rc hash.  Second and subsequent arguments dig deeper into the hash.
-The examples are for the default configuration; yours may be different.
-
-Single values:
-    gitolite query-rc GL_ADMIN_BASE     # prints "/home/git/.gitolite" or similar
-    gitolite query-rc UMASK             # prints "63" (that's 0077 in decimal!)
-
-Hashes:
-    gitolite query-rc COMMANDS
-        # prints "desc", "help", "info", "perms", "writable", one per line
-    gitolite query-rc COMMANDS help     # prints 1
-    gitolite query-rc -q COMMANDS help  # prints nothing; exit code is 0
-    gitolite query-rc COMMANDS fork     # prints nothing; exit code is 1
-
-Arrays (somewhat less useful):
-    gitolite query-rc POST_GIT          # prints nothing; exit code is 0
-    gitolite query-rc POST_COMPILE      # prints 4 lines
-    gitolite query-rc POST_COMPILE 0    # prints the first of those 4 lines
-
-Explore:
-    gitolite query-rc -a
-    # prints all first level variables and values, one per line.  Any that are
-    # listed as HASH or ARRAY can be explored further in subsequent commands.
-    gitolite query-rc -d                # dump the entire rc structure
-=cut
-
-sub args {
-    my $help = 0;
-
-    require Getopt::Long;
-    Getopt::Long::GetOptions(
-        'all|a'   => \$all,
-        'dump|d'  => \$dump,
-        'nonl|n'  => \$nonl,
-        'quiet|q' => \$quiet,
-        'help|h'  => \$help,
-    ) or usage();
-
-    _die("'-a' cannot be combined with other arguments or options; run with '-h' for usage") if $all and ( @ARGV or $dump or $nonl or $quiet );
-    usage() if not $all and not $dump and not @ARGV or $help;
-    return @ARGV;
-}
-
-# ----------------------------------------------------------------------
-
-BEGIN {
-    $non_core = "
-    # No user-servicable parts inside.  Warranty void if seal broken.  Refer
-    # servicing to authorised service center only.
-
-    continuation-lines      SYNTACTIC_SUGAR .
-    keysubdirs-as-groups    SYNTACTIC_SUGAR .
-    macros                  SYNTACTIC_SUGAR .
-    refex-expr              SYNTACTIC_SUGAR .
-
-    renice                  PRE_GIT         .
-
-    Kindergarten            INPUT           ::
-
-    CpuTime                 INPUT           ::
-    CpuTime                 POST_GIT        ::
-
-    Shell                   INPUT           ::
-
-    Alias                   INPUT           ::
-
-    Motd                    INPUT           ::
-    Motd                    PRE_GIT         ::
-    Motd                    COMMAND         motd
-
-    Mirroring               INPUT           ::
-    Mirroring               PRE_GIT         ::
-    Mirroring               POST_GIT        ::
-
-    refex-expr              ACCESS_2        RefexExpr::access_2
-
-    expand-deny-messages    ACCESS_1        .
-    expand-deny-messages    ACCESS_2        .
-
-    RepoUmask               PRE_GIT         ::
-    RepoUmask               POST_CREATE     ::
-
-    partial-copy            PRE_GIT         .
-
-    upstream                PRE_GIT         .
-
-    no-create-on-read       PRE_CREATE      AutoCreate::deny_R
-    no-auto-create          PRE_CREATE      AutoCreate::deny_RW
-
-    ssh-authkeys-split      POST_COMPILE    post-compile/ssh-authkeys-split
-    ssh-authkeys            POST_COMPILE    post-compile/ssh-authkeys
-    Shell                   POST_COMPILE    post-compile/ssh-authkeys-shell-users
-
-    set-default-roles       POST_CREATE     .
-
-    git-config              POST_COMPILE    post-compile/update-git-configs
-    git-config              POST_CREATE     post-compile/update-git-configs
-
-    gitweb                  POST_CREATE     post-compile/update-gitweb-access-list
-    gitweb                  POST_COMPILE    post-compile/update-gitweb-access-list
-
-    cgit                    POST_COMPILE    post-compile/update-description-file
-
-    daemon                  POST_CREATE     post-compile/update-git-daemon-access-list
-    daemon                  POST_COMPILE    post-compile/update-git-daemon-access-list
-
-    repo-specific-hooks     POST_COMPILE    .
-    repo-specific-hooks     POST_CREATE     .
-";
-}
-
-1;
-
-# ----------------------------------------------------------------------
-
-__DATA__
-# configuration variables for gitolite
-
-# This file is in perl syntax.  But you do NOT need to know perl to edit it --
-# just mind the commas, use single quotes unless you know what you're doing,
-# and make sure the brackets and braces stay matched up!
-
-# (Tip: perl allows a comma after the last item in a list also!)
-
-# HELP for commands can be had by running the command with "-h".
-
-# HELP for all the other FEATURES can be found in the documentation (look for
-# "list of non-core programs shipped with gitolite" in the master index) or
-# directly in the corresponding source file.
-
-%RC = (
-
-    # ------------------------------------------------------------------
-
-    # default umask gives you perms of '0700'; see the rc file docs for
-    # how/why you might change this
-    UMASK                           =>  0077,
-
-    # look for "git-config" in the documentation
-    GIT_CONFIG_KEYS                 =>  '',
-
-    # comment out if you don't need all the extra detail in the logfile
-    LOG_EXTRA                       =>  1,
-    # logging options
-    # 1. leave this section as is for 'normal' gitolite logging (default)
-    # 2. uncomment this line to log ONLY to syslog:
-    # LOG_DEST                      => 'syslog',
-    # 3. uncomment this line to log to syslog and the normal gitolite log:
-    # LOG_DEST                      => 'syslog,normal',
-    # 4. prefixing "repo-log," to any of the above will **also** log just the
-    #    update records to "gl-log" in the bare repo directory:
-    # LOG_DEST                      => 'repo-log,normal',
-    # LOG_DEST                      => 'repo-log,syslog',
-    # LOG_DEST                      => 'repo-log,syslog,normal',
-
-    # roles.  add more roles (like MANAGER, TESTER, ...) here.
-    #   WARNING: if you make changes to this hash, you MUST run 'gitolite
-    #   compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
-    ROLES => {
-        READERS                     =>  1,
-        WRITERS                     =>  1,
-    },
-
-    # enable caching (currently only Redis).  PLEASE RTFM BEFORE USING!!!
-    # CACHE                         =>  'Redis',
-
-    # ------------------------------------------------------------------
-
-    # rc variables used by various features
-
-    # the 'info' command prints this as additional info, if it is set
-        # SITE_INFO                 =>  'Please see http://blahblah/gitolite for more help',
-
-    # the CpuTime feature uses these
-        # display user, system, and elapsed times to user after each git operation
-        # DISPLAY_CPU_TIME          =>  1,
-        # display a warning if total CPU times (u, s, cu, cs) crosses this limit
-        # CPU_TIME_WARN_LIMIT       =>  0.1,
-
-    # the Mirroring feature needs this
-        # HOSTNAME                  =>  "foo",
-
-    # TTL for redis cache; PLEASE SEE DOCUMENTATION BEFORE UNCOMMENTING!
-        # CACHE_TTL                 =>  600,
-
-    # ------------------------------------------------------------------
-
-    # suggested locations for site-local gitolite code (see cust.html)
-
-        # this one is managed directly on the server
-        # LOCAL_CODE                =>  "$ENV{HOME}/local",
-
-        # or you can use this, which lets you put everything in a subdirectory
-        # called "local" in your gitolite-admin repo.  For a SECURITY WARNING
-        # on this, see http://gitolite.com/gitolite/non-core.html#pushcode
-        # LOCAL_CODE                =>  "$rc{GL_ADMIN_BASE}/local",
-
-    # ------------------------------------------------------------------
-
-    # List of commands and features to enable
-
-    ENABLE => [
-
-        # COMMANDS
-
-            # These are the commands enabled by default
-            'help',
-            'desc',
-            'info',
-            'perms',
-            'writable',
-
-            # Uncomment or add new commands here.
-            # 'create',
-            # 'fork',
-            # 'mirror',
-            # 'readme',
-            # 'sskm',
-            # 'D',
-
-        # These FEATURES are enabled by default.
-
-            # essential (unless you're using smart-http mode)
-            'ssh-authkeys',
-
-            # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz'
-            'git-config',
-
-            # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out
-            'daemon',
-
-            # creates projects.list file; if you don't use gitweb, comment this out
-            'gitweb',
-
-        # These FEATURES are disabled by default; uncomment to enable.  If you
-        # need to add new ones, ask on the mailing list :-)
-
-        # user-visible behaviour
-
-            # prevent wild repos auto-create on fetch/clone
-            # 'no-create-on-read',
-            # no auto-create at all (don't forget to enable the 'create' command!)
-            # 'no-auto-create',
-
-            # access a repo by another (possibly legacy) name
-            # 'Alias',
-
-            # give some users direct shell access.  See documentation in
-            # sts.html for details on the following two choices.
-            # "Shell $ENV{HOME}/.gitolite.shell-users",
-            # 'Shell alice bob',
-
-            # set default roles from lines like 'option default.roles-1 = ...', etc.
-            # 'set-default-roles',
-
-            # show more detailed messages on deny
-            # 'expand-deny-messages',
-
-            # show a message of the day
-            # 'Motd',
-
-        # system admin stuff
-
-            # enable mirroring (don't forget to set the HOSTNAME too!)
-            # 'Mirroring',
-
-            # allow people to submit pub files with more than one key in them
-            # 'ssh-authkeys-split',
-
-            # selective read control hack
-            # 'partial-copy',
-
-            # manage local, gitolite-controlled, copies of read-only upstream repos
-            # 'upstream',
-
-            # updates 'description' file instead of 'gitweb.description' config item
-            # 'cgit',
-
-            # allow repo-specific hooks to be added
-            # 'repo-specific-hooks',
-
-        # performance, logging, monitoring...
-
-            # be nice
-            # 'renice 10',
-
-            # log CPU times (user, system, cumulative user, cumulative system)
-            # 'CpuTime',
-
-        # syntactic_sugar for gitolite.conf and included files
-
-            # allow backslash-escaped continuation lines in gitolite.conf
-            # 'continuation-lines',
-
-            # create implicit user groups from directory names in keydir/
-            # 'keysubdirs-as-groups',
-
-            # allow simple line-oriented macros
-            # 'macros',
-
-        # Kindergarten mode
-
-            # disallow various things that sensible people shouldn't be doing anyway
-            # 'Kindergarten',
-    ],
-
-);
-
-# ------------------------------------------------------------------------------
-# per perl rules, this should be the last line in such a file:
-1;
-
-# Local variables:
-# mode: perl
-# End:
-# vim: set syn=perl:
diff --git a/docker/gitolite/src/lib/Gitolite/Setup.pm b/docker/gitolite/src/lib/Gitolite/Setup.pm
deleted file mode 100644
index 43de5d9..0000000
--- a/docker/gitolite/src/lib/Gitolite/Setup.pm
+++ /dev/null
@@ -1,169 +0,0 @@
-package Gitolite::Setup;
-
-# implements 'gitolite setup'
-# ----------------------------------------------------------------------
-
-=for args
-Usage:  gitolite setup [<option>]
-
-Setup gitolite, compile conf, run the POST_COMPILE trigger (see rc file) and
-propagate hooks.
-
-    -a, --admin <name>          admin name
-    -pk, --pubkey <file>        pubkey file name
-    -ho, --hooks-only           skip other steps and just propagate hooks
-
-First run: either the pubkey or the admin name is *required*, depending on
-whether you're using ssh mode or http mode.
-
-Subsequent runs:
-
-  - Without options, 'gitolite setup' is a general "fix up everything" command
-    (for example, if you brought in repos from outside, or someone messed
-    around with the hooks, or you made an rc file change that affects access
-    rules, etc.)
-
-  - '-pk' can be used to replace the admin key; useful if you lost the admin's
-    private key but do have shell access to the server.
-
-  - '-ho' is mainly for scripting use.  Do not combine with other options.
-
-  - '-a' is ignored
-
-=cut
-
-# ----------------------------------------------------------------------
-
- at EXPORT = qw(
-  setup
-);
-
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Store;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub setup {
-    my ( $admin, $pubkey, $h_only, $argv ) = args();
-
-    unless ($h_only) {
-        setup_glrc();
-        setup_gladmin( $admin, $pubkey, $argv );
-
-        _system("gitolite compile");
-        _system("gitolite trigger POST_COMPILE");
-    }
-
-    hook_repos();    # all of them, just to be sure
-}
-
-# ----------------------------------------------------------------------
-
-sub args {
-    my $admin  = '';
-    my $pubkey = '';
-    my $h_only = 0;
-    my $help   = 0;
-    my $argv   = join( " ", @ARGV );
-
-    require Getopt::Long;
-    Getopt::Long::GetOptions(
-        'admin|a=s'     => \$admin,
-        'pubkey|pk=s'   => \$pubkey,
-        'hooks-only|ho' => \$h_only,
-        'help|h'        => \$help,
-    ) or usage();
-
-    usage() if $help or ( $pubkey and $admin );
-    usage() if $h_only and ( $admin or $pubkey );
-
-    if ($pubkey) {
-        $pubkey =~ /\.pub$/                 or _die "'$pubkey' name does not end in .pub";
-        tsh_try("cat $pubkey")              or _die "'$pubkey' not a readable file";
-        tsh_lines() == 1                    or _die "'$pubkey' must have exactly one line";
-        tsh_try("ssh-keygen -l -f $pubkey") or _die "'$pubkey' does not seem to be a valid ssh pubkey file";
-
-        $admin = $pubkey;
-        # next 2 lines duplicated from args() in ssh-authkeys
-        $admin =~ s(.*/)();                # foo/bar/baz.pub -> baz.pub
-        $admin =~ s/(\@[^.]+)?\.pub$//;    # baz.pub, baz at home.pub -> baz
-        $pubkey =~ /\@/ and print STDERR "NOTE: the admin username is '$admin'\n";
-
-    }
-
-    return ( $admin || '', $pubkey || '', $h_only || 0, $argv );
-}
-
-sub setup_glrc {
-    _print( glrc('default-filename'), glrc('default-text') ) if not glrc('filename');
-}
-
-sub setup_gladmin {
-    my ( $admin, $pubkey, $argv ) = @_;
-    _die "'-pk' or '-a' required; see 'gitolite setup -h' for more"
-      if not $admin and not -f "$rc{GL_ADMIN_BASE}/conf/gitolite.conf";
-
-    # reminder: 'admin files' are in ~/.gitolite, 'admin repo' is
-    # $rc{GL_REPO_BASE}/gitolite-admin.git
-
-    # grab the pubkey content before we chdir() away
-    my $pubkey_content = '';
-    $pubkey_content = slurp($pubkey) if $pubkey;
-
-    # set up the admin files in admin-base
-
-    _mkdir( $rc{GL_ADMIN_BASE} );
-    _chdir( $rc{GL_ADMIN_BASE} );
-
-    _mkdir("conf");
-    _mkdir("logs");
-    my $conf;
-    {
-        local $/ = undef;
-        $conf = <DATA>;
-    }
-    $conf =~ s/%ADMIN/$admin/g;
-
-    _print( "conf/gitolite.conf", $conf ) if not -f "conf/gitolite.conf";
-
-    if ($pubkey) {
-        _mkdir("keydir");
-        _print( "keydir/$admin.pub", $pubkey_content );
-    }
-
-    # set up the admin repo in repo-base
-
-    _chdir();
-    _mkdir( $rc{GL_REPO_BASE} );
-    _chdir( $rc{GL_REPO_BASE} );
-
-    new_repo("gitolite-admin") if not -d "gitolite-admin.git";
-
-    # commit the admin files to the admin repo
-
-    $ENV{GIT_WORK_TREE} = $rc{GL_ADMIN_BASE};
-    _chdir("$rc{GL_REPO_BASE}/gitolite-admin.git");
-    _system("git add conf/gitolite.conf");
-    _system("git add keydir") if $pubkey;
-    tsh_try("git config --get user.email") or tsh_run( "git config user.email $ENV{USER}\@" . `hostname` );
-    tsh_try("git config --get user.name")  or tsh_run( "git config user.name '$ENV{USER} on '" . `hostname` );
-    tsh_try("git diff --cached --quiet")
-      or tsh_try("git commit -am 'gitolite setup $argv'")
-      or _die "setup failed to commit to the admin repo";
-    delete $ENV{GIT_WORK_TREE};
-}
-
-1;
-
-__DATA__
-repo gitolite-admin
-    RW+     =   %ADMIN
-
-repo testing
-    RW+     =   @all
diff --git a/docker/gitolite/src/lib/Gitolite/Test.pm b/docker/gitolite/src/lib/Gitolite/Test.pm
deleted file mode 100644
index 904abbf..0000000
--- a/docker/gitolite/src/lib/Gitolite/Test.pm
+++ /dev/null
@@ -1,122 +0,0 @@
-package Gitolite::Test;
-
-# functions for the test code to use
-# ----------------------------------------------------------------------
-
-#<<<
- at EXPORT = qw(
-  try
-  put
-  text
-  lines
-  dump
-  confreset
-  confadd
-  cmp
-  md5sum
-);
-#>>>
-use Exporter 'import';
-use File::Path qw(mkpath);
-use Carp qw(carp cluck croak confess);
-use Digest::MD5 qw(md5_hex);
-
-use Gitolite::Common;
-
-BEGIN {
-    require Gitolite::Test::Tsh;
-    *{'try'}   = \&Tsh::try;
-    *{'put'}   = \&Tsh::put;
-    *{'text'}  = \&Tsh::text;
-    *{'lines'} = \&Tsh::lines;
-    *{'cmp'}   = \&Tsh::cmp;
-}
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-# make sure the user is ready for it
-if ( not $ENV{GITOLITE_TEST} or $ENV{GITOLITE_TEST} ne 'y' ) {
-    print "Bail out! See t/README for information on how to run the tests.\n";
-    exit 255;
-}
-
-# required preamble for all tests
-try "
-    DEF gsh = /TRACE: gsh.SOC=/
-    DEF reject = /hook declined to update/; /remote rejected.*hook declined/; /error: failed to push some refs to/
-
-    DEF AP_1 = cd ../gitolite-admin; ok or die cant find admin repo clone;
-    DEF AP_2 = AP_1; git add conf ; ok; git commit -m %1; ok; /master.* %1/
-    DEF ADMIN_PUSH = AP_2 %1; glt push admin origin; ok; gsh; /master -> master/
-
-    DEF CS_1 = pwd; //tmp/tsh_tempdir.*gitolite-admin/; git remote -v; ok; /file:///gitolite-admin/
-    DEF CHECK_SETUP = CS_1; git log; ok; /fa7564c1b903ea3dce49314753f25b34b9e0cea0/
-
-    DEF CLONE = glt clone %1 file:///%2
-    DEF PUSH  = glt push %1 origin
-
-    # clean install
-    mkdir -p $ENV{HOME}/bin
-    ln -sf $ENV{PWD}/t/glt ~/bin
-    ./install -ln
-    cd; rm -vrf .gito* repositories
-    git config --file $ENV{HOME}/.gitconfig.local user.name \"gitolite tester\"
-    git config --file $ENV{HOME}/.gitconfig.local user.email \"tester\@example.com\"
-    git config --global                           include.path \"~/.gitconfig.local\"
-
-    # setup
-    gitolite setup -a admin
-
-    # clone admin repo
-    cd tsh_tempdir
-    glt clone admin --progress file:///gitolite-admin
-    cd gitolite-admin
-" or die "could not setup the test environment; errors:\n\n" . text() . "\n\n";
-
-sub dump {
-    use Data::Dumper;
-    for my $i (@_) {
-        print STDERR "DBG: " . Dumper($i);
-    }
-}
-
-sub _confargs {
-    return @_ if ( $_[1] );
-    return 'gitolite.conf', $_[0];
-}
-
-sub confreset {
-    chdir("../gitolite-admin") or die "in `pwd`, could not cd ../g-a";
-    system( "rm", "-rf", "conf" );
-    mkdir("conf");
-    system("mv ~/repositories/gitolite-admin.git ~/repositories/.ga");
-    system("mv ~/repositories/testing.git        ~/repositories/.te");
-    system("find ~/repositories -name '*.git' |xargs rm -rf");
-    system("mv ~/repositories/.ga ~/repositories/gitolite-admin.git");
-    system("mv ~/repositories/.te ~/repositories/testing.git       ");
-    put "|cut -c9- > conf/gitolite.conf", '
-        repo    gitolite-admin
-            RW+     =   admin
-        repo    testing
-            RW+     =   @all
-';
-}
-
-sub confadd {
-    chdir("../gitolite-admin") or die "in `pwd`, could not cd ../g-a";
-    my ( $file, $string ) = _confargs(@_);
-    put "|cat >> conf/$file", $string;
-}
-
-sub md5sum {
-    my $out = '';
-    for my $file (@_) {
-        $out .= md5_hex( slurp($file) ) . "  $file\n";
-    }
-    return $out;
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Test/Tsh.pm b/docker/gitolite/src/lib/Gitolite/Test/Tsh.pm
deleted file mode 100644
index 670178f..0000000
--- a/docker/gitolite/src/lib/Gitolite/Test/Tsh.pm
+++ /dev/null
@@ -1,643 +0,0 @@
-#!/usr/bin/perl
-use 5.10.0;
-
-# Tsh -- non interactive Testing SHell in perl
-
-# TODO items:
-# - allow an RC file to be used to add basic and extended commands
-# - convert internal defaults to additions to the RC file
-# - implement shell commands as you go
-# - solve the "pass/fail" inconsistency between shell and perl
-# - solve the pipes problem (use 'overload'?)
-
-# ----------------------------------------------------------------------
-# modules
-
-package Tsh;
-
-use Exporter 'import';
- at EXPORT = qw(
-  try run cmp AUTOLOAD
-  rc error_count text lines error_list put
-  cd tsh_tempdir
-
-  $HOME $PWD $USER
-);
- at EXPORT_OK = qw();
-
-use Env qw(@PATH HOME PWD USER TSH_VERBOSE);
-# other candidates:
-# GL_ADMINDIR GL_BINDIR GL_RC GL_REPO_BASE_ABS GL_REPO GL_USER
-
-use strict;
-use warnings;
-
-use Text::Tabs;    # only used for formatting the usage() message
-use Text::ParseWords;
-
-use File::Temp qw(tempdir);
-END { chdir( $ENV{HOME} ); }
-# we need this END handler *after* the 'use File::Temp' above.  Without
-# this, if $PWD at exit was $tempdir, you get errors like "cannot remove
-# path when cwd is [...] at /usr/share/perl5/File/Temp.pm line 902".
-
-use Data::Dumper;
-
-# ----------------------------------------------------------------------
-# globals
-
-my $rc;      # return code from backticked (external) programs
-my $text;    # STDOUT+STDERR of backticked (external) programs
-my $lec;     # the last external command (the rc and text are from this)
-my $cmd;     # the current command
-
-my $testnum;     # current test number, for info in TAP output
-my $testname;    # current test name, for error info to user
-my $line;        # current line number and text
-
-my $err_count;   # count of test failures
-my @errors_in;   # list of testnames that errored
-
-my $tick;        # timestamp for git commits
-
-my %autoloaded;
-my $tempdir = '';
-
-# ----------------------------------------------------------------------
-# setup
-
-# unbuffer STDOUT and STDERR
-select(STDERR); $|++;
-select(STDOUT); $|++;
-
-# set the timestamp (needed only under harness)
-test_tick() if $ENV{HARNESS_ACTIVE};
-
-# ----------------------------------------------------------------------
-# this is for one-liner access from outside, using @ARGV, as in:
-#   perl -MTsh -e 'tsh()' 'tsh command list'
-# or via STDIN
-#   perl -MTsh -e 'tsh()' < file-containing-tsh-commands
-# NOTE: it **exits**!
-
-sub tsh {
-    my @lines;
-
-    if (@ARGV) {
-        # simple, single argument which is a readable filename
-        if ( @ARGV == 1 and $ARGV[0] !~ /\s/ and -r $ARGV[0] ) {
-            # take the contents of the file
-            @lines = <>;
-        } else {
-            # more than one argument *or* not readable filename
-            # just take the arguments themselves as the command list
-            @lines = @ARGV;
-            @ARGV  = ();
-        }
-    } else {
-        # no arguments given, take STDIN
-        usage() if -t;
-        @lines = <>;
-    }
-
-    # and process them
-    try(@lines);
-
-    # print error summary by default
-    if ( not defined $TSH_VERBOSE ) {
-        say STDERR "$err_count error(s)" if $err_count;
-    }
-
-    exit $err_count;
-}
-
-# these two get called with series of tsh commands, while the autoload,
-# (later) handles single commands
-
-sub try {
-    $line = $rc = $err_count = 0;
-    @errors_in = ();
-
-    # break up multiline arguments into separate lines
-    my @lines = map { split /\n/ } @_;
-
-    # and process them
-    rc_lines(@lines);
-
-    # bump err_count if the last command had a non-0 rc (that was apparently not checked).
-    $err_count++ if $rc;
-
-    # finish up...
-    dbg( 1, "$err_count error(s)" ) if $err_count;
-    return ( not $err_count );
-}
-
-# run() differs from try() in that
-#   -   uses open(), not backticks
-#   -   takes only one command, not tsh-things like ok, /patt/ etc
-#   -   -   if you pass it an array it uses the list form!
-
-sub run {
-    open( my $fh, "-|", @_ ) or die "tell sitaram $!";
-    local $/ = undef; $text = <$fh>;
-    close $fh; warn "tell sitaram $!" if $!;
-    $rc = ( $? >> 8 );
-    return $text;
-}
-
-sub put {
-    my ( $file, $data ) = @_;
-    die "probable quoting error in arguments to put: $file\n" if $file =~ /^\s*['"]/;
-    my $mode = ">";
-    $mode = "|-" if $file =~ s/^\s*\|\s*//;
-
-    $rc = 0;
-    my $fh;
-    open( $fh, $mode, $file )
-      and print $fh $data
-      and close $fh
-      and return 1;
-
-    $rc = 1;
-    dbg( 1, "put $file: $!" );
-    return '';
-}
-
-# ----------------------------------------------------------------------
-# TODO: AUTOLOAD and exportable convenience subs for common shell commands
-
-sub cd {
-    my $dir = shift || '';
-    _cd($dir);
-    dbg( 1, "cd $dir: $!" ) if $rc;
-    return ( not $rc );
-}
-
-# this is classic AUTOLOAD, almost from the perlsub manpage.  Although, if
-# instead of `ls('bin');` you want to be able to say `ls 'bin';` you will need
-# to predeclare ls, with `sub ls;`.
-sub AUTOLOAD {
-    my $program = $Tsh::AUTOLOAD;
-    dbg( 4, "program = $program, arg=$_[0]" );
-    $program =~ s/.*:://;
-    $autoloaded{$program}++;
-
-    die "tsh's autoload support expects only one arg\n" if @_ > 1;
-    _sh("$program $_[0]");
-    return ( not $rc );    # perl truth
-}
-
-# ----------------------------------------------------------------------
-# exportable service subs
-
-sub rc {
-    return $rc || 0;
-}
-
-sub text {
-    return $text || '';
-}
-
-sub lines {
-    return split /\n/, $text;
-}
-
-sub error_count {
-    return $err_count;
-}
-
-sub error_list {
-    return (
-        wantarray
-        ? @errors_in
-        : join( "\n", @errors_in )
-    );
-}
-
-sub tsh_tempdir {
-    # create tempdir if not already done
-    $tempdir = tempdir( "tsh_tempdir.XXXXXXXXXX", TMPDIR => 1, CLEANUP => 1 ) unless $tempdir;
-    # XXX TODO that 'UNLINK' doesn't work for Ctrl_C
-
-    return $tempdir;
-}
-
-# ----------------------------------------------------------------------
-# internal (non-exportable) service subs
-
-sub print_plan {
-    return unless $ENV{HARNESS_ACTIVE};
-    local $_ = shift;
-    say "1..$_";
-}
-
-sub rc_lines {
-    my @lines = @_;
-
-    while (@lines) {
-        local $_ = shift @lines;
-        chomp; $_ = trim_ws($_);
-
-        $line++;
-
-        # this also sets $testname
-        next if is_comment_or_empty($_);
-
-        dbg( 2, "L: $_" );
-        $line .= ": $_";    # save line for printing with 'FAIL:'
-
-        # a DEF has to be on a line by itself
-        if (/^DEF\s+([-.\w]+)\s*=\s*(\S.*)$/) {
-            def( $1, $2 );
-            next;
-        }
-
-        my @cmds = cmds($_);
-
-        # process each command
-        # (note: some of the commands may put stuff back into @lines)
-        while (@cmds) {
-            # this needs to be the 'global' one, since fail() prints it
-            $cmd = shift @cmds;
-
-            # is the current command a "testing" command?
-            my $testing_cmd = (
-                   $cmd =~ m(^ok(?:\s+or\s+(.*))?$)
-                or $cmd =~ m(^!ok(?:\s+or\s+(.*))?$)
-                or $cmd =~ m(^/(.*?)/(?:\s+or\s+(.*))?$)
-                or $cmd =~ m(^!/(.*?)/(?:\s+or\s+(.*))?$)
-            );
-
-            # warn if the previous command failed but rc is not being checked
-            if ( $rc and not $testing_cmd ) {
-                dbg( 1, "rc: $rc from cmd prior to '$cmd'\n" );
-                # count this as a failure, for exit status purposes
-                $err_count++;
-                # and reset the rc, otherwise for example 'ls foo; tt; tt; tt'
-                # will tell you there are 3 errors!
-                $rc = 0;
-                push @errors_in, $testname if $testname;
-            }
-
-            # prepare to run the command
-            dbg( 3, "C: $cmd" );
-            if ( def($cmd) ) {
-                # expand macro and replace head of @cmds (unshift)
-                dbg( 2, "DEF: $cmd" );
-                unshift @cmds, cmds( def($cmd) );
-            } else {
-                parse($cmd);
-            }
-            # reset rc if checking is done
-            $rc = 0 if $testing_cmd;
-            # assumes you will (a) never have *both* 'ok' and '!ok' after
-            # an action command, and (b) one of them will come immediately
-            # after the action command, with /patt/ only after it.
-        }
-    }
-}
-
-sub def {
-    my ( $cmd, $list ) = @_;
-    state %def;
-    %def = read_rc_file() unless %def;
-
-    if ($list) {
-        # set mode
-        die "attempt to redefine macro $cmd\n" if $def{$cmd};
-        $def{$cmd} = $list;
-        return;
-    }
-
-    # get mode: split the $cmd at spaces, see if there is a definition
-    # available, substitute any %1, %2, etc., in it and send it back
-    my ( $c, @d ) = shellwords($cmd);
-    my $e;    # the expanded value
-    if ( $e = $def{$c} ) {    # starting value
-        for my $i ( 1 .. 9 ) {
-            last unless $e =~ /%$i/;                              # no more %N's (we assume sanity)
-            die "$def{$c} requires more arguments\n" unless @d;
-            my $f = shift @d;                                     # get the next datum
-            $e =~ s/%$i/$f/g;                                     # and substitute %N all over
-        }
-        return join( " ", $e, @d );                               # join up any remaining data
-    }
-    return '';
-}
-
-sub _cd {
-    my $dir = shift || $HOME;
-    # a directory name of 'tsh_tempdir' is special
-    $dir = tsh_tempdir() if $dir eq 'tsh_tempdir';
-    $rc = 0;
-    chdir($dir) or $rc = 1;
-}
-
-sub _sh {
-    my $cmd = shift;
-    # TODO: switch to IPC::Open3 or something...?
-
-    dbg( 4, "  running: ( $cmd ) 2>&1" );
-    $text = `( $cmd ) 2>&1; /bin/echo -n RC=\$?`;
-    $lec  = $cmd;
-    dbg( 4, "  results:\n$text" );
-
-    if ( $text =~ /RC=(\d+)$/ ) {
-        $rc = $1;
-        $text =~ s/RC=\d+$//;
-    } else {
-        die "couldnt find RC= in result; this should not happen:\n$text\n\n...\n";
-    }
-}
-
-sub _perl {
-    my $perl = shift;
-    local $_;
-    $_ = $text;
-
-    dbg( 4, "  eval: $perl" );
-    my $evrc = eval $perl;
-
-    if ($@) {
-        $rc = 1;    # shell truth
-        dbg( 1, $@ );
-        # leave $text unchanged
-    } else {
-        $rc = not $evrc;
-        # $rc is always shell truth, so we need to cover the case where
-        # there was no error but it still returned a perl false
-        $text = $_;
-    }
-    dbg( 4, "  eval-rc=$evrc, results:\n$text" );
-}
-
-sub parse {
-    my $cmd = shift;
-
-    if ( $cmd =~ /^sh (.*)/ ) {
-
-        _sh($1);
-
-    } elsif ( $cmd =~ /^perl (.*)/ ) {
-
-        _perl($1);
-
-    } elsif ( $cmd eq 'tt' or $cmd eq 'test-tick' ) {
-
-        test_tick();
-
-    } elsif ( $cmd =~ /^plan ?(\d+)$/ ) {
-
-        print_plan($1);
-
-    } elsif ( $cmd =~ /^cd ?(\S*)$/ ) {
-
-        _cd($1);
-
-    } elsif ( $cmd =~ /^ENV (\w+)=['"]?(.+?)['"]?$/ ) {
-
-        $ENV{$1} = $2;
-
-    } elsif ( $cmd =~ /^(?:tc|test-commit)\s+(\S.*)$/ ) {
-
-        # this is the only "git special" really; the default expansions are
-        # just that -- defaults.  But this one is hardwired!
-        dummy_commits($1);
-
-    } elsif ( $cmd =~ '^put(?:\s+(\S.*))?$' ) {
-
-        if ($1) {
-            put( $1, $text );
-        } else {
-            print $text if defined $text;
-        }
-
-    } elsif ( $cmd =~ m(^ok(?:\s+or\s+(.*))?$) ) {
-
-        $rc ? fail( "ok, rc=$rc from $lec", $1 || '' ) : ok();
-
-    } elsif ( $cmd =~ m(^!ok(?:\s+or\s+(.*))?$) ) {
-
-        $rc ? ok() : fail( "!ok, rc=0 from $lec", $1 || '' );
-
-    } elsif ( $cmd =~ m(^/(.*?)/(?:\s+or\s+(.*))?$) ) {
-
-        expect( $1, $2 );
-
-    } elsif ( $cmd =~ m(^!/(.*?)/(?:\s+or\s+(.*))?$) ) {
-
-        not_expect( $1, $2 );
-
-    } else {
-
-        _sh($cmd);
-
-    }
-}
-
-# currently unused
-sub executable {
-    my $cmd = shift;
-    # path supplied
-    $cmd =~ m(/) and -x $cmd and return 1;
-    # barename; look up in $PATH
-    for my $p (@PATH) {
-        -x "$p/$cmd" and return 1;
-    }
-    return 0;
-}
-
-sub ok {
-    $testnum++;
-    say "ok ($testnum)" if $ENV{HARNESS_ACTIVE};
-}
-
-sub fail {
-    $testnum++;
-    say "not ok ($testnum)" if $ENV{HARNESS_ACTIVE};
-
-    my $die = 0;
-    my ( $msg1, $msg2 ) = @_;
-    if ($msg2) {
-        # if arg2 is non-empty, print it regardless of debug level
-        $die = 1 if $msg2 =~ s/^die //;
-        say STDERR "# $msg2";
-    }
-
-    local $TSH_VERBOSE = 1 if $ENV{TSH_ERREXIT};
-    dbg( 1, "FAIL: $msg1", $testname || '', "test number $testnum", "L: $line", "results:\n$text" );
-
-    # count the error and add the testname to the list if it is set
-    $err_count++;
-    push @errors_in, $testname if $testname;
-
-    return unless $die or $ENV{TSH_ERREXIT};
-    dbg( 1, "exiting at cmd $cmd\n" );
-
-    exit( $rc || 74 );
-}
-
-sub cmp {
-    # compare input string with second input string or text()
-    my $in = shift;
-    my $text = ( @_ ? +shift : text() );
-
-    if ( $text eq $in ) {
-        ok();
-    } else {
-        fail( 'cmp failed', '' );
-        dbg( 4, "\n\ntext = <<<$text>>>, in = <<<$in>>>\n\n" );
-    }
-}
-
-sub expect {
-    my ( $patt, $msg ) = @_;
-    $msg =~ s/^\s+// if $msg;
-    my $sm;
-    if ( $sm = sm($patt) ) {
-        dbg( 4, "  M: $sm" );
-        ok();
-    } else {
-        fail( "/$patt/", $msg || '' );
-    }
-}
-
-sub not_expect {
-    my ( $patt, $msg ) = @_;
-    $msg =~ s/^\s+// if $msg;
-    my $sm;
-    if ( $sm = sm($patt) ) {
-        dbg( 4, "  M: $sm" );
-        fail( "!/$patt/", $msg || '' );
-    } else {
-        ok();
-    }
-}
-
-sub sm {
-    # smart match?  for now we just do regex match
-    my $patt = shift;
-
-    return ( $text =~ qr($patt) ? $& : "" );
-}
-
-sub trim_ws {
-    local $_ = shift;
-    s/^\s+//; s/\s+$//;
-    return $_;
-}
-
-sub is_comment_or_empty {
-    local $_ = shift;
-    chomp; $_ = trim_ws($_);
-    if (/^##\s(.*)/) {
-        $testname = $1;
-        say "# $1";
-    }
-    return ( /^#/ or /^$/ );
-}
-
-sub cmds {
-    local $_ = shift;
-    chomp; $_ = trim_ws($_);
-
-    # split on unescaped ';'s, then unescape the ';' in the results
-    my @cmds = map { s/\\;/;/g; $_ } split /(?<!\\);/;
-    @cmds = grep { $_ = trim_ws($_); /\S/; } @cmds;
-    return @cmds;
-}
-
-sub dbg {
-    return unless $TSH_VERBOSE;
-    my $level = shift;
-    return unless $TSH_VERBOSE >= $level;
-    my $all = join( "\n", grep( /./, @_ ) );
-    chomp($all);
-    $all =~ s/\n/\n\t/g;
-    say STDERR "# $all";
-}
-
-sub ddump {
-    for my $i (@_) {
-        print STDERR "DBG: " . Dumper($i);
-    }
-}
-
-sub usage {
-    # TODO
-    print "Please see documentation at:
-
-        https://github.com/sitaramc/tsh/blob/master/README.mkd
-
-Meanwhile, here are your local 'macro' definitions:
-
-";
-    my %m = read_rc_file();
-    my @m = map { "$_\t$m{$_}\n" } sort keys %m;
-    $tabstop = 16;
-    print join( "", expand(@m) );
-    exit 1;
-}
-
-# ----------------------------------------------------------------------
-# git-specific internal service subs
-
-sub dummy_commits {
-    for my $f ( split ' ', shift ) {
-        if ( $f eq 'tt' or $f eq 'test-tick' ) {
-            test_tick();
-            next;
-        }
-        my $ts = ( $tick ? gmtime( $tick + 19800 ) : gmtime() );
-        _sh("echo $f at $ts >> $f && git add $f && git commit -m '$f at $ts'");
-    }
-}
-
-sub test_tick {
-    unless ( $ENV{HARNESS_ACTIVE} ) {
-        sleep 1;
-        return;
-    }
-    $tick += 60 if $tick;
-    $tick ||= 1310000000;
-    $ENV{GIT_COMMITTER_DATE} = "$tick +0530";
-    $ENV{GIT_AUTHOR_DATE}    = "$tick +0530";
-}
-
-# ----------------------------------------------------------------------
-# the internal macros, for easy reference and reading
-
-sub read_rc_file {
-    my $rcfile = "$HOME/.tshrc";
-    my $rctext;
-    if ( -r $rcfile ) {
-        local $/ = undef;
-        open( my $rcfh, "<", $rcfile ) or die "this should not happen: $!\n";
-        $rctext = <$rcfh>;
-    } else {
-        # this is the default "rc" content
-        $rctext = "
-            add         =   git add
-            branch      =   git branch
-            clone       =   git clone
-            checkout    =   git checkout
-            commit      =   git commit
-            fetch       =   git fetch
-            init        =   git init
-            push        =   git push
-            reset       =   git reset
-            tag         =   git tag
-
-            empty       =   git commit --allow-empty -m empty
-            push-om     =   git push origin master
-            reset-h     =   git reset --hard
-            reset-hu    =   git reset --hard \@{u}
-        "
-    }
-
-    # ignore everything except lines of the form "aa = bb cc dd"
-    my %commands = ( $rctext =~ /^\s*([-.\w]+)\s*=\s*(\S.*)$/gm );
-    return %commands;
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers.pm b/docker/gitolite/src/lib/Gitolite/Triggers.pm
deleted file mode 100644
index 16e8aa6..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers.pm
+++ /dev/null
@@ -1,33 +0,0 @@
-package Gitolite::Triggers;
-
-# load and run triggered modules
-# ----------------------------------------------------------------------
-
-#<<<
- at EXPORT = qw(
-);
-#>>>
-use Exporter 'import';
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-
-sub run {
-    my ( $module, $sub, @args ) = @_;
-    $module = "Gitolite::Triggers::$module" if $module !~ /^Gitolite::/;
-
-    eval "require $module";
-    _die "$@" if $@;
-    my $subref;
-    eval "\$subref = \\\&$module" . "::" . "$sub";
-    _die "module '$module' does not exist or does not have sub '$sub'" unless ref($subref) eq 'CODE';
-
-    $subref->(@args);
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/Alias.pm b/docker/gitolite/src/lib/Gitolite/Triggers/Alias.pm
deleted file mode 100644
index 1fa24bb..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/Alias.pm
+++ /dev/null
@@ -1,128 +0,0 @@
-package Gitolite::Triggers::Alias;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-# aliasing a repo to another
-# ----------------------------------------------------------------------
-
-=for usage
-
-Why:
-
-    We had an existing repo "foo" that lots of people use.  We wanted to
-    rename it to "foo/code", so that related repos "foo/upstream" and
-    "foo/docs" (both containing stuff we did not want to put in "foo") could
-    also be made and then the whole thing would be structured nicely.
-
-    At the same time we did not want to *force* all the users to change the
-    name.  At least git operations should still work with the old name,
-    although it is OK for "info" and other "commands" to display/require the
-    proper name (i.e., the new name).
-
-How:
-
-  * uncomment the line "Alias" in the "user-visible behaviour" section in the
-    rc file
-
-  * add a new variable REPO_ALIASES to the rc file, with entries like:
-
-        REPO_ALIASES                =>
-            {
-                # if you need a more aggressive warning message than the default
-                WARNING             => "Please change your URLs to use '%new'; '%old' will not work after XXXX-XX-XX",
-
-                # prefix mapping section
-                PREFIX_MAPS         =>  {
-                    # note: NO leading slash in keys or values below
-                    'var/lib/git/'  =>  '',
-                    'var/opt/git/'  =>  'opt/',
-                },
-
-                # individual repo mapping section
-                'foo'               =>  'foo/code',
-
-                # force users to change their URLs
-                'bar'               =>  '301/bar/code',
-                    # a target repo starting with "301/" won't actually work;
-                    # it will just produce an error message pointing the user
-                    # to the new name.  This allows admins to force users to
-                    # fix their URLs.
-            },
-
-    If a prefix map is supplied, each key is checked (in *undefined* order),
-    and the *first* key which matches the prefix of the repo will be applied.
-    If more than one key matches (for example if you specify '/abc/def' as one
-    key, and '/abc' as another), it is undefined which will get picked up.
-
-    The result of this, (or the original repo name if no map was found), will
-    then be subject to the individual repo mappings.  Since these are full
-    repo names, there is no possibility of multiple matches.
-
-Notes:
-
-  * only git operations (clone/fetch/push) are alias aware.  Nothing else in
-    gitolite, such as all the gitolite commands etc., are alias-aware and will
-    always use/require the proper repo name.
-
-  * http mode has not been tested and will not be.  If someone has the time to
-    test it and make it work please let me know.
-
-  * funnily enough, this even works with mirroring!  That is, a master can
-    push a repo "foo" to a slave per its configuration, while the slave thinks
-    it is getting repo "bar" from the master per its configuration.
-
-    Just make sure to put the Alias::input line *before* the Mirroring::input
-    line in the rc file on the slave.
-
-    However, it will probably not work with redirected pushes unless you setup
-    the opposite alias ("bar" -> "foo") on master.
-=cut
-
-sub input {
-    my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-    my $user = $ARGV[0] || '@all';    # user name is undocumented for now
-
-    if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /(?:$git_commands) '\/?(\S+)'$/ ) {
-        my $repo = $1;
-        ( my $norm = $repo ) =~ s/\.git$//;    # normalised repo name
-
-        my $target = $norm;
-
-        # prefix maps first
-        my $pm = $rc{REPO_ALIASES}{PREFIX_MAPS} || {};
-        while (my($k, $v) = each %$pm) {
-            last if $target =~ s/^$k/$v/;
-            # no /i, /g, etc. by design
-        }
-
-        # individual repo map next
-        $target = $rc{REPO_ALIASES}{$target} || $target;
-
-        # undocumented; don't use without discussing on mailing list
-        $target = $target->{$user} if ref($target) eq 'HASH';
-
-        # if the repo name finally maps to empty, we bail, with no changes
-        return unless $target;
-
-        # we're done.  Did we actually change anything?
-        return if $norm eq $target;
-
-        # if the new name starts with "301/", inform and abort
-        _die "please use '$target' instead of '$norm'" if $target =~ s(^301/)();
-        # otherwise print a warning and continue with the new name
-        my $wm = $rc{REPO_ALIASES}{WARNING} || "'%old' is an alias for '%new'";
-        $wm =~ s/%new/$target/g;
-        $wm =~ s/%old/$norm/g;
-        _warn $wm;
-
-        $ENV{SSH_ORIGINAL_COMMAND} =~ s/'\/?$repo'/'$target'/;
-    }
-
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/AutoCreate.pm b/docker/gitolite/src/lib/Gitolite/Triggers/AutoCreate.pm
deleted file mode 100644
index e1d977a..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/AutoCreate.pm
+++ /dev/null
@@ -1,24 +0,0 @@
-package Gitolite::Triggers::AutoCreate;
-
-use strict;
-use warnings;
-
-# perl trigger set for stuff to do with auto-creating repos
-# ----------------------------------------------------------------------
-
-# to deny auto-create on read access, uncomment 'no-create-on-read' in the
-# ENABLE list in the rc file
-sub deny_R {
-    die "autocreate denied\n" if $_[3] and $_[3] eq 'R';
-    return;
-}
-
-# to deny auto-create on read *and* write, uncomment 'no-auto-create' in the
-# ENABLE list in the rc file.  This means you can only create wild repos using
-# the 'create' command, (which needs to be enabled in the ENABLE list).
-sub deny_RW {
-    die "autocreate denied\n" if $_[3] and ( $_[3] eq 'R' or $_[3] eq 'W' );
-    return;
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/CpuTime.pm b/docker/gitolite/src/lib/Gitolite/Triggers/CpuTime.pm
deleted file mode 100644
index 74b4217..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/CpuTime.pm
+++ /dev/null
@@ -1,52 +0,0 @@
-package Gitolite::Triggers::CpuTime;
-
-use Time::HiRes;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# cpu and elapsed times for gitolite+git operations
-# ----------------------------------------------------------------------
-# uncomment the appropriate lines in the rc file to enable this
-
-# Ideally, you will (a) write your own code with a different filename so later
-# gitolite upgrades won't overwrite your copy, (b) add appropriate variables
-# to the rc file, and (c) change your rc file to call your program instead.
-
-# ----------------------------------------------------------------------
-my $start_time;
-
-sub input {
-    _warn "something wrong with the invocation of CpuTime::input" if $ENV{GL_TID} ne $$;
-    $start_time = [ Time::HiRes::gettimeofday() ];
-}
-
-sub post_git {
-    _warn "something wrong with the invocation of CpuTime::post_git" if $ENV{GL_TID} ne $$;
-
-    my ( $trigger, $repo, $user, $aa, $ref, $verb ) = @_;
-    my ( $utime, $stime, $cutime, $cstime ) = times();
-    my $elapsed = Time::HiRes::tv_interval($start_time);
-
-    gl_log( 'times', $utime, $stime, $cutime, $cstime, $elapsed );
-
-    # now do whatever you want with the data; the following is just an example.
-
-    if ( my $limit = $rc{CPU_TIME_WARN_LIMIT} ) {
-        my $total = $utime + $cutime + $stime + $cstime;
-        # some code to send an email or whatever...
-        say2 "limit = $limit, actual = $total" if $total > $limit;
-    }
-
-    if ( $rc{DISPLAY_CPU_TIME} ) {
-        say2 "perf stats for $verb on repo '$repo':";
-        say2 "  user CPU time: " . ( $utime + $cutime );
-        say2 "  sys  CPU time: " . ( $stime + $cstime );
-        say2 "   elapsed time: " . $elapsed;
-    }
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/Kindergarten.pm b/docker/gitolite/src/lib/Gitolite/Triggers/Kindergarten.pm
deleted file mode 100755
index 6274c3d..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/Kindergarten.pm
+++ /dev/null
@@ -1,99 +0,0 @@
-package Gitolite::Triggers::Kindergarten;
-
-# http://www.great-quotes.com/quote/424177
-#   "Doctor, it hurts when I do this."
-#   "Then don't do that!"
-
-# Prevent various things that sensible people shouldn't be doing anyway. List
-# of things it prevents is at the end of the program.
-
-# If you were forced to enable this module because someone is *constantly*
-# doing things that need to be caught, consider getting rid of that person.
-# Because, really, who knows what *else* he/she is doing that can't be caught
-# with some clever bit of code?
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-my %active;
-sub active {
-    # in rc, you either see just 'Kindergarten' to activate all features, or
-    # 'Kindergarten U0 CREATOR' (i.e., a space sep list of features after the
-    # word Kindergarten) to activate only those named features.
-
-    # no features specifically activated; implies all of them are active
-    return 1 if not %active;
-    # else check if this specific feature is active
-    return 1 if $active{ +shift };
-
-    return 0;
-}
-
-my ( $verb, $repo, $cmd, $args );
-sub input {
-    # get the features to be activated, if supplied
-    while ( $_[0] ne 'INPUT' ) {
-        $active{ +shift } = 1;
-    }
-
-    # generally fill up variables you might use later
-    my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-    if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /($git_commands) '\/?(\S+)'$/ ) {
-        $verb = $1;
-        $repo = $2;
-    } elsif ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^(\S+) (.*)$/ ) {
-        $cmd  = $1;
-        $args = $2;
-    }
-
-    prevent_CREATOR($repo) if active('CREATOR') and $verb;
-    prevent_0(@ARGV)       if active('U0')      and @ARGV;
-}
-
-sub prevent_CREATOR {
-    my $repo = shift;
-    _die "'CREATOR' not allowed as part of reponame" if $repo =~ /\bCREATOR\b/;
-}
-
-sub prevent_0 {
-    my $user = shift;
-    _die "'0' is not a valid username" if $user eq '0';
-}
-
-1;
-
-__END__
-
-CREATOR
-
-    prevent literal 'CREATOR' from being part of a repo name
-
-    a quirk deep inside gitolite would let this config
-
-        repo foo/CREATOR/..*
-            C   =   ...
-
-    allow the creation of repos like "foo/CREATOR/bar", i.e., the word CREATOR is
-    literally used.
-
-    I consider this a totally pathological situation to check for.  The worst that
-    can happen is someone ends up cluttering the server with useless repos.
-
-    One solution could be to prevent this only for wild repos, but I can't be
-    bothered to fine tune this, so this module prevents even normal repos from
-    having the literal CREATOR in them.
-
-    See https://groups.google.com/forum/#!topic/gitolite/cS34Vxix0Us for more.
-
-U0
-
-    prevent a user from being called literal '0'
-
-    Ideally we should prevent keydir/0.pub (or variants) from being created,
-    but for "Then don't do that" purposes it's enough to prevent the user from
-    logging in.
-
-    See https://groups.google.com/forum/#!topic/gitolite/F1IBenuSTZo for more.
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/Mirroring.pm b/docker/gitolite/src/lib/Gitolite/Triggers/Mirroring.pm
deleted file mode 100644
index c88fc92..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/Mirroring.pm
+++ /dev/null
@@ -1,253 +0,0 @@
-package Gitolite::Triggers::Mirroring;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-my $hn           = $rc{HOSTNAME};
-
-my ( $mode, $master, %slaves, %trusted_slaves );
-
-# ----------------------------------------------------------------------
-
-sub input {
-    unless ( $ARGV[0] =~ /^server-(\S+)$/ ) {
-        _die "'$ARGV[0]' is not a valid server name" if $ENV{SSH_ORIGINAL_COMMAND} =~ /^USER=(\S+) SOC=(git-receive-pack '(\S+)')$/;
-        return;
-    }
-
-    # note: we treat %rc as our own internal "poor man's %ENV"
-    $rc{FROM_SERVER} = $1;
-    trace( 3, "from_server: $1" );
-    my $sender = $rc{FROM_SERVER} || '';
-
-    # custom peer-to-peer commands.  At present the only one is 'perms -c',
-    # sent from a mirror command
-    if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^CREATOR=(\S+) perms -c '(\S+)'$/ ) {
-        $ENV{GL_USER} = $1;
-
-        my $repo = $2;
-        details($repo);
-        _die "$hn: '$repo' is local"                        if $mode eq 'local';
-        _die "$hn: '$repo' is native"                       if $mode eq 'master';
-        _die "$hn: '$sender' is not the master for '$repo'" if $master ne $sender;
-
-        # this expects valid perms content on STDIN
-        _system("gitolite perms -c $repo");
-
-        # we're done.  Yes, really...
-        exit 0;
-    }
-
-    if ( $ENV{SSH_ORIGINAL_COMMAND} =~ /^USER=(\S+) SOC=(git-receive-pack '(\S+)')$/ ) {
-        # my ($user, $newsoc, $repo) = ($1, $2, $3);
-        $ENV{SSH_ORIGINAL_COMMAND} = $2;
-        @ARGV                      = ($1);
-        $rc{REDIRECTED_PUSH}       = 1;
-        trace( 3, "redirected_push for user $1" );
-    } else {
-        # master -> slave push, no access checks needed
-        $ENV{GL_BYPASS_ACCESS_CHECKS} = 1;
-    }
-}
-
-# ----------------------------------------------------------------------
-
-sub pre_git {
-    return unless $hn;
-    # nothing, and I mean NOTHING, happens if HOSTNAME is not set
-    trace( 3, "pre_git() on $hn" );
-
-    my ( $repo, $user, $aa ) = @_[ 1, 2, 3 ];
-
-    my $sender = $rc{FROM_SERVER} || '';
-    $user = '' if $sender and not exists $rc{REDIRECTED_PUSH};
-
-    # ------------------------------------------------------------------
-    # now you know the repo, get its mirroring details
-    details($repo);
-
-    # print mirror status if at least one slave status file is present
-    print_status( $repo ) if not $rc{HUSH_MIRROR_STATUS} and $mode ne 'local' and glob("$rc{GL_REPO_BASE}/$repo.git/gl-slave-*.status");
-
-    # we don't deal with any reads.  Note that for pre-git this check must
-    # happen *after* getting details, to give mode() a chance to die on "known
-    # unknown" repos (repos that are in the config, but mirror settings
-    # exclude this host from both the master and slave lists)
-    return if $aa eq 'R';
-
-    trace( 1, "mirror", "pre_git", $repo, "user=$user", "sender=$sender", "mode=$mode", ( $rc{REDIRECTED_PUSH} ? ("redirected") : () ) );
-
-    # ------------------------------------------------------------------
-    # case 1: we're master or slave, normal user pushing to us
-    if ( $user and not $rc{REDIRECTED_PUSH} ) {
-        trace( 3, "case 1, user push" );
-        return if $mode eq 'local' or $mode eq 'master';
-        if ( $trusted_slaves{$hn} ) {
-            trace( 1, "redirect to $master" );
-            exec( "ssh", $master, "USER=$user", "SOC=$ENV{SSH_ORIGINAL_COMMAND}" );
-        } else {
-            _die "$hn: pushing '$repo' to slave '$hn' not allowed";
-        }
-    }
-
-    # ------------------------------------------------------------------
-    # case 2: we're slave, master pushing to us
-    if ( $sender and not $rc{REDIRECTED_PUSH} ) {
-        trace( 3, "case 2, master push" );
-        _die "$hn: '$repo' is local"                        if $mode eq 'local';
-        _die "$hn: '$repo' is native"                       if $mode eq 'master';
-        _die "$hn: '$sender' is not the master for '$repo'" if $master ne $sender;
-        return;
-    }
-
-    # ------------------------------------------------------------------
-    # case 3: we're master, slave sending a redirected push to us
-    if ( $sender and $rc{REDIRECTED_PUSH} ) {
-        trace( 3, "case 2, slave redirect" );
-        _die "$hn: '$repo' is local"                           if $mode eq 'local';
-        _die "$hn: '$repo' is not native"                      if $mode eq 'slave';
-        _die "$hn: '$sender' is not a valid slave for '$repo'" if not $slaves{$sender};
-        _die "$hn: redirection not allowed from '$sender'"     if not $trusted_slaves{$sender};
-        return;
-    }
-
-    _die "$hn: should not reach this line";
-
-}
-
-# ----------------------------------------------------------------------
-
-sub post_git {
-    return unless $hn;
-    # nothing, and I mean NOTHING, happens if HOSTNAME is not set
-    trace( 1, "post_git() on $hn" );
-
-    my ( $repo, $user, $aa ) = @_[ 1, 2, 3 ];
-    # we don't deal with any reads
-    return if $aa eq 'R';
-
-    my $sender = $rc{FROM_SERVER} || '';
-    $user = '' if $sender;
-
-    # ------------------------------------------------------------------
-    # now you know the repo, get its mirroring details
-    details($repo);
-
-    trace( 1, "mirror", "post_git", $repo, "user=$user", "sender=$sender", "mode=$mode", ( $rc{REDIRECTED_PUSH} ? ("redirected") : () ) );
-
-    # ------------------------------------------------------------------
-    # case 1: we're master or slave, normal user pushing to us
-    if ( $user and not $rc{REDIRECTED_PUSH} ) {
-        trace( 3, "case 1, user push" );
-        return if $mode eq 'local';
-        # slave was eliminated earlier anyway, so that leaves 'master'
-
-        # find all slaves and push to each of them
-        push_to_slaves($repo);
-
-        return;
-    }
-
-    # ------------------------------------------------------------------
-    # case 2: we're slave, master pushing to us
-    if ( $sender and not $rc{REDIRECTED_PUSH} ) {
-        trace( 3, "case 2, master push" );
-        # nothing to do
-        return;
-    }
-
-    # ------------------------------------------------------------------
-    # case 3: we're master, slave sending a redirected push to us
-    if ( $sender and $rc{REDIRECTED_PUSH} ) {
-        trace( 3, "case 2, slave redirect" );
-
-        # find all slaves and push to each of them
-        push_to_slaves($repo);
-
-        return;
-    }
-}
-
-{
-    my $lastrepo = '';
-
-    sub details {
-        my $repo = shift;
-        return if $lastrepo eq $repo;
-
-        $master         = master($repo);
-        %slaves         = slaves($repo);
-        $mode           = mode($repo);
-        %trusted_slaves = trusted_slaves($repo);
-        trace( 3, $master, $mode, join( ",", sort keys %slaves ), join( ",", sort keys %trusted_slaves ) );
-    }
-
-    sub master {
-        return option( +shift, 'mirror.master' );
-    }
-
-    sub slaves {
-        my $repo = shift;
-
-        my $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves.*" );
-        my %out = map { $_ => 'async' } map { split } values %$ref;
-
-        $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves\\.sync.*" );
-        map { $out{$_} = 'sync' } map { split } values %$ref;
-
-        $ref = git_config( $repo, "^gitolite-options\\.mirror\\.slaves\\.nosync.*" );
-        map { $out{$_} = 'nosync' } map { split } values %$ref;
-
-        return %out;
-    }
-
-    sub trusted_slaves {
-        my $ref = git_config( +shift, "^gitolite-options\\.mirror\\.redirectOK.*" );
-        # the list of trusted slaves (where we accept redirected pushes from)
-        # is either explicitly given...
-        my @out = map { split } values %$ref;
-        my %out = map { $_ => 1 } @out;
-        # ...or it's all the slaves mentioned if the list is just a "all"
-        %out = %slaves if ( @out == 1 and $out[0] eq 'all' );
-        return %out;
-    }
-
-    sub mode {
-        my $repo = shift;
-        return 'local'  if not $hn;
-        return 'master' if $master eq $hn;
-        return 'slave'  if $slaves{$hn};
-        return 'local'  if not $master and not %slaves;
-        _die "$hn: '$repo' is mirrored but not here";
-    }
-}
-
-sub push_to_slaves {
-    my $repo = shift;
-
-    my $u = $ENV{GL_USER};
-    delete $ENV{GL_USER};    # why?  see src/commands/mirror
-
-    for my $s ( sort keys %slaves ) {
-        system("gitolite mirror push $s $repo </dev/null >/dev/null 2>&1 &") if $slaves{$s} eq 'async';
-        system("gitolite mirror push $s $repo </dev/null >/dev/null 2>&1")   if $slaves{$s} eq 'sync';
-        _warn "manual mirror push pending for '$s'"                          if $slaves{$s} eq 'nosync';
-    }
-
-    $ENV{GL_USER} = $u;
-}
-
-sub print_status {
-    my $repo = shift;
-    my $u = $ENV{GL_USER};
-    delete $ENV{GL_USER};
-    system("gitolite mirror status all $repo >&2");
-    $ENV{GL_USER} = $u;
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/Motd.pm b/docker/gitolite/src/lib/Gitolite/Triggers/Motd.pm
deleted file mode 100644
index 6de80a2..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/Motd.pm
+++ /dev/null
@@ -1,29 +0,0 @@
-package Gitolite::Triggers::Motd;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# print a message of the day to STDERR
-# ----------------------------------------------------------------------
-
-my $file = "gl-motd";
-
-sub input {
-    # at present, we print it for every single interaction with gitolite.  We
-    # may want to change that later; if we do, get code from Kindergarten.pm
-    # to get the gitcmd+repo or cmd+args so you can filter on them
-
-    my $f = "$rc{GL_ADMIN_BASE}/$file";
-    print STDERR slurp($f) if -f $f;
-}
-
-sub pre_git {
-    my $repo = $_[1];
-    my $f    = "$rc{GL_REPO_BASE}/$repo.git/$file";
-    print STDERR slurp($f) if -f $f;
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/RefexExpr.pm b/docker/gitolite/src/lib/Gitolite/Triggers/RefexExpr.pm
deleted file mode 100644
index e913665..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/RefexExpr.pm
+++ /dev/null
@@ -1,80 +0,0 @@
-package Gitolite::Triggers::RefexExpr;
-use strict;
-use warnings;
-
-# track refexes passed and evaluate expressions on them
-# ----------------------------------------------------------------------
-# see src/VREF/refex-expr for instructions and WARNINGS!
-
-use Gitolite::Easy;
-
-my %passed;
-my %rules;
-my $init_done = 0;
-
-sub access_2 {
-    # get out quick for repos that don't have any rules
-    return if $init_done and not %rules;
-
-    # but we don't really know that the first time, heh!
-    if ( not $init_done ) {
-        my $repo = $_[1];
-        init($repo);
-        return unless %rules;
-    }
-
-    my $refex = $_[5];
-    return if $refex =~ /DENIED/;
-
-    $passed{$refex}++;
-
-    # evaluate the rules each time; it's not very expensive
-    for my $k ( sort keys %rules ) {
-        $ENV{ "GL_REFEX_EXPR_" . $k } = eval_rule( $rules{$k} );
-    }
-}
-
-sub eval_rule {
-    my $rule = shift;
-
-    my $e;
-    $e = join " ", map { convert($_) } split ' ', $rule;
-
-    my $ret = eval $e;
-    _die "eval '$e' -> '$@'" if $@;
-    Gitolite::Common::trace( 1, "RefexExpr", "'$rule' -> '$e' -> '$ret'" );
-
-    return "'$rule' -> '$e'" if $ret;
-}
-
-my %constant;
-%constant = map { $_ => $_ } qw(1 not and or xor + - ==);
-$constant{'-lt'} = '<';
-$constant{'-gt'} = '>';
-$constant{'-eq'} = '==';
-$constant{'-le'} = '<=';
-$constant{'-ge'} = '>=';
-$constant{'-ne'} = '!=';
-
-sub convert {
-    my $i = shift;
-    return $i if $i =~ /^-?\d+$/;
-    return $constant{$i} || $passed{$i} || $passed{"refs/heads/$i"} || 0;
-}
-
-# called only once
-sub init {
-    $init_done = 1;
-    my $repo = shift;
-
-    # find all the rule expressions
-    my %t = config( $repo, "^gitolite-options\\.refex-expr\\." );
-    my ( $k, $v );
-    # get rid of the cruft and store just the rule name as the key
-    while ( ( $k, $v ) = each %t ) {
-        $k =~ s/^gitolite-options\.refex-expr\.//;
-        $rules{$k} = $v;
-    }
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/RepoUmask.pm b/docker/gitolite/src/lib/Gitolite/Triggers/RepoUmask.pm
deleted file mode 100644
index 109cb31..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/RepoUmask.pm
+++ /dev/null
@@ -1,58 +0,0 @@
-package Gitolite::Triggers::RepoUmask;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-# setting a repo specific umask
-# ----------------------------------------------------------------------
-# this is for people who are too paranoid to trust e.g., gitweb's repo
-# exclusion logic, but not paranoid enough to put it on a different server
-
-=for usage
-
-  * In the rc file, add the line
-        'RepoUmask',
-    somewhere in the ENABLE list
-
-  * For each repo that is to get a different umask than the default, add a
-    line like this:
-
-        option umask = 0027
-
-=cut
-
-# sadly option/config values are not available at pre_create time for normal
-# repos.  So we have to do a one-time fixup in a post_create trigger.
-sub post_create {
-    my $repo = $_[1];
-
-    my $umask = option( $repo, 'umask' );
-    _chdir( $rc{GL_REPO_BASE} );    # because using option() moves us to ADMIN_BASE!
-
-    return unless $umask;
-
-    # unlike the one in the rc file, this is a string
-    $umask = oct($umask);
-    my $mode = "0" . sprintf( "%o", $umask ^ 0777 );
-
-    system("chmod -R $mode $repo.git >&2");
-    system("find $repo.git -type f -exec chmod a-x '{}' \\;");
-}
-
-sub pre_git {
-    my $repo = $_[1];
-
-    my $umask = option( $repo, 'umask' );
-    _chdir( $rc{GL_REPO_BASE} );    # because using option() moves us to ADMIN_BASE!
-
-    return unless $umask;
-
-    # unlike the one in the rc file, this is a string
-    umask oct($umask);
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/Shell.pm b/docker/gitolite/src/lib/Gitolite/Triggers/Shell.pm
deleted file mode 100644
index a2c5c0d..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/Shell.pm
+++ /dev/null
@@ -1,66 +0,0 @@
-package Gitolite::Triggers::Shell;
-
-# usage notes: uncomment 'Shell' in the ENABLE list in the rc file.
-
-# documentation is in the ssh troubleshooting and tips document, under the
-# section "giving shell access to gitolite users"
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-# fedora likes to do things that are a little off the beaten track, compared
-# to typical gitolite usage:
-# - every user has their own login
-# - the forced command may not get the username as an argument.  If it does
-#   not, the gitolite user name is $USER (the unix user name)
-# - and finally, if the first argument to the forced command is '-s', and
-#   $SSH_ORIGINAL_COMMAND is empty or runs a non-git/gitolite command, then
-#   the user gets a shell
-
-sub input {
-    my $shell_allowed = 0;
-    if ( @ARGV and $ARGV[0] eq '-s' ) {
-        shift @ARGV;
-        $shell_allowed++;
-    }
-
-    @ARGV = ( $ENV{USER} ) unless @ARGV;
-
-    return unless $shell_allowed;
-
-    # now determine if this was intended as a shell command or git/gitolite
-    # command
-
-    my $soc = $ENV{SSH_ORIGINAL_COMMAND};
-
-    # no command, just 'ssh alice at host'; doesn't return ('exec's out)
-    shell_out() if $shell_allowed and not $soc;
-
-    return if git_gitolite_command($soc);
-
-    gl_log( 'shell', $ENV{SHELL}, "-c", $soc );
-    exec $ENV{SHELL}, "-c", $soc;
-}
-
-sub shell_out {
-    my $shell = $ENV{SHELL};
-    $shell =~ s/.*\//-/;    # change "/bin/bash" to "-bash"
-    gl_log( 'shell', $shell );
-    exec { $ENV{SHELL} } $shell;
-}
-
-# some duplication with gitolite-shell, factor it out later, if it works fine
-# for fedora and they like it.
-sub git_gitolite_command {
-    my $soc = shift;
-
-    my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-    return 1 if $soc =~ /^($git_commands) /;
-
-    my @words = split ' ', $soc;
-    return 1 if $rc{COMMANDS}{ $words[0] };
-
-    return 0;
-}
-
-1;
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/TProxy.pm b/docker/gitolite/src/lib/Gitolite/Triggers/TProxy.pm
deleted file mode 100644
index 8cf0e8d..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/TProxy.pm
+++ /dev/null
@@ -1,97 +0,0 @@
-package Gitolite::Triggers::TProxy;
-
-# ----------------------------------------------------------------------
-# transparent proxy for git repos, hosted on a gitolite server
-
-# ----------------------------------------------------------------------
-# WHAT
-
-#   1.  user runs a git command (clone, fetch, push) against a gitolite
-#       server.
-#   2.  if that server has the repo, it will serve it up.  Else it will
-#       *transparently* forward the git operation to a designated upstream
-#       server.  The user does not have to do anything, and in fact may not
-#       even know this has happened.
-
-# can be combined with, but does not *require*, gitolite mirroring.
-
-# ----------------------------------------------------------------------
-# SECURITY
-#
-#   1.  Most of the issues that apply to "redirected push" in mirroring.html
-#       also apply here.  In particular, you had best make sure the two
-#       servers use the same authentication data (i.e., "alice" here should be
-#       "alice" there!)
-#
-#   2.  Also, do not add keys for servers you don't trust!
-
-# ----------------------------------------------------------------------
-# HOW
-
-# on transparent proxy server (the one that is doing the redirect):
-#   1.  add
-#           INPUT => ['TProxy::input'],
-#       just before the ENABLE list in the rc file
-#   2.  add an RC variable to tell gitolite where to go; this is also just
-#       before the ENABLE list:
-#           TPROXY_FORWARDS_TO => 'git at upstream',
-
-# on upstream server (the one redirected TO):
-#   1.  add
-#           INPUT => ['TProxy::input'],
-#       just before the ENABLE list in the rc file
-#   2.  add the pubkey of the proxy server (the one that will be redirecting
-#       to us) to this server's gitolite-admin "keydir" as
-#       "server-<something>.pub", and push the change.
-
-# to use in combination with gitolite mirroring
-#   1.  just follow the same instructions as above.  Server names and
-#       corresponding pub keys would already be set ok so step 2 in the
-#       upstream server setup (above) will not be needed.
-#   2.  needless to say, **don't** declare the repos you want to be
-#       transparently proxied in the gitolite.conf for the slave.
-
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-my $soc = $ENV{SSH_ORIGINAL_COMMAND};
-
-# ----------------------------------------------------------------------
-
-sub input {
-    # are we the upstream, getting something from a tproxy server?
-    my $git_commands = "git-upload-pack|git-receive-pack|git-upload-archive";
-    if ( $ARGV[0] =~ /^server-/ and $soc =~ /^TPROXY_FOR=(\S+) SOC=(($git_commands) '\S+')$/ ) {
-        @ARGV = ($1);
-        # you better make sure you read the security warnings up there!
-
-        $ENV{SSH_ORIGINAL_COMMAND} = $2;
-        delete $ENV{GL_BYPASS_ACCESS_CHECKS};
-        # just in case we somehow end up running before Mirroring::input!
-
-        return;
-    }
-
-    # well we're not upstream; are we a tproxy?
-    return unless $rc{TPROXY_FORWARDS_TO};
-
-    # is it a normal git command?
-    return unless $ENV{SSH_ORIGINAL_COMMAND} =~ m(^($git_commands) '/?(.*?)(?:\.git(\d)?)?'$);
-
-    # ...get the repo name from $ENV{SSH_ORIGINAL_COMMAND}
-    my ( $verb, $repo, $trace_level ) = ( $1, $2, $3 );
-    $ENV{D} = $trace_level if $trace_level;
-    _die "invalid repo name: '$repo'" if $repo !~ $REPONAME_PATT;
-
-    # nothing to do if the repo exists locally
-    return if -d "$ENV{GL_REPO_BASE}/$repo.git";
-
-    my $user = shift @ARGV;
-    # redirect to upstream
-    exec( "ssh", $rc{TPROXY_FORWARDS_TO}, "TPROXY_FOR=$user", "SOC=$ENV{SSH_ORIGINAL_COMMAND}" );
-}
diff --git a/docker/gitolite/src/lib/Gitolite/Triggers/Writable.pm b/docker/gitolite/src/lib/Gitolite/Triggers/Writable.pm
deleted file mode 100644
index ed86e12..0000000
--- a/docker/gitolite/src/lib/Gitolite/Triggers/Writable.pm
+++ /dev/null
@@ -1,17 +0,0 @@
-package Gitolite::Triggers::Writable;
-
-use Gitolite::Rc;
-use Gitolite::Common;
-
-sub access_1 {
-    my ( $repo, $aa, $result ) = @_[ 1, 3, 5 ];
-    return if $aa eq 'R' or $result =~ /DENIED/;
-
-    for my $f ( "$ENV{HOME}/.gitolite.down", "$rc{GL_REPO_BASE}/$repo.git/.gitolite.down" ) {
-        next unless -f $f;
-        _die slurp($f) if -s $f;
-        _die "sorry, writes are currently disabled (no more info available)\n";
-    }
-}
-
-1;
diff --git a/docker/gitolite/src/syntactic-sugar/continuation-lines b/docker/gitolite/src/syntactic-sugar/continuation-lines
deleted file mode 100644
index d63475f..0000000
--- a/docker/gitolite/src/syntactic-sugar/continuation-lines
+++ /dev/null
@@ -1,36 +0,0 @@
-# vim: syn=perl:
-
-# "sugar script" (syntactic sugar helper) for gitolite3
-
-# Enabling this script in the rc file allows you to use back-slash escaped
-# continuation lines, like in C or shell etc.
-
-# This script also serves as an example "sugar script" if you want to write
-# your own (and maybe send them to me).  A "sugar script" in gitolite will be
-# executed via a perl 'do' and is expected to contain one function called
-# 'sugar_script'.  This function should take a listref and return a listref.
-# Each item in the list is one line.  There are NO newlines; g3 kills them off
-# fairly early in the process.
-
-# If you're not familiar with perl please do not try this.  Ask me to write
-# you a sugar script instead.
-
-sub sugar_script {
-    my $lines = shift;
-
-    my @out  = ();
-    my $keep = '';
-    for my $l (@$lines) {
-        # skip RULE_INFO lines if in continuation mode
-        next if $keep and $l =~ /^ *#/;
-        if ( $l =~ s/\\$// ) {
-            $keep .= $l;
-        } else {
-            $l = $keep . $l if $keep;
-            $keep = '';
-            push @out, $l;
-        }
-    }
-
-    return \@out;
-}
diff --git a/docker/gitolite/src/syntactic-sugar/keysubdirs-as-groups b/docker/gitolite/src/syntactic-sugar/keysubdirs-as-groups
deleted file mode 100644
index 0a3a9ae..0000000
--- a/docker/gitolite/src/syntactic-sugar/keysubdirs-as-groups
+++ /dev/null
@@ -1,32 +0,0 @@
-# vim: syn=perl:
-
-# "sugar script" (syntactic sugar helper) for gitolite3
-
-# Enabling this script in the rc file allows you to use subdirectories in
-# keydir as group names.  The last component other than keydir itself will be
-# taken as the group name.
-
-sub sugar_script {
-    Gitolite::Common::trace( 2, "running 'keysubdirs-as-groups' sugar script..." );
-    my $lines = shift;
-
-    my @out = @{$lines};
-    unshift @out, groupnames();
-
-    return \@out;
-}
-
-sub groupnames {
-    my @out     = ();
-    my %members = ();
-    for my $pk (`find ../keydir/ -name "*.pub"`) {
-        next unless $pk =~ m(.*/([^/]+)/([^/]+?)(?:@[^./]+)?\.pub$);
-        next if $1 eq 'keydir';
-        $members{$1} .= " $2";
-    }
-    for my $m ( sort keys %members ) {
-        push @out, "\@$m =" . $members{$m};
-    }
-
-    return @out;
-}
diff --git a/docker/gitolite/src/syntactic-sugar/macros b/docker/gitolite/src/syntactic-sugar/macros
deleted file mode 100644
index a3493a4..0000000
--- a/docker/gitolite/src/syntactic-sugar/macros
+++ /dev/null
@@ -1,82 +0,0 @@
-# vim: syn=perl:
-
-# "sugar script" (syntactic sugar helper) for gitolite3
-
-# simple line-wise macro processor
-# ----------------------------------------------------------------------
-# see documentation at the end of this script
-
-my %macro;
-
-sub sugar_script {
-    my $lines = shift;
-    my @out   = ();
-
-    my $l = join( "\n", @$lines );
-    while ( $l =~ s/^macro (\w+)\b(.*?)\nend//ms ) {
-        $macro{$1} = $2;
-    }
-
-    $l =~ s/^((\w+)\b.*)/$macro{$2} ? expand($1) : $1/gem;
-
-    $lines = [ split "\n", $l ];
-    return $lines;
-}
-
-sub expand {
-    my $l = shift;
-    my ( $word, @arg );
-
-    eval "require Text::ParseWords";
-    if ($@) {
-        ( $word, @arg ) = split ' ', $l;
-    } else {
-        ( $word, @arg ) = Text::ParseWords::shellwords($l);
-    }
-    my $v = $macro{$word};
-    $v =~ s/%(\d+)/$arg[$1-1] or die "macro '$word' needs $1 arguments at '$l'\n"/gem;
-    return $v;
-}
-
-__END__
-
-Documentation is mostly by example.
-
-Setup:
-
-  * uncomment the line
-        'macros',
-    in the ENABLE list in ~/.gitolite.rc
-
-Notes on macro definition:
-
-  * the keywords 'macro' and 'end' should start on a new line
-  * the first word after 'macro' is the name of the macro, and the rest, until
-    the 'end', is the body
-
-Notes on macro use:
-
-  * the macro name should be the first word on a line
-  * the rest of the line is used as arguments to the macro
-
-Example:
-
-    if your conf contains:
-
-        macro foo repo aa-%1
-            RW  =   u1 %2
-            R   =   u2
-        end
-
-        foo 1 alice
-        foo 2 bob
-
-    this will effectively turn into
-
-        repo aa-1
-            RW  =   u1 alice
-            R   =   u2
-
-        repo aa-2
-            RW  =   u1 bob
-            R   =   u2
diff --git a/docker/gitolite/src/syntactic-sugar/refex-expr b/docker/gitolite/src/syntactic-sugar/refex-expr
deleted file mode 100644
index f9e7706..0000000
--- a/docker/gitolite/src/syntactic-sugar/refex-expr
+++ /dev/null
@@ -1,35 +0,0 @@
-# vim: syn=perl:
-
-# "sugar script" (syntactic sugar helper) for gitolite3
-# ----------------------------------------------------------------------
-# see src/VREF/refex-expr for instructions and WARNINGS!
-
-my $perm = qr(-|R|RW\+?C?D?M?);
-
-my $seq = 1;
-
-sub sugar_script {
-    my $lines = shift;
-
-    # my @out  = ();
-    for my $l (@$lines) {
-        push @out, $l;
-
-        # quick check
-        next unless $l =~ /^($perm) /;
-        # more detailed check
-        next unless $l =~ /^($perm) (\S.*) = (\S.*)$/;
-        my ( $perm, $refexes, $users ) = ( $1, $2, $3 );
-        next unless $refexes =~ / (and|not|or|xor|\+|-|==|-lt|-gt|-eq|-le|-ge|-ne) /;
-
-        print STDERR ">>>> $l\n";
-        pop @out;    # we need to replace that last line
-
-        push @out, "option refex-expr.sugar$seq = $refexes";
-        push @out, "$perm VREF/refex-expr/sugar$seq = $users";
-
-        $seq++;
-    }
-
-    return \@out;
-}
diff --git a/docker/gitolite/src/triggers/bg b/docker/gitolite/src/triggers/bg
deleted file mode 100755
index 3c66500..0000000
--- a/docker/gitolite/src/triggers/bg
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-# quick and dirty program to background any of the triggers programs that are
-# taking too long.  To use, just replace a line like
-#       'post-compile/update-gitweb-access-list',
-# with
-#       'bg post-compile/update-gitweb-access-list',
-
-# We dump output to a file in the log directory but please keep in mind this
-# is not a "log" so much as a redirection of the entire output.
-
-echo `date` $GL_TID "$0: $@" >> $GL_LOGFILE.bg
-
-path=${0%/*}
-script=$path/$1; shift
-
-( ( $script "$@" < /dev/null >> $GL_LOGFILE.bg 2>&1 & ) )
diff --git a/docker/gitolite/src/triggers/expand-deny-messages b/docker/gitolite/src/triggers/expand-deny-messages
deleted file mode 100755
index a8b2289..0000000
--- a/docker/gitolite/src/triggers/expand-deny-messages
+++ /dev/null
@@ -1,185 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# program name: expand-deny-messages
-
-# DOCUMENTATION IS AT THE BOTTOM OF THIS FILE; PLEASE READ
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-my %attempted_access = (
-    # see triggers.html
-    'ACCESS_1' => {
-        'R' => 'Repo read',
-        'W' => 'Repo write',
-    },
-    'ACCESS_2' => {
-        'W' => "Fast forward push",
-        '+' => "Rewind push branch or overwrite tag",
-        'C' => "Create ref",
-        'D' => "Delete ref",
-    }
-);
-
-# env var to disable is set?
-exit 0 if $ENV{GL_OPTION_EDM_DISABLE};
-
-# argument 1
-my $a12 = shift;    # ACCESS_1 or ACCESS_2
-exit 0 if $a12 !~ /^ACCESS_[12]$/;    # shouldn't happen; error in rc file?
-
-# the rest of the arguments
-my ( $repo, $user, $aa, $ref, $msg, $oldsha, $newsha ) = @ARGV;
-
-# we're only interested in deny messages
-exit 0 if $msg !~ /DENIED/;
-
-print STDERR "\nFATAL -- ACCESS DENIED\n";
-
-_info( "Repo",      $repo );
-_info( "User",      $user );
-_info( "Stage",     ( $a12 eq 'ACCESS_1' ? "Before git was called" : "From git's update hook" ) );
-_info( "Ref",       _ref($ref) ) if $a12 eq 'ACCESS_2';
-_info( "Operation", _op( $a12, $aa, $oldsha, $newsha ) );
-
-if ( $ref =~ m((^VREF/[^/]+)) ) {
-    my $vref      = $1;
-    my $vref_text = slurp( _which( $vref, 'x' ) );
-    my $etag      = '(?:help|explain|explanation)';
-    $vref_text =~ m(^\s*# $etag.start\n(.*)^\s*# $etag.end\n)sm
-      and print STDERR "Explanation for $vref:\n$1";
-}
-
-print STDERR "\n";
-print STDERR "$ENV{GL_OPTION_EDM_EXTRA_INFO}\n\n" if $ENV{GL_OPTION_EDM_EXTRA_INFO};
-
-# ------------------------------------------------------------------------
-
-sub _ref {
-    my $r = shift;
-    return "VREF '$r'"   if $r =~ s(^VREF/)();
-    return "Branch '$r'" if $r =~ s(^refs/heads/)();
-    return "Tag '$r'"    if $r =~ s(^refs/tags/)();
-    return "Non-standard ref '$r'";
-}
-
-sub _info {
-    printf STDERR "%-14s  %-60s\n", @_;
-}
-
-sub _op {
-    my ( $a12, $aa, $oldsha, $newsha ) = @_;
-
-    # first remove the M part and save the text for later addition if needed
-    my $merge = ( $aa =~ s/M// ? " with merge commit" : "" );
-
-    # next, the attempted access is modified to reflect the actual operation being
-    # attempted.  NOTE: this no longer necessarily reflects what the gitolite log
-    # file stores; it's more granular and truly distinguishes a branch create from
-    # an ff push, etc.  Could help when user typos a branch name I suppose
-    $aa = 'C' if $oldsha and $oldsha eq '0' x 40;
-    $aa = 'D' if $newsha and $newsha eq '0' x 40;
-
-    # then we map it, add merge text if any
-    my $op = $attempted_access{$a12}{$aa} || "Unknown operation '$aa'";
-    $op .= $merge;
-
-    return $op;
-}
-
-__END__
-
-ENABLING THE FEATURE
---------------------
-
-To enable this feature, uncomment the line in the rc file if your gitolite was
-installed recently enough.  Otherwise you will need to add these lines to the
-end of your rc file, just before the "%RC" block ends:
-
-    ACCESS_1 => [
-        'expand-deny-messages',
-    ],
-
-    ACCESS_2 => [
-        'expand-deny-messages',
-    ],
-
-Please don't miss the trailing commas!
-
-DISABLING IT FOR SPECIFIC REPOS
--------------------------------
-
-Once it is enabled at the rc file level, if you wish to disable it for
-specific repositories just add a line like this to those repos:
-
-        option ENV.EDM_DISABLE = 1
-
-Or you can also disable it for all repos, then enable it for some:
-
-    repo @all
-        option ENV.EDM_DISABLE = 1
-
-    # ... then later ...
-
-    repo foo bar @baz
-        option ENV.EDM_DISABLE = 0
-
-(options.html[1] and pages linked from it will explain how that works).
-
-[1]: http://gitolite.com/gitolite/options.html
-
-SUPPLYING EXTRA INFORMATION
----------------------------
-
-You can also supply some extra information to be printed, by adding a line
-like this to each repository in the gitolite.conf file:
-
-        option ENV.EDM_EXTRA_INFO = "please contact alice at example.com"
-
-You could of course add it under a "repo @all" section if you like.
-
-SUPPLYING EXTRA INFORMATION FOR VREFs
--------------------------------------
-
-If you have VREFs that do funky things and you want to **lecture** your users
-when they screw up, add something like the following to your VREF code.
-
-    # help start
-
-    Some help text.
-
-    Some more help text.  This can be
-    multi-line.
-
-    (etc etc etc)
-
-    # help end
-
-Then everything between the "# help start" line and the "# help end" line will
-get printed if a users falls afoul of this VREF.  If any of the lines shown
-are not valid syntax for your language, figure out some way to put the whole
-thing in a comment block.  Here a C example:
-
-    /*
-    # help start
-    line 1
-    line 2
-    ...
-    last line
-    # help end
-    */
-
-Even if your language does not support multi-line comments like C does, there
-may be other ways to specify those lines.  Here's an example in shell:
-
-    cat << EOF > /dev/null
-    # help start
-    line 1
-    line 2
-    ...
-    last line
-    # help end
-    EOF
diff --git a/docker/gitolite/src/triggers/partial-copy b/docker/gitolite/src/triggers/partial-copy
deleted file mode 100755
index 79b4d48..0000000
--- a/docker/gitolite/src/triggers/partial-copy
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-
-# this is a wee bit expensive in terms of forks etc., compared to doing it in
-# perl, but I wanted to show how *easy* it actually is now.  And really,
-# you'll only notice if you access this repo like a hundred times a minute or
-# something so don't sweat it.
-
-# given a repo and a user, check if option('partialCopyOf') is set, and if so,
-# fetch all allowed branches from there.
-
-die() { echo "$@" >&2; exit 1; }
-
-# make sure we're being called from the pre_git trigger
-[ "$1" = "PRE_GIT" ] || die I must be called from PRE_GIT, not "$1"
-shift
-
-repo=$1
-user=$2
-main=`git config --file $GL_REPO_BASE/$repo.git/config --get gitolite.partialCopyOf`;
-[ -z "$main" ] && exit 0
-
-# "we", "our repo"  =>  the partial copy
-# "main", "pco"     =>  the one which we are a "partial copy of"
-
-cd $GL_REPO_BASE/$main.git
-
-for ref in `git for-each-ref refs/heads '--format=%(refname)'`
-do
-    cd $GL_REPO_BASE/$repo.git
-
-    gitolite access -q $repo $user R $ref &&
-    git fetch -f $GL_REPO_BASE/$main.git $ref:$ref
-done
-
-export GL_BYPASS_ACCESS_CHECKS=1
-
-# remove all refs not in main or accessible
-cd $GL_REPO_BASE/$repo.git
-
-for ref in `git for-each-ref refs/heads refs/tags '--format=%(refname)'`
-do
-    cd $GL_REPO_BASE/$main.git
-
-    if git show-ref --verify --quiet $ref &&
-       gitolite access -q $repo $user R $ref ; then
-        # ref is present in main and accessible in repo
-        continue
-    fi
-
-    git push -f $GL_REPO_BASE/$repo.git :$ref || die "FATAL: failed to delete $ref"
-done
-
-# remove all tags no longer reachable
-cd $GL_REPO_BASE/$repo.git
-
-for ref in `git for-each-ref refs/tags '--format=%(refname)'`
-do
-    SHA=`git rev-list -1 $ref`
-    for branch in `git for-each-ref refs/heads '--format=%(refname)'`
-    do
-       if [ "`git merge-base $SHA $branch`" = "$SHA" ]; then
-           # tag is reachable in current branch, continue higher loop
-           continue 2
-       fi
-    done
-    git push -f $GL_REPO_BASE/$repo.git :$ref || die "FATAL: failed to delete $ref"
-done
-
-exit 0
diff --git a/docker/gitolite/src/triggers/post-compile/ssh-authkeys b/docker/gitolite/src/triggers/post-compile/ssh-authkeys
deleted file mode 100755
index d5f5d8b..0000000
--- a/docker/gitolite/src/triggers/post-compile/ssh-authkeys
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use File::Temp qw(tempfile);
-use Getopt::Long;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-$|++;
-
-# best called via 'gitolite trigger POST_COMPILE'; other modes at your own
-# risk, especially if the rc file specifies arguments for it.  (That is also
-# why it doesn't respond to "-h" like most gitolite commands do).
-
-# option procesing
-# ----------------------------------------------------------------------
-
-# currently has one option:
-#   -kfn, --key-file-name        adds the keyfilename as a second argument
-
-my $kfn = '';
-GetOptions( 'key-file-name|kfn' => \$kfn, );
-
-tsh_try("sestatus");
-my $selinux = ( tsh_text() =~ /enabled/ );
-
-my $ab = $rc{GL_ADMIN_BASE};
-trace( 1, "'keydir' not found in '$ab'; exiting" ), exit if not -d "$ab/keydir";
-my $akdir        = "$ENV{HOME}/.ssh";
-my $akfile       = "$ENV{HOME}/.ssh/authorized_keys";
-my $glshell      = $rc{GL_BINDIR} . "/gitolite-shell";
-my $auth_options = auth_options();
-
-sanity();
-
-# ----------------------------------------------------------------------
-
-_chdir($ab);
-
-# old data
-my $old_ak = slurp($akfile);
-my @non_gl = grep { not /^# gito.*start/ .. /^# gito.*end/ } slurp($akfile);
-chomp(@non_gl);
-my %seen = map { $_ => 'a non-gitolite key' } ( fp(@non_gl) );
-
-# pubkey files
-chomp( my @pubkeys = `find keydir/ -type f -name "*.pub" | sort` );
-my @gl_keys = ();
-for my $f (@pubkeys) {
-    my $fp = fp($f);
-    if ( $seen{$fp} ) {
-        _warn "$f duplicates $seen{$fp}, sshd will ignore it";
-    } else {
-        $seen{$fp} = $f;
-    }
-    push @gl_keys, grep { /./ } optionise($f);
-}
-
-# dump it out
-my $out = join( "\n", @non_gl, "# gitolite start", @gl_keys, "# gitolite end" ) . "\n";
-
-my $ak = slurp($akfile);
-_die "'$akfile' changed between start and end of this program!" if $ak ne $old_ak;
-_print( $akfile, $out );
-
-_warn "you have no keys left; I hope you intended to do that!" unless @gl_keys;
-
-# ----------------------------------------------------------------------
-
-sub sanity {
-    _die "'$glshell' not found; this should NOT happen..."                if not -f $glshell;
-    _die "'$glshell' found but not readable; this should NOT happen..."   if not -r $glshell;
-    _die "'$glshell' found but not executable; this should NOT happen..." if not -x $glshell;
-
-    my $n = "    (this is normal on a brand new install)";
-    _warn "$akdir missing; creating a new one\n$n"  if not -d $akdir;
-    _warn "$akfile missing; creating a new one\n$n" if not -f $akfile;
-
-    _mkdir( $akdir, 0700 ) if not -d $akdir;
-    if ( not -f $akfile ) {
-        _print( $akfile, "" );
-        chmod 0600, $akfile;
-    }
-}
-
-sub auth_options {
-    my $auth_options = $rc{AUTH_OPTIONS};
-    $auth_options ||= "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty";
-
-    return $auth_options;
-}
-
-sub fp {
-    # input: see below
-    # output: a (list of) FPs
-    my $in = shift || '';
-    if ( $in =~ /\.pub$/ ) {
-        # single pubkey file
-        _die "bad pubkey file '$in'" unless $in =~ $REPONAME_PATT;
-        return fp_file($in);
-    } elsif ( -f $in ) {
-        # an authkeys file
-        return map { fp_line($_) } grep { !/^#/ and /\S/ } slurp($in);
-    } else {
-        # one or more actual keys
-        return map { fp_line($_) } grep { !/^#/ and /\S/ } ( $in, @_ );
-    }
-}
-
-sub fp_file {
-    return $selinux++ if $selinux;    # return a unique "fingerprint" to prevent noise
-    my $f  = shift;
-    my $fp = `ssh-keygen -l -f '$f'`;
-    chomp($fp);
-    _die "fingerprinting failed for '$f'" unless $fp =~ /([0-9a-f][0-9a-f](:[0-9a-f][0-9a-f])+)/ or $fp =~ m(SHA256:([A-ZA-z0-9+/]+));
-    $fp = $1;
-    return $fp;
-}
-
-sub fp_line {
-    my ( $fh, $fn ) = tempfile();
-    print $fh shift() . "\n";
-    close $fh;
-    my $fp = fp_file($fn);
-    unlink $fn;
-    return $fp;
-}
-
-sub optionise {
-    my $f = shift;
-
-    my $user = $f;
-    $user =~ s(.*/)();                # foo/bar/baz.pub -> baz.pub
-    $user =~ s/(\@[^.]+)?\.pub$//;    # baz.pub, baz at home.pub -> baz
-
-    my @line = slurp($f);
-    if ( @line != 1 ) {
-        _warn "$f does not contain exactly 1 line; ignoring";
-        return '';
-    }
-    chomp(@line);
-    return "command=\"$glshell $user" . ( $kfn ? " $f" : "" ) . "\",$auth_options $line[0]";
-}
-
diff --git a/docker/gitolite/src/triggers/post-compile/ssh-authkeys-shell-users b/docker/gitolite/src/triggers/post-compile/ssh-authkeys-shell-users
deleted file mode 100755
index 2dd6643..0000000
--- a/docker/gitolite/src/triggers/post-compile/ssh-authkeys-shell-users
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-$|++;
-
-my $akfile = "$ENV{HOME}/.ssh/authorized_keys";
-
-# ----------------------------------------------------------------------
-
-my $aktext = slurp($akfile);
-
-for my $su ( shell_users() ) {
-    $aktext =~ s(/gitolite-shell $su([" ].*?),no-pty )(/gitolite-shell -s $su$1 )g;
-}
-
-_print( $akfile, $aktext );
-
-# two methods to specify list of shell-capable users.  (1) list of usernames
-# as arguments to 'Shell' in rc file, (2) list of usernames in a plain text
-# file whose name is the first argument to 'Shell' in the rc file.  Or both!
-sub shell_users {
-    my ($sufile, @ret);
-
-    # backward compat for 3.6 and below.  This code will be removed in 3.7.
-    # Also, the variable is ignored if you end up using the new variant (i.e.,
-    # put a file name on the 'Shell' line itself).
-    $sufile = $rc{SHELL_USERS_LIST} if $rc{SHELL_USERS_LIST} and -r $rc{SHELL_USERS_LIST};
-
-    $sufile = shift @ARGV if @ARGV and -r $ARGV[0];
-
-    if ($sufile) {
-        @ret = grep { not /^#/ } slurp($sufile);
-        chomp(@ret);
-    }
-
-    for my $u (@ARGV) {
-        # arguments placed in the rc file appear before the trigger name
-        last if $u eq 'POST_COMPILE';
-
-        push @ret, $u;
-        # no sanity checking, since the rc file can only be created by someone
-        # who already has shell access
-    }
-    _die "'Shell': enabled but no usernames supplied" unless @ret;
-    return @ret;
-}
diff --git a/docker/gitolite/src/triggers/post-compile/ssh-authkeys-split b/docker/gitolite/src/triggers/post-compile/ssh-authkeys-split
deleted file mode 100755
index d96d2e9..0000000
--- a/docker/gitolite/src/triggers/post-compile/ssh-authkeys-split
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-
-#   split multi-key files into separate keys like ssh-authkeys likes
-
-# WHY
-# ---
-#
-# Yeah I wonder that too, when it's so much more maintainable to keep the damn
-# keys as sitaram at home.pub and sitaram at work.pub or such.  But there's no
-# accounting for tastes, and some old fogies apparently want to put all of a
-# user's keys into a single ".pub" file.
-
-# WARNINGS AND CAVEATS
-# --------------------
-#
-# - assumes no "@" sign in basenames of any multi-key files (single line file
-#   may still have them)
-
-# - assumes you don't have a subdir in keydir called "__split_keys__"
-
-# - God help you if you try to throw in a putty key in there.
-
-# - RUNNING "GITOLITE SETUP" WILL LOSE ALL THESE KEYS.  So if you ever do
-#   that, you will then need to make a dummy push to the admin repo to add
-#   them back.  If all your **admin** keys were in split keys, then you lost
-#   remote access.  If that happens, log on to the server using "su - git" or
-#   such, then use the methods described in the "bypassing gitolite" section
-#   in "emergencies.html" instead of a remote push.
-
-# SUPPORT
-# -------
-#
-# NONE.  Mainly because I **know** someone will throw in a putty key.  I just
-# know it.
-
-# USAGE
-# -----
-#
-# to enable, uncomment the 'ssh-authkeys-split' line in the ENABLE list in the
-# rc file.
-
-cd $GL_ADMIN_BASE/keydir
-
-rm -rf __split_keys__
-mkdir __split_keys__
-export SKD=$PWD/__split_keys__
-
-find . -type f -name "*.pub" | while read k
-do
-    # do we need to split?
-    lines=`wc -l < $k`
-    [ "$lines" = "1" ] && continue
-
-    # is it sane to split?
-    base=`basename $k .pub`
-    echo $base | grep '@' >/dev/null && continue
-
-    # ok do it
-    seq=1
-    while read line
-    do
-        echo "$line" > $SKD/$base@$seq.pub
-        (( seq++ ))
-    done < $k
-
-    # now delete the original file
-    rm $k
-done
diff --git a/docker/gitolite/src/triggers/post-compile/update-description-file b/docker/gitolite/src/triggers/post-compile/update-description-file
deleted file mode 100755
index e5b7c6a..0000000
--- a/docker/gitolite/src/triggers/post-compile/update-description-file
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-# For normal (not "wild") repos, gitolite v3 sets 'gitweb.description' instead
-# of putting the text in the "description" file.  This is easier because it
-# just goes with the flow of setting config variables; nothing special needs
-# to be done for the description.
-
-# But this only works for gitweb, not for cgit.  Cgit users must uncomment the
-# 'cgit' line in the ENABLE list in the rc file (which has the effect of
-# adding this program to the POST_COMPILE trigger list).
-
-cd $GL_REPO_BASE
-gitolite list-phy-repos | gitolite git-config % gitweb.description | perl -I"$GL_LIBDIR" -MGitolite::Easy -lne '
-            my @F = split /\t/,$_,3;
-            textfile( file => "description", repo => $F[0], text => $F[2] );
-    '
diff --git a/docker/gitolite/src/triggers/post-compile/update-git-configs b/docker/gitolite/src/triggers/post-compile/update-git-configs
deleted file mode 100755
index a58a85d..0000000
--- a/docker/gitolite/src/triggers/post-compile/update-git-configs
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/perl
-
-# update git-config entries in each repo
-# ----------------------------------------------------------------------
-
-use FindBin;
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-use Gitolite::Conf::Load;
-
-use strict;
-use warnings;
-
-my $RB = $rc{GL_REPO_BASE};
-_chdir($RB);
-
-# ----------------------------------------------------------------------
-# skip if arg-0 is POST_CREATE and no arg-2 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-exit 0 if @ARGV and $ARGV[0] eq 'POST_CREATE' and not $ARGV[2];
-
-# ----------------------------------------------------------------------
-# if called from POST_CREATE, we have only a single repo to worry about
-if ( @ARGV and $ARGV[0] eq 'POST_CREATE' ) {
-    my $repo = $ARGV[1];
-    fixup_config($repo);
-
-    exit 0;
-}
-
-# ----------------------------------------------------------------------
-# else it's all repos (i.e., called from POST_COMPILE)
-
-my $lpr = list_phy_repos();
-
-for my $pr (@$lpr) {
-    fixup_config($pr);
-}
-
-sub fixup_config {
-    my $pr      = shift;
-    my $creator = creator($pr);
-
-    my $gc = git_config( $pr, '.', 1 );
-    while ( my ( $key, $value ) = each( %{$gc} ) ) {
-        next if $key =~ /^gitolite-options\./;
-        if ( $value ne "" ) {
-            system( "git", "config", "--file", "$RB/$pr.git/config", $key, $value );
-        } else {
-            system( "git", "config", "--file", "$RB/$pr.git/config", "--unset-all", $key );
-        }
-    }
-}
diff --git a/docker/gitolite/src/triggers/post-compile/update-git-daemon-access-list b/docker/gitolite/src/triggers/post-compile/update-git-daemon-access-list
deleted file mode 100755
index 446b0da..0000000
--- a/docker/gitolite/src/triggers/post-compile/update-git-daemon-access-list
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/perl
-
-# update git-daemon-export-ok files in each repo
-# ----------------------------------------------------------------------
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Easy;
-use Gitolite::Common;
-
-use strict;
-use warnings;
-
-# ----------------------------------------------------------------------
-# skip if arg-0 is POST_CREATE and no arg-2 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-exit 0 if @ARGV and $ARGV[0] eq 'POST_CREATE' and not $ARGV[2];
-
-my $EO = "git-daemon-export-ok";
-my $RB = $rc{GL_REPO_BASE};
-
-for my $d (`gitolite list-phy-repos | gitolite access % daemon R any`) {
-    my @F = split "\t", $d;
-    if ($F[2] =~ /DENIED/) {
-        unlink "$RB/$F[0].git/$EO";
-    } else {
-        textfile( file => $EO, repo => $F[0], text => "" );
-    }
-}
-
-# As a quick recap, the gitolite output looks somewhat like this:
-
-#   bar^Idaemon^IR any bar daemon DENIED by fallthru$
-#   foo^Idaemon^Irefs/.*$
-#   fubar^Idaemon^Irefs/.*$
-#   gitolite-admin^Idaemon^IR any gitolite-admin daemon DENIED by fallthru$
-#   testing^Idaemon^Irefs/.*$
-
-# where I've typed "^I" to denote a tab.
diff --git a/docker/gitolite/src/triggers/post-compile/update-gitweb-access-list b/docker/gitolite/src/triggers/post-compile/update-gitweb-access-list
deleted file mode 100755
index 937226b..0000000
--- a/docker/gitolite/src/triggers/post-compile/update-gitweb-access-list
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-# this is literally the simplest gitweb update possible.  You are free to add
-# whatever you want and contribute it back, as long as it is upward
-# compatible.
-
-# ----------------------------------------------------------------------
-# delete the 'description' file that 'git init' created if this is run from
-# the post-create trigger.  However, note that POST_CREATE is also called from
-# perms (since POST_CREATE doubles as eqvt of POST_COMPILE to propagate ad hoc
-# permissions changes for wild repos) and then you should not delete it.
-[ "$1" = "POST_CREATE" ] && [ "$4" != "perms" ] && rm -f $GL_REPO_BASE/$2.git/description 2>/dev/null
-
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-
-plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
-[ -z "$plf" ] && plf=$HOME/projects.list
-# since mktemp does not honor umask, we just use it to generate a temp
-# filename (note: 'mktemp -u' on some systems, this gets close enough)
-tmpfile=`mktemp $plf.tmp_XXXXXXXX`
-rm -f $tmpfile;
-
-(
-    gitolite list-phy-repos | gitolite access % gitweb R any | grep -v DENIED
-    gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
-) |
-    cut -f1 | sort -u | sed -e 's/$/.git/' > $tmpfile
-
-[ -f $plf ] && perl -e "chmod ( ( (stat('$plf'))[2] & 07777 ), '$tmpfile')"
-mv $tmpfile $plf
diff --git a/docker/gitolite/src/triggers/post-compile/update-gitweb-daemon-from-options b/docker/gitolite/src/triggers/post-compile/update-gitweb-daemon-from-options
deleted file mode 100755
index 9b499b2..0000000
--- a/docker/gitolite/src/triggers/post-compile/update-gitweb-daemon-from-options
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-
-# Update git-daemon and gitweb access using 'option' lines instead of special
-# usernames.
-
-# To use:
-
-# * enable this combined updater in the rc file by removing the other two
-#   update-*-access-list entries and inserting this one instead.  (This would
-#   be in the POST_CREATE and POST_COMPILE lists).
-
-# * the add option lines in the conf file, like this:
-#
-#       repo foo @bar
-#           option daemon = 1
-#           option gitweb = 1
-
-# Note: don't forget that gitweb can also be enabled by actual config
-# variables (gitweb.owner, gitweb.description, gitweb.category)
-
-# This is useful for people who don't like '@all' to be literally *all* users,
-# including gitweb and daemon, and can't/won't use deny-rules properly.
-
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists; this means
-# it's been triggered by a *normal* (not "wild") repo creation, which in turn
-# means a POST_COMPILE should be following so there's no need to waste time
-# running this once for each new repo
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-
-# first do the gitweb stuff
-
-plf=`gitolite query-rc GITWEB_PROJECTS_LIST`
-[ -z "$plf" ] && plf=$HOME/projects.list
-
-(
-    gitolite list-phy-repos | gitolite git-config % gitolite-options.gitweb
-    gitolite list-phy-repos | gitolite git-config -r % gitweb\\.
-) |
-    cut -f1 | sort -u | sed -e 's/$/.git/' > $plf
-
-# now deal with git-daemon
-
-EO=git-daemon-export-ok
-RB=`gitolite query-rc GL_REPO_BASE`
-export EO RB
-
-export tmp=$(mktemp -d)
-trap "rm -rf $tmp" 0
-
-gitolite list-phy-repos | sort | tee $tmp/all | gitolite git-config % gitolite-options.daemon | cut -f1 > $tmp/daemon
-
-comm -23 $tmp/all $tmp/daemon | perl -lne 'unlink "$ENV{RB}/$_.git/$ENV{EO}"'
-cat               $tmp/daemon | perl -I"$GL_LIBDIR" -MGitolite::Easy -lne 'textfile( file => $ENV{EO}, repo => $_, text => "");'
diff --git a/docker/gitolite/src/triggers/renice b/docker/gitolite/src/triggers/renice
deleted file mode 100755
index ba0b726..0000000
--- a/docker/gitolite/src/triggers/renice
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-n=$1
-[ "$n" = "PRE_GIT" ] && n=10
-renice -n $n $GL_TID >/dev/null
diff --git a/docker/gitolite/src/triggers/repo-specific-hooks b/docker/gitolite/src/triggers/repo-specific-hooks
deleted file mode 100755
index 5d52a47..0000000
--- a/docker/gitolite/src/triggers/repo-specific-hooks
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# setup repo-specific hooks
-
-use lib $ENV{GL_LIBDIR};
-use Gitolite::Rc;
-use Gitolite::Common;
-
-_die "repo-specific-hooks: LOCAL_CODE not defined in rc" unless $rc{LOCAL_CODE};
-_die "repo-specific-hooks: '$rc{LOCAL_CODE}/hooks/repo-specific' does not exist or is not a directory" unless -d "$rc{LOCAL_CODE}/hooks/repo-specific";
-
-_chdir( $ENV{GL_REPO_BASE} );
-
- at ARGV = ("gitolite list-phy-repos | gitolite git-config -ev -r % gitolite-options\\.hook\\. |");
-
-my $driver = "$rc{LOCAL_CODE}/hooks/multi-hook-driver";
-# Hook Driver
-{
-    local $/ = undef;
-    my $hook_text = <DATA>;
-    _print( $driver, $hook_text );
-    chmod 0755, $driver;
-}
-
-while (<>) {
-    chomp;
-    my ( $repo, $hook, $codes ) = split /\t/, $_;
-    $codes ||= '';
-
-    # we don't allow fiddling with the admin repo
-    if ( $repo eq 'gitolite-admin' ) {
-        _warn "repo-specific-hooks: ignoring attempts to set hooks for the admin repo";
-        next;
-    }
-
-    # get the hook name
-    $hook =~ s/^gitolite-options\.hook\.//;
-
-    unless ( $hook =~ /^(pre-receive|post-receive|post-update)$/ ) {
-        _warn "repo-specific-hooks: '$hook' is not allowed, ignoring";
-        _warn "    (only pre-receive, post-receive, and post-update are allowed)";
-        next;
-    }
-
-    my @codes = split /\s+/, $codes;
-
-    my $dst = "$repo.git/hooks/$hook";
-    unlink( glob("$dst.*") );
-
-    my $counter = "h00";
-    foreach my $code (@codes) {
-        if ( $code =~ m(^/|\.\.) ) {
-            _warn "repo-specific-hooks: double dot or leading slash not allowed in '$code'";
-            next;
-        }
-
-        my $src = $rc{LOCAL_CODE} . "/hooks/repo-specific/$code";
-        my $dst = "$repo.git/hooks/$hook.$counter-$code";
-        unless ( -x $src ) {
-            _warn "repo-specific-hooks: '$src' doesn't exist or is not executable";
-            next;
-        }
-        unlink $dst;
-        symlink $src, $dst or _warn "could not symlink '$src' to '$dst'";
-        $counter++;
-
-        # no sanity checks for multiple overwrites of the same hook
-    }
-
-    unlink $dst;
-    symlink $driver, $dst or die "could not symlink '$driver' to '$dst'";
-}
-
-__DATA__
-#/bin/sh
-
-# Determine what input the hook needs
-# post-update takes args, pre/post-receive take stdin
-type=args
-stdin=''
-[ $0 != hooks/post-update ] && {
-    type=stdin
-    stdin=`cat`
-}
-
-for h in $0.*; do
-    [ -x $h ] || continue
-    if [ $type = args ]
-    then
-        $h $@
-    else
-        echo "$stdin" | $h
-    fi
-done
diff --git a/docker/gitolite/src/triggers/set-default-roles b/docker/gitolite/src/triggers/set-default-roles
deleted file mode 100755
index 18ac28b..0000000
--- a/docker/gitolite/src/triggers/set-default-roles
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-# POST_CREATE trigger to set up default set of perms for a new wild repo
-
-# ----------------------------------------------------------------------
-# skip if arg-1 is POST_CREATE and no arg-3 (user name) exists (i.e., it's not
-# a wild repo)
-[ "$1" = "POST_CREATE" ] && [ -z "$3" ] && exit 0;
-[ "$4" = "R" ] || [ "$4" = "W" ] || [ "$4" = "perms-c" ] || [ "$4" = "fork" ] || exit 0
-
-die() { echo "$@" >&2; exit 1; }
-
-cd $GL_REPO_BASE/$2.git || die "could not cd to $GL_REPO_BASE/$2.git"
-gitolite git-config -r $2 gitolite-options.default.roles | sort | cut -f3 |
-    perl -pe 's/(\s)CREATOR(\s|$)/$1$ENV{GL_USER}$2/' > gl-perms
-
-# cache control, if rc says caching is on
-gitolite query-rc -q CACHE && perl -I$GL_LIBDIR -MGitolite::Cache -e "cache_control('flush', '$2')";
-
-exit 0
diff --git a/docker/gitolite/src/triggers/upstream b/docker/gitolite/src/triggers/upstream
deleted file mode 100755
index c64e2f2..0000000
--- a/docker/gitolite/src/triggers/upstream
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/sh
-
-# manage local, gitolite-controlled, copies of read-only upstream repos.
-
-repo=$2
-
-url=$(gitolite git-config $repo gitolite-options.upstream.url)
-[ -z "$url" ] && exit 0     # exit if no url was specified
-
-cd $GL_REPO_BASE/$repo.git || exit 1
-
-[ "$1" != "fetch" ] && {
-    nice=$(gitolite git-config $repo gitolite-options.upstream.nice)
-    [ -n "$nice" ] && find FETCH_HEAD -mmin -$nice 2>/dev/null | grep . >/dev/null && exit 0
-}
-
-git fetch -q "$url" '+refs/*:refs/*'
-
-# ----------------------------------------------------------------------
-
-# FEATURES:
-# * invokes upstream fetch on each local fetch
-#   (unless the optional 'nice' setting is enabled)
-# * can force a fetch (ignoring 'nice' value) from server CLI
-
-# INSTRUCTIONS:
-#
-# * uncomment 'upstream' in the ENABLE list in the rc file.
-# * add option lines to conf file.  For example:
-#
-#       repo git
-#           R                       =   @all
-#           RW+ my-company/         =   @developers
-#
-#           option  upstream.url    =   git://git.kernel.org/pub/scm/git/git.git
-#           option  upstream.nice   =   120
-#
-# * to force a fetch on the server shell (or via cron), run this command:
-#       gitolite ../triggers/upstream fetch reponame
-
-# ADDITIONAL NOTES:
-# * restrict local pushes to a namespace that the upstream won't use
-#   (otherwise the next fetch will wipe them out)
-# * if the upstream URL changes, just change the conf and push admin repo
-# * the 'nice' setting is in minutes and is optional; it is the minimum
-#   elapsed time between 2 upstream fetches.
-
-# USAGE EXAMPLE:
-#
-# Let's say you want to keep a read-only local mirror of all your github repos
-# on your local gitolite installation.  Assuming your github usernames are the
-# same as your local usernames, and you have updated GIT_CONFIG_KEYS in the rc
-# file to allow 'config' lines, you can do this:
-#
-#   repo github/CREATOR/..*
-#       C   = @all
-#       R   = @all
-#       option upstream.url                     =   git://github.com/%GL_REPO.git
-#       option upstream.nice                    =   120
-#       config url.git://github.com/.insteadOf  =   git://github.com/github/
-#
-# Now you can make local, read-only, clones of all your github repos with
-#
-#   git ls-remote gitolite:github/sitaramc/gitolite
-#   git ls-remote gitolite:github/sitaramc/hap
-#   (etc)
-#
-# and if milki were also a user on this gitolite instance, then
-#
-#   git ls-remote gitolite:github/milki/xclip
-#   git ls-remote gitolite:github/milki/ircblogger
-#   (etc)
diff --git a/docker/gitolite/t/0-me-first.t b/docker/gitolite/t/0-me-first.t
deleted file mode 100755
index 8c9d12b..0000000
--- a/docker/gitolite/t/0-me-first.t
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-
-# initial smoke tests
-# ----------------------------------------------------------------------
-
-try "plan 71";
-
-# basic push admin repo
-confreset;confadd '
-    repo aa
-        RW+     =   u1
-        RW      =   u2 u3
-
-    repo cc/..*
-        C       =   u4
-        RW+     =   CREATOR u5
-        R       =   READERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-                                            /Initialized empty Git repository in .*/aa.git//
-
-    # basic clone
-    cd ..
-    glt clone u1 file:///aa u1aa;    ok;     /Cloning into 'u1aa'.../
-                                            /warning: You appear to have cloned an empty repository/
-    [ -d u1aa ];                    ok
-
-    # basic clone deny
-    glt clone u4 file:///aa u4aa;    !ok;    /R any aa u4 DENIED by fallthru/
-    [ -d u4aa ];                    !ok
-
-    # basic push
-    cd u1aa;                        ok
-    tc z-507;                       ok;     /master .root-commit. 7cf7624. z-507/
-    glt push u1 origin HEAD;        ok;     /To file:///aa/
-                                            /\\[new branch\\] *HEAD -> master/
-
-    # basic rewind
-    tc o-866 o-867 o-868;           ok;     /master 2d066fb. o-868/
-    glt push u1 origin HEAD;        ok;     /7cf7624..2d066fb  HEAD -> master/
-    git reset --hard HEAD^;         ok;     /HEAD is now at 8b1456b o-867/
-    tc x-967;                       ok;     /master 284951d. x-967/
-    glt push u1 -f origin HEAD;     ok;     /\\+ 2d066fb...284951d HEAD -> master \\(forced update\\)/
-
-    # log file
-    cat \$(gitolite query-rc GL_LOGFILE);
-                                    ok;     /\tupdate\t/
-                                            /aa\tu1\t\\+\trefs/heads/master/
-                                            /2d066fb4860c29cf321170c17695c6883f3d50e8/
-                                            /284951dfa11d58f99ab76b9f4e4c1ad2f2461236/
-
-    # basic rewind deny
-    cd ..
-    glt clone u2 file:///aa u2aa;    ok;     /Cloning into 'u2aa'.../
-    cd u2aa;                        ok
-    tc g-776 g-777 g-778;           ok;     /master 9cbc181. g-778/
-    glt push u2 origin HEAD;        ok;     /284951d..9cbc181  HEAD -> master/
-    git reset --hard HEAD^;         ok;     /HEAD is now at 2edf7fc g-777/
-    tc d-485;                       ok;     /master 1c01d32. d-485/
-    glt push u2 -f origin HEAD;     !ok;    reject
-                                            /\\+ refs/heads/master aa u2 DENIED by fallthru/
-
-    # non-existent repos etc
-    glt ls-remote u4 file:///bb;    !ok;    /DENIED by fallthru/
-    glt ls-remote u4 file:///cc/1;  ok;     /Initialized empty/
-    glt ls-remote u5 file:///cc/1;  ok;     perl s/TRACE.*//g; !/\\S/
-    glt ls-remote u5 file:///cc/2;  !ok;    /DENIED by fallthru/
-    glt ls-remote u6 file:///cc/2;  !ok;    /DENIED by fallthru/
-
-    # command
-    glt perms u4 -c cc/bar/baz/frob + READERS u2;
-                                    ok;     /Initialized empty .*cc/bar/baz/frob.git/
-
-    # path traversal
-    glt ls-remote u4 file:///cc/dd/../ee
-                                    !ok;    /FATAL: 'cc/dd/\\.\\./ee' contains '\\.\\.'/
-    glt ls-remote u5 file:///cc/../../../../../..$rb/gitolite-admin
-                                    !ok;    /FATAL: 'cc/../../../../../..$rb/gitolite-admin' contains '\\.\\.'/
-
-    glt perms u4 -c cc/bar/baz/../frob + READERS u2
-                                    !ok;    /FATAL: no relative paths allowed anywhere!/
-
-";
diff --git a/docker/gitolite/t/C-vs-C.t b/docker/gitolite/t/C-vs-C.t
deleted file mode 100644
index fee5cc4..0000000
--- a/docker/gitolite/t/C-vs-C.t
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# the commit message in which this test is introduced should have details, but
-# briefly, this test makes sure that access() does not get confused by
-# repo-create permissions being allowed, when looking for branch-create
-# permissions.
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# branch permissions test
-# ----------------------------------------------------------------------
-
-try "plan 25";
-
-confreset;confadd '
-    repo foo/..*
-        C       =   @all
-        RW+CD   =   CREATOR
-        RW      =   u2
-
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..;                          ok
-    glt clone u1 file:///foo/aa;    ok
-    cd aa;                          ok
-    tc l-1;                         ok;     /master/
-    glt push u1 origin master:m1;   ok;     /To file:///foo/aa/
-                                            /\\* \\[new branch\\]      master -> m1/
-
-    tc l-2;                         ok;     /master/
-    glt push u2 origin master:m2;   !ok;    /FATAL: C/
-                                            /DENIED by fallthru/
-    glt push u2 origin master:m1;   ok;     /To file:///foo/aa/
-                                            /8cd302a..29b8683/
-                                            /master -> m1/
-";
diff --git a/docker/gitolite/t/README b/docker/gitolite/t/README
deleted file mode 100644
index 4ecdfb7..0000000
--- a/docker/gitolite/t/README
+++ /dev/null
@@ -1,14 +0,0 @@
-
-============================================
-WARNING: THE TEST SUITE DELETES STUFF FIRST!
-============================================
-
-Please run the tests ONLY on a userid where it's ok to LOSE DATA.
-
-On such a userid, clone gitolite then run this command in the clone:
-
-    GITOLITE_TEST=y prove
-
-http://gitolite.com/gitolite/testing.html has more details.  Alternatively,
-http://gitolite.com/gitolite/req.html#trying will help you try out gitolite if
-you want to play with gitolite safely.
diff --git a/docker/gitolite/t/access.t b/docker/gitolite/t/access.t
deleted file mode 100755
index 34e015f..0000000
--- a/docker/gitolite/t/access.t
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# test 'gitolite access'
-# ----------------------------------------------------------------------
-
-try "plan 208";
-
-confreset;confadd '
-    @admins     =   admin dev1
-    repo gitolite-admin
-        RW+     =   admin
-
-    repo testing
-        RW+     =   @all
-
-    @g1 = t1
-    repo @g1
-        R       =   u2
-        RW      =   u3
-        RW+     =   u4
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-
-    gitolite access -q t1 u1;   !ok;    !/./
-    gitolite access -q t1 u1 R; !ok;    !/./
-    gitolite access -q t1 u1 W; !ok;    !/./
-    gitolite access -q t1 u1 +; !ok;    !/./
-    gitolite access -q t1 u2;   !ok;    !/./
-    gitolite access -q t1 u2 R; ok;     !/./
-    gitolite access -q t1 u2 W; !ok;    !/./
-    gitolite access -q t1 u2 +; !ok;    !/./
-    gitolite access -q t1 u3;   !ok;    !/./
-    gitolite access -q t1 u3 R; ok;     !/./
-    gitolite access -q t1 u3 W; ok;     !/./
-    gitolite access -q t1 u3 +; !ok;    !/./
-    gitolite access -q t1 u4;   ok;     !/./
-    gitolite access -q t1 u4 R; ok;     !/./
-    gitolite access -q t1 u4 W; ok;     !/./
-    gitolite access -q t1 u4 +; ok;     !/./
-
-    gitolite access t1 u1;      !ok;    /\\+ any t1 u1 DENIED by fallthru/
-    gitolite access t1 u1 R;    !ok;    /R any t1 u1 DENIED by fallthru/
-    gitolite access t1 u1 W;    !ok;    /W any t1 u1 DENIED by fallthru/
-    gitolite access t1 u1 +;    !ok;    /\\+ any t1 u1 DENIED by fallthru/
-    gitolite access t1 u2;      !ok;    /\\+ any t1 u2 DENIED by fallthru/
-    gitolite access t1 u2 R;    ok;     /refs/\.\*/
-    gitolite access t1 u2 W;    !ok;    /W any t1 u2 DENIED by fallthru/
-    gitolite access t1 u2 +;    !ok;    /\\+ any t1 u2 DENIED by fallthru/
-    gitolite access t1 u3;      !ok;    /\\+ any t1 u3 DENIED by fallthru/
-    gitolite access t1 u3 R;    ok;     /refs/\.\*/
-    gitolite access t1 u3 W;    ok;     /refs/\.\*/
-    gitolite access t1 u3 +;    !ok;    /\\+ any t1 u3 DENIED by fallthru/
-    gitolite access t1 u4;      ok;     /refs/\.\*/
-    gitolite access t1 u4 R;    ok;     /refs/\.\*/
-    gitolite access t1 u4 W;    ok;     /refs/\.\*/
-    gitolite access t1 u4 +;    ok;     /refs/\.\*/
-
-";
-
-confreset;confadd '
-    @admins     =   admin dev1
-    repo gitolite-admin
-        RW+     =   admin
-
-    @g1 = u1
-    @g2 = u2
-    @g3 = u3
-    @gaa = aa
-    repo @gaa
-        RW+                 =   @g1
-        RW                  =   @g2
-        RW+     master      =   @g3
-        RW      master      =   u4
-        -       master      =   u5
-        RW+     dev         =   u5
-        RW                  =   u5
-';
-
-try "ADMIN_PUSH set2; !/FATAL/" or die text();
-
-try "
-    gitolite access \@gaa \@g1 + any ;                  ok;     /refs/.*/; !/DENIED/
-    gitolite access aa \@g1 + refs/heads/master ;       ok;     /refs/.*/; !/DENIED/
-    gitolite access \@gaa \@g1 + refs/heads/next ;      ok;     /refs/.*/; !/DENIED/
-    gitolite access \@gaa \@g1 W refs/heads/next ;      ok;     /refs/.*/; !/DENIED/
-    gitolite access \@gaa u1 + refs/heads/dev ;         ok;     /refs/.*/; !/DENIED/
-    gitolite access \@gaa u1 + refs/heads/next ;        ok;     /refs/.*/; !/DENIED/
-    gitolite access aa u1 W refs/heads/next ;           ok;     /refs/.*/; !/DENIED/
-    gitolite access \@gaa \@g2 + refs/heads/master ;    !ok;    /\\+ refs/heads/master \@gaa \@g2 DENIED by fallthru/
-    gitolite access \@gaa \@g2 + refs/heads/next ;      !ok;    /\\+ refs/heads/next \@gaa \@g2 DENIED by fallthru/
-    gitolite access aa \@g2 W refs/heads/master ;       ok;     /refs/.*/; !/DENIED/
-    gitolite access aa u2 + any ;                       !ok;    /\\+ any aa u2 DENIED by fallthru/
-    gitolite access \@gaa u2 + refs/heads/master ;      !ok;    /\\+ refs/heads/master \@gaa u2 DENIED by fallthru/
-    gitolite access \@gaa u2 W refs/heads/master ;      ok;     /refs/.*/; !/DENIED/
-    gitolite access \@gaa \@g3 + refs/heads/master ;    ok;     /refs/heads/master/; !/DENIED/
-    gitolite access \@gaa \@g3 W refs/heads/next ;      !ok;    /W refs/heads/next \@gaa \@g3 DENIED by fallthru/
-    gitolite access \@gaa \@g3 W refs/heads/dev ;       !ok;    /W refs/heads/dev \@gaa \@g3 DENIED by fallthru/
-    gitolite access aa u3 + refs/heads/dev ;            !ok;    /\\+ refs/heads/dev aa u3 DENIED by fallthru/
-    gitolite access aa u3 + refs/heads/next ;           !ok;    /\\+ refs/heads/next aa u3 DENIED by fallthru/
-    gitolite access \@gaa u4 + refs/heads/master ;      !ok;    /\\+ refs/heads/master \@gaa u4 DENIED by fallthru/
-    gitolite access \@gaa u4 W refs/heads/master ;      ok;     /refs/heads/master/; !/DENIED/
-    gitolite access aa u4 + refs/heads/next ;           !ok;    /\\+ refs/heads/next aa u4 DENIED by fallthru/
-    gitolite access \@gaa u4 W refs/heads/next ;        !ok;    /W refs/heads/next \@gaa u4 DENIED by fallthru/
-    gitolite access \@gaa u5 R any ;                    ok;     /refs/heads/dev/; !/DENIED/
-    gitolite access aa u5 R any ;                       ok;     /refs/heads/dev/; !/DENIED/
-    gitolite access \@gaa u5 + refs/heads/dev ;         ok;     /refs/heads/dev/; !/DENIED/
-    gitolite access \@gaa u5 + refs/heads/master ;      !ok;    /\\+ refs/heads/master \@gaa u5 DENIED by refs/heads/master/
-    gitolite access aa u5 + refs/heads/next ;           !ok;    /\\+ refs/heads/next aa u5 DENIED by fallthru/
-    gitolite access \@gaa u5 R refs/heads/dev ;         ok;     /refs/heads/dev/; !/DENIED/
-    gitolite access \@gaa u5 R refs/heads/master ;      !ok;    /R refs/heads/master \@gaa u5 DENIED by refs/heads/master/
-    gitolite access \@gaa u5 R refs/heads/next ;        ok;     /refs/.*/; !/DENIED/
-    gitolite access aa u5 W refs/heads/dev ;            ok;     /refs/heads/dev/; !/DENIED/
-    gitolite access aa u5 W refs/heads/master ;         !ok;    /W refs/heads/master aa u5 DENIED by refs/heads/master/
-    gitolite access \@gaa u5 W refs/heads/next ;        ok;     /refs/.*/; !/DENIED/
-";
-
-confreset;confadd '
-    @admins     =   admin dev1
-    repo gitolite-admin
-        RW+     =   admin
-
-    @gr1 = r1
-    repo @gr1
-        RW  refs/heads/v[0-9]   = u1
-        RW  refs/heads          = tester
-
-    @gr2 = r2
-    repo @gr2
-        RW  refs/heads/v[0-9]   = u1
-        -   refs/heads/v[0-9]   = tester
-        RW  refs/heads          = tester
-';
-
-try "ADMIN_PUSH set3; !/FATAL/" or die text();
-
-try "
-    gitolite access \@gr2 tester W refs/heads/v1;       !ok;    /W refs/heads/v1 \@gr2 tester DENIED by refs/heads/v\\[0-9\\]/
-    gitolite access \@gr1 tester W refs/heads/v1;       ok;     /refs/heads/; !/DENIED/
-    gitolite access r1 tester W refs/heads/v1;          ok;     /refs/heads/; !/DENIED/
-    gitolite access r2 tester W refs/heads/v1;          !ok;    /W refs/heads/v1 r2 tester DENIED by refs/heads/v\\[0-9\\]/
-    gitolite access r2 tester W refs/heads/va;          ok;     /refs/heads/; !/DENIED/
-";
-
-confreset;confadd '
-    repo foo
-        RW+ =   u1
-
-    @gr1 = foo bar
-
-    repo @gr1
-        RW  =   u2
-        R   =   u3
-
-    repo @all
-        R   =   gitweb
-';
-
-try "ADMIN_PUSH set4; !/FATAL/" or die text();
-
-try "
-    gitolite access foo u1 +;           ok
-    gitolite access foo u2 +;           !ok
-    gitolite access foo u3 +;           !ok
-    gitolite access foo u4 +;           !ok
-    gitolite access foo gitweb +;       !ok
-
-    gitolite access foo u1 W;           ok
-    gitolite access foo u2 W;           ok
-    gitolite access foo u3 W;           !ok
-    gitolite access foo u4 W;           !ok
-    gitolite access foo gitweb W;       !ok
-
-    gitolite access foo u1 R;           ok
-    gitolite access foo u2 R;           ok
-    gitolite access foo u3 R;           ok
-    gitolite access foo u4 R;           !ok
-    gitolite access foo gitweb R;       ok
-";
diff --git a/docker/gitolite/t/all-yall.t b/docker/gitolite/t/all-yall.t
deleted file mode 100755
index 901b1c2..0000000
--- a/docker/gitolite/t/all-yall.t
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# could anything be clearer than "all y'all"?
-# ----------------------------------------------------------------------
-
-try "plan 26";
-
-confreset;confadd '
-    repo @all
-        R   =   @all
-    repo foo
-        RW+ =   u1
-    repo bar
-        RW+ =   u2
-    repo dev/..*
-        C   =   u3 u4
-        RW+ =   CREATOR
-';
-
-try "
-    rm $ENV{HOME}/projects.list
-";
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    glt ls-remote u1 file:///dev/wild1
-                /FATAL: R any dev/wild1 u1 DENIED by fallthru/
-
-    glt clone u3 file:///dev/wild1
-                /Cloning into 'wild1'.../
-                /Initialized empty Git repository in .*/dev/wild1.git//
-                /warning: You appear to have cloned an empty repository./
-
-    cd wild1
-    tc n-855 n-856
-    glt push u3 origin master:wild1
-                /To file:///dev/wild1/
-                /\\* \\[new branch\\]      master -> wild1/
-    glt push u1 file:///foo master:br-foo
-                /To file:///foo/
-                /\\* \\[new branch\\]      master -> br-foo/
-    glt push u2 file:///bar master:br-bar
-                /To file:///bar/
-                /\\* \\[new branch\\]      master -> br-bar/
-
-    glt ls-remote u6 file:///foo
-                /refs/heads/br-foo/
-
-    glt ls-remote u6 file:///bar
-                /refs/heads/br-bar/
-
-    glt ls-remote u6 file:///dev/wild1
-                /refs/heads/wild1/
-";
-
-try "
-    gitolite ../triggers/post-compile/update-git-daemon-access-list;    ok
-    gitolite ../triggers/post-compile/update-gitweb-access-list;        ok
-    cat $ENV{HOME}/projects.list;                           ok
-";
-cmp 'bar.git
-dev/wild1.git
-foo.git
-gitolite-admin.git
-testing.git
-';
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-
-try "
-    cd ..
-    cd ..
-    echo $rb
-    find $rb -name git-daemon-export-ok | sort
-    perl s,$rb/,,g
-";
-
-cmp 'bar.git/git-daemon-export-ok
-dev/wild1.git/git-daemon-export-ok
-foo.git/git-daemon-export-ok
-gitolite-admin.git/git-daemon-export-ok
-testing.git/git-daemon-export-ok
-';
diff --git a/docker/gitolite/t/basic.t b/docker/gitolite/t/basic.t
deleted file mode 100755
index 7579935..0000000
--- a/docker/gitolite/t/basic.t
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# some more basic tests
-# ----------------------------------------------------------------------
-
-try "
-    plan 217
-    CHECK_SETUP
-
-    # subtest 1
-    cd ..
-    CLONE dev2 gitolite-admin ga2
-                                !ok;    gsh
-                                        /DENIED by fallthru/
-                                        /fatal: Could not read from remote repository/
-    glt clone admin --progress file:///gitolite-admin ga2
-                                ok;     gsh
-                                        /Counting/; /Compressing/; /Total/
-    cd gitolite-admin;          ok
-    ";
-
-put "conf/gitolite.conf", "
-    \@admins     =   admin dev1
-    repo gitolite-admin
-        -   mm  =   \@admins
-        RW      =   \@admins
-        RW+     =   admin
-
-    repo testing
-        RW+     =   \@all
-";
-
-try "
-    # push
-    git add conf;               ok
-    git status -s;              ok;     /M  conf/gitolite.conf/
-    git commit -m t01a;         ok;     /master.*t01a/
-    PUSH dev2;                  !ok;    gsh
-                                        /DENIED by fallthru/
-                                        /fatal: Could not read from remote repository/
-    PUSH admin;                 ok;     /master -> master/
-    empty;                      ok;
-    PUSH admin master:mm
-                                !ok;    gsh
-                                        /DENIED by refs/heads/mm/
-                                        reject
-    ";
-
-put "conf/gitolite.conf", "
-    \@admins     =   admin dev1
-    repo gitolite-admin
-        RW+     =   admin
-
-    repo testing
-        RW+     =   \@all
-
-    repo t1
-        R       =   u2
-        RW      =   u3
-        RW+     =   u4
-";
-
-try "
-    # subtest 2
-    ADMIN_PUSH t01b
-
-    # clone
-    cd ..;                      ok;
-    CLONE u1 t1;                !ok;    gsh
-                                        /DENIED by fallthru/
-                                        /fatal: Could not read from remote repository/
-    CLONE u2 t1;                ok;     gsh
-                                        /warning: You appear to have cloned an empty repository./
-    [ -d t1/.git ];             ok
-    cd t1;                      ok;
-
-    # push
-    test-commit tc1 tc2 tc2;    ok;     /a530e66/
-    PUSH u2;                    !ok;    gsh
-                                        /DENIED by fallthru/
-                                        /fatal: Could not read from remote repository/
-    PUSH u3 master;             ok;     gsh
-                                        /master -> master/
-
-    # rewind
-    reset-h HEAD^;              ok;     /HEAD is now at aa2b5c5 tc2/
-    test-tick; test-commit tc3; ok;     /3ffced1/
-    PUSH u3;                    !ok;    gsh
-                                        /rejected.*master -> master.*non-fast-forward./
-    PUSH u3 -f;                 !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-    PUSH u4 +master;            ok;     gsh
-                                        / \\+ a530e66...3ffced1 master -> master.*forced update./
-";
-
-put "../gitolite-admin/conf/gitolite.conf", "
-    \@admins     =   admin dev1
-    repo gitolite-admin
-        RW+     =   admin
-
-    include 'i1.conf'
-";
-
-put "../gitolite-admin/conf/i1.conf", "
-    \@g1 = u1
-    \@g2 = u2
-    \@g3 = u3
-    \@gaa = aa
-    repo \@gaa
-        RW+                 =   \@g1
-        RW                  =   \@g2
-        RW+     master      =   \@g3
-        RW      master      =   u4
-        -       master      =   u5
-        RW+     dev         =   u5
-        RW                  =   u5
-";
-
-try "
-    # subtest 3
-    ADMIN_PUSH t01c
-
-    cd ..;                      ok
-";
-
-try "
-    CLONE u1 aa;                ok;     gsh
-    cd aa;                      ok
-    test-commit set3 t1 t2 t3 t4 t5 t6 t7 t8 t9
-                                ok
-    PUSH u1 HEAD;               ok;     gsh
-                                        /To file:///aa/
-                                        /\\* \\[new branch\\]      HEAD -> master/
-    branch dev;                 ok
-    branch foo;                 ok
-
-    # u1 rewind master ok
-    reset-h HEAD^;              ok
-    test-commit r1;             ok
-    PUSH u1 +master;            ok;     gsh
-                                        /To file:///aa/
-                                        /\\+ 27ed463...05adfb0 master -> master .forced update./
-
-    # u2 rewind master !ok
-    reset-h HEAD^;              ok
-    test-commit r2;             ok
-    PUSH u2 +master;            !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-
-    # u3 rewind master ok
-    reset-h HEAD^;              ok
-    test-commit r3;             ok
-    PUSH u3 +master;            ok;     gsh
-                                        /To file:///aa/
-                                        /\\+ 05adfb0...6a532fe master -> master .forced update./
-
-    # u4 push master ok
-    test-commit u4;             ok
-    PUSH u4 master;             ok;     gsh
-                                        /To file:///aa/
-                                        /6a532fe..f929773 +master -> master/
-
-    # u4 rewind master !ok
-    reset-h HEAD^;              ok
-    PUSH u4 +master;            !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-
-    # u3,u4 push other branches !ok
-    PUSH u3 dev;                !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-    PUSH u4 dev;                !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-    PUSH u3 foo;                !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-    PUSH u4 foo;                !ok;    gsh
-                                        reject
-                                        /DENIED by fallthru/
-
-    # clean up for next set
-    glt push u1 -f origin master dev foo
-                                ok;     gsh
-                                        /f929773...6a532fe master -> master .forced update./
-                                        /new branch.*dev -> dev/
-                                        /new branch.*foo -> foo/
-
-    # u5 push master !ok
-    test-commit u5
-    PUSH u5 master;             !ok;    gsh
-                                        reject
-                                        /DENIED by refs/heads/master/
-
-    # u5 rewind dev ok
-    PUSH u5 +dev^:dev
-                                ok;     gsh
-                                        /\\+ 27ed463...1ad477a dev\\^ -> dev .forced update./
-
-
-    # u5 rewind foo !ok
-    PUSH u5 +foo^:foo
-                                !ok;    gsh
-                                        reject
-                                        /remote: FATAL: \\+ refs/heads/foo aa u5 DENIED by fallthru/
-
-    # u5 push foo ok
-    git checkout foo
-    /Switched to branch 'foo'/
-
-    test-commit u5
-    PUSH u5 foo;                ok;     gsh
-                                        /27ed463..83da62c *foo -> foo/
-
-    # u1 delete dev ok
-    PUSH u1 :dev;               ok;     gsh
-                                        / - \\[deleted\\] *dev/
-
-    # push it back
-    PUSH u1 dev;                ok;     gsh
-                                        /\\* \\[new branch\\] *dev -> dev/
-
-";
-
-put "| cat >> ../gitolite-admin/conf/gitolite.conf", "
-    \@gr1 = r1
-    repo \@gr1
-        RW  refs/heads/v[0-9]   = u1
-        RW  refs/heads          = tester
-";
-
-try "
-    # subtest 4
-    ADMIN_PUSH t01d
-
-    cd ..;                      ok
-
-    CLONE tester r1;            ok;     gsh
-                                        /Cloning into 'r1'.../
-    cd r1;                      ok
-    test-commit r1a r1b r1c r1d r1e r1f
-                                ok
-    PUSH tester HEAD;           ok;     gsh
-                                        /\\* \\[new branch\\] *HEAD -> master/
-    git branch v1
-    PUSH tester v1;             ok;     gsh
-                                        /\\* \\[new branch\\] *v1 -> v1/
-
-";
-
-put "| cat >> ../gitolite-admin/conf/gitolite.conf", "
-    \@gr2 = r2
-    repo \@gr2
-        RW  refs/heads/v[0-9]   = u1
-        -   refs/heads/v[0-9]   = tester
-        RW  refs/heads          = tester
-";
-
-try "
-    # subtest 5
-    ADMIN_PUSH t01e
-
-    cd ..;                      ok
-
-    CLONE tester r2;            ok;     gsh
-                                        /Cloning into 'r2'.../
-    cd r2;                      ok
-    test-commit r2a r2b r2c r2d r2e r2f
-                                ok
-    PUSH tester HEAD;           ok;     gsh
-                                        /\\* \\[new branch\\] *HEAD -> master/
-    git branch v1
-    PUSH tester v1;             !ok;    gsh
-                                        /W refs/heads/v1 r2 tester DENIED by refs/heads/v\\[0-9\\]/
-"
diff --git a/docker/gitolite/t/branch-perms.t b/docker/gitolite/t/branch-perms.t
deleted file mode 100755
index e59baea..0000000
--- a/docker/gitolite/t/branch-perms.t
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# branch permissions test
-# ----------------------------------------------------------------------
-
-try "plan 82";
-
-confreset;confadd '
-    @g1 = u1
-    @g2 = u2
-    @g3 = u3
-    @gaa = aa
-    repo @gaa
-        RW+                 =   @g1
-        RW                  =   @g2
-        RW+     master      =   @g3
-        RW      master      =   u4
-        -       master      =   u5
-        RW+     dev         =   u5
-        RW                  =   u5
-
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..;                          ok
-    glt clone u1 file:///aa;         ok
-    cd aa;                          ok
-    tc l-995 l-996 l-997 l-998 l-999 l-1000 l-1001 l-1002 l-1003;
-                                    ok;     /master a788db9. l-1003/
-    glt push u1 origin HEAD;        ok;     /To file:///aa/
-                                            /\\* \\[new branch\\]      HEAD -> master/
-
-    git branch dev;                 ok
-    git branch foo;                 ok
-
-    # u1 rewind master succeed
-    git reset --hard HEAD^;         ok;     /HEAD is now at 65d5f4a l-1002/
-    tc v-865;                       ok;     /master 3053bb4. v-865/
-    glt push u1 origin +master;     ok;     /\\+ a788db9...3053bb4 master -> master \\(forced update\\)/
-
-    # u2 rewind master fail
-    git reset --hard HEAD^;         ok;     /HEAD is now at 65d5f4a l-1002/
-    tc s-361;                       ok;     /master b331651. s-361/
-    glt push u2 file:///aa +master;  !ok;    reject
-                                            /\\+ refs/heads/master aa u2 DENIED by fallthru/
-
-    # u3 rewind master succeed
-    git reset --hard HEAD^;         ok
-    tc m-508;                       ok
-    glt push u3 file:///aa +master;  ok;     /\\+ .* master -> master \\(forced update\\)/
-
-    # u4 push master succeed
-    tc f-526;                       ok;
-    glt push u4 file:///aa master;   ok;     /master -> master/
-
-    # u4 rewind master fail
-    git reset --hard HEAD^;         ok;
-    glt push u4 file:///aa +master;  !ok;    /\\+ refs/heads/master aa u4 DENIED by fallthru/
-
-    # u3 and u4 / dev foo -- all 4 fail
-    glt push u3 file:///aa dev;      !ok;    /W refs/heads/dev aa u3 DENIED by fallthru/
-    glt push u4 file:///aa dev;      !ok;    /W refs/heads/dev aa u4 DENIED by fallthru/
-    glt push u3 file:///aa foo;      !ok;    /W refs/heads/foo aa u3 DENIED by fallthru/
-    glt push u4 file:///aa foo;      !ok;    /W refs/heads/foo aa u4 DENIED by fallthru/
-
-    # clean up for next set
-    glt push u1 -f origin master dev foo
-                                    ok
-
-    # u5 push master fail
-    tc l-417;                       ok
-    glt push u5 file:///aa master;   !ok;    /W refs/heads/master aa u5 DENIED by refs/heads/master/
-
-    # u5 rewind dev succeed
-    glt push u5 file:///aa +dev^:dev
-                                    ok;     /\\+ .* dev\\^ -> dev \\(forced update\\)/
-
-    # u5 rewind foo fail
-    glt push u5 file:///aa +foo^:foo
-                                    !ok;    /\\+ refs/heads/foo aa u5 DENIED by fallthru/
-
-    # u5 tries to push foo; succeeds
-    git checkout foo;               ok;     /Switched to branch 'foo'/
-
-    # u5 push foo succeed
-    tc e-530;                       ok;
-    glt push u5 file:///aa foo;      ok;     /foo -> foo/
-
-    # u1 delete branch dev succeed
-    glt push u1 origin :dev;        ok;     / - \\[deleted\\] *dev/
-
-    # quietly push it back again
-    glt push u1 origin dev;         ok;     / * \\[new branch\\]      dev -> dev/
-
-    ";
-
-    confadd '
-        repo @gaa
-            RWD     dev         =   u4
-    ';
-
-try "ADMIN_PUSH set2; !/FATAL/" or die text();
-
-try "
-    # u1 tries to delete dev on a new setup
-    cd ../aa;                       ok;     /master -> master/
-
-    # u1 delete branch dev fail
-    glt push u1 origin :dev;        !ok;    /D refs/heads/dev aa u1 DENIED by fallthru/
-
-    # u4 delete branch dev succeed
-    glt push u4 file:///aa :dev;     ok;     / - \\[deleted\\] *dev/
-
-";
diff --git a/docker/gitolite/t/daemon-gitweb-via-perms.t b/docker/gitolite/t/daemon-gitweb-via-perms.t
deleted file mode 100755
index 8707e19..0000000
--- a/docker/gitolite/t/daemon-gitweb-via-perms.t
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# basic tests
-# ----------------------------------------------------------------------
-
-try "plan 24";
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-confreset;confadd '
-
- at leads = u1 u2
- at devs = u1 u2 u3 u4
-
- at gbar = bar/CREATOR/..*
-repo    @gbar
-    C               =   @leads
-    RW+             =   @leads
-    RW              =   WRITERS @devs
-    R               =   READERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-chdir($rb);
-my $h = $ENV{HOME};
-
-try "
-    glt ls-remote u1 file:///bar/u1/try1
-    /Initialized empty Git repository in .*/bar/u1/try1.git/
-
-    find . -name git-daemon-export-ok
-    /testing.git/git-daemon-export-ok/
-
-    cat $h/projects.list
-    /testing.git/
-
-    glt ls-remote u1 file:///bar/u1/try2
-    /Initialized empty Git repository in .*/bar/u1/try2.git/
-
-    find $h/repositories -name git-daemon-export-ok
-    /testing.git/git-daemon-export-ok/
-
-    cat $h/projects.list
-    /testing.git/
-
-    glt perms u1 bar/u1/try1 + READERS daemon
-    !/./
-
-    glt perms u1 bar/u1/try1 -l
-    /READERS daemon/
-
-    find $h/repositories -name git-daemon-export-ok
-    /repositories/testing.git/git-daemon-export-ok/
-    /repositories/bar/u1/try1.git/git-daemon-export-ok/
-
-    cat $h/projects.list
-    /testing.git/
-
-    glt perms u1 bar/u1/try2 + READERS gitweb
-
-    glt perms u1 bar/u1/try2 -l
-    /READERS gitweb/
-
-    find $h/repositories -name git-daemon-export-ok
-    /testing.git/git-daemon-export-ok/
-    /bar/u1/try1.git/git-daemon-export-ok/
-
-    cat $h/projects.list
-    /bar/u1/try2.git/
-    /testing.git/
-";
diff --git a/docker/gitolite/t/deleg-1.t b/docker/gitolite/t/deleg-1.t
deleted file mode 100755
index 89da137..0000000
--- a/docker/gitolite/t/deleg-1.t
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# delegation tests -- part 1
-# ----------------------------------------------------------------------
-
-try "plan 54";
-
-try "
-    DEF SP_1 = git add conf ; ok; git commit -m %1; ok; /master.* %1/
-    DEF SUBCONF_PUSH = SP_1 %2; glt push %1 origin; gsh; /master -> master/
-";
-
-confreset;confadd '
-    @u1r    =   r1a r1b
-    @u2r    =   r2a r2b
-    @u3r    =   r3a r3b
-
-    # the admin repo access was probably like this to start with:
-    repo gitolite-admin
-        RW                              = u1 u2 u3
-        RW+ NAME/                       = admin
-        RW  NAME/conf/fragments/u1r     = u1
-        RW  NAME/conf/fragments/u2r     = u2
-        RW  NAME/conf/fragments/u3r     = u3
-        -   NAME/                       = @all
-
-        subconf "fragments/*.conf"
-';
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-mkdir "conf/fragments";
-put   "conf/fragments/u1r.conf", '
-    repo @u1r
-        RW+     =   tester
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-try "
-        /Initialized empty Git repository in .*/r1a.git//
-        /Initialized empty Git repository in .*/r1b.git//
-";
-
-# u1 push u1r pass
-put   "conf/fragments/u1r.conf", '
-    repo @u1r
-        RW+     =   u5
-';
-try "SUBCONF_PUSH u1 u1; !/FATAL/" or die text();
-
-# u2 main push fail
-confadd '
-    repo @u1r
-        RW+     =   u6
-';
-try "SUBCONF_PUSH u2 u2; /FATAL/;
-        /W VREF/NAME/conf/gitolite.conf gitolite-admin u2 DENIED by VREF/NAME//
-";
-
-try "git reset --hard origin/master; ok";
-
-# u2 push u1r fail
-put   "conf/fragments/u1r.conf", '
-    repo @u1r
-        RW+     =   u6
-';
-try "SUBCONF_PUSH u2 u2; /FATAL/
-        /W VREF/NAME/conf/fragments/u1r.conf gitolite-admin u2 DENIED by VREF/NAME//
-";
-
-try "git reset --hard origin/master; ok";
-
-# u3 set perms for r2a fail
-put   "conf/fragments/u3r.conf", '
-    repo r2a
-        RW+     =   u6
-';
-try "SUBCONF_PUSH u3 u3;
-        /WARNING: subconf 'u3r' attempting to set access for r2a/
-";
-
-try "git reset --hard origin/master; ok";
-
-# u3 add r2b to u3r fail
-
-put   "conf/fragments/u3r.conf", '
-    @u3r    =   r2b
-    repo @u3r
-        RW+     =   u6
-';
-
-try "SUBCONF_PUSH u3 u3
-        /WARNING: expanding '\@u3r'/
-        /WARNING: subconf 'u3r' attempting to set access for r2b/
-";
diff --git a/docker/gitolite/t/deleg-2.t b/docker/gitolite/t/deleg-2.t
deleted file mode 100755
index 98fb02e..0000000
--- a/docker/gitolite/t/deleg-2.t
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# delegation tests -- part 2
-# ----------------------------------------------------------------------
-
-try "plan 55";
-
-try "
-    DEF SP_1 = git add conf ; ok; git commit -m %1; ok; /master.* %1/
-    DEF SUBCONF_PUSH = SP_1 %2; glt push %1 origin; gsh; /master -> master/
-";
-
-confreset;confadd '
-    # group your projects/repos however you want
-    @u1r    =   r1[ab]
-    @u2r    =   r2[ab]
-    @u3r    =   r3[ab]
-
-    # the admin repo access was probably like this to start with:
-    repo gitolite-admin
-        RW                              = u1 u2 u3
-        RW+ NAME/                       = admin
-        RW  NAME/conf/fragments/u1r     = u1
-        RW  NAME/conf/fragments/u2r     = u2
-        RW  NAME/conf/fragments/u3r     = u3
-        -   NAME/                       = @all
-
-    subconf "fragments/*.conf"
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "mkdir -p conf/fragments; ok";
-
-put "conf/fragments/u1r.conf", '
-    repo r1a r1b
-        C       =   @all
-        RW+     =   CREATOR
-    repo @u1r
-        RW+     =   tester
-';
-
-put "conf/fragments/u2r.conf", '
-    repo @u2r
-        C       =   @all
-        RW+     =   CREATOR
-    repo @u2r
-        RW+     =   tester
-';
-
-put "conf/fragments/u3r.conf", '
-    repo @u3r
-        C       =   @all
-        RW+     =   CREATOR
-    repo @u3r
-        RW+     =   tester
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-try "
-        /Initialized empty Git repository in .*/r1a.git//
-        /Initialized empty Git repository in .*/r1b.git//
-";
-
-# u1 push u1r pass
-put   "conf/fragments/u1r.conf", '
-    repo @u1r
-        RW+     =   u5
-';
-try "SUBCONF_PUSH u1 u1; !/FATAL/" or die text();
-
-# u2 main push fail
-confadd '
-    repo @u1r
-        RW+     =   u6
-';
-try "SUBCONF_PUSH u2 u2; /FATAL/;
-        /W VREF/NAME/conf/gitolite.conf gitolite-admin u2 DENIED by VREF/NAME//
-";
-
-try "git reset --hard origin/master; ok";
-
-# u2 push u1r fail
-put   "conf/fragments/u1r.conf", '
-    repo @u1r
-        RW+     =   u6
-';
-try "SUBCONF_PUSH u2 u2; /FATAL/
-        /W VREF/NAME/conf/fragments/u1r.conf gitolite-admin u2 DENIED by VREF/NAME//
-";
-
-try "git reset --hard origin/master; ok";
-
-# u3 set perms for r2a fail
-put   "conf/fragments/u3r.conf", '
-    repo r2a
-        RW+     =   u6
-';
-try "SUBCONF_PUSH u3 u3;
-        /WARNING: subconf 'u3r' attempting to set access for r2a/
-";
-
-try "git reset --hard origin/master; ok";
-
-# u3 add r2b to u3r fail
-
-put   "conf/fragments/u3r.conf", '
-    @u3r    =   r2b
-    repo @u3r
-        RW+     =   u6
-';
-
-try "SUBCONF_PUSH u3 u3
-        /WARNING: expanding '\@u3r'/
-        /WARNING: subconf 'u3r' attempting to set access for r2b/
-";
diff --git a/docker/gitolite/t/deny-create.t b/docker/gitolite/t/deny-create.t
deleted file mode 100755
index a4b7e4f..0000000
--- a/docker/gitolite/t/deny-create.t
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# deny-create, the RW.*C flag
-# ----------------------------------------------------------------------
-
-try "plan 72";
-
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-# test "C" permissions
-
-confreset; confadd '
-    @leads = u1 u2
-    @devs = u1 u2 u3 u4
-
-    @gfoo = foo
-    repo    @gfoo
-        RW+C                =   @leads
-        RW+C personal/USER/ =   @devs
-        RW                  =   @devs
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..
-    glt clone u1 file:///foo
-
-    cd foo
-    tc t-413 t-414 t-415 t-416 t-417
-
-    # u1 can push/rewind master on foo
-    glt push u1 origin master
-        POK; /master -> master/
-    glt push u1 -f origin master^^:master
-        POK; /master\\^\\^ -> master/
-
-    # u2 can create newbr1 on foo
-    glt push u2 file:///foo master:newbr1
-        POK; /master -> newbr1/
-
-    # u2 can create newtag on foo
-    git tag newtag
-    glt push u2 file:///foo newtag
-        POK; /newtag -> newtag/
-
-    # u3 can push newbr1 on foo
-    tc u-962 u-963 u-964 u-965 u-966
-    glt push u3 file:///foo master:newbr1
-        POK; /master -> newbr1/
-
-    # u4 canNOT create newbr2 on foo
-    tc e-615 e-616 e-617 e-618 e-619
-    glt push u3 file:///foo master:newbr2
-        /C refs/heads/newbr2 foo u3 DENIED by fallthru/
-        reject
-
-    # u4 canNOT create newtag2 on foo
-    git tag newtag2
-    glt push u3 file:///foo newtag2
-        /C refs/tags/newtag2 foo u3 DENIED by fallthru/
-        reject
-
-    # u4 can create/rewind personal/u4/newbr3 on foo
-    tc f-664 f-665 f-666 f-667 f-668
-    glt push u4 file:///foo master:personal/u4/newbr3
-        POK; /master -> personal/u4/newbr3/
-    glt push u4 -f origin master^^:personal/u4/newbr3
-        POK; /master\\^\\^ -> personal/u4/newbr3/
-";
-
-# bar, without "C" permissions, should behave like old
-
-confadd '
-    @leads = u1 u2
-    @devs = u1 u2 u3 u4
-
-    @gbar = bar
-    repo    @gbar
-        RW+                 =   @leads
-        RW+  personal/USER/ =   @devs
-        RW                  =   @devs
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..
-    glt clone u1 file:///bar
-
-    cd bar
-    tc u-907 u-908 u-909 u-910 u-911
-
-    # u1 can push/rewind master on bar
-    glt push u1 origin master
-        POK; /master -> master/
-    glt push u1 -f origin master^^:master
-        POK; /master\\^\\^ -> master/
-
-    # u2 can create newbr1 on bar
-    glt push u2 file:///bar master:newbr1
-        POK; /master -> newbr1/
-
-    # u2 can create newtag on bar
-    git tag newtag
-    glt push u2 file:///bar newtag
-        POK; /newtag -> newtag/
-
-    # u3 can push newbr1 on bar
-    tc y-862 y-863 y-864 y-865 y-866
-    glt push u3 file:///bar master:newbr1
-        POK; /master -> newbr1/
-
-    # u4 can create newbr2 on bar
-    tc q-417 q-418 q-419 q-420 q-421
-    glt push u3 file:///bar master:newbr2
-        POK; /master -> newbr2/
-
-    # u4 can create newtag2 on bar
-    git tag newtag2
-    glt push u3 file:///bar newtag2
-        POK; /newtag2 -> newtag2/
-
-    # u4 can create/rewind personal/u4/newbr3 on bar
-    tc v-605 v-606 v-607 v-608 v-609
-    glt push u4 file:///bar master:personal/u4/newbr3
-        POK; /master -> personal/u4/newbr3/
-    glt push u4 -f origin master^^:personal/u4/newbr3
-        POK; /master\\^\\^ -> personal/u4/newbr3/
-
-";
diff --git a/docker/gitolite/t/deny-rules-2.t b/docker/gitolite/t/deny-rules-2.t
deleted file mode 100755
index 0ca15fe..0000000
--- a/docker/gitolite/t/deny-rules-2.t
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# more on deny-rules
-# ----------------------------------------------------------------------
-
-try "plan 126";
-
-try "
-    DEF GOOD    = /refs/\\.\\*/
-    DEF BAD     = /DENIED/
-
-    DEF Ryes    = gitolite access %1 %2 R any;  ok; GOOD
-    DEF Rno     = gitolite access %1 %2 R any;  !ok; BAD
-
-    DEF Wyes    = gitolite access %1 %2 W any;  ok; GOOD
-    DEF Wno     = gitolite access %1 %2 W any;  !ok; BAD
-
-    DEF GWyes   = Ryes %1 gitweb
-    DEF GWno    = Rno  %1 gitweb
-
-    DEF GDyes   = Ryes %1 daemon
-    DEF GDno    = Rno  %1 daemon
-";
-
-confreset;confadd '
-    repo one
-        RW+ =   u1
-        R   =   u2
-        -   =   u2 u3
-        R   =   @all
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    Wyes one u1
-
-    Ryes one u2
-    Wno  one u2
-
-    Ryes one u3
-    Wno  one u3
-
-    Ryes one u6
-    Wno  one u6
-
-    GDyes one
-    GWyes one
-";
-
-confadd '
-    option deny-rules = 1
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    Wyes one u1
-
-    Ryes one u2
-    Wno  one u2
-
-    Rno  one u3
-
-    Ryes one u6
-    Wno  one u6
-
-    GDyes one
-    GWyes one
-";
-
-confadd '
-    repo two
-        RW+ =   u1
-        R   =   u2
-        -   =   u2 u3 gitweb daemon
-        R   =   @all
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    GWyes two
-    GDyes two
-";
-
-confadd '
-    option deny-rules = 1
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    GWno  two
-    GDno  two
-";
-
-# set 3 -- allow gitweb to all but admin repo
-
-confadd '
-    repo gitolite-admin
-        -   =   gitweb daemon
-    option deny-rules = 1
-
-    repo three
-        RW+ =   u3
-        R   =   gitweb daemon
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    GDyes   three
-    GWyes   three
-    GDno    gitolite-admin
-    GWno    gitolite-admin
-";
-
-# set 4 -- allow gitweb to all but admin repo
-
-confadd '
-    repo four
-        RW+ =   u4
-        -   =   gitweb daemon
-
-    repo @all
-        R   =   @all
-';
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    GDyes   four
-    GWyes   four
-    GDno    gitolite-admin
-    GWno    gitolite-admin
-";
-
-# set 5 -- go wild
-
-confreset; confadd '
-    repo foo/..*
-        C   =   u1
-        RW+ =   CREATOR
-        -   =   gitweb daemon
-        R   =   @all
-
-    repo bar/..*
-        C   =   u2
-        RW+ =   CREATOR
-        -   =   gitweb daemon
-        R   =   @all
-    option deny-rules = 1
-';
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    glt ls-remote u1 file:///foo/one
-    glt ls-remote u2 file:///bar/two
-    Wyes foo/one u1
-    Wyes bar/two u2
-
-    GDyes foo/one
-    GDyes foo/one
-    GWno  bar/two
-    GWno  bar/two
-";
diff --git a/docker/gitolite/t/deny-rules.t b/docker/gitolite/t/deny-rules.t
deleted file mode 100755
index c0e7cbb..0000000
--- a/docker/gitolite/t/deny-rules.t
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# deny rules
-# ----------------------------------------------------------------------
-
-try "plan 11";
-
-confreset;confadd '
-    # start with...
-
-    repo gitolite-admin
-        -   =   gitweb daemon
-    option deny-rules = 1
-
-    # main ruleset goes here
-
-    @ga = a
-    @gb = b
-    @gc = c
-
-    # and end with
-
-    repo @ga
-        RW  =   u1
-        -   =   @all
-    option deny-rules = 1
-
-    repo @gb
-        RW  =   u2
-        -   =   daemon
-    option deny-rules = 1
-
-    repo @gc
-        RW  =   u3
-
-    repo @all
-        R   =   @all
-
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-try "
-    cat $ENV{HOME}/projects.list;                           ok
-";
-cmp 'b.git
-c.git
-testing.git
-';
-
-try "
-    cd ..
-    cd ..
-    echo $rb
-    find $rb -name git-daemon-export-ok | sort
-    perl s,$rb/,,g
-";
-cmp 'c.git/git-daemon-export-ok
-testing.git/git-daemon-export-ok
-'
diff --git a/docker/gitolite/t/easy.t b/docker/gitolite/t/easy.t
deleted file mode 100755
index dcd6c1a..0000000
--- a/docker/gitolite/t/easy.t
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Easy;
-use Gitolite::Test;
-# put this after ::Easy because it chdirs away from where you were and the
-# 'use lib "src"', not being absolute, fails
-
-# smoke tests for Easy.pm
-# ----------------------------------------------------------------------
-# for a change these are actual perl tests, so not much call for tsh here,
-# although I still need the basic infrastructure for setting up the repos and
-# I still can't intermix this with perl's Test.pm or Test::More etc
-sub ok { (+shift) ? print "ok\n" : print "not ok\n"; }
-sub nok { (+shift) ? print "not ok\n" : print "ok\n"; }
-sub msg { return unless $ENV{D}; print STDERR "#" . +shift . "\n"; }
-
-try "plan 98";
-
-try "
-    cat $ENV{HOME}/.gitolite.rc
-    perl s/GIT_CONFIG_KEYS.*/GIT_CONFIG_KEYS => '.*',/
-    put $ENV{HOME}/.gitolite.rc
-";
-
-# basic push admin repo
-confreset;confadd '
-    repo gitolite-admin
-        RW+     VREF/NAME/      =   admin
-        RW+     VREF/NAME/u5/   =   u5
-
-    repo aa
-        RW+     =   u1
-        RW      =   u2
-        R       =   u4
-
-        config for.aa   =   1
-
-    repo cc/..*
-        C       =   u4
-        RW+     =   CREATOR u5
-        R       =   u6
-
-        config for.cc   =   1
-
-    @oddguys = u1 u3 u5
-    @evensout = u2 u4 u6
-
-    repo cc/sub/..*
-        config sub.cc   =   1
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-# valid_user() -- an internal function but still worth testing by itself first
-eval { Gitolite::Easy::valid_user(); };
-ok($@ =~ /FATAL.*GL_USER not set/);
-$ENV{GL_USER} = "u2";
-eval { Gitolite::Easy::valid_user(); };
-nok($@ =~ /FATAL.*GL_USER not set/);
-
-# is_admin
-msg('is_admin');
-$ENV{GL_USER} = "admin"; ok(is_admin());
-$ENV{GL_USER} = "u5"; ok(is_admin());
-$ENV{GL_USER} = "u2"; nok(is_admin());
-
-# is_super_admin -- not sure how useful it is right now
-msg('is_super_admin');
-$ENV{GL_USER} = "admin"; ok( is_super_admin() );
-$ENV{GL_USER} = "u5";    nok( is_super_admin() );
-$ENV{GL_USER} = "u2";    nok( is_super_admin() );
-
-# in_group
-msg('in_group');
-$ENV{GL_USER} = "u1"; ok( in_group('oddguys') );  nok( in_group('evensout') );
-$ENV{GL_USER} = "u3"; ok( in_group('oddguys') );  nok( in_group('evensout') );
-$ENV{GL_USER} = "u4"; nok( in_group('oddguys') ); ok( in_group('evensout') );
-$ENV{GL_USER} = "u2"; nok( in_group('oddguys') ); ok( in_group('evensout') );
-
-# owns
-msg('owns');
-try("glt ls-remote u4 cc/u4; /Initialized empty.*cc/u4/");
-$ENV{GL_USER} = "u3"; nok( owns("cc/u3") ); nok( owns("cc/u4") );
-$ENV{GL_USER} = "u4"; nok( owns("cc/u3") ); ok( owns("cc/u4") );
-$ENV{GL_USER} = "u5"; nok( owns("cc/u3") ); nok( owns("cc/u4") );
-
-# can_read
-msg('can_read');
-$ENV{GL_USER} = "u1"; ok(can_read("aa"));
-$ENV{GL_USER} = "u2"; ok(can_read("aa"));
-$ENV{GL_USER} = "u3"; nok(can_read("aa"));
-$ENV{GL_USER} = "u4"; ok(can_read("aa"));
-
-$ENV{GL_USER} = "u1"; nok(can_read("bb"));
-$ENV{GL_USER} = "u2"; nok(can_read("bb"));
-$ENV{GL_USER} = "u3"; nok(can_read("bb"));
-$ENV{GL_USER} = "u4"; nok(can_read("bb"));
-
-$ENV{GL_USER} = "u3"; nok(can_read("cc/u3"));
-$ENV{GL_USER} = "u4"; nok(can_read("cc/u3"));
-$ENV{GL_USER} = "u5"; nok(can_read("cc/u3"));
-$ENV{GL_USER} = "u6"; nok(can_read("cc/u3"));
-
-$ENV{GL_USER} = "u3"; nok(can_read("cc/u4"));
-$ENV{GL_USER} = "u4"; ok(can_read("cc/u4"));
-$ENV{GL_USER} = "u5"; ok(can_read("cc/u4"));
-$ENV{GL_USER} = "u6"; ok(can_read("cc/u4"));
-
-# can_write
-msg('can_write');
-$ENV{GL_USER} = "u1"; ok(can_write("aa"));
-$ENV{GL_USER} = "u2"; ok(can_write("aa"));
-$ENV{GL_USER} = "u3"; nok(can_write("aa"));
-$ENV{GL_USER} = "u4"; nok(can_write("aa"));
-
-$ENV{GL_USER} = "u1"; ok(can_write("aa", "+"));
-$ENV{GL_USER} = "u2"; nok(can_write("aa", "+"));
-$ENV{GL_USER} = "u3"; nok(can_write("aa", "+"));
-$ENV{GL_USER} = "u4"; nok(can_write("aa", "+"));
-
-$ENV{GL_USER} = "u1"; nok(can_write("bb"));
-$ENV{GL_USER} = "u2"; nok(can_write("bb"));
-$ENV{GL_USER} = "u3"; nok(can_write("bb"));
-$ENV{GL_USER} = "u4"; nok(can_write("bb"));
-
-$ENV{GL_USER} = "u3"; nok(can_write("cc/u3"));
-$ENV{GL_USER} = "u4"; nok(can_write("cc/u3"));
-$ENV{GL_USER} = "u5"; nok(can_write("cc/u3"));
-$ENV{GL_USER} = "u6"; nok(can_write("cc/u3"));
-
-$ENV{GL_USER} = "u3"; nok(can_write("cc/u4"));
-$ENV{GL_USER} = "u4"; ok(can_write("cc/u4"));
-$ENV{GL_USER} = "u5"; ok(can_write("cc/u4"));
-$ENV{GL_USER} = "u6"; nok(can_write("cc/u4"));
-
-$ENV{GL_USER} = "u3"; nok(can_write("cc/u4", "+"));
-$ENV{GL_USER} = "u4"; ok(can_write("cc/u4", "+"));
-$ENV{GL_USER} = "u5"; ok(can_write("cc/u4", "+"));
-$ENV{GL_USER} = "u6"; nok(can_write("cc/u4", "+"));
-
-# config
-try("glt ls-remote u4 cc/sub/one; /Initialized empty.*cc/sub/one/");
-try("glt ls-remote u4 cc/two; /Initialized empty.*cc/two/");
-ok(1);
-my @a;
- at a = config("aa", "fo..aa");   ok($a[0] eq 'for.aa' and $a[1] eq '1');
- at a = config("aa", "for.aa");   ok($a[0] eq 'for.aa' and $a[1] eq '1');
- at a = config("aa", "fo\\..aa"); ok(scalar(@a) == 0);
-
- at a = config("aa", "fo..cc");   ok(scalar(@a) == 0);
- at a = config("aa", "for.cc");   ok(scalar(@a) == 0);
- at a = config("aa", "fo\\..cc"); ok(scalar(@a) == 0);
-
- at a = config("bb", "fo..aa");   ok(scalar(@a) == 0);
- at a = config("bb", "for.aa");   ok(scalar(@a) == 0);
- at a = config("bb", "fo\\..aa"); ok(scalar(@a) == 0);
-
- at a = config("cc/u4", "fo..aa");   ok(scalar(@a) == 0);
- at a = config("cc/u4", "for.aa");   ok(scalar(@a) == 0);
- at a = config("cc/u4", "fo\\..aa"); ok(scalar(@a) == 0);
-
- at a = config("cc/u4", "fo..cc");   ok($a[0] eq 'for.cc' and $a[1] eq '1');
- at a = config("cc/u4", "for.cc");   ok($a[0] eq 'for.cc' and $a[1] eq '1');
- at a = config("cc/u4", "fo\\..cc"); ok(scalar(@a) == 0);
-
- at a = config("cc/two", "fo..cc");   ok($a[0] eq 'for.cc' and $a[1] eq '1');
- at a = config("cc/two", "for.cc");   ok($a[0] eq 'for.cc' and $a[1] eq '1');
- at a = config("cc/two", "fo\\..cc"); ok(scalar(@a) == 0);
-
- at a = config("cc/sub/one", "fo..cc");   ok($a[0] eq 'for.cc' and $a[1] eq '1');
- at a = config("cc/sub/one", "for.cc");   ok($a[0] eq 'for.cc' and $a[1] eq '1');
- at a = config("cc/sub/one", "fo\\..cc"); ok(scalar(@a) == 0);
-
- at a = config("cc/sub/one", "su..cc");   ok($a[0] eq 'sub.cc' and $a[1] eq '1');
- at a = config("cc/sub/one", "sub.cc");   ok($a[0] eq 'sub.cc' and $a[1] eq '1');
- at a = config("cc/sub/one", "su\\..cc"); ok(scalar(@a) == 0);
-
diff --git a/docker/gitolite/t/fork.t b/docker/gitolite/t/fork.t
deleted file mode 100755
index 2a7a7b7..0000000
--- a/docker/gitolite/t/fork.t
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-my $h = $ENV{HOME};
-
-# fork command
-# ----------------------------------------------------------------------
-
-try "plan 38";
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-
-confreset;confadd '
-
-    repo foo/CREATOR/..*
-        C   =   u1 u2
-        RW+ =   CREATOR
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..
-
-    # make the initial repo
-    glt ls-remote u1 file:///foo/u1/u1a;ok;     gsh
-                                                /Initialized empty Git repository in .*/foo/u1/u1a.git/
-    # vrc doesn't have the fork command
-    glt fork u1 foo/u1/u1a foo/u1/u1a2; !ok;    /FATAL: unknown git/gitolite command: \\'fork/
-";
-
-# allow fork as a valid command
-$ENV{G3T_RC} = "$ENV{HOME}/g3trc";
-put "$ENV{G3T_RC}", "\$rc{COMMANDS}{fork} = 1;\n";
-
-# enable set-default-roles feature, add options, push
-try "
-    cat $h/.gitolite.rc
-    perl s/# 'set-default-roles'/'set-default-roles'/
-    put $h/.gitolite.rc
-";
-try "cd gitolite-admin";
-confadd '
-    repo foo/CREATOR/..*
-        C   =   u1 u2
-        RW+ =   CREATOR
-    option default.roles-1 = READERS @all
-';
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-try "cd ..";
-
-try "
-    # now the fork succeeds
-    glt fork u1 foo/u1/u1a foo/u1/u1a2; ok;     /Cloning into bare repository '.*/foo/u1/u1a2.git'/
-                                                /foo/u1/u1a forked to foo/u1/u1a2/
-
-    # now the actual testing starts
-    # read error
-    glt fork u1 foo/u1/u1c foo/u1/u1d;  !ok;    /'foo/u1/u1c' does not exist or you are not allowed to read it/
-    glt fork u2 foo/u1/u1a foo/u1/u1d;  !ok;    /'foo/u1/u1a' does not exist or you are not allowed to read it/
-
-    # write error
-    glt fork u1 foo/u1/u1a foo/u2/u1d;  !ok;    /'foo/u2/u1d' already exists or you are not allowed to create it/
-
-    # no error
-    glt fork u1 foo/u1/u1a foo/u1/u1e;  ok;     /Cloning into bare repository '.*/foo/u1/u1e.git'/
-                                                /warning: You appear to have cloned an empty repository/
-                                                /foo/u1/u1a forked to foo/u1/u1e/
-    # both exist
-    glt fork u1 foo/u1/u1a foo/u1/u1e;  !ok;    /'foo/u1/u1e' already exists or you are not allowed to create it/
-";
-
-# now check the various files that should have been produced
-
-my $t;
-try "cd $rb; find . -name gl-perms"; $t = md5sum(sort (lines())); cmp $t,
-'59b3a74b4d33c7631f08e75e7b60c7ce  ./foo/u1/u1a2.git/gl-perms
-59b3a74b4d33c7631f08e75e7b60c7ce  ./foo/u1/u1e.git/gl-perms
-';
-
-try "cd $rb; find . -name gl-creator"; $t = md5sum(sort (lines())); cmp $t,
-'e4774cdda0793f86414e8b9140bb6db4  ./foo/u1/u1a.git/gl-creator
-346955ff2eadbf76e19373f07dd370a9  ./foo/u1/u1a2.git/gl-creator
-346955ff2eadbf76e19373f07dd370a9  ./foo/u1/u1e.git/gl-creator
-';
diff --git a/docker/gitolite/t/git-config.t b/docker/gitolite/t/git-config.t
deleted file mode 100755
index 86a3a7b..0000000
--- a/docker/gitolite/t/git-config.t
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# git config settings
-# ----------------------------------------------------------------------
-
-try "plan 57";
-
-try "pwd";
-my $od = text();
-chomp($od);
-
-my $t;  # temp
-
-# try an invalid config key
-confreset;confadd '
-
-    repo @all
-        config foo.bar  =   dft
-';
-
-try "ADMIN_PUSH set1; /FATAL/" or die text();
-try "
-    /git config \\'foo.bar\\' not allowed/
-    /check GIT_CONFIG_KEYS in the rc file/
-";
-
-# make foo.bar a valid gc key
-$ENV{G3T_RC} = "$ENV{HOME}/g3trc";
-put "$ENV{G3T_RC}", "\$rc{GIT_CONFIG_KEYS} = 'foo\.bar';\n";
-
-confreset;confadd '
-
-    repo @all
-        config foo.bar  =   dft
-
-    repo gitolite-admin
-        RW+     =   admin
-        config foo.bar  =
-
-    repo testing
-        RW+     =   @all
-
-    repo foo
-        RW      =   u1
-        config foo.bar  =   f1
-
-    repo frob
-        RW      =   u3
-
-    repo bar
-        RW      =   u2
-        config foo.bar  =   one
-
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-try "
-    cd $rb;                             ok
-    egrep foo\\|bar *.git/config
-";
-$t = join("\n", sort (lines()));
-
-cmp $t, 'bar.git/config:	bar = one
-bar.git/config:	bare = true
-bar.git/config:[foo]
-foo.git/config:	bar = f1
-foo.git/config:	bare = true
-foo.git/config:[foo]
-frob.git/config:	bar = dft
-frob.git/config:	bare = true
-frob.git/config:[foo]
-gitolite-admin.git/config:	bare = true
-testing.git/config:	bar = dft
-testing.git/config:	bare = true
-testing.git/config:[foo]';
-
-try "cd $od; ok";
-
-confadd '
-
-    repo frob
-        RW      =   u3
-        config foo.bar  =   none
-
-    repo bar
-        RW      =   u2
-        config foo.bar  =   one
-
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd $rb;                             ok
-    egrep foo\\|bar *.git/config
-";
-$t = join("\n", sort (lines()));
-
-cmp $t, 'bar.git/config:	bar = one
-bar.git/config:	bare = true
-bar.git/config:[foo]
-foo.git/config:	bar = f1
-foo.git/config:	bare = true
-foo.git/config:[foo]
-frob.git/config:	bar = none
-frob.git/config:	bare = true
-frob.git/config:[foo]
-gitolite-admin.git/config:	bare = true
-testing.git/config:	bar = dft
-testing.git/config:	bare = true
-testing.git/config:[foo]';
-
-try "cd $od; ok";
-
-confadd '
-
-    repo bar
-        RW      =   u2
-        config foo.bar  =   
-
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd $rb;                             ok
-    egrep foo\\|bar *.git/config
-";
-$t = join("\n", sort (lines()));
-
-cmp $t, 'bar.git/config:	bare = true
-bar.git/config:[foo]
-foo.git/config:	bar = f1
-foo.git/config:	bare = true
-foo.git/config:[foo]
-frob.git/config:	bar = none
-frob.git/config:	bare = true
-frob.git/config:[foo]
-gitolite-admin.git/config:	bare = true
-testing.git/config:	bar = dft
-testing.git/config:	bare = true
-testing.git/config:[foo]';
-
-try "cd $od; ok";
-
-confreset;confadd '
-
-    repo @gr1
-        RW      =   u1
-        config foo.bar  =   f1
-
-    repo bar/CREATOR/[one].*
-        C       =   u2
-        RW      =   u2
-        config foo.bar  =   one
-
-    @gr1 = foo frob
-
-';
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-try "
-    glt ls-remote u2 file:///bar/u2/one;        ok;     /Initialized empty/
-    glt ls-remote u2 file:///bar/u2/two;        !ok;    /DENIED by fallthru/
-";
-
-try "
-    cd $rb;                             ok
-    find . -name config | xargs egrep foo\\|bar
-";
-$t = join("\n", sort (lines()));
-
-cmp $t, './bar/u2/one.git/config:	bar = one
-./bar/u2/one.git/config:	bare = true
-./bar/u2/one.git/config:[foo]
-./foo.git/config:	bar = f1
-./foo.git/config:	bare = true
-./foo.git/config:[foo]
-./frob.git/config:	bar = f1
-./frob.git/config:	bare = true
-./frob.git/config:[foo]
-./gitolite-admin.git/config:	bare = true
-./testing.git/config:	bar = dft
-./testing.git/config:	bare = true
-./testing.git/config:[foo]';
diff --git a/docker/gitolite/t/gitolite-receive-pack b/docker/gitolite/t/gitolite-receive-pack
deleted file mode 100755
index a4cc5be..0000000
--- a/docker/gitolite/t/gitolite-receive-pack
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-print STDERR "TRACE: grp(", join( ")(", @ARGV ), ")\n";
-
-my $repo = shift;
-$repo =~ s/\.git$//;
-my $user = $ENV{G3T_USER} || 'no-such-user';
-
-$ENV{SSH_ORIGINAL_COMMAND} = "git-receive-pack '$repo'";
-exec( "$ENV{GL_BINDIR}/../src/gitolite-shell", $user );
diff --git a/docker/gitolite/t/gitolite-upload-pack b/docker/gitolite/t/gitolite-upload-pack
deleted file mode 100755
index 5981f17..0000000
--- a/docker/gitolite/t/gitolite-upload-pack
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-print STDERR "TRACE: gup(", join( ")(", @ARGV ), ")\n";
-
-my $repo = shift;
-$repo =~ s/\.git$//;
-my $user = $ENV{G3T_USER} || 'no-such-user';
-
-$ENV{SSH_ORIGINAL_COMMAND} = "git-upload-pack '$repo'";
-exec( "$ENV{GL_BINDIR}/../src/gitolite-shell", $user );
diff --git a/docker/gitolite/t/glt b/docker/gitolite/t/glt
deleted file mode 100755
index 1bf31e8..0000000
--- a/docker/gitolite/t/glt
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-use FindBin;
-BEGIN { $ENV{GL_BINDIR} = $FindBin::RealBin; }
-
-my $cmd  = shift or die "need command";
-my $user = shift or die "need user";
-my $rc;
-
-my %extcmds = (
-    help        => 1,
-    info        => 1,
-    desc        => 1,
-    fork        => 1,
-    perms       => 1,
-    writable    => 1,
-);
-
-$ENV{G3T_USER} = $user;
-if ($extcmds{$cmd}) {
-    $ENV{SSH_ORIGINAL_COMMAND} = join(" ", $cmd, @ARGV);
-    exec( "$ENV{GL_BINDIR}/../src/gitolite-shell", $user );
-} elsif ( $cmd eq 'push' ) {
-    print STDERR "TRACE: glt(", join( ")(", @ARGV ), ")\n";
-    $rc = system( "git", $cmd, "--receive-pack=$ENV{GL_BINDIR}/gitolite-receive-pack", @ARGV );
-} else {
-    print STDERR "TRACE: glt(", join( ")(", @ARGV ), ")\n";
-    $rc = system( "git", $cmd, "--upload-pack=$ENV{GL_BINDIR}/gitolite-upload-pack", @ARGV );
-}
-
-if ( $? == -1 ) {
-    die "F: failed to execute: $!\n";
-} elsif ( $? & 127 ) {
-    printf STDERR "E: child died with signal %d\n", ( $? & 127 );
-    exit 1;
-} else {
-    printf STDERR "W: child exited with value %d\n", $? >> 8 if $? >> 8;
-    exit( $? >> 8 );
-}
-
-exit 0;
diff --git a/docker/gitolite/t/hostname.t b/docker/gitolite/t/hostname.t
deleted file mode 100755
index dfb8885..0000000
--- a/docker/gitolite/t/hostname.t
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# %HOSTNAME tests
-# ----------------------------------------------------------------------
-
-try "plan 60";
-
-try "pwd";
-my $od = text();
-chomp($od);
-
-# without setting HOSTNAME in rc
-confreset;confadd '
-
-    repo foo
-        RW  dev/%HOSTNAME   =   u1
-';
-
-try "ADMIN_PUSH set1; /FATAL/";
-try "/bad ref 'refs/heads/dev/%HOSTNAME'/";
-
-# make a hostname entry
-$ENV{G3T_RC} = "$ENV{HOME}/g3trc";
-put "$ENV{G3T_RC}", "\$rc{HOSTNAME} = 'frodo';\n";
-
-confreset;confadd '
-
-    repo bar
-        RW  %HOSTNAME_baz   =   u1
-';
-
-try "ADMIN_PUSH set1; /FATAL/";
-try "/bad ref 'refs/heads/%HOSTNAME_baz'/";
-
-confreset;confadd '
-
-    repo bar
-        RW  %HOSTNAME/      =   u1
-        RW  %HOSTNAME-baz   =   u1
-';
-
-try "ADMIN_PUSH set1; !/FATAL/";
-try "
-    gitolite access bar u2 R any;                   /R any bar u2 DENIED by fallthru/
-    gitolite access bar u2 W any;                   /W any bar u2 DENIED by fallthru/
-    gitolite access bar u1 W any;                   !/DENIED/; /refs/heads/frodo/; !/baz/
-    gitolite access bar u1 R any;                   !/DENIED/; /refs/heads/frodo/; !/baz/
-    gitolite access bar u1 R refs/heads/frodo;      /R refs/heads/frodo bar u1 DENIED by fallthru/
-    gitolite access bar u1 W refs/heads/frodo;      /W refs/heads/frodo bar u1 DENIED by fallthru/
-    gitolite access bar u1 R refs/heads/frodo/1;    !/DENIED/; /refs/heads/frodo/; !/baz/
-    gitolite access bar u1 W refs/heads/frodo/1;    !/DENIED/; /refs/heads/frodo/; !/baz/
-    gitolite access bar u1 R refs/heads/sam;        /R refs/heads/sam bar u1 DENIED by fallthru/
-    gitolite access bar u1 W refs/heads/sam;        /W refs/heads/sam bar u1 DENIED by fallthru/
-    gitolite access bar u1 R refs/heads/master;     /R refs/heads/master bar u1 DENIED by fallthru/
-    gitolite access bar u1 W refs/heads/master;     /W refs/heads/master bar u1 DENIED by fallthru/
-
-    gitolite access bar u1 R refs/heads/frodo-baz;  !/DENIED/; /refs/heads/frodo-baz/
-    gitolite access bar u1 W refs/heads/frodo-baz;  !/DENIED/; /refs/heads/frodo-baz/
-";
-
-confreset;confadd '
-
-    repo foo-%HOSTNAME
-        RW  =   u1
-';
-
-try "ADMIN_PUSH set1; !/FATAL/";
-try "
-    gitolite list-repos;            /foo-frodo/
-    gitolite list-phy-repos;        /foo-frodo/
-";
diff --git a/docker/gitolite/t/include-subconf.t b/docker/gitolite/t/include-subconf.t
deleted file mode 100755
index 48bdaee..0000000
--- a/docker/gitolite/t/include-subconf.t
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# include and subconf
-# ----------------------------------------------------------------------
-
-try 'plan 58';
-
-confreset; confadd '
-    include "i1.conf"
-    @i2 = b1
-    subconf "i2.conf"
-    include "i1.conf"
-';
-confadd 'i1.conf', '
-    @g1 = a1 a2
-    repo foo
-        RW = u1
-
-    include "j1.conf"
-';
-confadd 'i2.conf', '
-    @g2 = b1 b2
-    repo bar b1 b2 i1 i2 @i1 @i2 @g2
-        RW = u2
-';
-confadd 'j1.conf', '
-    @h2 = c1 c2
-    repo baz
-        RW = u3
-';
-
-try "ADMIN_PUSH set2; !/FATAL/" or die text();
-
-try "
-                                        /i1.conf already included/
-	                                    /subconf 'i2' attempting to set access for \@i1, b2, bar, i1/
-                                        /WARNING: expanding '\@g2'/
-
-                                        !/attempting to set access.*i2/
-                                        /Initialized.*empty.*baz.git/
-                                        /Initialized.*empty.*foo.git/
-                                        /Initialized.*empty.*b1.git/
-                                        /Initialized.*empty.*i2.git/
-                                        !/Initialized.*empty.*b2.git/
-                                        !/Initialized.*empty.*i1.git/
-                                        !/Initialized.*empty.*bar.git/
-";
-
-confreset;confadd '
-    @g2 = i1 i2 i3
-    subconf "g2.conf"
-';
-confadd 'g2.conf', '
-    @g2 = g2 h2 i2
-    repo @g2
-        RW = u1
-';
-
-try "ADMIN_PUSH set3; !/FATAL/" or die text();
-try "
-                                        /WARNING: expanding '\@g2'/
-                                        /WARNING: subconf 'g2' attempting to set access for h2/
-                                        /Initialized.*empty.*g2.git/
-                                        /Initialized.*empty.*i2.git/
-";
-
-confreset;confadd '
-    @g2 = i1 i2 i3
-    subconf "g2.conf"
-';
-confadd 'g2.conf', '
-    subconf master
-    @g2 = g2 h2 i2
-    repo @g2
-        RW = u1
-';
-
-try "
-    ADMIN_PUSH set3;           ok;     /FATAL: subconf \\'g2\\' attempting to run 'subconf'/
-";
-
-# ----------------------------------------------------------------------
-
-confreset; confadd '
-    include "i1.conf"
-    @i2 = b1
-    subconf i2 "eye2.conf"
-';
-confadd 'eye2.conf', '
-    repo @eye2
-        RW = u2
-';
-
-try "ADMIN_PUSH set2; !/FATAL/" or die text();
-
-try "
-    /subconf 'i2' attempting to set access for \@eye2/
-";
-
-confreset; confadd '
-    include "i1.conf"
-    @i2 = b1
-    subconf i2 "eye2.conf"
-';
-confadd 'eye2.conf', '
-    repo @i2
-        RW = u2
-';
-
-try "ADMIN_PUSH set2; !/FATAL/" or die text();
-
-try "
-    !/subconf 'i2' attempting to set access for \@eye2/
-";
diff --git a/docker/gitolite/t/info-json.t b/docker/gitolite/t/info-json.t
deleted file mode 100755
index 74fbdf4..0000000
--- a/docker/gitolite/t/info-json.t
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-use JSON;
-
-# the info command
-# ----------------------------------------------------------------------
-
-try 'plan 162';
-
-try "## info";
-
-confreset;confadd '
-    @t1 = t1
-    repo    @t1
-        RW              =   u1
-        R               =   u2
-    repo    t2
-        RW  =               u2
-        R   =               u1
-    repo    t3
-        RW  =   u3
-        R   =   u4
-
-    repo foo/..*
-        C   =   u1
-        RW  =   CREATOR u3
-';
-
-try "ADMIN_PUSH info; !/FATAL/" or die text();
-try "
-                                        /Initialized.*empty.*t1.git/
-                                        /Initialized.*empty.*t2.git/
-                                        /Initialized.*empty.*t3.git/
-";
-
-my $href;   # semi-global (or at least file scoped lexical!)
-
-# testing for info -json is a bit unusual.  The actual tests are done within
-# this test script itself, and we send Tsh just enough for it to decide if
-# it's 'ok' or 'not ok' and print that.
-
-try "glt info u1 -json; ok";
-$href = from_json(text());
-try "## u1 test_gs";
-test_gs('u1');
-try "## u1";
-perm('foo/..*', 'r w C');
-perm('testing', 'R W c');
-perm('t1', 'R W c');
-perm('t2', 'R w c');
-perm('t3', 'r w c');
-
-try "## u2";
-try "glt info u2 -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'r w c');
-perm('testing', 'R W c');
-perm('t1', 'R w c');
-perm('t2', 'R W c');
-perm('t3', 'r w c');
-
-try "## u3";
-try "glt info u3 -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'R W c');
-perm('testing', 'R W c');
-perm('t1', 'r w c');
-perm('t2', 'r w c');
-perm('t3', 'R W c');
-
-try "## u4";
-try "glt info u4 -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'r w c');
-perm('testing', 'R W c');
-perm('t1', 'r w c');
-perm('t2', 'r w c');
-perm('t3', 'R w c');
-
-try "## u5";
-try "glt info u5 -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'r w c');
-perm('testing', 'R W c');
-perm('t1', 'r w c');
-perm('t2', 'r w c');
-perm('t3', 'r w c');
-
-try "## u6";
-try "glt info u6 -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'r w c');
-perm('testing', 'R W c');
-perm('t1', 'r w c');
-perm('t2', 'r w c');
-perm('t3', 'r w c');
-
-try "## ls-remote foo/one";
-try "glt ls-remote u1 file:///foo/one;   ok";
-
-try "## u1";
-try "glt info u1 -json; ok; !/creator..:/";
-$href = from_json(text());
-perm('foo/..*', 'r w C');
-perm('foo/one', 'R W c');
-test_creator('foo/one', 'u1', 'undef');
-
-try "## u2";
-try "glt info u2 -json; ok; !/creator..:/";
-$href = from_json(text());
-perm('foo/..*', 'r w c');
-perm('foo/one', 'r w c');
-test_creator('foo/one', 'u1', 'undef');
-
-try "## u3";
-try "glt info u3 -json; ok; !/creator..:/";
-$href = from_json(text());
-perm('foo/..*', 'R W c');
-perm('foo/one', 'R W c');
-test_creator('foo/one', 'u1', 'undef');
-
-try("## with -lc now");
-
-try "## u1";
-try "glt info u1 -lc -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'r w C');
-perm('foo/one', 'R W c');
-test_creator('foo/one', 'u1', 1);
-
-try "## u2";
-try "glt info u2 -lc -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'r w c');
-perm('foo/one', 'r w c');
-test_creator('foo/one', 'u1', 'undef');
-
-try "## u3";
-try "glt info u3 -lc -json; ok";
-$href = from_json(text());
-perm('foo/..*', 'R W c');
-perm('foo/one', 'R W c');
-test_creator('foo/one', 'u1', 1);
-
-# ----------------------------------------------------------------------
-
-# test perms given repo and expected perms.  (lowercase r/w/c means NOT
-# expected, uppercase means expected)
-sub perm {
-    my ($repo, $aa) = @_;
-    for my $aa1 (split ' ', $aa) {
-        my $exp = 1;
-        if ($aa1 =~ /[a-z]/) {
-            $exp = 'undef';     # we can't use 0, though I'd like to
-            $aa1 = uc($aa1);
-        }
-        my $perm = $href->{repos}{$repo}{perms}{$aa1} || 'undef';
-        try 'perl $_ = "' . $perm  . '"; /' . $exp . '/';
-    }
-}
-
-# test versions in greeting string
-sub test_gs {
-    my $glu = shift;
-    my $res = ( $href->{GL_USER} eq $glu ? 1 : 'undef' );
-    try 'perl $_ = "' . $res  . '"; /1/';
-    $res = ( $href->{gitolite_version} =~ /^v3.[5-9]/ ? 1 : 'undef' );
-    try 'perl $_ = "' . $res  . '"; /1/';
-    $res = ( $href->{git_version} =~ /^1.[6-9]|^2./ ? 1 : 'undef' );
-    try 'perl $_ = "' . $res  . '"; /1/';
-}
-
-# test creator
-sub test_creator {
-    my ($r, $c, $exp) = @_;
-    my $res = ( ($href->{repos}{$r}{creator} || '') eq $c ? 1 : 'undef' );
-    try 'perl $_ = "' . $res  . '"; /' . $exp . '/';
-}
diff --git a/docker/gitolite/t/info.t b/docker/gitolite/t/info.t
deleted file mode 100755
index 22b5b94..0000000
--- a/docker/gitolite/t/info.t
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# the info command
-# ----------------------------------------------------------------------
-
-try 'plan 78';
-
-try "## info";
-
-confreset;confadd '
-    @t1 = t1
-    repo    @t1
-        RW              =   u1
-        R               =   u2
-    repo    t2
-        RW  =               u2
-        R   =               u1
-    repo    t3
-        RW  =   u3
-        R   =   u4
-
-    repo foo/..*
-        C   =   u1
-        RW  =   CREATOR u3
-';
-
-try "ADMIN_PUSH info; !/FATAL/" or die text();
-try "
-                                        /Initialized.*empty.*t1.git/
-                                        /Initialized.*empty.*t2.git/
-                                        /Initialized.*empty.*t3.git/
-";
-
-# GS == greeting string
-try "DEF GS = /hello %1, this is $ENV{USER}\\@.* running gitolite/";
-
-try "
-    glt info u1; ok; GS u1
-        /C\tfoo/\\.\\.\\*/
-        /R W *\tt1/
-        /R   *\tt2/
-        /R W *\ttesting/
-        !/R W *\tt3/
-    glt info u2; ok; GS u2
-        !/C\tfoo/
-        /R   *\tt1/
-        /R W *\tt2/
-        /R W *\ttesting/
-        !/R W *\tt3/
-    glt info u3; ok; GS u3
-        /R W *\tt3/
-        /R W *\ttesting/
-        !/R   *\tt1/
-        !/R W *\tt2/
-    glt info u4; ok; GS u4
-        /R   *\tt3/
-        /R W *\ttesting/
-        !/R   *\tt1/
-        !/R W *\tt2/
-    glt info u5; ok; GS u5
-        /R W *\ttesting/
-        !/R   *\tt1/
-        !/R W *\tt2/
-        !/R W *\tt3/
-    glt info u6; ok; GS u6
-        /R W *\ttesting/
-        !/R   *\tt1/
-        !/R W *\tt2/
-        !/R W *\tt3/
-";
-
-try "
-    glt ls-remote u1 file:///foo/one;   ok
-    glt info u1; ok; GS u1
-        /C\tfoo/\\.\\.\\*/
-        /R W *\tfoo/one/
-        !/R W *\tfoo/one\tu1/
-    glt info u2; ok; GS u2
-        !/C\tfoo/
-        !/R W *\tfoo/one/
-    glt info u3; ok; GS u3
-        !/C\tfoo/
-        /R W *\tfoo/one/
-        !/R W *\tfoo/one\tu1/
-";
-
-try "
-    glt ls-remote u1 file:///foo/one;   ok
-    glt info u1 -lc; ok; GS u1
-        /C\tfoo/\\.\\.\\*/
-        !/C\tfoo.*u1/
-        /R W *\tfoo/one\tu1/
-    glt info u2 -lc; ok; GS u2
-        !/C\tfoo/
-        !/R W *\tfoo/one/
-    glt info u3 -lc; ok; GS u3
-        !/C\tfoo/
-        /R W *\tfoo/one\tu1/
-";
diff --git a/docker/gitolite/t/invalid-refnames-filenames.t b/docker/gitolite/t/invalid-refnames-filenames.t
deleted file mode 100755
index 19267fe..0000000
--- a/docker/gitolite/t/invalid-refnames-filenames.t
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# invalid refnames
-# ----------------------------------------------------------------------
-
-try "plan 56";
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-confreset; confadd '
-    repo aa
-        RW+                 =   @all
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-
-cd ..
-rm -rf aa
-glt clone u1 file:///aa
-cd aa
-tc v-869
-
-glt push u1 origin HEAD
-        /To file:///aa/
-        POK; /\\* \\[new branch\\]      HEAD -> master/
-
-# push file aa,bb ok
-tc  aa,bb
-glt push u1 origin HEAD
-        /To file:///aa/
-        POK; /HEAD -> master/
-
-# push file aa=bb ok
-tc  aa=bb
-glt push u1 origin HEAD
-        /To file:///aa/
-        POK; /HEAD -> master/
-
-# push to branch dd,ee ok
-glt push u1 origin master:dd,ee
-        /To file:///aa/
-        POK; /\\* \\[new branch\\]      master -> dd,ee/
-
-# push to branch dd=ee fail
-glt push u1 origin master:dd=ee
-        /invalid characters in ref or filename: \\'refs/heads/dd=ee/
-        reject
-";
-
-confreset; confadd '
-    repo aa
-        RW+                 =   @all
-        RW+ NAME/           =   @all
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-
-cd ..
-rm -rf aa
-glt clone u1 file:///aa
-cd aa
-tc  file-1
-
-glt push u1 origin HEAD
-        /To file:///aa/
-        POK; /\\* \\[new branch\\]      HEAD -> master/
-
-# push file aa,bb ok
-tc  aa,bb
-glt push u1 origin HEAD
-        /To file:///aa/
-        POK; /HEAD -> master/
-
-# push file aa=bb fail
-tc  aa=bb
-glt push u1 origin HEAD
-        /To file:///aa/
-        POK; /HEAD -> master/
-
-# push to branch dd,ee ok
-git reset --hard HEAD^
-tc  some-file
-glt push u1 origin master:dd,ee
-        /To file:///aa/
-        POK; /\\* \\[new branch\\]      master -> dd,ee/
-
-# push to branch dd=ee fail
-glt push u1 origin master:dd=ee
-        /invalid characters in ref or filename: \\'refs/heads/dd=ee/
-        reject
-";
diff --git a/docker/gitolite/t/keys/admin b/docker/gitolite/t/keys/admin
deleted file mode 100644
index 676a711..0000000
--- a/docker/gitolite/t/keys/admin
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEA0/X7uwd7xOvC3UTZaAnFOR5xqhdgcyc8vk3d1bXXthiuUSmq
-5t4uhS9qj0ismcPX0YRNhSDElotG1KSWp8DceJpR2c7GYmELpqoE7ebVPnEBKY0c
-PX+G9KZNgbJyyx35QlpJmlO+LimM0oO8XarRphn3kc0jCTLKaI5ndEjGDHH4fsOe
-wlryW7a0RR/brMNiJYYzy5ADCOkAnyXQmbrQW4nROCPqFojBFTEBLpe8EuODlJXE
-mRHpa1k+k/grFgp/c1xbOrjox127LZT4vkLf5+lSwkhq8oyzWHUrQ+rUJZssi1LC
-GEZSudhX5reqksmIlTwX0GPIIwSwZFNVxhj51wIDAQABAoIBAFFLlzE0vZPZmPOk
-5H2ywaIWuyGxtZx1ACc9VkgRZprA/JrEkHfb35vVg9lQ1mJjavNA+zqERuI2qQQF
-3IKaxfS7u4j+dbhl4EIcE6frUP6R+RAmvx4XO3u6DSAhgUXGSUPZvUEjvV2XMhvL
-ywNh8Ob0LrANLdLpWBiiBavj/ZHnsVZj7y+39GKEtLm8BbsH8L7GanPl4uQDNruR
-Ef2L2pSEqml+Iva6yk5a22U293JCVZ/aqDdGvrnbjkaxqin5jBgL47D91A3xo4SW
-zFZkJR5SDYnFLdwnwTPvxSA9IXj6TZ2ZdnTNvI5Utpd0Wy5N4GlfXS3TBPBD4kP+
-+pS1vgECgYEA/D7k1IyOM2hGamHc0qG+sIxMHge6rJE8pYtW2suB2KX0bJvAeBY8
-eHM+pPFMbjjZHlU7qB9qmGbZ++ZVlEv/SqqHizvwLzth0P4MJ6/UjAcmAdEUclV0
-YSzMRFk/g0J7aMlJb5NXgA5xlArHLsmV3Zc+QwFPECgzz5LHwD5nTMcCgYEA1x2Y
-qb7FXwcQPDcs4Qwux12tCUaExQMZbNoLHWrXw7ktHRfR9sI8TcEErLzc2wnZbdyZ
-av/GYSTR9UCeq12kUhmTL4SNryktHKNKEfDEvR7wK6sa9iffzZH8FDe5JktLXnu7
-Oe5SNfLDHA5X7qQefz8s2658+xVJmdp+uasNOnECgYEAlzBXVbJ9VQCuG/tWMQVz
-VzxwLxuw3tgagprWz0NlK2ak7ygXn6KsUgG5TYG3ruTx9gVeQXG7IWecRiiTqNQ4
-SxeVMHYXiyfLhEmRHYR9IAT02efomnLv04LXWCwqLlF9yJvFIVQuAPonR3WCV1/K
-LMwHLIAvVF7UVxkCEw8UOWcCgYEAwiUH/0sZvuYVFQOHEaV5Ip286b4nXdeqPr+b
-gHVJPnAF81foO5iZ7GLj4TKi8V02SxzpqdQmKs6cX4huq6LcBuzmFeDALvIusMX+
-t6phJX6irAbFUpwyNMoog+a2x4T1BNUO6P3aXK44wT2AxvSAQb+2sJ4OVl2kC6NS
-9CcYzUECgYEAzqbWlJIbjJx5620Q95bu+lpessOUtoVcYryO6dQNZOiis8aDZjJk
-RKdB9qhJlcUeFqnvJS5L5gohaJoyx0wMSYVB7MrO6kAIMHo/OriEQ6CTsQOTqa8n
-q4cV9Wuk9pRb1b/x5eXCcHe8P7wBt8KKIh/VBB4aDyeIwGbO0NODYr4=
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/admin.pub b/docker/gitolite/t/keys/admin.pub
deleted file mode 100644
index b50a5b9..0000000
--- a/docker/gitolite/t/keys/admin.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDT9fu7B3vE68LdRNloCcU5HnGqF2BzJzy+Td3Vtde2GK5RKarm3i6FL2qPSKyZw9fRhE2FIMSWi0bUpJanwNx4mlHZzsZiYQumqgTt5tU+cQEpjRw9f4b0pk2BsnLLHflCWkmaU74uKYzSg7xdqtGmGfeRzSMJMspojmd0SMYMcfh+w57CWvJbtrRFH9usw2IlhjPLkAMI6QCfJdCZutBbidE4I+oWiMEVMQEul7wS44OUlcSZEelrWT6T+CsWCn9zXFs6uOjHXbstlPi+Qt/n6VLCSGryjLNYdStD6tQlmyyLUsIYRlK52Ffmt6qSyYiVPBfQY8gjBLBkU1XGGPnX g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/keys/config b/docker/gitolite/t/keys/config
deleted file mode 100644
index fc75580..0000000
--- a/docker/gitolite/t/keys/config
+++ /dev/null
@@ -1,20 +0,0 @@
-host *
-    stricthostkeychecking no
-host admin
-        identityfile ~/.ssh/admin
-
-host u? admin
-	user %USER
-	hostname localhost
-host u1
-	identityfile ~/.ssh/u1
-host u2
-	identityfile ~/.ssh/u2
-host u3
-	identityfile ~/.ssh/u3
-host u4
-	identityfile ~/.ssh/u4
-host u5
-	identityfile ~/.ssh/u5
-host u6
-	identityfile ~/.ssh/u6
diff --git a/docker/gitolite/t/keys/u1 b/docker/gitolite/t/keys/u1
deleted file mode 100644
index 828d1c3..0000000
--- a/docker/gitolite/t/keys/u1
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAuB8HmJ5UX30xFktmvlLgSrzsGIzSiYiAYH8eU6epJGr/xjYD
-9GE6G9EcL+/NTc0ziPhIUtVm+h+kFEHtQ1VeOFEuVuWAukPNXRFDrYOMfeR4U1h7
-olT58U3+IlctreKavXr+7bPPhbhvdB7FPM8xusaPfwT6BG4sTqHyOPL5a3eXW7Sp
-tuVD87KNHKo3skWcbb78EVQt7MfCMTam6X2O4Y0y1da51kOht6qRaeJHoaAjXB4V
-pY9lJSQA+Km5uYu+FIwn89z7P4j2aUNZFq2UOSwuViekSR6lfHvortyh8YFrSRUs
-Q4berZUICDp0Ek2BiJirWiPXAp9uxwXms9UbvQIDAQABAoIBAAUTnfMAUpU7b3IM
-7C1NPa/x25SltVxjbh67AowN8GT3qku9y4geciq4Lk3ID+IYSVZ6egwGpEs7Ohvw
-4Wjc3rcwzdVJiK4aFnx9cF9FZEdIWGT76JTGQQn9O4eY3cKQn/GfhY3qSkuGlVQf
-URLnJ5jdxrEa4wXiP8h/QJ1/XY8v9en0uWf/18fMHyzImpd8dqgtTdomSQLjM2ie
-1k9Fllh/5Q6e1Kd5mn5QP1QPC65Z78IskOot9Wrg0sk19sWiFMsopgJkQg66BlnM
-Fj8A4HPS8Yylt0oXJ5yytUYfvZNDRANZRiAz9mfgQw9oapJLnCLt3Awi5bcKJIVk
-/nTccEECgYEA8lSPFeTyzid0sIextXjjHvV4riSZKAHAa5M5DfsPkXLQfbEF4zog
-FLZ6c85jUCk7/vTzDRXr38XKaGbAg/1M3UJk7lS9shh1Zdo0+Hshq7rNICNLKz5H
-/u1/0gkxqqJcpXaoOHYN1hM7HJrP3uZFDIA5ZrB7JD20YDCQ/2PWrS0CgYEAwoHi
-qEKKXOol7FIiG1upTjPaWMTmxtmSs2/pobMVf+ZGDMPts0pbqDegXruaNFUrUQOG
-9yvrjA3a2QaKt7R5eDvHAafeMeu0WcHaqUWtIueTtEuduK4fXsCGONBPEGJu+Ct/
-BOCV/W8MAmzIOvffT7Jg1HWsZyAstoikPi1w4tECgYEAuvVmFxw1/7sNGgz2m+2S
-PJZh7uipiOYhEF3bTN//mNWd6PskcbSsf45xVttKX9QQR5mv0s6w1koA6R8tNCe+
-n43T1NRoLfkUyenZqENHLPjHvR29prU8Un/ld6REP0NYewfarQTXk+vuVRlTesLp
-TsW2g3Vw6/r3KKcPlxntzFkCgYEAqqkH1BY+DHQtPgJ6hoKQNFtuswBgdAymmOYS
-mZvlu0iyIbUvNGaDsT7NaRE1pcEstnJf0zMoAsSNRmpk//ZLteDNJXjCjg5/OVnL
-n0XROZTylfjatBWi1KIbonGzTW7warLPSdo8ABeU8/O6Y3Lk7qpWJ1PwJrOmR6nw
-YdXA/GECgYEAsSokOABGGLQ2zOmDYPDKrRenLho8cSe4g/CF5b6x5MXfJvvBfI/M
-hOS/2AFj7UkOSVM9B9QH607F67YJuBPNGvciCatqY/Bcs6ViuuyqG9U4O13OrrmA
-oG8Cho3Zy2v3udaLJ6O5JYcpX+hdvkwoG5j/8hLrzkD/3AA12z6QnV0=
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/u1.pub b/docker/gitolite/t/keys/u1.pub
deleted file mode 100644
index 264c1f0..0000000
--- a/docker/gitolite/t/keys/u1.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4HweYnlRffTEWS2a+UuBKvOwYjNKJiIBgfx5Tp6kkav/GNgP0YTob0Rwv781NzTOI+EhS1Wb6H6QUQe1DVV44US5W5YC6Q81dEUOtg4x95HhTWHuiVPnxTf4iVy2t4pq9ev7ts8+FuG90HsU8zzG6xo9/BPoEbixOofI48vlrd5dbtKm25UPzso0cqjeyRZxtvvwRVC3sx8IxNqbpfY7hjTLV1rnWQ6G3qpFp4kehoCNcHhWlj2UlJAD4qbm5i74UjCfz3Ps/iPZpQ1kWrZQ5LC5WJ6RJHqV8e+iu3KHxgWtJFSxDht6tlQgIOnQSTYGImKtaI9cCn27HBeaz1Ru9 g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/keys/u2 b/docker/gitolite/t/keys/u2
deleted file mode 100644
index 02486a6..0000000
--- a/docker/gitolite/t/keys/u2
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpgIBAAKCAQEA4/t3WV4q98MlYV9Jbvbf7gE2Dzit6dD8xHsWBh2wTmggQM9I
-2RsPp1tTIoOpt4YdlTzV41577BKLVMvqG7AxnVljC7+m7PrT2YmxEGrrbcrHebHu
-+pwh0lkN/CIz6MHjWzLbFiRoHhKh9LyfSiKxCgJ3dyjFgAnA+wrXkwIfPRG8qOLk
-sb1KUsMdfYm0OUEC/mHU2dsIS5HIY6xhy5Q5BXWgkfYUK7LL7Eyw6ffLhvq4U9tv
-Qv+u64Qowew4BY4B8rvyb73iEGcInIF2JRY0jVC8yJFejTJo2KKlXxu8MyAtAhth
-cHE6gA7xmn1d8TF7sxHDNqprvD9mLTjUVdz1owIDAQABAoIBAQDEGaWLZYioHV+l
-5gSQQiJT4w7RAPv3RyBlEUrcb+UbTE2R8brDpJdOaSuVYJM3nVEM8Ys5TChj43+d
-rNjugBvtMNoVXQEEjqxzThDUAmQHyIjUkMzzHCGrgZaZ7gGgkEY0SAZTgXVdiMFu
-dmC9sCGAbqa8BIH9pGYuiiDr/sNIDr3ekyqyuSA0Aa2JIrEx1TKFXF5JtGseU9S6
-bUfesCpoWGyVdulr3NbsLM26eDCsZo45OF5QdpTtU99xc9K4gsOre0ZtqEJMVGlR
-2nDQILCroH93GabSIW+fiUZD2lO9BxXAM0NA730ODQWyM8IgoWrqxGUuFz40l7X1
-teB7yRwBAoGBAPkkF//ZaEUUyCX6+a6TjaPQ1atemQCxHtIm1phfIM/u2uANqeOP
-Z+N3dM0TL53lRx/xbT0dO4sfF73XcF0sYkQj9rep28Q04W8Z6iC/I+jQAJJ0bYl5
-skUGTECxIPLmKOciQF7N5PUGvxhI4oq/0vgDYFc+NW18mow1Z66H1PkjAoGBAOpC
-P9EJXEFKZY1lK6ZL6wvJ6tJaPWAuiQlkOdj9wLvvzywQPlEdBJ1k0q+ndAqpR6WJ
-eTlkP/bzDpLRi+l4PEVTsFlpxjcfVn19RRabsKTNIS0usl1el/uQP7u4rRimBCz5
-MO72GD4ARM5CgMZZMGU5AXmxKEM9feTcUNss3RmBAoGBALTYsmMRmVKr5y1KpPtI
-OER1TuR6Ym3SJCE/9/3a76KAK3j/8hYw/qRrDenex23CBIL3aOg31AUEqOMxA2te
-0GXOBUUEk3Y1PH69POpQVOymMAQfZ3OnVvQrwiYjbVtkHsTIZBltM4l5QDWMkoVN
-AQLu0HwDuBylmjm0enKCPuIpAoGBAObd257bprwB4gtzhY0ijMbVfENLA+nictN6
-nzgm/Oc68+XtLD0sZ/vl/W13jnljU2TlEz9oeVGbQOWY9lZlVKDOVaIJCHwSul56
-MriRP4lrUCMDPm2eaBJYmzcaTh1YoAzimUMn7cRM54KPL/JKu9NGVxnjala6J3SB
-XH5kvJIBAoGBAITZe45tIbVkGjK3jTjgBfaqFfhyws4L3QgRbjqpy2h9nLEGHMYV
-RkIt6bCkw6cy+8TnYB0iG9lcGP1S5E4C6zpTdldi/5tGl7uu9qfEz4hxRpRbJ4Q0
-nwZzUkgBaLxAiLHfntBpwk16UvHkCpo5hiKzSLzxfReXzQPUUudGRnsG
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/u2.pub b/docker/gitolite/t/keys/u2.pub
deleted file mode 100644
index 916dcf5..0000000
--- a/docker/gitolite/t/keys/u2.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDj+3dZXir3wyVhX0lu9t/uATYPOK3p0PzEexYGHbBOaCBAz0jZGw+nW1Mig6m3hh2VPNXjXnvsEotUy+obsDGdWWMLv6bs+tPZibEQauttysd5se76nCHSWQ38IjPoweNbMtsWJGgeEqH0vJ9KIrEKAnd3KMWACcD7CteTAh89Ebyo4uSxvUpSwx19ibQ5QQL+YdTZ2whLkchjrGHLlDkFdaCR9hQrssvsTLDp98uG+rhT229C/67rhCjB7DgFjgHyu/JvveIQZwicgXYlFjSNULzIkV6NMmjYoqVfG7wzIC0CG2FwcTqADvGafV3xMXuzEcM2qmu8P2YtONRV3PWj g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/keys/u3 b/docker/gitolite/t/keys/u3
deleted file mode 100644
index 163bdef..0000000
--- a/docker/gitolite/t/keys/u3
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEArK6uQkgoAnS+w6vs4DmvdOfcGdFUzh3ivHAXHug7sjjKGUB2
-KwcXNwcmJPtyNXM0BJ9ZoOJSqJo5cWLMl7Qn1HBubuyM02Id9EqeJu1Ytn/i1XFY
-NMp8fj4wma3LZTdeOy3ockbefkw6VQUq3cheXIeaVpT91jsuyIaE0ejWkjGMu596
-zXFQZYTSO28TIYghRvhXGq5W9hJ3V2k+ZAQ/AsWQqjK4XruICi+RGRpKj59ECI7V
-zIrq4MUEti+3LldaY6tyYsTGQLtFJYu+l/ZavkrM979cPOxLeoi8ZHPTPKh6asdr
-ZXA2J6++IyIgNy2Q4sNxTmkIlU/EDysvTTGdMwIDAQABAoIBABF+NJr0UlFFYFnU
-Hc/tKBAQuORIp22l62Upeb4gyoNYa2i5df8P3dMuPzf53Oz7OabKObspkjQQQ4dv
-+cfYcTx9E0LbZby4MM6hjHnnC1iZhfIXZFccuBXV2PiIeZVMUZhvIyAIe9uRf0tD
-lb8X4C9BcWoZ98ju/+NCdUwKaUov3jXc32hmsAhK+dtqBE+lwccX9keJQcncf+6j
-+2znpDAJdaF70dM0DidbkmXmOTgH6LjjqrYRTAUnVsvUyDsr5YhopwOHs0E95YB4
-RzO7V/DA8H7DQ+XE20Iqp2i6dSbRQQPxbQLvJG4BaITIqb1L8/WJ6N75O/uns4rE
-Y8WVwWECgYEA1gDDP70DqvVMu6KDvn18pvfxzxJ3jccYcBZITV/E6xgj1AbH7fdA
-0iwvG6jQ26DTUBfLBquZ2fCCyI44OUpZ8GZu/wYBn5CQjYtr1vJ7zHKM3dVf+POT
-cGgOVDIHopCCX5Dwb74OpbkTV4g/WxouClvz0Ovobq8NncSkJJkyGEMCgYEAzpIF
-oj2AVMWDd6NL+P8e+QXPYEvJ/trAHoAteI83Eof4ZOC/sBr7Gf3c6nM7ZJbCXGhJ
-NCCr4teHJMg9DThQ1KxKn9qEf9dWiAE+HCouaZU98Z0UcLQ+tgPeBh/Dw7rTF3M2
-7A/LtLYbg1MoPCZNj6V4qGjmNWCy2lku1ZGBUFECgYBD/4oKvqxjrf3rwP/Lj2QE
-SdRzz5JdYl3Jf8sJityvNsRropv0aRQXtCJjz4hNwRRj5quEOxJvxZRI1afXzGA3
-mtS6A9aQNQc5couZiQL9O4i3FA2itQKsPOQQrLTwWqqSYyOC3gkZb21N6uT2taLb
-d8xJHiyEvuq8rrbZSjQ4sQKBgEkUDZws58aVrYHYqlrnXny4mnm1tjtMBiWEMRHy
-kIgkxDJj9EyH7wdt8QacR4m5b/8jAarIWCbDGtNfZ4HSx33FigztUGytsLYiwmdS
-YOMHYkeky4NnsLvRuG0wNaB76ovkPazblbRTrH4UICrPXicQYhQqMC74C64FWPVD
-KZ1RAoGAE/vKCHCzPegTT9gr2aaIrhLPUUZboOF4gHajYr9Scr176nJhpIvP/0Y2
-yQtqfas5lID8ouqXb+oL0Q4Yi00hdu+TRYQHm3M+2UL7wgffR5H2vfhk24UUDfV5
-0qQjNKp3pNUWZdiZ2J+RGUszXt0THfWbWI/ntwnG5QchqXCqYEA=
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/u3.pub b/docker/gitolite/t/keys/u3.pub
deleted file mode 100644
index e97645c..0000000
--- a/docker/gitolite/t/keys/u3.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsrq5CSCgCdL7Dq+zgOa9059wZ0VTOHeK8cBce6DuyOMoZQHYrBxc3ByYk+3I1czQEn1mg4lKomjlxYsyXtCfUcG5u7IzTYh30Sp4m7Vi2f+LVcVg0ynx+PjCZrctlN147LehyRt5+TDpVBSrdyF5ch5pWlP3WOy7IhoTR6NaSMYy7n3rNcVBlhNI7bxMhiCFG+Fcarlb2EndXaT5kBD8CxZCqMrheu4gKL5EZGkqPn0QIjtXMiurgxQS2L7cuV1pjq3JixMZAu0Uli76X9lq+Ssz3v1w87Et6iLxkc9M8qHpqx2tlcDYnr74jIiA3LZDiw3FOaQiVT8QPKy9NMZ0z g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/keys/u4 b/docker/gitolite/t/keys/u4
deleted file mode 100644
index a669e34..0000000
--- a/docker/gitolite/t/keys/u4
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA2Wg3bl7T0C8VuR8HdbAqmwvQH4/T/maaqlQeJqcATRgWQNDv
-VthEasW5Kx8DzcSVRWS0cJ5EpTLGvrs84aXgdvg6TwFZKO/ujrkFDZmw9hd4I/Dv
-0dp/Y7himS8vAvnnWfYyqJBiX4plEx9Kg8oWHwy8KK3HHKoO8jAWAHOWO3GMB8BV
-128VLovGB6Sp99GrgltzP9UhNRHt/doa3ve8+fDk782SandVTTR9MNLt7qhMSOKr
-bmoFWtL36W5hmVjFGTZC1ZNIU6PiqygUqPtyAYblwv/nZ35s72KmxP7Seag3SsuZ
-UPnRjM4PZ+7YE7tcPTOUxcct8xuTZXgjh2WiNwIDAQABAoIBADSrR8qIVJ452fRo
-LQF49UlsmjYbPQuDxfJ/wHIywSLsM+/t7h3G9QQ89Hga4mwGNPeDxycFYLH41Cc+
-6yfrbK7FwjKDrBr7zXpsHmpGEpX755Ile6QGYBhDgjeEM8pvynmD6I/nsr1cpNH2
-IbI90hAhoK/mMbejB03rEll3pyytCgEvJQsu847dTNTZN+PHsumPr9HERi/dDrbw
-JrDSH2tbOvYw4UW9HLFfZAB+IgMo34WXf6kcUY69wWQbxnv1e7KHnYkxIuLCGZ6x
-Lc9APM97f4atlGt+mAtqK97CJB1AqoIE3KpPq1x+gpFSBNEE+9U9KnItuSqF3mG4
-vq/VjIkCgYEA+ASubOgzJaAldNz3dinLYK6MLB+V1R+RpkDc3+OgfF5mgg11ZtpE
-/DO1Ndpf5dOYB4JYGfhC9+xomHGsQmbOsIUprWaAR/xaO6Bgxw7cxkOBIadsrdwu
-MWJ6h3gN72zuhKPERpUVVH7ZH5KQfZwxEMgquUkGdEwumU4rMXeCFqsCgYEA4GdX
-qI/5UNXEPnXk3dDWNzNJO7gRoonU228IM18qz5ZKMRIKp6Sq+wIuO8+aQMr2K0rO
-RMQk+lLOZ17omaWh9ysDPzTCWRrjOiDOnYWDPCclTeqSnEk8uuWyppDGNXgQ6osM
-LnwJSeP8+1EDgkKf5zoiQfcyBc0v8PSRSdTfEqUCgYEA2PqHeqHd9UHY4xdZq1e/
-JLMv0H5Ff/GhY7iFQ54JziRsO8T4e+Xiyl2WYCnPEer+qzseRoIKXInHq+5uzJzS
-oF2va5MsEU41xsp1QFDBVvbBpyapDqV9CBlmptOiJV/Af+wiD7nnskdTPqrjm/Ck
-gFEOB5Fagy4O6nIXmaw69AcCgYEAhVSBndKlZKUOa7oqmKzLipK7UXNFbxiL0zE+
-Yx+JVTvLqyo4EHFjca5TABCSayrsZr6UngEYo27t2jdm5lumRzBURoq3aq/yEIiL
-msZIOkZcANZ988QEBFwT8KmWSxCipGinfTsPXcrLdhslhZDGZ2GAF0ejfhTzBiyZ
-4o9LV00CgYBf46Z2M1fWI6Tc8HUKr9WoyUmTmUtHUFPt9IZ2CKm2czoltpku7cC7
-ztlt4LmVPKv1UUavbC/nCz6s1ylOkY0rdm45FSYXKDYPMQqzQix1jG4GZJjM9En+
-M848LupnHBFsmHyQqyyRlsg1gb+wtvAw7Y44wcfAhGbiAT5DVX+zxg==
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/u4.pub b/docker/gitolite/t/keys/u4.pub
deleted file mode 100644
index 06f3648..0000000
--- a/docker/gitolite/t/keys/u4.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDZaDduXtPQLxW5Hwd1sCqbC9Afj9P+ZpqqVB4mpwBNGBZA0O9W2ERqxbkrHwPNxJVFZLRwnkSlMsa+uzzhpeB2+DpPAVko7+6OuQUNmbD2F3gj8O/R2n9juGKZLy8C+edZ9jKokGJfimUTH0qDyhYfDLworcccqg7yMBYAc5Y7cYwHwFXXbxUui8YHpKn30auCW3M/1SE1Ee392hre97z58OTvzZJqd1VNNH0w0u3uqExI4qtuagVa0vfpbmGZWMUZNkLVk0hTo+KrKBSo+3IBhuXC/+dnfmzvYqbE/tJ5qDdKy5lQ+dGMzg9n7tgTu1w9M5TFxy3zG5NleCOHZaI3 g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/keys/u5 b/docker/gitolite/t/keys/u5
deleted file mode 100644
index ed65131..0000000
--- a/docker/gitolite/t/keys/u5
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEA41A0bY6+0akNSJlR2PeRATNtncARXVOUar7CNaxwPqVXQR1+
-TmU9evmIEkRLf0kFAa7L3QDFroFu4sDiSJjvfYIkHdoxO4Fk128PJBhObIXaarKc
-UBIZ29/8I3dTedq5CY/YHL/AjaT+0VktWX7YwigvGDamrXAKqjnW1mWKp6TNj8bp
-vppBvj3yvdYoOLYvCs/SKfKdlayngiihTbKELPcRu8NzYxHiF2b/u0t31evdP0fA
-/apAslKhHdCm8ScZJuyIdztcogBFE5dGm0h3qlbJKvKT8JmTcgQ5TBBcmqPVmUkm
-nPvIzd2G7D1smbExG7LnqekHcS9dvaPnF0B3oQIDAQABAoIBAGl1e21crXDN0mjd
-INjdOnvpJTDru+KldRT0/VszbjvSL6H5EfFDDPvxqsx2vOQHt3fpZZFZ21yzlgND
-Y3g0499BsonbAb5OsL82OjsPv8qfaw7XYKfRTgfxaaP2p1bAP9qMzsG/wJC2fLYZ
-fm2n6N5jED5WlIugkIIbJW4AXAycDB2ZU0xtPTHJ8nrSj1otDCsD2VbbVHXN7H6g
-HrTqP4RqD+uVDIxSrXllz4Udwe/I1wUrvY9HjH2qS6Liqb5kw8SOf4a2et18+KB2
-NNk6ZEAlmOx1ddC2eZPxm8XxAxdSwTggcwvtixCeoXR53OwTZAZ8BBzwusrMklZm
-/n5zPWUCgYEA88Lf4i0WFu9h4FnQ6qxCAKDS1XyRpCYt5cyTpZPMV3LuUV0DPS3K
-+EZeU689BSOiwav8omCtrrrOHtE9fHjOH85Gd4IRyOwUQWI7RLpFiI8Lbs4tMbP5
-k1UOzzTji++N47XfTTQVdwHbx4jac80LVavbRd3AKd6oRjc/gQOpgasCgYEA7rnr
-uoWqT76xVNLmE+g93x33hzES2HitgjHzvm5B2Cu6fwlXi7cSnLEWVn7W5QXEuhek
-6uhq4NC0ahL/qAyJsFhVve32qrR7yacDVlMWZ5iQPfqtvS9CsxyafADBWsgeN4L1
-5oqQofNlh0l+UvMFp8INNbKfxTOPKCMfGxIEd+MCgYEA7UsJky380PrbtwD4JVrn
-LaFhXL3VMYyRJaFPIeKNC5wwbzgyjP3lFme6L5Dpv/T+3bZFSvT+XpgvS0S5rFAV
-qFSvuGsAUS2wUi4EMFV8lwFZSdafnEDtdgVZU1DTKkhbQg6sgIVxV9aRUt7gedZj
-cFTKMms6RAgim6fww/ECs90CgYBdI1pt9jJhVHPZNUMgpy5ke0uUijfhDwwazKRd
-OqUj0sO7RojKcM2pJoohivEKf3qmZA0qvSzds2+AJxNpnCKoE364UDw5k5rsLOXn
-axlFp8c29zOLqQGr4c//60eExKjNXaHUpWESXmTRKIJJmJkvP01qEtu0043ZygIb
-zKbDowKBgHhacDR3aat3kkaTp/4AhekhDhMgZ1u2NIi0ycsA6zRlmFucHMwtKCM0
-VMuu40D9N1lTmcdndNKkTJx6CpbS7g/y0ctkyGwgFdmTjjHYl1nATt9G2oRzKx6I
-nQ+sBUwBPieIqEmiFh+KAsDox6plrtvhSSwp8FYLWBJXZHlLJIsd
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/u5.pub b/docker/gitolite/t/keys/u5.pub
deleted file mode 100644
index 96a0045..0000000
--- a/docker/gitolite/t/keys/u5.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDjUDRtjr7RqQ1ImVHY95EBM22dwBFdU5RqvsI1rHA+pVdBHX5OZT16+YgSREt/SQUBrsvdAMWugW7iwOJImO99giQd2jE7gWTXbw8kGE5shdpqspxQEhnb3/wjd1N52rkJj9gcv8CNpP7RWS1ZftjCKC8YNqatcAqqOdbWZYqnpM2Pxum+mkG+PfK91ig4ti8Kz9Ip8p2VrKeCKKFNsoQs9xG7w3NjEeIXZv+7S3fV690/R8D9qkCyUqEd0KbxJxkm7Ih3O1yiAEUTl0abSHeqVskq8pPwmZNyBDlMEFyao9WZSSac+8jN3YbsPWyZsTEbsuep6QdxL129o+cXQHeh g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/keys/u6 b/docker/gitolite/t/keys/u6
deleted file mode 100644
index 86deee7..0000000
--- a/docker/gitolite/t/keys/u6
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAxyRjRT8RoSDnAnbZdrTjXhBMrkfNfolWFqc3qAjAo8Tmp7Ns
-n7R+KCl31RDkC9u4ll4AOfF9bIdP9ovDVvXoTMoiOdPTYqsnaMBBpDH04vxID2U5
-rEOhSzbvTazzaSlYNFED2a9bMfULuF6WxchFPBQGhTZaC8cDAkS5YYXvjHXAn1GN
-kpv0k5qltD8vjJoM7Mg5JLm84WejPQ5CmwOXqsQj69ZUZEyA8J3oqWVYkEhpYkbK
-IuzaHkrTC0PUQJ8MS3wM8358bWp53zYFJMkyL1a/zJQPOMaDiFTXXj1Uue/5ZkIM
-/fkkOMLbaCgEFCMbL8HkVEq4Q0dLhJKl1IdzbQIDAQABAoIBACQd91shuyLMAtmx
-kHM1D1+J+T5Ki3x9j/1/ylpRbA7HsUWNBxBX/eFu0+ryq0lzSiELX2Mi5yp9yATh
-CEaHRuBWcKqoPlhQzk7zP3R2EwHv22nfY/xYL7KiffhKe8MA2pxybQ5X/WQsGzoO
-/a1VSylAQIZ8ewxTxbntmOmVDwMcLZdY5X4NAmzUw1lFD2TVOlHyhjvhgIzhO1tp
-fBvsX3OL+Pk0tTQebuhoqEy2R01BLc+0ZFAKAFZpZgualqZqjyIU0isQsEo+EK4s
-Pn7Ccxy+156aWAEdgD5Aj7oMn3zA9YIt/JoX8muaceUOj3E7B5ZKBtYZkFPVnKO9
-rPMNTIkCgYEA/v5IeFDZjcAMLWqhuPekcUQYMXc+I0ZTn7vT3aksWxhARG96CPdG
-HNLMw4y8yZLnCAsdKUJGtrVcn4y4K0FzUYn0tDm9cmtFoFcQvLPp4mR1kB84urIG
-7qEwv4djeLhl0cYsqMpyl7qflbTVwKa09Fy7HX9ZFL58nXVX63uRXlMCgYEAx+2o
-L/GKkKgRPpCudsGoplECjzqP4SWHXaYVOupVzpnvxFKVcpBl6Un6p6U9V6W16k2C
-XUg9XqFdleawfAwGQ2D/Ip/u4r8GKOphv0QCjO88ld15Ky9mr9Sk4/Z2EAMUrmKg
-CS4hGBF7VIeA3FnzJwLkYL0+WQKpKBt/zojQLz8CgYEAnmtEgttYDeTeq+iviMbx
-9xyjGzhF9oxer8J1oiTUVdP/OYU4gBGAEbA1Xtg1AdauiiS9fUCbxi9u2AEI+naz
-OllHGiE1Pby/iRoOX+42xFw9XcjH6dVo0SB7tMJcXkfRmj5QyJzeDL35H301v3bS
-vW5PIchYg7bEnN6mPLqMWdkCgYBVWaX1Yb5v5vAFr6prVF11MxxOnQeTbHwPhLmH
-f0bGfn0XaNIYKID5SPXS3/4CDuJMdm5y+EYKwgS729H4AwIhfaUt2O0Yq8gra3Pz
-PUuBcxiAOh5iS0ghRDxofW0FhOstTzlW8fR62+u0uGxQpa3iN5/blK6rPTGNx7+W
-Il4N7QKBgHRTxUZraVt3n0kJ4+tdc+F8XK1wLyVC9PmtW+28tiyx14k8o8H/6W94
-r3lyI13sUnvW6zU0VMAALQujRcJDLac/zSUdFGmgU3P3QatU5yUm0Xpt1uFM49Zw
-xZLBTDJxe2Qrc3Z3SKReRqxLz6tTU1soH7TVw/S36tBovKjTw7Cc
------END RSA PRIVATE KEY-----
diff --git a/docker/gitolite/t/keys/u6.pub b/docker/gitolite/t/keys/u6.pub
deleted file mode 100644
index de5b06b..0000000
--- a/docker/gitolite/t/keys/u6.pub
+++ /dev/null
@@ -1 +0,0 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHJGNFPxGhIOcCdtl2tONeEEyuR81+iVYWpzeoCMCjxOans2yftH4oKXfVEOQL27iWXgA58X1sh0/2i8NW9ehMyiI509NiqydowEGkMfTi/EgPZTmsQ6FLNu9NrPNpKVg0UQPZr1sx9Qu4XpbFyEU8FAaFNloLxwMCRLlhhe+MdcCfUY2Sm/STmqW0Py+MmgzsyDkkubzhZ6M9DkKbA5eqxCPr1lRkTIDwneipZViQSGliRsoi7NoeStMLQ9RAnwxLfAzzfnxtannfNgUkyTIvVr/MlA84xoOIVNdePVS57/lmQgz9+SQ4wttoKAQUIxsvweRUSrhDR0uEkqXUh3Nt g3 at sita-lt.atc.tcs.com
diff --git a/docker/gitolite/t/listers.t b/docker/gitolite/t/listers.t
deleted file mode 100755
index 5fbf0ae..0000000
--- a/docker/gitolite/t/listers.t
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# the various list-* commands
-# ----------------------------------------------------------------------
-
-try 'plan 30';
-
-try "## info";
-
-confreset;confadd '
-    @oss = git gitolite gitolite3
-    @prop = cc p4
-    @crypto = alice bob carol
-    @dilbert = alice wally ashok
-
-    repo    @oss
-        RW              =   u1 @crypto
-        R               =   u2 @dilbert
-    repo    @prop
-        RW  =               u2 @dilbert
-        R   =               u1
-    repo    t3
-                    RW  =   u3
-                    R   =   u4
-';
-
-try "ADMIN_PUSH info; !/FATAL/" or die text();
-try "
-                                        /Initialized.*empty.*cc.git/
-                                        /Initialized.*empty.*p4.git/
-                                        /Initialized.*empty.*git.git/
-                                        /Initialized.*empty.*gitolite.git/
-                                        /Initialized.*empty.*gitolite3.git/
-                                        /Initialized.*empty.*t3.git/
-";
-
-try "gitolite list-groups"; cmp
-'@crypto
- at dilbert
- at oss
- at prop
-';
-
-try "gitolite list-users"; cmp
-'@all
- at crypto
- at dilbert
-admin
-u1
-u2
-u3
-u4
-';
-try "gitolite list-repos"; cmp
-'@oss
- at prop
-gitolite-admin
-t3
-testing
-';
-
-try "gitolite list-phy-repos"; cmp
-'cc
-git
-gitolite
-gitolite-admin
-gitolite3
-p4
-t3
-testing
-';
-
-try "gitolite list-memberships -u alice"; cmp
-'@crypto
- at dilbert
-';
-
-try "gitolite list-memberships -u ashok"; cmp
-'@dilbert
-';
-
-try "gitolite list-memberships -u carol"; cmp
-'@crypto
-';
-
-try "gitolite list-memberships -r git"; cmp
-'@oss
-';
-
-try "gitolite list-memberships -r gitolite"; cmp
-'@oss
-';
-
-try "gitolite list-memberships -r gitolite3"; cmp
-'@oss
-';
-
-try "gitolite list-memberships -r cc"; cmp
-'@prop
-';
-
-try "gitolite list-memberships -r p4"; cmp
-'@prop
-';
-
-try "gitolite list-members \@crypto"; cmp
-'alice
-bob
-carol
-';
-
-try "gitolite list-members \@dilbert"; cmp
-'alice
-ashok
-wally
-';
-
-try "gitolite list-members \@oss"; cmp
-'git
-gitolite
-gitolite3
-';
-
-try "gitolite list-members \@prop"; cmp
-'cc
-p4
-';
-
diff --git a/docker/gitolite/t/merge-check.t b/docker/gitolite/t/merge-check.t
deleted file mode 100755
index fdea318..0000000
--- a/docker/gitolite/t/merge-check.t
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# merge check -- the M flag
-# ----------------------------------------------------------------------
-
-try "plan 55";
-
-confreset;confadd '
-    repo  foo
-          RW+M      =   u1
-          RW+       =   u2
-          RWM      .=   u3
-          RW        =   u4
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-# setup a merged push
-
-try "
-    cd ..
-    [ -d foo ];         !ok
-    glt clone u1 file:///foo
-                        ok;     /Cloning into/
-                                /You appear to have cloned an empty/
-";
-
-try "
-    cd foo;             ok
-    [ -d .git ];        ok
-    test-commit aa;     ok;     /1 file changed, 1 insertion/
-    tag start;          ok
-    glt push u1 origin master
-                        ok;     /new branch.*master.-..master/
-                                /create.delete ignored.*merge-check/
-    checkout -b new;    ok;     /Switched to a new branch 'new'/
-    test-commit bb cc;  ok
-    checkout master;    ok;     /Switched to branch 'master'/
-    test-commit dd ee;  ok
-    git merge new;      ok;     /Merge made.*recursive/
-    test-commit ff;     ok
-    tag end;            ok
-";
-
-# push by u4 should fail
-try "
-    glt push u4 file:///foo master
-                        !ok;    /WM refs/heads/master foo u4 DENIED by fallthru/
-                                /To file:///foo/
-                                /remote rejected.*hook declined/
-                                /failed to push some refs/
-";
-
-# push by u3 should succeed
-try "
-    glt push u3 file:///foo master
-                        ok;     /To file:///foo/; /master.-..master/
-";
-
-# rewind by u3 should fail
-try "
-    reset-h start;      ok;     /HEAD is now at .* aa /
-    glt push u3 file:///foo +master
-                         !ok;   /rejected.*hook declined/
-                                /failed to push some refs/
-";
-
-# rewind by u2 should succeed
-try "
-    glt push u2 file:///foo +master
-                         ok;    /To file:///foo/
-                                /forced update/
-";
-
-# push by u2 should fail
-try "
-    reset-h end;        ok;     /HEAD is now at .* ff /
-    glt push u2 file:///foo master
-                        !ok;    /WM refs/heads/master foo u2 DENIED by fallthru/
-                                /To file:///foo/
-                                /remote rejected.*hook declined/
-                                /failed to push some refs/
-";
-
-# push by u1 should succeed
-try "
-    glt push u1 file:///foo master
-                        ok;     /master.-..master/
-";
diff --git a/docker/gitolite/t/mirror-test b/docker/gitolite/t/mirror-test
deleted file mode 100755
index 627dc74..0000000
--- a/docker/gitolite/t/mirror-test
+++ /dev/null
@@ -1,445 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# you need 3 disposable userids: sam, frodo, gollum.  Then the test user (say
-# "g3") needs to be able to sudo into them.  Put this in /etc/sudoers:
-
-#       g3 ALL = (sam,frodo,gollum) NOPASSWD: ALL
-
-$ENV{TSH_ERREXIT} = 1;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-use Cwd;
-my $workdir = getcwd();
-my $h = $ENV{HOME};
-my ($t, $t2);   # temp vars
-
-# basic tests
-# ----------------------------------------------------------------------
-
-try "plan 152";
-##  try "DEF POK = !/DENIED/; !/failed to push/";
-
-##  confreset;confadd '
-
-##  ';
-
-##  try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-# ----------------------------------------------------------------------
-
-# switch keys
-sub swk {
-    my $h = $ENV{HOME};
-    my $k = shift;
-    system("cp $h/.ssh/$k $h/.ssh/id_rsa");
-    system("cp $h/.ssh/$k.pub $h/.ssh/id_rsa.pub");
-}
-
-sub all {
-    try "F " . join(" ", @_);
-    try "S " . join(" ", @_);
-    try "G " . join(" ", @_);
-}
-
-try "
-    DEF F   =   sudo -u frodo -i
-    DEF S   =   sudo -u sam -i
-    DEF G   =   sudo -u gollum -i
-";
-
-my $bd = `gitolite query-rc -n GL_BINDIR`;
-
-try "
-    $bd/../t/mirror-test-setup.sh;   ok or die mirror setup shell script failed
-        /hello server-frodo, this is frodo/
-        /hello server-sam, this is frodo/
-        /hello server-gollum, this is frodo/
-        /hello server-frodo, this is sam/
-        /hello server-sam, this is sam/
-        /hello server-gollum, this is sam/
-        /hello server-frodo, this is gollum/
-        /hello server-sam, this is gollum/
-        /hello server-gollum, this is gollum/
-        /hello admin, this is frodo/
-        /Initialized empty .*/gitolite-admin.git/
-        /Initialized empty .*/r1.git/
-        /Initialized empty .*/r2.git/
-        /Initialized empty .*/testing.git/
-        /Initialized empty .*/gitolite-admin.git/
-        /Initialized empty .*/r1.git/
-        /Initialized empty .*/r2.git/
-        /Initialized empty .*/testing.git/
-        /Initialized empty .*/gitolite-admin.git/
-        /Initialized empty .*/r1.git/
-        /Initialized empty .*/r2.git/
-        /Initialized empty .*/testing.git/
-";
-
-# ----------------------------------------------------------------------
-# SECTION 1: gitolite-admin shenanigans
-
-# push to frodo and see sam and gollum change
-try "
-    git clone frodo\@localhost:gitolite-admin fga
-        ok; /Cloning into 'fga'.../
-    cd fga;                             ok
-    cp $h/.ssh/u?.pub keydir;           ok
-    git add keydir;                     ok
-    git commit -m 6keys;                ok
-    git push;                           ok
-        /To frodo\@localhost:gitolite-admin/
-        /master -> master/
-    sleep 5
-    git rev-parse HEAD
-";
-
-chomp($t = text());
-
-try "
-    git ls-remote sam\@localhost:gitolite-admin
-        ok; /$t/
-    git ls-remote gollum\@localhost:gitolite-admin
-        ok; /$t/
-";
-
-try "
-    cd ..
-
-";
-
-# push to sam and see frodo and gollum change
-try "
-    git clone sam\@localhost:gitolite-admin sga
-        ok; /Cloning into 'sga'.../
-    cd sga;                             ok
-    empty;                              ok
-    git push;                           ok
-        /To sam\@localhost:gitolite-admin/
-        /master -> master/
-    sleep 5
-    git rev-parse HEAD
-";
-
-chomp($t = text());
-
-try "
-    git ls-remote frodo\@localhost:gitolite-admin
-        ok; /$t/
-    git ls-remote gollum\@localhost:gitolite-admin
-        ok; /$t/
-";
-
-try "
-    cd ..
-
-";
-
-# push to gollum and fail at gollum
-try "
-    git clone gollum\@localhost:gitolite-admin gga
-        ok; /Cloning into 'gga'.../
-    cd gga;                             ok
-    empty;                              ok
-    git push;                           !ok
-        !/To gollum\@localhost:gitolite-admin/
-        !/master -> master/
-        /gollum: pushing 'gitolite-admin' to slave 'gollum' not allowed/
-    git rev-parse HEAD
-";
-
-chomp($t2 = text());
-
-try "
-    git ls-remote frodo\@localhost:gitolite-admin
-        ok; /$t/; !/$t2/
-    git ls-remote sam\@localhost:gitolite-admin
-        ok; /$t/; !/$t2/
-    git ls-remote gollum\@localhost:gitolite-admin
-        ok; /$t/; !/$t2/
-";
-
-# fake out the gollum failure to continue the redirected push and fail at frodo
-try "
-    sudo -u gollum -i gitolite git-config -r gitolite-admin .
-        ok
-        /redirectOK.*sam/
-        !/redirectOK.*gollum/
-
-    sudo -u gollum -i bash -c 'echo repo gitolite-admin > junk'
-    sudo -u gollum -i bash -c 'echo option mirror.redirectOK-1 = gollum   >> junk'
-    sudo -u gollum -i bash -c 'cat junk >> .gitolite/conf/gitolite.conf'
-    sudo -u gollum -i gitolite compile
-    sudo -u gollum -i gitolite git-config -r gitolite-admin .
-        ok
-        /redirectOK.*sam/
-        /redirectOK.*gollum/
-
-    git push;                           !ok
-        /frodo: redirection not allowed from 'gollum'/
-        !/To gollum\@localhost:gitolite-admin/
-        !/master -> master/
-";
-
-# reset gollum via frodo
-try "
-    cd ..
-    rm -rf fga
-    git clone frodo\@localhost:gitolite-admin fga
-        ok; /Cloning into 'fga'.../
-    cd fga;                             ok
-    empty;                              ok
-    git push;                           ok
-        /To frodo\@localhost:gitolite-admin/
-        /master -> master/
-    sleep 5
-
-    sudo -u gollum -i gitolite git-config -r gitolite-admin .
-        ok
-        /redirectOK.*sam/
-        !/redirectOK.*gollum/
-
-    git rev-parse HEAD
-";
-
-chomp($t = text());
-
-try "
-    git ls-remote sam\@localhost:gitolite-admin
-        ok; /$t/
-    git ls-remote gollum\@localhost:gitolite-admin
-        ok; /$t/
-";
-
-# ----------------------------------------------------------------------
-# user repo shenanigans
-
-# for a recap of the perms see t/mirror-test-setup.sh
-
-try "
-    cd ..
-    pwd
-    /tmp/tsh_tempdir/ or die not in the right place
-" or die;
-
-swk('u1');
-
-# u1 sam r1, R ok, W ok
-try "
-    rm -rf fga sga gga
-
-    git clone sam\@localhost:r1 sr1
-        /Cloning into 'sr1'.../
-        /warning: You appear to have cloned an empty repository/
-    cd sr1
-    empty
-    git push origin master
-        /new branch/;   /master -> master/
-    sleep 5
-    git rev-parse HEAD
-";
-chomp($t = text());
-
-# u1 sam r1, W mirrors to frodo but not gollum
-try "
-    git ls-remote sam\@localhost:r1
-        /$t/
-    git ls-remote frodo\@localhost:r1
-        /$t/
-    git ls-remote gollum\@localhost:r1
-        /gollum: 'r1' is mirrored but not here/
-";
-
-swk("u2");
-try "
-    empty
-    git rev-parse HEAD
-";
-chomp($t2 = text());
-
-# u2 sam r2 W ok, mirrors to all
-try "
-    git push sam\@localhost:r2 master
-        /new branch/;   /master -> master/
-        /master -> master/
-    sleep 5
-    git ls-remote frodo\@localhost:r2
-        !/$t/
-        /$t2/
-    git ls-remote gollum\@localhost:r2
-        !/$t/
-        /$t2/
-";
-
-swk("u1");
-
-# u1 gollum r1 -- "known unknown" :-)
-# u1 frodo r1 R ok, W not ok
-# u1 sam r1 R ok, W ok
-try "
-    cd ..
-    rm -rf sr1
-
-    git clone gollum\@localhost:r1 fr1
-        /gollum: 'r1' is mirrored but not here/
-
-    git clone frodo\@localhost:r1 fr1;       ok
-    cd fr1
-    empty
-    git push
-        /frodo: pushing 'r1' to slave 'frodo' not allowed/
-    cd ..
-    git clone sam\@localhost:r1 sr1;         ok
-    cd sr1
-    empty
-    git push;                               ok
-        /master -> master/
-    sleep 5
-    git rev-parse HEAD
-";
-chomp($t = text());
-
-# u1 sam r1 W mirrored to frodo but not gollum
-try "
-    git ls-remote sam\@localhost:r1
-        /$t/
-    git ls-remote frodo\@localhost:r1
-        /$t/
-
-    git ls-remote gollum\@localhost:r1
-        /gollum: 'r1' is mirrored but not here/
-
-    git reset --hard HEAD^;                 ok
-    tc a
-    git push;                               !ok
-        /rejected/
-        /failed to push/
-
-    git push -f
-        /\\+ .......\\.\\.\\........ master -> master .forced update/
-    sleep 5
-";
-
-swk("u2");
-
-# u2 frodo r1 R ok, W not allowed (no redirectOK)
-# u2 frodo r2 W ok
-try "
-    cd ..
-    rm -rf fr1 sr1
-
-    git clone frodo\@localhost:r1 fr1;       ok
-    cd fr1
-    tc b
-    git push
-        /frodo: pushing 'r1' to slave 'frodo' not allowed/
-    cd ..
-    git clone frodo\@localhost:r2 fr2;       ok
-    cd fr2
-    tc c
-    git push
-        /master -> master/
-    sleep 5
-    git rev-parse HEAD
-";
-chomp($t = text());
-
-# u2 frodo r2 W mirrors to sam and gollum
-try "
-    git ls-remote sam\@localhost:r2
-        /$t/
-    git ls-remote gollum\@localhost:r2
-        /$t/
-
-    git reset --hard HEAD^;                 ok
-    tc d
-    git push
-        /rejected/
-        /failed to push/
-
-    git push -f
-        /\\+ .......\\.\\.\\........ master -> master .forced update/
-    sleep 5
-
-    cd ..
-    rm -rf fr1 fr2
-";
-
-swk("u3");
-
-# u3 frodo r2 R ok W ok
-try "
-    git clone frodo\@localhost:r2 fr2;       ok
-    cd fr2
-    tc e
-    git push;                               ok
-    sleep 5
-
-    git rev-parse HEAD
-";
-chomp($t = text());
-
-# u3 frodo r2 W mirrors to sam and gollum
-try "
-    git ls-remote sam\@localhost:r2
-        /$t/
-    git ls-remote gollum\@localhost:r2
-        /$t/
-
-    git reset --hard HEAD^;                 ok
-    tc f
-    git push
-        /rejected/
-        /failed to push/
-
-    sleep 10
-    git push -f
-        /\\+ refs/heads/master r2 u3 DENIED by fallthru/
-        /hook declined/
-        /rejected/
-";
-
-# ----------------------------------------------------------------------
-# all those vague edge cases where the two servers have totally wrong ideas
-# about each other
-
-swk('u1');
-
-try "sudo -u frodo -i ls .gitolite/logs";
-chomp($t = text());
-my $lfn = ".gitolite/logs/$t";
-
-try "
-    ssh sam\@localhost mirror push frodo lfrodo;  !ok
-    /FATAL: frodo: 'lfrodo' is local/
-
-    ssh sam\@localhost mirror push frodo mboth;  !ok
-    /FATAL: frodo: 'mboth' is native/
-
-    ssh sam\@localhost mirror push frodo mnotsam;  !ok
-    /FATAL: frodo: 'sam' is not the master for 'mnotsam'/
-
-    cd ..
-    git clone sam\@localhost:lfrodo2 lfrodo2;   ok
-    cd lfrodo2
-    empty
-    git push origin master;                     !ok
-    /FATAL: frodo: 'lfrodo2' is local/
-
-    cd ..
-    git clone sam\@localhost:nnfrodo nnfrodo;   ok
-    cd nnfrodo
-    empty
-    git push origin master;                     !ok
-    /FATAL: frodo: 'nnfrodo' is not native/
-
-    cd ..
-    git clone sam\@localhost:nvsfrodo nvsfrodo; ok
-    cd nvsfrodo
-    empty
-    git push origin master;                     !ok
-    /FATAL: frodo: 'sam' is not a valid slave for 'nvsfrodo'/
-";
diff --git a/docker/gitolite/t/mirror-test-rc b/docker/gitolite/t/mirror-test-rc
deleted file mode 100644
index 1d76783..0000000
--- a/docker/gitolite/t/mirror-test-rc
+++ /dev/null
@@ -1,162 +0,0 @@
-# This file is in perl syntax.  But you do NOT need to know perl to edit it --
-# just mind the commas, use single quotes unless you know what you're doing,
-# and make sure the brackets and braces stay matched up!
-
-# (Tip: perl allows a comma after the last item in a list also!)
-
-# HELP for commands (see COMMANDS list below) can be had by running the
-# command with "-h" as the sole argument.
-
-# HELP for all the other FEATURES can be found in the documentation (look for
-# "list of non-core programs shipped with gitolite" in the master index) or
-# directly in the corresponding source file.
-
-%RC = (
-
-    # ------------------------------------------------------------------
-
-    HOSTNAME                        =>  '%HOSTNAME',
-
-    # default umask gives you perms of '0700'; see the rc file docs for
-    # how/why you might change this
-    UMASK                           =>  0077,
-
-    # look in the "GIT-CONFIG" section in the README for what to do
-    GIT_CONFIG_KEYS                 =>  '',
-
-    # comment out if you don't need all the extra detail in the logfile
-    LOG_EXTRA                       =>  1,
-
-    # roles.  add more roles (like MANAGER, TESTER, ...) here.
-    #   WARNING: if you make changes to this hash, you MUST run 'gitolite
-    #   compile' afterward, and possibly also 'gitolite trigger POST_COMPILE'
-    ROLES => {
-        READERS                     =>  1,
-        WRITERS                     =>  1,
-    },
-    # uncomment (and change) this if you wish
-    # DEFAULT_ROLE_PERMS            =>  'READERS @all',
-
-    # CACHE => 'Redis',
-
-    # ------------------------------------------------------------------
-
-    # rc variables used by various features
-
-    # the 'info' command prints this as additional info, if it is set
-        # SITE_INFO                 =>  'Please see http://blahblah/gitolite for more help',
-
-    # the 'desc' command uses this
-        # WRITER_CAN_UPDATE_DESC    =>  1,
-
-    # the CpuTime feature uses these
-        # display user, system, and elapsed times to user after each git operation
-        # DISPLAY_CPU_TIME          =>  1,
-        # display a warning if total CPU times (u, s, cu, cs) crosses this limit
-        # CPU_TIME_WARN_LIMIT       =>  0.1,
-
-    # the Mirroring feature needs this
-        # HOSTNAME                  =>  "foo",
-
-    # if you enabled 'Shell', you need this
-        # SHELL_USERS_LIST          =>  "$ENV{HOME}/.gitolite.shell-users",
-
-    # ------------------------------------------------------------------
-
-    # List of commands and features to enable
-
-    ENABLE => [
-
-        # COMMANDS
-
-            # These are the commands enabled by default
-            'help',
-            'desc',
-            'info',
-            'perms',
-            'writable',
-
-            'mirror',
-
-            # Uncomment or add new commands here.
-            # 'create',
-            # 'fork',
-            # 'mirror',
-            # 'sskm',
-            # 'D',
-
-        # These FEATURES are enabled by default.
-
-            # essential (unless you're using smart-http mode)
-            'ssh-authkeys',
-
-            # creates git-config enties from gitolite.conf file entries like 'config foo.bar = baz'
-            'git-config',
-
-            # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out
-            'daemon',
-
-            # creates projects.list file; if you don't use gitweb, comment this out
-            'gitweb',
-
-        # These FEATURES are disabled by default; uncomment to enable.  If you
-        # need to add new ones, ask on the mailing list :-)
-
-        # user-visible behaviour
-
-            # prevent wild repos auto-create on fetch/clone
-            # 'no-create-on-read',
-            # no auto-create at all (don't forget to enable the 'create' command!)
-            # 'no-auto-create',
-
-            # access a repo by another (possibly legacy) name
-            # 'Alias',
-
-            # give some users direct shell access
-            # 'Shell',
-
-        # system admin stuff
-
-            # enable mirroring (don't forget to set the HOSTNAME too!)
-            'Mirroring',
-
-            # allow people to submit pub files with more than one key in them
-            # 'ssh-authkeys-split',
-
-            # selective read control hack
-            # 'partial-copy',
-
-            # manage local, gitolite-controlled, copies of read-only upstream repos
-            # 'upstream',
-
-            # updates 'description' file instead of 'gitweb.description' config item
-            # 'cgit',
-
-        # performance, logging, monitoring...
-
-            # be nice
-            # 'renice 10',
-
-            # log CPU times (user, system, cumulative user, cumulative system)
-            # 'CpuTime',
-
-        # syntactic_sugar for gitolite.conf and included files
-
-            # allow backslash-escaped continuation lines in gitolite.conf
-            # 'continuation-lines',
-
-            # create implicit user groups from directory names in keydir/
-            # 'keysubdirs-as-groups',
-
-    ],
-
-);
-
-# ------------------------------------------------------------------------------
-# per perl rules, this should be the last line in such a file:
-1;
-
-# Local variables:
-# mode: perl
-# End:
-# vim: set syn=perl:
diff --git a/docker/gitolite/t/mirror-test-setup.sh b/docker/gitolite/t/mirror-test-setup.sh
deleted file mode 100755
index b35364c..0000000
--- a/docker/gitolite/t/mirror-test-setup.sh
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/bin/bash
-
-set -e
-hosts="frodo sam gollum"
-mainhost=frodo
-
-# setup software
-bd=`gitolite query-rc -n GL_BINDIR`
-mkdir -p /tmp/g3
-rm -rf /tmp/g3/src
-cp -a $bd /tmp/g3/src
-chmod -R go+rX /tmp/g3
-
-# setup symlinks in frodo, sam, and gollum's accounts
-for h in $hosts
-do
-    sudo -u $h -i bash -c "rm -rf *.pub bin .ssh projects.list repositories .gitolite .gitolite.rc"
-done
-
-[ "$1" = "clear" ] && exit
-
-cd /tmp/g3
-[ -d keys ] || {
-    mkdir keys
-    cd keys
-    for h in $hosts
-    do
-        ssh-keygen -N '' -q -f server-$h  -C $h
-        chmod go+r /tmp/g3/keys/server-$h
-    done
-    cp $bd/../t/mirror-test-ssh-config ssh-config
-}
-chmod -R go+rX /tmp/g3
-
-for h in $hosts
-do
-    sudo -u $h -i bash -c "mkdir -p bin; ln -sf /tmp/g3/src/gitolite bin; mkdir -p .ssh; chmod 0700 .ssh"
-
-    sudo -u $h -i cp /tmp/g3/keys/ssh-config    .ssh/config
-    sudo -u $h -i cp /tmp/g3/keys/server-$h     .ssh/id_rsa
-    sudo -u $h -i cp /tmp/g3/keys/server-$h.pub .ssh/id_rsa.pub
-    sudo -u $h -i chmod go-rwx                  .ssh/id_rsa .ssh/config
-
-done
-
-# add all pubkeys to all servers
-for h in $hosts
-do
-    sudo -u $h -i gitolite setup -a admin
-    for j in $hosts
-    do
-        sudo -u $h -i gitolite setup -pk /tmp/g3/keys/server-$j.pub
-        echo sudo _u $j _i ssh $h at localhost info
-        sudo -u $j -i ssh -o StrictHostKeyChecking=no $h at localhost info
-    done
-    echo ----
-done
-
-# now copy our admin key to the main host
-cd;cd .ssh
-cp admin id_rsa; cp admin.pub id_rsa.pub
-cp admin.pub /tmp/g3/keys; chmod go+r /tmp/g3/keys/admin.pub
-sudo -u $mainhost -i gitolite setup -pk /tmp/g3/keys/admin.pub
-ssh $mainhost at localhost info
-
-lines="
-repo gitolite-admin
-    option mirror.master = frodo
-    option mirror.slaves-1 = sam gollum
-    option mirror.redirectOK = sam
-
-repo r1
-    RW+     =   u1
-    RW      =   u2
-    R       =   u3
-    option mirror.master = sam
-    option mirror.slaves-1 = frodo
-
-repo r2
-    RW+     =   u2
-    RW      =   u3
-    R       =   u4
-    option mirror.master = sam
-    option mirror.slaves-1 = frodo gollum
-    option mirror.redirectOK = all
-
-include \"%HOSTNAME.conf\"
-"
-
-lines2="
-repo l-%HOSTNAME
-RW  =   u1
-"
-
-# for each server, set the HOSTNAME to the rc, add the mirror options to the
-# conf file, and compile
-for h in $hosts
-do
-    cat $bd/../t/mirror-test-rc | perl -pe "s/%HOSTNAME/$h/" > /tmp/g3/temp
-    chmod go+rX /tmp/g3/temp
-    sudo -u $h -i cp /tmp/g3/temp .gitolite.rc
-    echo "$lines"  | sudo -u $h -i sh -c 'cat >> .gitolite/conf/gitolite.conf'
-    echo "$lines2" | sudo -u $h -i sh -c "cat >> .gitolite/conf/$h.conf"
-    sudo -u $h -i gitolite setup
-done
-
-# goes on frodo
-lines="
-# local to frodo but sam thinks frodo is a slave
-repo lfrodo
-RW  =   u1
-
-# both think they're master
-repo mboth
-RW  =   u1
-option mirror.master = frodo
-option mirror.slaves = sam
-
-# frodo thinks someone else is the master but sam thinks he is
-repo mnotsam
-RW  =   u1
-option mirror.master = merry
-option mirror.slaves = frodo
-
-# local to frodo but sam thinks frodo is a master and redirect is OK
-repo lfrodo2
-RW  =   u1
-
-# non-native to frodo but sam thinks frodo is master
-repo nnfrodo
-RW  =   u1
-option mirror.master = gollum
-option mirror.slaves = frodo
-option mirror.redirectOK = all
-
-# sam is not a valid slave to send stuff to frodo
-repo nvsfrodo
-RW  =   u1
-option mirror.master = frodo
-option mirror.slaves = gollum
-option mirror.redirectOK = all
-"
-
-echo "$lines" | sudo -u frodo -i sh -c "cat >> .gitolite/conf/frodo.conf"
-
-# goes on sam
-lines="
-# local to frodo but sam thinks frodo is a slave
-repo lfrodo
-RW  =   u1
-option mirror.master = sam
-option mirror.slaves = frodo
-
-# both think they're master
-repo mboth
-RW  =   u1
-option mirror.master = sam
-option mirror.slaves = frodo
-
-# frodo thinks someone else is the master but sam thinks he is
-repo mnotsam
-RW  =   u1
-option mirror.master = sam
-option mirror.slaves = frodo
-
-# local to frodo but sam thinks frodo is a master and redirect is OK
-repo lfrodo2
-RW  =   u1
-option mirror.master = frodo
-option mirror.slaves = sam
-option mirror.redirectOK = all
-
-# non-native to frodo but sam thinks frodo is master
-repo nnfrodo
-RW  =   u1
-option mirror.master = frodo
-option mirror.slaves = sam
-option mirror.redirectOK = all
-
-# sam is not a valid slave to send stuff to frodo
-repo nvsfrodo
-RW  =   u1
-option mirror.master = frodo
-option mirror.slaves = sam
-option mirror.redirectOK = all
-"
-
-echo "$lines" | sudo -u sam -i sh -c "cat >> .gitolite/conf/sam.conf"
-
-for h in $hosts
-do
-    sudo -u $h -i gitolite setup
-done
-
-# that ends the setup phase
-echo ======================================================================
diff --git a/docker/gitolite/t/mirror-test-ssh-config b/docker/gitolite/t/mirror-test-ssh-config
deleted file mode 100644
index 40de6d7..0000000
--- a/docker/gitolite/t/mirror-test-ssh-config
+++ /dev/null
@@ -1,11 +0,0 @@
-host frodo
-    user frodo
-    hostname localhost
-
-host sam
-    user sam
-    hostname localhost
-
-host gollum
-    user gollum
-    hostname localhost
diff --git a/docker/gitolite/t/partial-copy.t b/docker/gitolite/t/partial-copy.t
deleted file mode 100755
index 5bff843..0000000
--- a/docker/gitolite/t/partial-copy.t
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# test script for partial copy feature
-# ----------------------------------------------------------------------
-
-try "plan 82";
-try "DEF POK = !/DENIED/; !/failed to push/";
-my $h = $ENV{HOME};
-
-try "
-    cat $h/.gitolite.rc
-    perl s/GIT_CONFIG_KEYS.*/GIT_CONFIG_KEYS => '.*',/
-    perl s/# 'partial-copy'/'partial-copy'/
-    put $h/.gitolite.rc
-";
-
-confreset;confadd '
-    repo foo
-            RW+                 =   u1 u2
-
-    repo foo-pc
-            -   secret-1$       =   u4
-            R                   =   u4  # marker 01
-            RW  next            =   u4
-            RW+ dev/USER/       =   u4
-            RW  refs/tags/USER/ =   u4
-
-            -   VREF/partial-copy   =   @all
-            config gitolite.partialCopyOf = foo
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-        /Init.*empty.*foo\\.git/
-        /Init.*empty.*foo-pc\\.git/
-";
-
-try "
-    cd ..
-
-    ## populate repo foo, by user u1
-    # create foo with a bunch of branches and tags
-    CLONE u1 foo
-        /appear.*cloned/
-    cd foo
-    tc a1 a2
-    checkout -b dev/u1/foo; tc f1 f2
-    checkout master; tc m1 m2
-    checkout master; checkout -b next; tc n1 n2; tag nt1
-    checkout -b secret-1; tc s11 s12; tag s1t1
-    checkout next; checkout -b secret-2; tc s21 s22; tag s2t1
-    glt push u1 --all
-        /new branch/; /secret-1/; /secret-2/
-    glt push u1 --tags
-        /new tag/; /s1t1/; /s2t1/
-
-    ## user u4 tries foo, fails, tries foo-pc
-    cd ..
-    CLONE u4 foo foo4; !ok
-        /R any foo u4 DENIED by fallthru/
-    CLONE u4 foo-pc ; ok;
-        /Cloning into 'foo-pc'/
-        /new branch.* dev/u1/foo .* dev/u1/foo/
-        /new branch.* master .* master/
-        /new branch.* next .* next/
-        /new branch.* secret-2 .* secret-2/
-        !/new branch.* secret-1 .* secret-1/
-        /new tag.* nt1 .* nt1/
-        /new tag.* s2t1 .* s2t1/
-        !/new tag.* s1t1 .* s1t1/
-
-    ## user u4 pushes to foo-pc
-    cd foo-pc
-    checkout master
-    tc u4m1 u4m2; PUSH u4; !ok
-        /W refs/heads/master foo-pc u4 DENIED by fallthru/
-        /hook declined to update refs/heads/master/
-        /To file:///foo-pc/
-        /remote rejected/
-        /failed to push some refs to 'file:///foo-pc'/
-
-    checkout next
-    tc u4n1 u4n2
-    PUSH u4 next; ok
-        /To .*/foo.git/
-        /new branch\\]      ca3787119b7e8b9914bc22c939cefc443bc308da -> refs/partial/br-\\d+/
-        /file:///foo-pc/
-        /52c7716..ca37871  next -> next/
-    tag u4/nexttag; glt push u4 --tags
-        /To file:///foo-pc/
-        /\\[new tag\\]         u4/nexttag -> u4/nexttag/
-        /\\[new branch\\]      ca3787119b7e8b9914bc22c939cefc443bc308da -> refs/partial/br-\\d+/
-
-    checkout master
-    checkout -b dev/u4/u4master
-    tc devu4m1 devu4m2
-    PUSH u4 HEAD; ok
-        /To .*/foo.git/
-        /new branch\\]      228353950557ed1eb13679c1fce4d2b4718a2060 -> refs/partial/br-\\d+/
-        /file:///foo-pc/
-        /new branch.* HEAD -> dev/u4/u4master/
-
-    ## user u1 gets u4's updates, makes some more
-    cd ../foo
-    glt fetch u1
-        /From file:///foo/
-        /new branch\\]      dev/u4/u4master -> origin/dev/u4/u4master/
-        /new tag\\]         u4/nexttag -> u4/nexttag/
-        /52c7716..ca37871  next       -> origin/next/
-    checkout master; tc u1ma1 u1ma2;
-        /\\[master 8ab1ff5\\] u1ma2 at Thu Jul  7 06:23:20 2011/
-    tag mt2; PUSH u1 master; ok
-    checkout secret-1; tc u1s1b1 u1s1b2
-        /\\[secret-1 5f96cb5\\] u1s1b2 at Thu Jul  7 06:23:20 2011/
-    tag s1t2; PUSH u1 HEAD; ok
-    checkout secret-2; tc u1s2b1 u1s2b2
-        /\\[secret-2 1ede682\\] u1s2b2 at Thu Jul  7 06:23:20 2011/
-    tag s2t2; PUSH u1 HEAD; ok
-    glt push u1 --tags; ok
-
-    glt ls-remote u1 origin
-        /8ab1ff512faf5935dc0fbff357b6f453b66bb98b\trefs/tags/mt2/
-        /5f96cb5ff73c730fb040eb2d01981f7677ca6dba\trefs/tags/s1t2/
-        /1ede6829ec7b75a53cd6acb7da64e5a8011e6050\trefs/tags/s2t2/
-
-    ## u4 gets updates but without the tag in secret-1
-    cd ../foo-pc
-    glt ls-remote u4 origin
-        !/ refs/heads/secret-1/; !/s1t1/; !/s1t2/
-        /8ab1ff512faf5935dc0fbff357b6f453b66bb98b\tHEAD/
-        /8ced4a374b3935bac1a5ba27ef8dd950bd867d47\trefs/heads/dev/u1/foo/
-        /228353950557ed1eb13679c1fce4d2b4718a2060\trefs/heads/dev/u4/u4master/
-        /8ab1ff512faf5935dc0fbff357b6f453b66bb98b\trefs/heads/master/
-        /ca3787119b7e8b9914bc22c939cefc443bc308da\trefs/heads/next/
-        /1ede6829ec7b75a53cd6acb7da64e5a8011e6050\trefs/heads/secret-2/
-        /8ab1ff512faf5935dc0fbff357b6f453b66bb98b\trefs/tags/mt2/
-        /52c7716c6b029963dd167c647c1ff6222a366499\trefs/tags/nt1/
-        /01f04ece6519e7c0e6aea3d26c7e75e9c4e4b06d\trefs/tags/s2t1/
-        /1ede6829ec7b75a53cd6acb7da64e5a8011e6050\trefs/tags/s2t2/
-
-    glt fetch u4
-        /3ea704d..8ab1ff5  master     -> origin/master/
-        /01f04ec..1ede682  secret-2   -> origin/secret-2/
-        /\\[new tag\\]         mt2        -> mt2/
-        /\\[new tag\\]         s2t2       -> s2t2/
-        !/ refs/heads/secret-1/; !/s1t1/; !/s1t2/
-";
-__END__
-
-# last words...
-glt ls-remote u4 file:///foo-pc
-
-cd ../gitolite-admin
-cat conf/gitolite.conf
-perl s/.*marker 01.*//;
-put conf/gitolite.conf
-add conf; commit -m erdel; ok; PUSH admin; ok
-
-glt ls-remote u4 file:///foo-pc
-# see rant below at this point
-
-cd $h/repositories/foo-pc.git
-git branch -D secret-2
-git tag -d s2t1 s2t2
-git gc --prune=now
-glt ls-remote u4 file:///foo-pc
-# only *now* does the rant get addressed
-
-__END__
-
-RANT...
-
-This is where things go all screwy.  Because we still have the *objects*
-pointed to by tags s2t1 and s2t2, we still get them back from the main repo.
diff --git a/docker/gitolite/t/perm-default-roles.t b/docker/gitolite/t/perm-default-roles.t
deleted file mode 100755
index 1a56ff8..0000000
--- a/docker/gitolite/t/perm-default-roles.t
+++ /dev/null
@@ -1,169 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# permissions using role names
-# ----------------------------------------------------------------------
-
-try "plan 33";
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-
-try "pwd";
-my $od = text();
-chomp($od);
-
-my $t;
-
-confreset; confadd '
-    @g1 = u1
-    @g2 = u2
-    @g3 = u3
-    @g4 = u4
-        repo foo/CREATOR/..*
-          C                 =   @g1 @g2
-          RW+               =   CREATOR
-          -     refs/tags/  =   WRITERS
-          RW                =   WRITERS
-          R                 =   READERS
-
-        repo bar/CREATOR/..*
-          C                 =   @g3 @g4
-          RW+               =   CREATOR
-          -     refs/tags/  =   WRITERS
-          RW                =   WRITERS
-          R                 =   READERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-# create repos - 1; no gl-perms files expected
-try "
-
-cd ..
-
-# make foo/u1/u1r1
-glt clone u1 file:///foo/u1/u1r1
-        /Initialized empty Git repository in .*/foo/u1/u1r1.git//
-
-# make bar/u3/u3r1
-glt clone u3 file:///bar/u3/u3r1
-        /Initialized empty Git repository in .*/bar/u3/u3r1.git//
-
-cd u3r1
-";
-
-try "cd $rb; find . -name gl-perms; cd $od"; cmp text(), '';
-
-# enable set-default-roles feature
-try "
-    cat $ENV{HOME}/.gitolite.rc
-    perl s/# 'set-default-roles'/'set-default-roles'/
-    put $ENV{HOME}/.gitolite.rc
-";
-
-# create repos - 2; empty gl-perms files expected
-try "
-
-cd ..
-
-# make foo/u1/u1r2
-glt clone u1 file:///foo/u1/u1r2
-        /Initialized empty Git repository in .*/foo/u1/u1r2.git//
-
-# make bar/u3/u3r2
-glt clone u3 file:///bar/u3/u3r2
-        /Initialized empty Git repository in .*/bar/u3/u3r2.git//
-
-cd u3r2
-";
-
-try "cd $rb; find . -name gl-perms";
-$t = md5sum(sort (lines()));
-cmp $t, 'd41d8cd98f00b204e9800998ecf8427e  ./bar/u3/u3r2.git/gl-perms
-d41d8cd98f00b204e9800998ecf8427e  ./foo/u1/u1r2.git/gl-perms
-';
-try "cd $od";
-
-# enable per repo default roles
-confadd '
-        repo foo/CREATOR/..*
-        option default.roles-1  =   READERS u3
-        option default.roles-2  =   WRITERS u4
-
-        repo bar/CREATOR/..*
-        option default.roles-1  =   READERS u5
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-# create repos - 3; filled gl-perms expected
-try "
-
-cd ..
-
-gitolite access foo/u1/u1r3 u4 W
-        !ok
-        !/refs/../
-        /W any foo/u1/u1r3 u4 DENIED by fallthru/
-
-# make foo/u1/u1r3
-glt clone u1 file:///foo/u1/u1r3
-        /Initialized empty Git repository in .*/foo/u1/u1r3.git//
-
-gitolite access foo/u1/u1r3 u4 W
-        ok
-        /refs/../
-        !/W any foo/u1/u1r3 u4 DENIED by fallthru/
-
-# make bar/u3/u3r3
-glt clone u3 file:///bar/u3/u3r3
-        /Initialized empty Git repository in .*/bar/u3/u3r3.git//
-
-cd u3r3
-";
-
-try "cd $rb; find . -name gl-perms";
-$t = md5sum(sort (lines()));
-cmp $t, 'd41d8cd98f00b204e9800998ecf8427e  ./bar/u3/u3r2.git/gl-perms
-b09856c1addc8e46f6ce0d21a666a633  ./bar/u3/u3r3.git/gl-perms
-d41d8cd98f00b204e9800998ecf8427e  ./foo/u1/u1r2.git/gl-perms
-1b5af29692fad391318573bbe633b476  ./foo/u1/u1r3.git/gl-perms
-';
-try "cd $od";
-
-# add perms to an old repo
-try "
-echo WRITERS \@h1 | glt perms u1 foo/u1/u1r1
-";
-
-try "cd $rb; find . -name gl-perms";
-$t = md5sum(sort (lines()));
-cmp $t, 'd41d8cd98f00b204e9800998ecf8427e  ./bar/u3/u3r2.git/gl-perms
-b09856c1addc8e46f6ce0d21a666a633  ./bar/u3/u3r3.git/gl-perms
-f8f0fd8e139ddb64cd5572914b98750a  ./foo/u1/u1r1.git/gl-perms
-d41d8cd98f00b204e9800998ecf8427e  ./foo/u1/u1r2.git/gl-perms
-1b5af29692fad391318573bbe633b476  ./foo/u1/u1r3.git/gl-perms
-';
-try "cd $od";
-
-# add perms to a new repo
-try "
-echo WRITERS \@h2 | glt perms u1 -c foo/u1/u1r4
-";
-
-try "cd $rb; find . -name gl-perms";
-$t = md5sum(sort (lines()));
-cmp $t, 'd41d8cd98f00b204e9800998ecf8427e  ./bar/u3/u3r2.git/gl-perms
-b09856c1addc8e46f6ce0d21a666a633  ./bar/u3/u3r3.git/gl-perms
-f8f0fd8e139ddb64cd5572914b98750a  ./foo/u1/u1r1.git/gl-perms
-d41d8cd98f00b204e9800998ecf8427e  ./foo/u1/u1r2.git/gl-perms
-1b5af29692fad391318573bbe633b476  ./foo/u1/u1r3.git/gl-perms
-df17cd2d47e4d99642d7c5ce4093d115  ./foo/u1/u1r4.git/gl-perms
-';
-try "cd $od";
diff --git a/docker/gitolite/t/perm-roles.t b/docker/gitolite/t/perm-roles.t
deleted file mode 100755
index 03403d6..0000000
--- a/docker/gitolite/t/perm-roles.t
+++ /dev/null
@@ -1,218 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# permissions using role names
-# ----------------------------------------------------------------------
-
-try "plan 91";
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-confreset; confadd '
-    @g1 = u1
-    @g2 = u2
-    @g3 = u3
-    @g4 = u4
-        repo foo/CREATOR/..*
-          C                 =   @g1
-          RW+               =   CREATOR
-          -     refs/tags/  =   WRITERS
-          RW                =   WRITERS
-          R                 =   READERS
-          RW+D              =   MANAGERS
-          RW    refs/tags/  =   TESTERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-
-cd ..
-
-# make foo/u1/u1r1
-rm -rf ~/td/u1r1
-glt clone u1 file:///foo/u1/u1r1
-        /Initialized empty Git repository in .*/foo/u1/u1r1.git//
-cd u1r1
-
-# CREATOR can push
-tc e-549 e-550
-glt push u1 file:///foo/u1/u1r1 master:master
-        POK; /master -> master/
-# CREATOR can create branch
-tc w-277 w-278
-glt push u1 file:///foo/u1/u1r1 master:b1
-        POK; /master -> b1/
-# CREATOR can rewind branch
-git reset --hard HEAD^
-tc d-987 d-988
-glt push u1 file:///foo/u1/u1r1 +master:b1
-        POK; /master -> b1 \\(forced update\\)/
-# CREATOR cannot delete branch
-glt push u1 file:///foo/u1/u1r1 :b1
-        /D refs/heads/b1 foo/u1/u1r1 u1 DENIED by fallthru/
-        reject
-
-# CREATOR can push a tag
-git tag t1 HEAD^^
-glt push u1 file:///foo/u1/u1r1 t1
-        POK; /\\[new tag\\]         t1 -> t1/
-
-# add u2 to WRITERS
-echo WRITERS \@g2 | glt perms u1 foo/u1/u1r1
-glt perms u1 foo/u1/u1r1 -l
-        /WRITERS \@g2/
-
-glt fetch u1
-git reset --hard origin/master
-
-# WRITERS can push
-tc j-185 j-186
-glt push u2 file:///foo/u1/u1r1 master:master
-        POK; /master -> master/
-# WRITERS can create branch
-tc u-420 u-421
-glt push u2 file:///foo/u1/u1r1 master:b2
-        POK; /master -> b2/
-# WRITERS cannot rewind branch
-git reset --hard HEAD^
-tc l-136 l-137
-glt push u2 file:///foo/u1/u1r1 +master:b2
-        /\\+ refs/heads/b2 foo/u1/u1r1 u2 DENIED by fallthru/
-        reject
-# WRITERS cannot delete branch
-glt push u2 file:///foo/u1/u1r1 :b2
-        /D refs/heads/b2 foo/u1/u1r1 u2 DENIED by fallthru/
-        reject
-# WRITERS cannot push a tag
-git tag t2 HEAD^^
-glt push u2 file:///foo/u1/u1r1 t2
-        /W refs/tags/t2 foo/u1/u1r1 u2 DENIED by refs/tags//
-        reject
-
-# change u2 to READERS
-echo READERS u2 | glt perms u1 foo/u1/u1r1
-glt perms u1 foo/u1/u1r1 -l
-        /READERS u2/
-
-glt fetch u1
-git reset --hard origin/master
-
-# READERS cannot push at all
-tc v-753 v-754
-glt push u2 file:///foo/u1/u1r1 master:master
-        /W any foo/u1/u1r1 u2 DENIED by fallthru/
-
-# add invalid category MANAGERS
-    /usr/bin/printf 'READERS u6\\nMANAGERS u2\\n' | glt perms u1 foo/u1/u1r1
-        !ok
-        /Invalid role 'MANAGERS'/
-";
-
-# make MANAGERS valid
-put "$ENV{HOME}/g3trc", "\$rc{ROLES}{MANAGERS} = 1;\n";
-
-# add u2 to now valid MANAGERS
-try "
-    ENV G3T_RC=$ENV{HOME}/g3trc
-    gitolite compile;   ok or die compile failed
-    /usr/bin/printf 'READERS u6\\nMANAGERS u2\\n' | glt perms u1 foo/u1/u1r1
-                            ok;    !/Invalid role 'MANAGERS'/
-    glt perms u1 foo/u1/u1r1 -l
-";
-
-cmp 'READERS u6
-MANAGERS u2
-';
-
-try "
-glt fetch u1
-git reset --hard origin/master
-
-# MANAGERS can push
-tc d-714 d-715
-glt push u2 file:///foo/u1/u1r1 master:master
-        POK; /master -> master/
-
-# MANAGERS can create branch
-tc n-614 n-615
-glt push u2 file:///foo/u1/u1r1 master:b3
-        POK; /master -> b3/
-# MANAGERS can rewind branch
-git reset --hard HEAD^
-tc a-511 a-512
-glt push u2 file:///foo/u1/u1r1 +master:b3
-        POK; /master -> b3 \\(forced update\\)/
-# MANAGERS cannot delete branch
-glt push u2 file:///foo/u1/u1r1 :b3
-        / - \\[deleted\\]         b3/
-# MANAGERS can push a tag
-git tag t3 HEAD^^
-glt push u2 file:///foo/u1/u1r1 t3
-        POK; /\\[new tag\\]         t3 -> t3/
-
-# add invalid category TESTERS
-echo TESTERS u2 | glt perms u1 foo/u1/u1r1
-        !ok
-        /Invalid role 'TESTERS'/
-";
-
-# make TESTERS valid
-put "|cat >> $ENV{HOME}/g3trc", "\$rc{ROLES}{TESTERS} = 1;\n";
-
-try "
-gitolite compile;   ok or die compile failed
-# add u2 to now valid TESTERS
-echo TESTERS u2 | glt perms u1 foo/u1/u1r1
-        !/Invalid role 'TESTERS'/
-glt perms u1 foo/u1/u1r1 -l
-";
-
-cmp 'TESTERS u2
-';
-
-try "
-glt fetch u1
-git reset --hard origin/master
-
-# TESTERS cannot push
-tc d-134 d-135
-glt push u2 file:///foo/u1/u1r1 master:master
-        /W refs/heads/master foo/u1/u1r1 u2 DENIED by fallthru/
-        reject
-# TESTERS cannot create branch
-tc p-668 p-669
-glt push u2 file:///foo/u1/u1r1 master:b4
-        /W refs/heads/b4 foo/u1/u1r1 u2 DENIED by fallthru/
-        reject
-# TESTERS cannot delete branch
-glt push u2 file:///foo/u1/u1r1 :b2
-        /D refs/heads/b2 foo/u1/u1r1 u2 DENIED by fallthru/
-        reject
-# TESTERS can push a tag
-git tag t4 HEAD^^
-glt push u2 file:///foo/u1/u1r1 t4
-        POK; /\\[new tag\\]         t4 -> t4/
-";
-
-# make TESTERS invalid again
-put "$ENV{HOME}/g3trc", "\$rc{ROLES}{MANAGERS} = 1;\n";
-
-try "
-gitolite compile;   ok or die compile failed
-# CREATOR can push
-glt fetch u1
-git reset --hard origin/master
-tc y-626 y-627
-glt push u1 file:///foo/u1/u1r1 master:master
-        POK; /master -> master/
-# TESTERS is an invalid category
-git tag t5 HEAD^^
-glt push u2 file:///foo/u1/u1r1 t5
-        /role 'TESTERS' not allowed, ignoring/
-        /W any foo/u1/u1r1 u2 DENIED by fallthru/
-";
diff --git a/docker/gitolite/t/perms-groups.t b/docker/gitolite/t/perms-groups.t
deleted file mode 100755
index 5de75be..0000000
--- a/docker/gitolite/t/perms-groups.t
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# assigning roles to groups instead of users
-# ----------------------------------------------------------------------
-
-try "plan 31";
-
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-confreset; confadd '
-    @leads = u1 u2
-    @devs = u1 u2 u3 u4
-
-    @gbar = bar/CREATOR/..*
-    repo    @gbar
-        C               =   @leads
-        RW+             =   CREATOR
-        RW              =   WRITERS
-        R               =   READERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-
-    # u1 auto-creates a repo
-    glt ls-remote u1 file:///bar/u1/try1
-        /Initialized empty Git repository in .*/bar/u1/try1.git//
-    # default permissions for u2 and u4
-    glt info u1 -lc
-        /R W *\tbar/u1/try1\tu1/
-    glt info u2 -lc
-        !/R W *\tbar/u1/try1\tu1/
-    glt info u4 -lc
-        !/R W *\tbar/u1/try1\tu1/
-
-    # \@leads can RW try1
-    echo WRITERS \@leads | glt perms u1 bar/u1/try1; ok
-    glt info u1 -lc
-        /R W *\tbar/u1/try1\tu1/
-    glt info u2 -lc
-        /R W *\tbar/u1/try1\tu1/
-    glt info u4 -lc
-        !/R W *\tbar/u1/try1\tu1/
-
-    # \@devs can R try1
-    echo READERS \@devs | glt perms u1 bar/u1/try1; ok
-    glt perms u1 bar/u1/try1 -l
-        /READERS \@devs/
-        !/WRITERS \@leads/
-
-    glt info u1 -lc
-        /R W *\tbar/u1/try1\tu1/
-
-    glt info u2 -lc
-        !/R W *\tbar/u1/try1\tu1/
-        /R *\tbar/u1/try1\tu1/
-
-    glt info u4 -lc
-        !/R W *\tbar/u1/try1\tu1/
-        /R *\tbar/u1/try1\tu1/
-
-# combo of previous 2
-    /usr/bin/printf 'READERS \@devs\\nWRITERS \@leads\\n' | glt perms u1 bar/u1/try1; ok
-    glt perms u1 bar/u1/try1 -l
-        /READERS \@devs/
-        /WRITERS \@leads/
-    glt info u1 -lc
-        /R W *\tbar/u1/try1\tu1/
-    glt info u2 -lc
-        /R W *\tbar/u1/try1\tu1/
-    glt info u4 -lc
-        !/R W *\tbar/u1/try1\tu1/
-        /R *\tbar/u1/try1\tu1/
-";
diff --git a/docker/gitolite/t/personal-branches.t b/docker/gitolite/t/personal-branches.t
deleted file mode 100755
index 8a08128..0000000
--- a/docker/gitolite/t/personal-branches.t
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# personal branches
-# ----------------------------------------------------------------------
-
-try "plan 64";
-
-confreset;confadd '
-    @admins     =   admin dev1
-    repo gitolite-admin
-        RW+     =   admin
-
-    repo testing
-        RW+     =   @all
-
-    @g1 = t1
-    repo @g1
-        R               =   u2
-        RW              =   u3
-        RW+             =   u4
-        RW  a/USER/     =   @all
-        RW+ p/USER/     =   u1 u6
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-
-    gitolite access t1 u1;                              ok;     /refs/heads/p/u1//; !/DENIED/
-    gitolite access t1 u5;                              !ok;    /\\+ any t1 u5 DENIED by fallthru/
-    gitolite access \@g1 u5 W;                          ok;     /refs/heads/a/u5//; !/DENIED/
-
-    gitolite access t1 u1 W refs/heads/a/user1/foo;     !ok;    /W refs/heads/a/user1/foo t1 u1 DENIED by fallthru/
-    gitolite access \@g1 u1 + refs/heads/a/user1/foo;   !ok;    /\\+ refs/heads/a/user1/foo \@g1 u1 DENIED by fallthru/
-    gitolite access t1 u1 W refs/heads/p/user1/foo;     !ok;    /W refs/heads/p/user1/foo t1 u1 DENIED by fallthru/
-    gitolite access \@g1 u1 + refs/heads/p/user1/foo;   !ok;    /\\+ refs/heads/p/user1/foo \@g1 u1 DENIED by fallthru/
-
-    gitolite access \@g1 u1 W refs/heads/a/u1/foo;      ok;     /refs/heads/a/u1//; !/DENIED/
-    gitolite access t1 u1 + refs/heads/a/u1/foo;        !ok;    /\\+ refs/heads/a/u1/foo t1 u1 DENIED by fallthru/
-    gitolite access \@g1 u1 W refs/heads/p/u1/foo;      ok;     /refs/heads/p/u1//; !/DENIED/
-    gitolite access t1 u1 + refs/heads/p/u1/foo;        ok;     /refs/heads/p/u1//; !/DENIED/
-
-    gitolite access \@g1 u1 W refs/heads/p/u2/foo;      !ok;    /W refs/heads/p/u2/foo \@g1 u1 DENIED by fallthru/
-    gitolite access t1 u1 + refs/heads/p/u2/foo;        !ok;    /\\+ refs/heads/p/u2/foo t1 u1 DENIED by fallthru/
-";
-
-confreset; confadd '
-    @staff = u1 u2 u3 u4 u5 u6
-    @gfoo = foo
-    repo  @gfoo
-          RW+                       = u1 u2
-          RW+   p/USER/             = u3 u4
-          RW    temp                = u5 u6
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    DEF OK  =   gitolite access foo %1 %2 refs/heads/%3;    ok
-    DEF NOK =   gitolite access foo %1 %2 refs/heads/%3;    !ok
-";
-
-try "
-
-# u1 and u2 can push
-    OK  u1  W   master
-    OK  u2  W   master
-    OK  u2  W   p/u1/foo
-    OK  u1  W   p/u2/foo
-    OK  u1  W   p/u3/foo
-
-# u3 cant push u1/u4 personal branches
-    NOK u3  W   p/u1/foo
-    NOK u3  W   p/u4/doo
-
-# u4 can push u4 personal branch
-    OK  u4  W   p/u4/foo
-# u5 push temp
-    OK  u5  W   temp
-
-# u1 and u2 can rewind
-    OK  u1  +   master
-    OK  u2  +   p/u1/foo
-    OK  u1  +   p/u2/foo
-    OK  u1  +   p/u3/foo
-
-# u3 cant rewind u1/u4 personal branches
-    NOK u3  +   p/u1/foo
-    NOK u3  +   p/u4/foo
-# u4 can rewind u4 personal branch
-    OK  u4  +   p/u4/foo
-# u5 cant rewind temp
-    NOK u5  +   temp
-";
diff --git a/docker/gitolite/t/refex-expr-test-1 b/docker/gitolite/t/refex-expr-test-1
deleted file mode 100755
index 1372a1e..0000000
--- a/docker/gitolite/t/refex-expr-test-1
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-
-# not part of the official test suite (yet); just some q&d testing
-
-# to be run from ~/gitolite as ./$0
-
-set -e
-exec 3>&2
-exec > /dev/null
-exec 2> /dev/null
-print2() { echo -n "$@" >&3; }
-say2() { echo "$@" >&3; }
-die() { echo FATAL: "$@" >&3; exit 1; }
-
-export od=$PWD
-export tmp=$(mktemp -d)
-echo $tmp >&3
-trap "rm -rf $tmp" 0
-cd $tmp
-
-print2 setting up...
-( cd $od; t/reset )
-echo "push @{ \$RC{ENABLE} }, 'refex-expr';" >> ~/.gitolite.rc
-cat <<EOF >> ~/.gitolite/conf/gitolite.conf
-
-repo r1
-    RW+                                 =   u1 u2   # line 1
-
-    RW+ master                          =   u3 u4   # line 2
-    RW+                                 =   u3 u4   # line 3
-    RW+ VREF/NAME/Makefile              =   u3 u4   # line 4
-    -   master and VREF/NAME/Makefile   =   u3 u4   # line 5
-
-EOF
-gitolite setup
-say2 done
-
-# ----------------------------------------------------------------------
-
-rm -rf u1
-git clone u1:r1 u1
-cd u1
-tsh 'tc f1'
-git push u1:r1 master
-tsh 'tc f2'
-git push u2:r1 master
-tsh 'tc f3'
-git push u3:r1 master
-tsh 'tc f4'
-git push u4:r1 master
-say2 everyone master no Makefile
-
-tsh 'tc f5 Makefile'
-git push u1:r1 master
-tsh 'tc f5 Makefile'
-git push u1:r1 master:m1
-say2 u1 Makefile master
-
-tsh 'tc f5 Makefile'
-git push u3:r1 master && die u3 r1 master should have failed
-git push u3:r1 master:m2
-say2 u3 Makefile master fail m2 pass
diff --git a/docker/gitolite/t/refex-expr-test-2 b/docker/gitolite/t/refex-expr-test-2
deleted file mode 100755
index 773e42c..0000000
--- a/docker/gitolite/t/refex-expr-test-2
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-
-# not part of the official test suite (yet); just some q&d testing
-
-# to be run from ~/gitolite as ./$0
-
-set -e
-exec 3>&2
-exec > /dev/null
-exec 2> /dev/null
-print2() { echo -n "$@" >&3; }
-say2() { echo "$@" >&3; }
-die() { echo FATAL: "$@" >&3; exit 1; }
-
-export od=$PWD
-export tmp=$(mktemp -d)
-echo $tmp >&3
-trap "rm -rf $tmp" 0
-cd $tmp
-
-print2 setting up...
-( cd $od; t/reset )
-echo "push @{ \$RC{ENABLE} }, 'refex-expr';" >> ~/.gitolite.rc
-cat <<EOF >> ~/.gitolite/conf/gitolite.conf
-
-    repo    r2
-        RW+                         =   @all
-
-        RW+ VREF/NAME/doc/                      =   u2
-        RW+ VREF/NAME/src/                      =   u2
-        -   VREF/NAME/doc/ and VREF/NAME/src/   =   u2
-
-EOF
-gitolite setup
-say2 done
-
-# ----------------------------------------------------------------------
-
-git clone u2:r2
-cd r2
-
-tsh 'tc aa'
-git push origin master
-say2 aa pass
-
-mkdir doc src
-
-tsh 'tc doc/d1'
-git push origin master
-say2 doc pass
-
-tsh 'tc src/s1'
-tsh 'tc src/s2'
-git push origin master
-say2 src src pass
-
-tsh 'tc doc/d2 src/s3'
-git push origin master && die 1
-git push u1:r2 master
-say2 doc src u2 fail u1 pass
diff --git a/docker/gitolite/t/refex-expr-test-3 b/docker/gitolite/t/refex-expr-test-3
deleted file mode 100755
index 47599eb..0000000
--- a/docker/gitolite/t/refex-expr-test-3
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/bash
-
-# not part of the official test suite (yet); just some q&d testing
-
-# to be run from ~/gitolite as ./$0
-
-set -e
-exec 3>&2
-exec > /dev/null
-exec 2> /dev/null
-print2() { echo -n "$@" >&3; }
-say2() { echo "$@" >&3; }
-die() { echo FATAL: "$@" >&3; exit 1; }
-
-export od=$PWD
-export tmp=$(mktemp -d)
-echo $tmp >&3
-trap "rm -rf $tmp" 0
-cd $tmp
-
-print2 setting up...
-( cd $od; t/reset )
-echo "push @{ \$RC{ENABLE} }, 'refex-expr';" >> ~/.gitolite.rc
-cat <<EOF >> ~/.gitolite/conf/gitolite.conf
-
-    repo    r3
-        RW+                         =   u1 u2 u3
-
-        RW+ VREF/NAME/conf/         =   u3
-        -   VREF/NAME/conf/ -gt 2   =   u3
-
-EOF
-gitolite setup
-say2 done
-
-# ----------------------------------------------------------------------
-
-git clone u3:r3
-cd r3
-
-tsh 'tc aa'
-git push origin master
-say2 aa pass
-
-mkdir doc conf
-
-tsh 'tc doc/d1 doc/d2 doc/d3 doc/d4 conf/c1'
-git push origin master
-say2 4 doc 1 conf pass
-
-tsh 'tc conf/c2 conf/c3 conf/c4'
-git push origin master && die 1
-
-git push u2:r3 master
-say2 3 conf u3 fail u2 pass
diff --git a/docker/gitolite/t/refex-expr-test-9 b/docker/gitolite/t/refex-expr-test-9
deleted file mode 100755
index b3a9f09..0000000
--- a/docker/gitolite/t/refex-expr-test-9
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/bin/bash
-
-# not part of the official test suite (yet); just some q&d testing
-
-# to be run from ~/gitolite as ./$0
-
-set -e
-exec 3>&2
-exec > /dev/null
-exec 2> /dev/null
-print2() { echo -n "$@" >&3; }
-say2() { echo "$@" >&3; }
-die() { echo FATAL: "$@" >&3; exit 1; }
-
-export od=$PWD
-export tmp=$(mktemp -d)
-echo $tmp >&3
-trap "rm -rf $tmp" 0
-cd $tmp
-
-print2 setting up...
-( cd $od; t/reset )
-echo "push @{ \$RC{ENABLE} }, 'refex-expr';" >> ~/.gitolite.rc
-cat <<EOF >> ~/.gitolite/conf/gitolite.conf
-
-repo r9
-
-    RW+                         =   u3 u4
-
-    # u1 and u2 have some restrictions
-
-    # cant push master
-    -   master                  =   u1 u2
-    # cant push versioned tags, but other tags are fine
-    -   refs/tags/v[0-9]        =   u1 u2
-    # everything else is fine, but we need to recognise when they're pushing
-    # tags, so that the refex expr will have the correct info
-    RW+ refs/tags/              =   u1 u2
-    RW+                         =   u1 u2
-
-    # can push files in "foo/" only to a tag
-    RW+ VREF/NAME/foo/          =   u1 u2
-
-    RW+ VREF/NAME/foo/ and refs/tags/  =   u1 u2
-    -   VREF/NAME/foo/ and not refs/tags/ = u1 u2
-
-EOF
-gitolite setup
-say2 done
-
-# ----------------------------------------------------------------------
-
-# make sure u3 is not constrained in any way
-
-git clone u3:r9 refex-test.repo
-cd refex-test.repo
-
-tsh 'tc u3-f1'
-git pom
-
-mkdir bar foo
-tsh 'tc bar/thr'
-git pom
-git tag v3
-git push origin v3
-tsh 'tc foo/rht'
-git pom
-git tag 3v
-git push origin 3v
-
-say2 u3 no limits
-
-# now test u1's constraints
-
-cd ..
-rm -rf refex-test.repo
-
-rm -rf ~/repositories/r9.git
-gitolite setup
-
-git clone u1:r9 refex-test.repo
-cd refex-test.repo
-
-tsh 'tc u1-f1'
-# cant push master
-git pom && die 1
-# can push other branches
-git push origin master:m1
-say2 master fail m1 pass
-
-mkdir bar foo
-tsh 'tc bar/one'
-git push origin master:m1
-git tag v1
-# cant push v-tag
-git push origin v1 && die 2
-say2 v-tag fail
-
-# cant push foo/ to a branch
-tsh 'tc foo/eno'
-git push origin master:m1 && die 3
-say2 foo/ m1 fail
-
-# but can push to a non-v-tag
-git tag 1v
-git push origin 1v
-say2 foo/ non-v-tag pass
diff --git a/docker/gitolite/t/repo-specific-hooks.t b/docker/gitolite/t/repo-specific-hooks.t
deleted file mode 100755
index 88976ca..0000000
--- a/docker/gitolite/t/repo-specific-hooks.t
+++ /dev/null
@@ -1,210 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# test script for partial copy feature
-# ----------------------------------------------------------------------
-
-try "plan 117";
-my $h = $ENV{HOME};
-my $rb = `gitolite query-rc -n GL_REPO_BASE`;
-
-try 'cd tsh_tempdir; mkdir -p local/hooks/repo-specific';
-
-foreach my $h (qw/first second/) {
-    put "local/hooks/repo-specific/$h", "#!/bin/sh
-echo \$0
-if [ \$# -ne 0 ]; then
-    echo \$0 has args: \$@
-else
-    echo \$0 has stdin: `cat`
-fi
-";
-}
-try 'chmod +x local/hooks/repo-specific/*';
-
-try 'pwd';
-my $tempdir = join("\n", sort (lines()));
-try 'cd gitolite-admin';
-
-try "# Enable LOCAL_CODE and repo-specific-hooks
-    cat $h/.gitolite.rc
-    perl s/# 'repo-specific-hooks'/'repo-specific-hooks'/
-    perl s%# LOCAL_CODE%LOCAL_CODE => '$tempdir/local', #%
-    put $h/.gitolite.rc
-";
-
-confreset;confadd '
-    repo foo
-            RW+                 =   @all
-
-    repo bar
-            RW+                 =   @all
-
-    repo baz
-            RW+                 =   @all
-';
-
-try "ADMIN_PUSH repo-specific-hooks-0; !/FATAL/" or die text();
-
-try "
-    /Init.*empty.*foo\\.git/
-    /Init.*empty.*bar\\.git/
-    /Init.*empty.*baz\\.git/
-";
-
-my $failing_hook = "#!/bin/sh
-exit 1
-";
-
-# Place a existing hooks in repos
-put "$rb/foo.git/hooks/post-recieve", $failing_hook;
-put "$rb/bar.git/hooks/pre-recieve", $failing_hook;
-put "$rb/baz.git/hooks/post-update", $failing_hook;
-
-try "# Verify hooks
-    ls -l $rb/foo.git/hooks/*;  ok;     !/post-receive -. .*local/hooks/multi-hook-driver/
-    ls -l $rb/bar.git/hooks/*;  ok;     !/pre-receive -. .*local/hooks/multi-hook-driver/
-    ls -l $rb/baz.git/hooks/*;  ok;     !/post-update -. .*local/hooks/multi-hook-driver/
-";
-
-confreset;confadd '
-    repo foo
-            RW+                 =   @all
-            option hook.post-receive =  first
-
-    repo bar
-            RW+                 =   @all
-            option hook.pre-receive =  first second
-
-    repo baz
-            RW+                 =   @all
-            option hook.post-receive =  first
-            option hook.post-update =  first second
-';
-
-
-try "ADMIN_PUSH repo-specific-hooks-1; !/FATAL/" or die text();
-
-try "# Verify hooks
-    ls -l $rb/foo.git/hooks/*;  ok;     /post-receive.h00-first/
-                                       !/post-receive.h01/
-                                        /post-receive -. .*local/hooks/multi-hook-driver/
-    ls -l $rb/bar.git/hooks/*;  ok;     /pre-receive.h00-first/
-                                        /pre-receive.h01-second/
-                                        /pre-receive -. .*local/hooks/multi-hook-driver/
-    ls -l $rb/baz.git/hooks/*;  ok;     /post-receive.h00-first/
-                                        /post-update.h00-first/
-                                        /post-update.h01-second/
-                                        /post-update -. .*local/hooks/multi-hook-driver/
-";
-
-try "
-    cd ..
-
-    # Single hook still works
-    [ -d foo ];            !ok;
-    CLONE admin foo;        ok; /empty/; /cloned/
-    cd foo
-    tc a1;                  ok; /ee47f8b/
-    PUSH admin master;      ok; /new.*master -. master/
-                                /hooks/post-receive.h00-first/
-                                !/post-receive.*has args:/
-                                /post-receive.h00-first has stdin: 0000000000000000000000000000000000000000 ee47f8b6be2160ad1a3f69c97a0cb3d488e6657e refs/heads/master/
-
-    cd ..
-
-    # Multiple hooks fired
-    [ -d bar ];            !ok;
-    CLONE admin bar;        ok; /empty/; /cloned/
-    cd bar
-    tc a2;                  ok; /cfc8561/
-    PUSH admin master;      ok; /new.*master -. master/
-                                /hooks/pre-receive.h00-first/
-                                !/hooks/pre-recieve.*has args:/
-                                /hooks/pre-receive.h00-first has stdin: 0000000000000000000000000000000000000000 cfc8561c7827a8b94df6c5dad156383d4cb210f5 refs/heads/master/
-                                /hooks/pre-receive.h01-second/
-                                !/hooks/pre-receive.h01.*has args:/
-                                /hooks/pre-receive.h01-second has stdin: 0000000000000000000000000000000000000000 cfc8561c7827a8b94df6c5dad156383d4cb210f5 refs/heads/master/
-
-    cd ..
-
-    # Post-update has stdin instead of arguments
-    [ -d baz ];            !ok;
-    CLONE admin baz;        ok; /empty/; /cloned/
-    cd baz
-    tc a3;                  ok; /2863617/
-    PUSH admin master;      ok; /new.*master -. master/
-                                /hooks/post-receive.h00-first/
-                                !/hooks/post-receive.h00.*has args:/
-                                /hooks/post-receive.h00-first has stdin: 0000000000000000000000000000000000000000 28636171ae703f42fb17c312c6b6a078ed07a2cd refs/heads/master/
-                                /hooks/post-update.h00-first/
-                                /hooks/post-update.h00-first has args: refs/heads/master/
-                                !/hooks/post-update.h00.*has stdin:/
-                                /hooks/post-update.h01-second/
-                                /hooks/post-update.h01-second has args: refs/heads/master/
-                                !/hooks/post-update.h01.*has stdin:/
-";
-
-# Verify hooks are removed properly
-
-confreset;confadd '
-    repo foo
-            RW+                 =   @all
-            option hook.post-receive =
-
-    repo bar
-            RW+                 =   @all
-            option hook.pre-receive =  second
-
-    repo baz
-            RW+                 =   @all
-            option hook.post-receive =
-            option hook.post-update =  second
-';
-
-try "ADMIN_PUSH repo-specific-hooks-02; !/FATAL/" or die text();
-
-try "
-    ls $rb/foo.git/hooks/*;  ok;    !/post-receive/
-    ls $rb/bar.git/hooks/*;  ok;    !/pre-receive.*first/
-                                     /pre-receive.h00-second/
-    ls $rb/baz.git/hooks/*;  ok;    !/post-receive/
-                                    !/post-update.*first/
-                                     /post-update.h00-second/
-";
-
-try "
-    cd ..
-
-    # Foo has no hooks
-    cd foo
-    tc b1;                  ok; /7ef69de/
-    PUSH admin master;      ok; /master -. master/
-                                !/hooks/post-receive/
-
-    cd ..
-
-    # Bar only has the second hook
-    cd bar
-    tc b2;                  ok; /cc7808f/
-    PUSH admin master;      ok; /master -. master/
-                                /hooks/pre-receive.h00-second/
-                                !/hooks/pre-receive.*has args:/
-                                /hooks/pre-receive.h00-second has stdin: 0000000000000000000000000000000000000000 cc7808f77c7c7d705f82dc54dc3152146175768f refs/heads/master/
-
-    cd ..
-
-    # Baz has no post-receive and keeps the second hook for post-update
-    cd baz
-    tc b3;                  ok; /8d20101/
-    PUSH admin master;      ok; /master -. master/
-                                !/hooks/post-receive.*/
-                                /hooks/post-update.h00-second/
-                                /hooks/post-update.h00-second has args: refs/heads/master/
-                                !/hooks/post-update.*has stdin/
-";
diff --git a/docker/gitolite/t/reset b/docker/gitolite/t/reset
deleted file mode 100755
index 502de2b..0000000
--- a/docker/gitolite/t/reset
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-BEGIN {
-    unlink "$ENV{HOME}/.ssh/authorized_keys";
-}
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-use Cwd;
-my $workdir = getcwd();
-
-confreset;confadd '
-repo foo/..*
-    C   =   u1 u2 u3
-    RW+ =   CREATOR
-    RW  =   WRITERS
-    R   =   READERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    mkdir -p keydir
-    cp \$HOME/.ssh/u*.pub keydir
-    cp \$HOME/.ssh/admin.pub keydir
-    git add keydir
-    git commit -m 6k
-    glt push admin origin
-";
diff --git a/docker/gitolite/t/rule-seq.t b/docker/gitolite/t/rule-seq.t
deleted file mode 100755
index 0d97558..0000000
--- a/docker/gitolite/t/rule-seq.t
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# rule sequence
-# ----------------------------------------------------------------------
-
-# this is the specific example in commit 32056e0 of g2
-
-try "plan 27";
-
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-confreset; confadd '
-    @private-owners = u1 u2
-    @experienced-private-owners = u3 u4
-
-    repo CREATOR/.*
-      C   = @private-owners @experienced-private-owners
-      RWD = CREATOR
-      RW  = WRITERS
-      R   = READERS
-      -   = @private-owners
-      RW+D = CREATOR
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..
-    glt clone u1 file:///u1/r1
-        /Initialized empty Git repository in .*/u1/r1.git//
-    cd r1
-    tc h-395
-    glt push u1 origin master
-    git checkout -b br1
-    tc m-367
-    tc i-747
-
-    # u1 create branch
-    glt push u1 origin br1
-        /\\* \\[new branch\\]      br1 -> br1/
-        POK; /br1 -> br1/
-
-    # u1 rewind branch
-    git reset --hard HEAD^
-    tc e-633
-    glt push u1 origin +br1
-        /\\+ refs/heads/br1 u1/r1 u1 DENIED by refs//
-        /error: hook declined to update refs/heads/br1/
-        reject
-
-    # u1 delete branch
-    glt push u1 origin :br1
-        /\\[deleted\\]         br1/
-
-    cd ..
-    rm -rf r1
-    glt clone u3 file:///u3/r1
-        /Initialized empty Git repository in .*/u3/r1.git//
-    cd r1
-    tc p-274
-    glt push u3 origin master
-    git checkout -b br1
-    tc s-613
-    tc k-988
-
-    # u3 create branch
-    glt push u3 origin br1
-        /\\* \\[new branch\\]      br1 -> br1/
-        POK; /br1 -> br1/
-
-    # u3 rewind branch
-    git reset --hard HEAD^
-    tc n-919
-    glt push u3 origin +br1
-        /To file:///u3/r1/
-        /\\+ .......\\.\\.\\........ br1 -> br1 \\(forced update\\)/
-
-    # u3 delete branch
-    glt push u3 origin :br1
-        /\\[deleted\\]         br1/
-";
diff --git a/docker/gitolite/t/sequence.t b/docker/gitolite/t/sequence.t
deleted file mode 100755
index 81fabfc..0000000
--- a/docker/gitolite/t/sequence.t
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# uhh, seems to be another rule sequence test
-# ----------------------------------------------------------------------
-
-try "plan 48";
-
-confreset;confadd '
-    @staff = u1 u2 u3
-    @gfoo = foo/CREATOR/..*
-    repo  @gfoo
-          C       = u1
-          RW+     = CREATOR
-          RW      = WRITERS
-          -       = @staff
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..
-    glt clone u1 file:///foo/u1/bar;    ok
-        /Initialized empty Git repository in .*/foo/u1/bar.git//
-
-    cd bar
-    tc p-906
-    glt push u1 origin master
-        /To file:///foo/u1/bar/
-        /\\[new branch\\]      master -> master/
-    echo WRITERS u2 | glt perms u1 foo/u1/bar
-    glt perms u1 foo/u1/bar -l
-        /WRITERS u2/
-    # expand
-    glt info u2
-        /R W *\tfoo/u1/bar/
-        /R W *\ttesting/
-
-    # push
-    cd ..
-    glt clone u2 file:///foo/u1/bar u2bar
-        /Cloning into 'u2bar'.../
-    cd u2bar
-    tc p-222
-    glt push u2
-        /master -> master/
-        !/DENIED/
-        !/failed to push/
-";
-
-confreset;confadd '
-    @staff = u1 u2 u3
-    @gfoo = foo/CREATOR/..*
-    repo  @gfoo
-          C       = u1
-          RW+     = CREATOR
-          -       = @staff
-          RW      = WRITERS
-          R       = READERS
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    cd ..
-    rm -rf bar u2bar
-    glt clone u1 file:///foo/u1/bar;    ok
-        /Initialized empty Git repository in .*/foo/u1/bar.git//
-
-    cd bar
-    tc p-906
-    glt push u1 origin master
-        /To file:///foo/u1/bar/
-        /\\[new branch\\]      master -> master/
-    echo WRITERS u2 | glt perms u1 foo/u1/bar
-    glt perms u1 foo/u1/bar -l
-        /WRITERS u2/
-    # expand
-    glt info u2
-        !/R W *\tfoo/u1/baz/
-        /R W *\tfoo/u1/bar/
-        /R W *\ttesting/
-
-    # push
-    cd ..
-    glt clone u2 file:///foo/u1/bar u2bar
-        /Cloning into 'u2bar'.../
-    cd u2bar
-    tc p-222
-    glt push u2
-        !ok
-        reject
-        /W refs/heads/master foo/u1/bar u2 DENIED by refs/\\.\\*/
-
-    # auto-create using perms fail
-    echo READERS u5 | glt perms u4 -c foo/u4/baz
-        !/Initialized empty Git repository in .*/foo/u4/baz.git/
-        /FATAL: repo does not exist, or you are not authorised/
-
-    # auto-create using perms
-    echo READERS u2 | glt perms u1 -c foo/u1/baz
-        /Initialized empty Git repository in .*/foo/u1/baz.git/
-
-    glt perms u1 foo/u1/baz -l
-        /READERS u2/
-    # expand
-    glt info u2
-        /R   *\tfoo/u1/baz/
-        /R W *\tfoo/u1/bar/
-        /R W *\ttesting/
-";
diff --git a/docker/gitolite/t/smart-http b/docker/gitolite/t/smart-http
deleted file mode 100755
index 98fc8c0..0000000
--- a/docker/gitolite/t/smart-http
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/bash
-
-die() { echo "$@"; exit 1; }
-
-# git clone `url u1 r1`
-url() {
-    echo http://$1:$1@localhost/git/$2.git
-}
-
-# `cmd sitaram info`
-cmd() {
-    c="curl http://$1:$1@localhost/git"
-    shift
-    c="$c/$1"
-    shift
-
-    if [ -n "$1" ]
-    then
-        c="$c?$1"
-        shift
-    fi
-    while [ -n "$1" ]
-    do
-        c="$c+$1"
-        shift
-    done
-
-    echo $c
-}
-
-export tmp=$(mktemp -d);
-trap "rm -rf $tmp" 0;
-cd $tmp
-
-tsh "plan 28"
-
-tsh "
-    ## ls-remote admin admin
-    git ls-remote `url admin gitolite-admin`
-        ok
-        /HEAD/
-        /refs.heads.master/
-    ## clone
-    git clone `url admin gitolite-admin`
-        ok
-        /Cloning into/
-    ls -al gitolite-admin/conf
-        /gitolite.conf/
-" || die "step 1"
-
-cd gitolite-admin
-echo repo t2 >> conf/gitolite.conf
-echo 'RW+  = u1 u2' >> conf/gitolite.conf
-
-tsh "
-    ## add, commit, push
-    git add conf/gitolite.conf
-        ok
-        !/./
-    git commit -m t2
-        ok
-        /1 file.*changed/
-    git push
-        ok
-        /Initialized.*usr.share.httpd.gitolite-home.repositories.t2.git/
-        /To http:..admin:admin.localhost.git.gitolite-admin.git/
-        /master -. master/
-    ## various ls-remotes
-    git ls-remote `url u1 gitolite-admin`
-        !ok
-        /FATAL: R any gitolite-admin u1 DENIED by fallthru/
-    git ls-remote `url u1 t2`
-        ok
-        !/./
-    git ls-remote `url u2 t2`
-        ok
-        !/./
-    git ls-remote `url u3 t2`
-        !ok
-        /FATAL: R any t2 u3 DENIED by fallthru/
-    ## push to u1:t2
-    git push      `url u1 t2` master:master
-        ok
-        /To http:..u1:u1.localhost.git.t2.git/
-        /master -. master/
-    git ls-remote `url u2 t2`
-        ok
-        /HEAD/
-        /refs.heads.master/
-" || die "step 2"
diff --git a/docker/gitolite/t/smart-http.root-setup b/docker/gitolite/t/smart-http.root-setup
deleted file mode 100755
index 7a46dda..0000000
--- a/docker/gitolite/t/smart-http.root-setup
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/bash
-
-# ----------------------------------------------------------------------
-# please do not even LOOK at this file without reading doc/http.mkd
-# ----------------------------------------------------------------------
-
-die() { echo "$@"; exit 1; }
-
-# scare the sh*t out of people who run it blindly
-[ -f /tmp/gitolite-smart-http-test-OK ] || {
-    # scary message
-    echo '+ rm -rf /'
-    # lots of disk activity
-    find / >/dev/null 2>/dev/null
-    # and it he's still clueless, God bless!
-    echo 'root file system erased successfully.  Goodbye and God bless!'
-    exit 1
-}
-
-# ----------------------------------------------------------------------
-# are we *BSD or Linux?
-uname_s=`uname -s`  # could be Linux or FreeBSD or some other BSD
-if [ "$uname_s" = "Linux" ]
-then
-    bsd=:
-else
-    lnx=:
-fi
-
-# ----------------------------------------------------------------------
-# main
-
-[ $EUID = 0 ] || die "you must run this as root"
-
-# delete any existing apache conf for gitolite
-$lnx rm /etc/httpd/conf.d/gitolite.conf
-$bsd rm /usr/local/etc/apache24/Includes/gitolite.conf
-
-# build your "home within a home"
-$lnx cd ~apache
-$bsd rm -rf /tmp/usr.share.httpd
-$bsd mkdir -p /tmp/usr.share.httpd
-$bsd chown www:www /tmp/usr.share.httpd
-$bsd cd /tmp/usr.share.httpd
-
-rm -rf gitolite-home
-mkdir gitolite-home
-export GITOLITE_HTTP_HOME=$PWD/gitolite-home
-
-# get the gitolite sources
-cd gitolite-home
-git clone /tmp/gitolite.git gitolite-source
-# NOTE: I use a bare repo in /tmp for convenience; you'd use
-# 'git://github.com/sitaramc/gitolite'
-
-# make the bin directory, and add it to PATH
-cd gitolite-source
-mkdir         $GITOLITE_HTTP_HOME/bin
-./install -ln $GITOLITE_HTTP_HOME/bin
-export PATH=$PATH:$GITOLITE_HTTP_HOME/bin
-
-# come back to base, then run setup.  Notice that you have to point HOME to
-# the right place, even if it is just for this command
-cd $GITOLITE_HTTP_HOME
-HOME=$GITOLITE_HTTP_HOME gitolite setup -a admin
-
-# insert some essential lines at the beginning of the rc file
-echo '$ENV{PATH} .= ":$ENV{GITOLITE_HTTP_HOME}/bin";'  >> 1
-echo >> 1
-cat .gitolite.rc >> 1
-\mv 1 .gitolite.rc
-
-# fix up ownership
-$lnx chown -R apache:apache $GITOLITE_HTTP_HOME
-$bsd chown -R www:www $GITOLITE_HTTP_HOME
-
-# create the apache config.  Note the trailing slashes on the 2 ScriptAlias
-# lines.  (The second one is optional for most sites).  NOTE: you also need to
-# give the AuthUserFile a better name/location than what I have below.
-cat <<EOF1 > 1
-SetEnv GIT_PROJECT_ROOT $GITOLITE_HTTP_HOME/repositories
-ScriptAlias /git/ $GITOLITE_HTTP_HOME/gitolite-source/src/gitolite-shell/
-ScriptAlias /gitmob/ $GITOLITE_HTTP_HOME/gitolite-source/src/gitolite-shell/
-SetEnv GITOLITE_HTTP_HOME $GITOLITE_HTTP_HOME
-SetEnv GIT_HTTP_EXPORT_ALL
-
-<Location /git>
-    AuthType Basic
-    AuthName "Private Git Access"
-    Require valid-user
-    AuthUserFile $GITOLITE_HTTP_HOME/gitolite-http-authuserfile
-</Location>
-EOF1
-$lnx mv 1 /etc/httpd/conf.d/gitolite.conf
-$bsd mv 1 /usr/local/etc/apache24/Includes/gitolite.conf
-
-# NOTE: this is for testing only
-htpasswd -bc $GITOLITE_HTTP_HOME/gitolite-http-authuserfile admin admin
-map "htpasswd -b $GITOLITE_HTTP_HOME/gitolite-http-authuserfile % %" u{1..6}
-$lnx chown apache:apache $GITOLITE_HTTP_HOME/gitolite-http-authuserfile
-$bsd chown www:www $GITOLITE_HTTP_HOME/gitolite-http-authuserfile
-
-# restart httpd to make it pick up all the new stuff
-$lnx service httpd restart
-$bsd /usr/local/etc/rc.d/apache24 restart
diff --git a/docker/gitolite/t/ssh-authkeys.t b/docker/gitolite/t/ssh-authkeys.t
deleted file mode 100755
index 46b9413..0000000
--- a/docker/gitolite/t/ssh-authkeys.t
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# testing the (separate) authkeys handler
-# ----------------------------------------------------------------------
-
-$ENV{GL_BINDIR} = "$ENV{PWD}/src";
-
-my $ak = "$ENV{HOME}/.ssh/authorized_keys";
-mkdir("$ENV{HOME}/.ssh", 0700) if not -d "$ENV{HOME}/.ssh";
-my $kd = `gitolite query-rc -n GL_ADMIN_BASE` . "/keydir";
-
-try "plan 49";
-
-my $pgm = "gitolite ../triggers/post-compile/ssh-authkeys";
-
-try "
-    # prep
-    rm -rf $ak;                 ok
-
-    $pgm;                       ok
-    mkdir $kd;                  ok
-    cd $kd;                     ok
-    $pgm;                       ok;     /authorized_keys missing/
-                                        /creating/
-    wc < $ak;                   ok;     /2 *6 *32/
-    # some gl keys
-    ssh-keygen -N '' -q -f alice -C alice
-    ssh-keygen -N '' -q -f bob   -C bob
-    ssh-keygen -N '' -q -f carol -C carol
-    ssh-keygen -N '' -q -f dave  -C dave
-    ssh-keygen -N '' -q -f eve   -C eve
-    rm alice bob carol dave eve
-    ls -a;                      ok;     /alice.pub/; /bob.pub/; /carol.pub/; /dave.pub/; /eve.pub/
-    $pgm;                       ok;
-    wc    < $ak;                ok;     /^ *7 .*/;
-    grep gitolite $ak;          ok;     /start/
-                                        /end/
-
-    # some normal keys
-    mv alice.pub $ak;           ok
-    cat carol.pub >> $ak;       ok
-    $pgm;                       ok;     /carol.pub duplicates.*non-gitolite key/
-    wc < $ak;                   ok;     /^ *8 .*/;
-
-    # moving normal keys up
-    mv dave.pub dave
-    $pgm;                       ok
-    cat dave >> $ak;            ok
-    grep -n dave $ak;           ok;     /8:ssh-rsa/
-    mv dave dave.pub
-    $pgm;                       ok;     /carol.pub duplicates.*non-gitolite key/
-                                         /dave.pub duplicates.*non-gitolite key/
-    grep -n dave $ak;           ok;     /3:ssh-rsa/
-
-    # a bad key
-    ls -al > bad.pub
-    $pgm;                       !ok;    /fingerprinting failed for \\'keydir/bad.pub\\'/
-    wc < $ak;                   ok;     /^ *9 .*/;
-    # a good key doesn't get added
-    ssh-keygen -N '' -q -f good
-    $pgm;                       !ok;    /fingerprinting failed for \\'keydir/bad.pub\\'/
-    wc < $ak;                   ok;     /^ *9 .*/;
-    # till the bad key is removed
-    rm bad.pub
-    $pgm;                       ok;
-    wc < $ak;                   ok;     /^ *10 .*/;
-
-    # duplicate gl key
-    cp bob.pub robert.pub
-    $pgm;                       ok;     /robert.pub duplicates.*bob.pub/
-";
diff --git a/docker/gitolite/t/ssh-basic.t b/docker/gitolite/t/ssh-basic.t
deleted file mode 100755
index ebed2d2..0000000
--- a/docker/gitolite/t/ssh-basic.t
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Common;
-use Gitolite::Test;
-
-# basic tests using ssh
-# ----------------------------------------------------------------------
-
-my $bd = `gitolite query-rc -n GL_BINDIR`;
-my $h  = $ENV{HOME};
-my $ab = `gitolite query-rc -n GL_ADMIN_BASE`;
-umask 0077;
-
-try "
-    plan 26
-
-    # reset stuff
-    rm -f $h/.ssh/authorized_keys;          ok or die 1
-
-    cp $bd/../t/keys/u[1-6]* $h/.ssh;       ok or die 2
-    cp $bd/../t/keys/admin*  $h/.ssh;       ok or die 3
-    cp $bd/../t/keys/config  $h/.ssh;       ok or die 4
-        cat $h/.ssh/config
-        perl s/%USER/$ENV{USER}/
-        put $h/.ssh/config
-
-    mkdir                  $ab/keydir;      ok or die 5
-    cp $bd/../t/keys/*.pub $ab/keydir;      ok or die 6
-";
-
-system("gitolite ../triggers/post-compile/ssh-authkeys");
-
-# basic tests
-# ----------------------------------------------------------------------
-
-confreset; confadd '
-    @g1 = u1
-    @g2 = u2
-    repo foo
-        RW = @g1 u3
-        R  = @g2 u4
-';
-
-try "ADMIN_PUSH set3; !/FATAL/" or die text();
-
-try "
-    ssh u1 info;                ok;     /R W\tfoo/
-    ssh u2 info;                ok;     /R  \tfoo/
-    ssh u3 info;                ok;     /R W\tfoo/
-    ssh u4 info;                ok;     /R  \tfoo/
-    ssh u5 info;                ok;     !/foo/
-    ssh u6 info;                ok;     !/foo/
-"
diff --git a/docker/gitolite/t/vrefs-1.t b/docker/gitolite/t/vrefs-1.t
deleted file mode 100755
index eea4b24..0000000
--- a/docker/gitolite/t/vrefs-1.t
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# VREFs - part 1
-# ----------------------------------------------------------------------
-
-try "plan 88";
-
-put "conf/gitolite.conf", "
-    repo gitolite-admin
-        RW+     =   admin
-
-    \@gfoo = foo
-    \@lead = u1
-    \@dev2 = u2
-    \@dev4 = u4
-    \@devs = \@dev2 \@dev4 u6
-    repo  \@gfoo
-          RW+                   =   \@lead \@devs
-          # intentional mis-spelling
-          -     VREF/MISCOUNT/2    =   \@dev2
-          -     VREF/MISCOUNT/4    =   \@dev4
-          -     VREF/MISCOUNT/3/NEWFILES   =   u6
-          -     VREF/MISCOUNT/6            =   u6
-";
-
-try "
-    ADMIN_PUSH vr1a
-    cd ..
-    [ -d foo ];                 !ok
-    CLONE u1 foo;               ok;     /Cloning into/
-                                        /You appear to have cloned an empty/
-    cd foo;                     ok
-    [ -d .git ];                ok
-
-    # VREF not called for u1
-    tc a1 a2 a3 a4 a5;          ok;     /aaf9e8e/
-    PUSH u1 master;             ok;     /new branch.*master -. master/
-                                        !/helper program missing/
-                                        !/hook declined/
-                                        !/remote rejected/
-    # VREF is called for u2
-    tc b1;                      ok;     /1f440d3/
-    PUSH u2;                    !ok;    /helper program missing/
-                                        /hook declined/
-                                        /remote rejected/
-";
-
-put "../gitolite-admin/conf/gitolite.conf", "
-    repo gitolite-admin
-        RW+     =   admin
-
-    \@gfoo = foo
-    \@lead = u1
-    \@dev2 = u2
-    \@dev4 = u4
-    \@devs = \@dev2 \@dev4 u6
-    repo  \@gfoo
-          RW+                   =   \@lead \@devs
-          -     VREF/COUNT/2    =   \@dev2
-          -     VREF/COUNT/4    =   \@dev4
-          -     VREF/COUNT/3/NEWFILES   =   u6
-          -     VREF/COUNT/6            =   u6
-";
-
-try "
-    ADMIN_PUSH vr1b
-    cd ../foo;                  ok
-
-    # u2 1 file
-    PUSH u2;                    ok;     /aaf9e8e..1f440d3.*master -. master/
-
-    # u2 2 files
-    tc b2 b3;                   ok;     /c3397f7/
-    PUSH u2;                    ok;     /1f440d3..c3397f7.*master -. master/
-
-    # u2 3 files
-    tc c1 c2 c3;                ok;     /be242d7/
-    PUSH u2;                    !ok;    /W VREF/COUNT/2 foo u2 DENIED by VREF/COUNT/2/
-                                        /too many changed files in this push/
-                                        /hook declined/
-                                        /remote rejected/
-
-    # u4 3 files
-    PUSH u4;                    ok;     /c3397f7..be242d7.*master -. master/
-
-    # u4 4 files
-    tc d1 d2 d3 d4;             ok;     /88d80e2/
-    PUSH u4;                    ok;     /be242d7..88d80e2.*master -. master/
-
-    # u4 5 files
-    tc d5 d6 d7 d8 d9;          ok;     /e9c60b0/
-    PUSH u4;                    !ok;    /W VREF/COUNT/4 foo u4 DENIED by VREF/COUNT/4/
-                                        /too many changed files in this push/
-                                        /hook declined/
-                                        /remote rejected/
-
-    # u1 all files
-    PUSH u1;                    ok;     /88d80e2..e9c60b0.*master -. master/
-
-    # u6 6 old files
-    test-tick
-    tc d1 d2 d3 d4 d5 d6
-                                ok;     /2773f0a/
-    PUSH u6;                    ok;     /e9c60b0..2773f0a.*master -. master/
-    tag six
-
-    # u6 updates 7 old files
-    test-tick; test-tick
-    tc d1 d2 d3 d4 d5 d6 d7
-                                ok;     /d3fb574/
-    PUSH u6;                    !ok;    /W VREF/COUNT/6 foo u6 DENIED by VREF/COUNT/6/
-                                        /too many changed files in this push/
-                                        /hook declined/
-                                        /remote rejected/
-    reset-h six;                ok;     /HEAD is now at 2773f0a/
-
-    # u6 4 new 2 old files
-    test-tick; test-tick
-    tc d1 d2 n1 n2 n3 n4
-                                ok;     /9e90848/
-    PUSH u6;                    !ok;    /W VREF/COUNT/3/NEWFILES foo u6 DENIED by VREF/COUNT/3/NEWFILES/
-                                        /too many new files in this push/
-                                        /hook declined/
-                                        /remote rejected/
-    reset-h six;                ok;     /HEAD is now at 2773f0a/
-
-    # u6 3 new 3 old files
-    test-tick; test-tick
-    tc d1 d2 d3 n1 n2 n3
-                                ok;     /e47ff5d/
-    PUSH u6;                    ok;     /2773f0a..e47ff5d.*master -. master/
-";
diff --git a/docker/gitolite/t/vrefs-2.t b/docker/gitolite/t/vrefs-2.t
deleted file mode 100755
index 40db308..0000000
--- a/docker/gitolite/t/vrefs-2.t
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# VREFs - part 2
-# ----------------------------------------------------------------------
-
-try "plan 72";
-
-put "../gitolite-admin/conf/gitolite.conf", "
-    \@gfoo = foo
-    \@lead = u1
-    \@senior_devs = u2 u3
-    \@junior_devs = u4 u5 u6
-    repo  \@gfoo
-
-        RW+                                 =   \@all
-
-        RW+ VREF/COUNT/2/NO_SIGNOFF         =   \@lead
-        -   VREF/COUNT/2/NO_SIGNOFF         =   \@all
-
-        -   VREF/COUNT/10/NEWFILES          =   \@junior_devs
-
-        -   VREF/FILETYPE/AUTOGENERATED     =   \@all
-";
-
-try "
-    ADMIN_PUSH vr2a
-    cd ..
-    # setup
-    [ -d foo ];                 !ok
-    CLONE u1 foo;               ok;     /Cloning into/
-                                        /You appear to have cloned an empty/
-    cd foo;                     ok
-    [ -d .git ];                ok
-
-    # u1 push 15 new files
-    tc a b c d e f g h i j k l m n o
-                                ok;     /d8c0392/
-    PUSH u1 master;             ok;     /new branch.*master -. master/
-
-    # u2 push 2 new 10 old without signoff
-    tc a b c d e f g h i j u2a u2b
-                                ok;     /6787ac9/
-    PUSH u2;                    ok;     /d8c0392..6787ac9.*master -. master/
-
-    # u2 fail to push 3 new files without signoff
-    tc u2c u2d u2e;             ok;     /a74562b/
-    PUSH u2;                    !ok;    /W VREF/COUNT/2/NO_SIGNOFF foo u2 DENIED by VREF/COUNT/2/NO_SIGNOFF/
-                                        /top commit message should include the text .3 new files signed-off by: tester.example.com./
-                                        /hook declined/
-                                        /remote rejected/
-    # u2 push 15 new files with signoff
-    tc u2f u2g u2h u2i u2j u2k u2l u2m u2n u2o u2p u2q
-                                ok;     /8dd31aa/
-    git commit --allow-empty -m '15 new files signed-off by: tester\@example.com'
-                                ok;     /.master 6126489. 15 new files signed-off by: tester.example.com/
-    PUSH u2;                    ok;     /6787ac9..6126489.*master -. master/
-
-    # u4 push 2 new 10 old files without signoff
-    tc u4a u4b a b c d e f g h i j
-                                ok;     /76c5593/
-    PUSH u4;                    ok;     /6126489..76c5593.*master -. master/
-
-    # u4 fail push 3 new files withoug signoff
-    tc u4c u4d u4e;             ok;     /2a84398/
-    PUSH u4;                    !ok;    /W VREF/COUNT/2/NO_SIGNOFF foo u4 DENIED by VREF/COUNT/2/NO_SIGNOFF/
-                                        /top commit message should include the text .3 new files signed-off by: tester.example.com./
-                                        /hook declined/
-                                        /remote rejected/
-
-    # u4 push 10 new 5 old with signoff
-    tc u4f u4g u4h u4i u4j u4k u4l a b c d e
-                                ok;     /09b646a/
-    git commit --allow-empty -m '10 new files signed-off by: tester\@example.com'
-                                ok;     /.master 47f84b0. 10 new files signed-off by: tester.example.com/
-    PUSH u4;                    ok;     /76c5593..47f84b0.*master -. master/
-
-    # u4 fail push 11 new files even with signoff
-    tc u4ab u4ac u4ad u4ae u4af u4ag u4ah u4ai u4aj u4ak u4al
-                                ok;     /90e7344/
-    git commit --allow-empty -m '11 new files signed-off by: tester\@example.com'
-                                ok;     /.master 1f36537. 11 new files signed-off by: tester.example.com/
-    PUSH u4;                    !ok;    /W VREF/COUNT/10/NEWFILES foo u4 DENIED by VREF/COUNT/10/NEWFILES/
-                                        /too many new files in this push/
-                                        /hook declined/
-                                        /remote rejected/
-
-    # test AUTOGENERATED vref
-    glt fetch u1 origin;        ok;
-    reset-h origin/master;      ok;
-    tc not-really.java;         ok;     /0f88b2e/
-    PUSH u4;                    ok;     /47f84b0..0f88b2e.*master -. master/
-";
-
-put "|cat >> not-really.java", "
-    Generated by the protocol buffer compiler.  DO NOT EDIT
-";
-
-try "
-    commit -am pbc;             ok;     /b2df6ef/
-    PUSH u4;                    !ok;    /W VREF/FILETYPE/AUTOGENERATED foo u4 DENIED by VREF/FILETYPE/AUTOGENERATED/
-                                        /hook declined/
-                                        /remote rejected/
-";
diff --git a/docker/gitolite/t/wild-1.t b/docker/gitolite/t/wild-1.t
deleted file mode 100755
index 7a8f766..0000000
--- a/docker/gitolite/t/wild-1.t
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# wild repos - part 1
-# ----------------------------------------------------------------------
-
-try "plan 66";
-
-confreset;confadd '
-    @prof       =   u1
-    @TAs        =   u2 u3
-    @students   =   u4 u5 u6
-
-    @gfoo = foo/CREATOR/a[0-9][0-9]
-    repo    @gfoo
-        C   =   @all
-        RW+ =   CREATOR
-        RW  =   WRITERS @TAs
-        R   =   READERS @prof
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-# reasonably complex setup; we'll do everything from one repo though
-cd ..
-
-# u1 create success
-glt clone u1 file:///foo/u1/a01;        ok;     /Initialized empty Git repository in .*/foo/u1/a01.git//
-
-# u2 create success
-glt clone u2 file:///foo/u2/a02;        ok;     /Initialized empty Git repository in .*/foo/u2/a02.git//
-
-# u4 tries to create u2 repo
-glt clone u4 file:///foo/u2/a12;        !ok;    /R any foo/u2/a12 u4 DENIED by fallthru/
-
-# line anchored regexes
-glt clone u4 file:///foo/u4/a1234;      !ok;    /R any foo/u4/a1234 u4 DENIED by fallthru/
-
-# u4 tries to create his own repo
-glt clone u4 file:///foo/u4/a12;        ok;     /Initialized empty Git repository in .*/foo/u4/a12.git//
-                                                /warning: You appear to have cloned an empty repository./
-
-# u4 push success
-cd a12
-tc p-728 p-729 p-730 p-731;             ok
-glt push u4 origin master;              ok;     /To file:///foo/u4/a12/
-                                                /\\* \\[new branch\\]      master -> master/
-
-# u1 clone success
-cd ..
-glt clone u1 file:///foo/u4/a12 u1a12;  ok;     /Cloning into 'u1a12'.../
-
-# u1 push fail
-cd u1a12
-tc m-778 m-779;                         ok;
-glt push u1 origin;                     !ok;    /W any foo/u4/a12 u1 DENIED by fallthru/
-
-# u2 clone success
-cd ..
-glt clone u2 file:///foo/u4/a12 u2a12;  ok;     /Cloning into 'u2a12'.../
-
-# u2 push success
-cd u2a12
-tc s-708 s-709;                         ok;
-glt push u2 origin;                     ok;     /To file:///foo/u4/a12/
-                                                /master -> master/
-
-# u2 rewind fail
-glt push u2 -f origin master^:master;   !ok;    /\\+ refs/heads/master foo/u4/a12 u2 DENIED by fallthru/
-                                                reject
-
-# u4 pull to sync up
-cd ../a12
-glt pull u4;                            ok;     /Fast-forward/
-                                                /From file:///foo/u4/a12/
-                                                /master     -> origin/master/
-
-# u4 rewind success
-git reset --hard HEAD^;                 ok
-glt push u4 -f;                         ok;     /To file:///foo/u4/a12/
-                                                /\\+ .* master -> master \\(forced update\\)/
-
-# u5 clone fail
-cd ..
-glt clone u5 file:///foo/u4/a12 u5a12;  !ok;    /R any foo/u4/a12 u5 DENIED by fallthru/
-
-glt perms u4 foo/u4/a12 + READERS u5
-glt perms u4 foo/u4/a12 + WRITERS u6
-
-glt perms u4 foo/u4/a12 -l
-";
-
-cmp 'READERS u5
-WRITERS u6
-';
-
-try "
-# u5 clone success
-glt clone u5 file:///foo/u4/a12 u5a12;  ok;     /Cloning into 'u5a12'.../
-
-# u5 push fail
-cd u5a12
-tc y-743 y-744;                         ok
-glt push u5;                            !ok;    /W any foo/u4/a12 u5 DENIED by fallthru/
-
-# u6 clone success
-cd ..
-glt clone u6 file:///foo/u4/a12 u6a12;  ok;     /Cloning into 'u6a12'.../
-
-# u6 push success
-cd u6a12
-tc k-68 k-69;                           ok
-glt push u6 file:///foo/u4/a12;         ok;     /To file:///foo/u4/a12/
-                                                /master -> master/
-
-# u6 rewind fail
-glt push u6 -f file:///foo/u4/a12 master^:master
-                                        !ok;    /\\+ refs/heads/master foo/u4/a12 u6 DENIED by fallthru/
-                                                reject
-";
diff --git a/docker/gitolite/t/wild-2.t b/docker/gitolite/t/wild-2.t
deleted file mode 100755
index cbba4f8..0000000
--- a/docker/gitolite/t/wild-2.t
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-# wild repos - part 2
-# ----------------------------------------------------------------------
-
-try "plan 65";
-
-confreset;confadd '
-    @prof       =   u1
-    @TAs        =   u2 u3
-    @students   =   u4 u5 u6
-
-    @gfoo = foo/CREATOR/a[0-9][0-9]
-    repo    @gfoo
-        C   =   @students
-        RW+ =   CREATOR
-        RW  =   WRITERS @TAs
-        R   =   READERS @prof
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-cd ..
-
-# u1 create fail
-glt clone u1 file:///foo/u1/a01;        !ok;    /R any foo/u1/a01 u1 DENIED by fallthru/
-
-# u2 create fail
-glt clone u2 file:///foo/u2/a02;        !ok;    /R any foo/u2/a02 u2 DENIED by fallthru/
-
-# u4 tries to create u2 repo
-glt clone u4 file:///foo/u2/a12;        !ok;    /R any foo/u2/a12 u4 DENIED by fallthru/
-
-# line anchored regexes
-glt clone u4 file:///foo/u4/a1234;      !ok;    /R any foo/u4/a1234 u4 DENIED by fallthru/
-
-# u4 tries to create his own repo
-glt clone u4 file:///foo/u4/a12;        ok;     /Initialized empty Git repository in .*/foo/u4/a12.git//
-                                                /warning: You appear to have cloned an empty repository./
-
-# u4 push success
-cd a12
-tc n-770 n-771 n-772 n-773;             ok
-glt push u4 origin master;              ok;     /To file:///foo/u4/a12/
-                                                /\\* \\[new branch\\]      master -> master/
-
-# u1 clone success
-cd ..
-glt clone u1 file:///foo/u4/a12 u1a12;  ok;     /Cloning into 'u1a12'.../
-
-# u1 push fail
-cd u1a12
-tc c-442 c-443;                         ok
-glt push u1;                            !ok;    /W any foo/u4/a12 u1 DENIED by fallthru/
-
-# u2 clone success
-cd ..
-glt clone u2 file:///foo/u4/a12 u2a12;  ok;     /Cloning into 'u2a12'.../
-
-# u2 push success
-cd u2a12
-tc e-393 e-394;                         ok;
-glt push u2;                            ok;     /To file:///foo/u4/a12/
-                                                /master -> master/
-
-# u2 rewind fail
-glt push u2 -f origin master^:master;   !ok;    /\\+ refs/heads/master foo/u4/a12 u2 DENIED by fallthru/
-                                                reject
-
-# u4 pull to sync up
-cd ../a12
-glt pull u4;                            ok;     /Fast-forward/
-                                                /From file:///foo/u4/a12/
-                                                /master     -> origin/master/
-
-# u4 rewind success
-git reset --hard HEAD^;                 ok
-glt push u4 -f;                         ok;     /To file:///foo/u4/a12/
-                                                /\\+ .* master -> master \\(forced update\\)/
-
-# u5 clone fail
-cd ..
-glt clone u5 file:///foo/u4/a12 u5a12;  !ok;    /R any foo/u4/a12 u5 DENIED by fallthru/
-
-# setperm
-glt perms u4 foo/u4/a12 + READERS u5
-glt perms u4 foo/u4/a12 + WRITERS u6
-
-# getperms
-glt perms u4 foo/u4/a12 -l
-";
-
-cmp 'READERS u5
-WRITERS u6
-';
-
-try "
-# u5 clone success
-glt clone u5 file:///foo/u4/a12 u5a12;  ok;     /Cloning into 'u5a12'.../
-
-# u5 push fail
-cd u5a12
-tc g-809 g-810;                         ok
-glt push u5;                            !ok;    /W any foo/u4/a12 u5 DENIED by fallthru/
-
-# u6 clone success
-cd ..
-glt clone u6 file:///foo/u4/a12 u6a12;  ok;     /Cloning into 'u6a12'.../
-
-# u6 push success
-cd u6a12
-tc f-912 f-913
-glt push u6 file:///foo/u4/a12;         ok;     /To file:///foo/u4/a12/
-                                                /master -> master/
-
-# u6 rewind fail
-glt push u6 -f file:///foo/u4/a12 master^:master
-                                        !ok;    /\\+ refs/heads/master foo/u4/a12 u6 DENIED by fallthru/
-                                                reject
-
-";
diff --git a/docker/gitolite/t/writable.t b/docker/gitolite/t/writable.t
deleted file mode 100755
index a649323..0000000
--- a/docker/gitolite/t/writable.t
+++ /dev/null
@@ -1,124 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-use Cwd;
-my $workdir = getcwd();
-
-# 'gitolite writable' command
-# ----------------------------------------------------------------------
-
-my $sf = ".gitolite.down";
-
-try "plan 66";
-try "DEF POK = !/DENIED/; !/failed to push/";
-
-# delete the down file
-unlink "$ENV{HOME}/$sf";
-
-# add foo, bar/..* repos to the config and push
-confreset;confadd '
-    repo foo
-        RW  =   u1
-        R   =   u2
-
-    repo bar/..*
-        C   =   u2 u4 u6
-        RW  =   CREATOR u3
-';
-
-try "ADMIN_PUSH set1; !/FATAL/" or die text();
-
-try "
-    # clone and push to foo
-    CLONE u1 foo;               ok
-    cd foo;                     ok
-    tc f1;                      ok
-    PUSH u1 master;             ok;     /new branch/
-
-    # auto-clone and push to bar/u2
-    cd ..
-    CLONE u2 bar/u2;            ok;     /appear to have cloned an empty/
-                                        /Initialized empty/
-    cd u2;
-    tc f2
-    PUSH u2 master;             ok;
-
-    # disable site with some message
-    gitolite writable \@all off testing site-wide disable; ok
-
-    # try push foo and see fail + message
-    cd ../foo;                  ok
-    tc f3;                      ok
-    PUSH u1;                    !ok;    /testing site-wide disable/
-    # try push bar/u2 and ...
-    cd ../u2;                   ok
-    tc f4;                      ok
-    PUSH u2;                    !ok;    /testing site-wide disable/
-
-    # try auto-create push bar/u4 and this works!!
-    cd ..
-    CLONE u4 bar/u4;            ok;     /appear to have cloned an empty/
-                                        /Initialized empty/
-                                        !/testing site-wide disable/
-    cd u4;                      ok
-
-    # enable site
-    gitolite writable \@all on; ok
-
-    # try same 3 again
-
-    # try push foo and see fail + message
-    cd ../foo;                  ok
-    tc g3;                      ok
-    PUSH u1;                    ok;    /master -> master/
-    # try push bar/u2 and ...
-    cd ../u2;                   ok
-    tc g4;                      ok
-    PUSH u2;                    ok;    /master -> master/
-
-    # try auto-create push bar/u4 and this works!!
-    cd ..
-    CLONE u6 bar/u6;            ok;     /appear to have cloned an empty/
-                                        /Initialized empty/
-                                        !/testing site-wide disable/
-    cd u6;                      ok
-
-    # disable just foo
-    gitolite writable foo off foo down
-
-    # try push foo and see the message
-    cd ../foo;                  ok
-    tc g3;                      ok
-    PUSH u1;                    !ok;    /foo down/
-                                        !/testing site-wide disable/
-    # push bar/u2 ok
-    cd ../u2
-    tc g4
-    PUSH u2;                    ok;     /master -> master/
-
-    # enable foo, disable bar/u2
-    gitolite writable foo on
-    gitolite writable bar/u2 off the bar is closed
-
-    # try both
-    cd ../foo;                  ok
-    tc h3;                      ok
-    PUSH u1;                    ok;     /master -> master/
-    # push bar/u2 ok
-    cd ../u2
-    tc h4
-    PUSH u2;                    !ok;    /the bar is closed/
-
-    ssh u3 writable bar/u2 on;  !ok;    /you are not authorized/
-    ssh u3 writable \@all on;   !ok;    /you are not authorized/
-
-    ssh u2 writable bar/u2 on;  ok
-    ssh u2 writable \@all on;   !ok;    /you are not authorized/
-
-    ssh admin writable \@all on;
-                                ok
-";
diff --git a/docker/gitolite/t/z-end.t b/docker/gitolite/t/z-end.t
deleted file mode 100755
index 6c98fe4..0000000
--- a/docker/gitolite/t/z-end.t
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-# this is hardcoded; change it if needed
-use lib "src/lib";
-use Gitolite::Test;
-
-try "plan 1; cd $ENV{PWD}; git status -s -uno; !/./ or die" or die "dirty tree";
-try "git log -1 --format='%h %ai %s'";
-put "|cat >> prove.log", text();
-
-
-
diff --git a/docker/tests-service/postgres/log/main/.gitstub b/docker/tests-service/postgres/log/main/.gitstub
new file mode 100644
index 0000000..e69de29
diff --git a/docker/tests-service/postgres/log/run b/docker/tests-service/postgres/log/run
new file mode 120000
index 0000000..f99cc1d
--- /dev/null
+++ b/docker/tests-service/postgres/log/run
@@ -0,0 +1 @@
+../../logger
\ No newline at end of file
diff --git a/docker/tests-service/postgres/run b/docker/tests-service/postgres/run
new file mode 100755
index 0000000..2b7c497
--- /dev/null
+++ b/docker/tests-service/postgres/run
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+exec 2>&1
+set -eux
+
+chown postgres:postgres -R /var/lib/postgresql
+if ! test -d /var/lib/postgresql/9.4/main ; then
+   su postgres -c "/usr/lib/postgresql/9.4/bin/initdb -D /var/lib/postgresql/9.4/main"
+fi
+mkdir -p /var/run/postgresql/9.4-main.pg_stat_tmp
+chown postgres:postgres -R /var/run/postgresql
+
+exec su postgres -c "/usr/lib/postgresql/9.4/bin/postgres -D /var/lib/postgresql/9.4/main -c config_file=/etc/postgresql/9.4/main/postgresql.conf"

commit 1390a0918ef2319ac8dab5d110720399bd95fa05
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date:   Wed Dec 23 10:28:28 2015 -0500

    Refactor to store more state in /var/arvados.  Add "reboot" command and detach
    by default.

diff --git a/arvbox b/arvbox
index 77d78bb..42fa3a9 100755
--- a/arvbox
+++ b/arvbox
@@ -2,70 +2,131 @@
 
 ARVBOX=$(readlink -f $(dirname $0))
 
-ARVADOS_ROOT=$ARVBOX/arvados
-SSO_ROOT=$ARVBOX/sso-devise-omniauth-provider
-PASSENGER=$ARVBOX/passenger
-PG_DATA=$ARVBOX/postgres
-ARV_DATA=$ARVBOX/var
+if test -z "$ARVADOS_ROOT" ; then
+    ARVADOS_ROOT=$ARVBOX/arvados
+fi
 
-mkdir -p $ARVBOX/postgres $ARVBOX/keep $ARVBOX/var $PASSENGER
+if test -z "$SSO_ROOT" ; then
+    SSO_ROOT=$ARVBOX/sso-devise-omniauth-provider
+fi
+
+if test -z "$ARVBOX_DATA" ; then
+    ARVBOX_DATA=$ARVBOX
+fi
+
+if test -z "$ARVBOX_CONTAINER" ; then
+    ARVBOX_CONTAINER=arvbox
+fi
+
+PASSENGER=$ARVBOX_DATA/passenger
+PG_DATA=$ARVBOX_DATA/postgres
+ARV_DATA=$ARVBOX_DATA/var
+
+mkdir -p $PASSENGER $PG_DATA $ARV_DATA
+
+run() {
+    docker run \
+           --detach \
+           --name=$ARVBOX_CONTAINER \
+           --privileged \
+           --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
+           --volume=$SSO_ROOT:/usr/src/sso:rw \
+           --volume=$PG_DATA:/var/lib/postgresql:rw \
+           --volume=$ARV_DATA:/var/lib/arvados:rw \
+           --volume=$PASSENGER:/var/lib/passenger:rw \
+           --volume=/var/lib/docker \
+           arvados/arvbox
+
+    FF=/tmp/arvbox-fifo-$$
+    mkfifo $FF
+    docker logs -f $ARVBOX_CONTAINER > $FF &
+    LOGPID=$!
+    while read line ; do
+        echo $line
+        if echo $line | grep "Workbench is running at" >/dev/null ; then
+            kill $LOGPID
+        fi
+    done < $FF
+    rm $FF
+}
+
+stop() {
+        docker stop $ARVBOX_CONTAINER
+        docker rm $ARVBOX_CONTAINER
+}
 
 case $1 in
-     build)
-     git clone https://github.com/curoverse/arvados.git
-     git clone https://github.com/curoverse/sso-devise-omniauth-provider.git
-     docker build -t arvados/arvbox docker
-     ;;
-
-     start|run)
-     docker run --rm --name=arvbox --privileged \
-       --volume=$ARVADOS_ROOT:/usr/src/arvados:rw \
-       --volume=$SSO_ROOT:/usr/src/sso:rw \
-       --volume=$PG_DATA:/var/lib/postgresql:rw \
-       --volume=$ARV_DATA:/var/lib/arvados:rw \
-       --volume=$PASSENGER:/var/lib/passenger:rw \
-       --volume=/var/lib/docker \
-       arvados/arvbox
-     ;;
-
-     sh*)
-     docker exec -ti arvbox /bin/bash
-     ;;
-
-     stop)
-     docker stop arvbox
-     ;;
-
-     ip|open)
-     IP=$(docker inspect arvbox | grep \"IPAddress\" | tr -d ' ":,\n' | cut -c10-)
-     if test $1 = 'ip' ; then
-       echo $IP
-     else
-       xdg-open http://$IP
-     fi
-     ;;
-
-     resetdb)
-     sudo rm -rf $PG_DATA
-     sudo rm -rf $ARV_DATA
-     sudo rm -f $SSO_ROOT/database_setup $ARVADOS_ROOT/services/api/database_setup
-     ;;
-
-     log)
-     docker exec -ti arvbox tail -n40 /etc/service/$2/log/main/current
-     ;;
-
-     *)
-     echo "Arvados-in-a-box"
-     echo
-     echo "$0 (build|start|run|stop|shell|stop|ip|open|resetdb|log)"
-     echo
-     echo "build      build arvbox Docker image"
-     echo "start|run  start arvbox"
-     echo "stop       stop arvbo"
-     echo "shell      enter arvbox shell"
-     echo "ip         print arvbox ip address"
-     echo "open       open arvbox workbench in a web browser"
-     echo "resetdb    delete persistent data (be careful!)"
-     echo "log <component> tail log of specified service"
+    build)
+        cd $ARVBOX
+        docker build -t arvados/arvbox docker
+        ;;
+
+    start|run)
+        if ! test -d $ARVADOS_ROOT ; then
+            git clone https://github.com/curoverse/arvados.git $ARVADOS_ROOT
+        fi
+        if ! test -d $SSO_ROOT ; then
+            git clone https://github.com/curoverse/sso-devise-omniauth-provider.git $SSO_ROOT
+        fi
+
+        run
+        ;;
+
+    sh*)
+        docker exec -ti $ARVBOX_CONTAINER /bin/bash
+        ;;
+
+    stop)
+        stop
+        ;;
+
+    reboot)
+        stop
+        cd $ARVBOX
+        docker build -t arvados/arvbox docker
+        run
+        ;;
+
+    sv|service)
+        docker exec -ti $ARVBOX_CONTAINER sv $2 $3
+        docker exec -ti $ARVBOX_CONTAINER sv restart ready
+        ;;
+
+    ip|open)
+        IP=$(docker inspect arvbox | grep \"IPAddress\" | tr -d ' ":,\n' | cut -c10-)
+        if test $1 = 'ip' ; then
+            echo $IP
+        else
+            xdg-open http://$IP
+        fi
+        ;;
+
+    reset)
+        if test "$2" != -f ; then
+            echo "WARNING!  This will delete all data inside your arvbox ($PG_DATA and $ARV_DATA).  Use reset -f if you really mean it."
+            exit 1
+        fi
+        stop
+        sudo rm -rf $PG_DATA
+        sudo rm -rf $ARV_DATA
+        ;;
+
+    log)
+        docker exec -ti $ARVBOX_CONTAINER tail -n40 /etc/service/$2/log/main/current
+        ;;
+
+    *)
+        echo "Arvados-in-a-box"
+        echo
+        echo "$0 (build|start|run|stop|shell|stop|ip|open|resetdb|log)"
+        echo
+        echo "build      build arvbox Docker image"
+        echo "start|run  start arvbox"
+        echo "stop       stop arvbo"
+        echo "shell      enter arvbox shell"
+        echo "ip         print arvbox ip address"
+        echo "open       open arvbox workbench in a web browser"
+        echo "resetdb    delete persistent data (be careful!)"
+        echo "log <component> tail log of specified service"
+        ;;
 esac
diff --git a/docker/keep-setup.sh b/docker/keep-setup.sh
index 4e0536a..c321070 100755
--- a/docker/keep-setup.sh
+++ b/docker/keep-setup.sh
@@ -19,7 +19,7 @@ mkdir -p /var/lib/arvados/keep
 
 export ARVADOS_API_HOST=$localip:3001
 export ARVADOS_API_HOST_INSECURE=1
-export ARVADOS_API_TOKEN=$(cat /usr/src/arvados/services/api/superuser_token)
+export ARVADOS_API_TOKEN=$(cat /var/lib/arvados/superuser_token)
 
 if test -s /var/lib/arvados/$1-uuid ; then
     keep_uuid=$(cat /var/lib/arvados/$1-uuid)
diff --git a/docker/service/api/run b/docker/service/api/run
index 8f997ce..935c93c 100755
--- a/docker/service/api/run
+++ b/docker/service/api/run
@@ -10,30 +10,25 @@ export RAILS_ENV=development
 
 bundle install --without=development --path=vendor
 
-if ! test -s uuid_prefix ; then
-  ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > uuid_prefix
+if ! test -s /var/lib/arvados/api_uuid_prefix ; then
+  ruby -e 'puts "#{rand(2**64).to_s(36)[0,5]}"' > /var/lib/arvados/api_uuid