You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2022/11/11 18:40:11 UTC

[trafficcontrol] branch master updated: Run CDN in a Box for Developers services as unprivileged users (#7142)

This is an automated email from the ASF dual-hosted git repository.

ocket8888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new fe72b09038 Run CDN in a Box for Developers services as unprivileged users (#7142)
fe72b09038 is described below

commit fe72b09038228e44a14f968e2a3f839c3e21fe76
Author: Zach Hoffman <zr...@apache.org>
AuthorDate: Fri Nov 11 18:40:04 2022 +0000

    Run CDN in a Box for Developers services as unprivileged users (#7142)
    
    * Run CDN in a Box for Developers services as unprivileged users
    
    * Reuse ats user for running t3c
    
    * trafficrouter user for traffic_router
    
    * Use local cache for NPM dependencies
    
    * Use local cache for Maven dependencies
    
    * Always use trafficcontrol directory to get ownership
    
    * Change owner to the unprivileged user if files are owned as root from a previous run
    
    * Use bash shell on Debian Bullseye, not dash
    
    * Do not hard-code user id 1000
    
    * Use Debian adduser syntax in trafficportal and tpv2 run scripts
    
    * TPv2: Change owner to the unprivileged user if files are owned as root from a previous run
    
    * Chown Go bin and pkg directories as unprivileged user
    
    * Set PGPASSWORD for db/admin process
    
    * Run db/admin as the unprivileged user
    
    * Check if directory exists before checking ownership
    
    * Remove /root GOPATH prefix
    
    * Explicitly allow non-root users to bind ports under 1024 to preserve nerdctl support
    
    * Get the user id of the current user, not explicitly the unprivileged user
    
    * Run traffic_server without su
    
    * Run as unprivileged user before building db/admin
---
 dev/atc.dev.sh                     |  2 +-
 dev/t3c/Dockerfile                 |  7 ++++---
 dev/t3c/run.sh                     | 24 +++++++++++++++++++++---
 dev/tpv2/Dockerfile                |  9 +++++----
 dev/tpv2/run.sh                    | 21 ++++++++++++++++++++-
 dev/traffic_monitor/Dockerfile     | 10 ++++++----
 dev/traffic_monitor/run.sh         | 15 +++++++++++++++
 dev/traffic_monitor/tm.config.json |  6 +++---
 dev/traffic_ops/Dockerfile         | 11 ++++++-----
 dev/traffic_ops/run.sh             | 21 ++++++++++++++++++++-
 dev/traffic_portal/Dockerfile      |  9 +++++----
 dev/traffic_portal/config.js       |  2 +-
 dev/traffic_portal/run.sh          | 23 +++++++++++++++++++++--
 dev/traffic_router/run.sh          | 29 ++++++++++++++++++-----------
 docker-compose.yml                 | 26 ++++++++++++++++++++------
 traffic_ops/app/db/admin.go        |  7 ++++---
 16 files changed, 170 insertions(+), 52 deletions(-)

diff --git a/dev/atc.dev.sh b/dev/atc.dev.sh
index 9d3a819c87..128f3e52c6 100644
--- a/dev/atc.dev.sh
+++ b/dev/atc.dev.sh
@@ -137,7 +137,7 @@ function atc {
 	return "$?";
 }
 
-export t3cDir="/root/go/src/github.com/apache/trafficcontrol/cache-config";
+export t3cDir="/go/src/github.com/apache/trafficcontrol/cache-config";
 
 function t3c {
 	trap 'atc-exec t3c ps | grep dlv | tr -s " " | cut -d " " -f1 | xargs docker exec trafficcontrol_t3c_1 kill' INT;
diff --git a/dev/t3c/Dockerfile b/dev/t3c/Dockerfile
index 411dc029fb..6f2f384450 100644
--- a/dev/t3c/Dockerfile
+++ b/dev/t3c/Dockerfile
@@ -23,7 +23,7 @@ ENV PATH=/usr/local/go/bin:${PATH} \
 	GOPATH=/go
 ENV PATH=${GOPATH}/bin:${PATH}
 
-ENV TC="/root/go/src/github.com/apache/trafficcontrol/" GOFLAGS="--buildvcs=false"
+ENV TC="/go/src/github.com/apache/trafficcontrol" GOFLAGS="--buildvcs=false"
 VOLUME $TC
 EXPOSE 80 8081
 
@@ -35,8 +35,9 @@ RUN apk add --no-cache \
 	make \
 	# gcc and musl-dev are used to build packages using CGO
 	gcc musl-dev && \
-	go install github.com/go-delve/delve/cmd/dlv@latest
+	go install github.com/go-delve/delve/cmd/dlv@latest && \
+	rm -rf $GOPATH/pkg/*
 
 RUN echo "stats_over_http.so" >> /etc/trafficserver/plugin.config && echo "system_stats.so" >> /etc/trafficserver/plugin.config
 
-CMD /root/go/src/github.com/apache/trafficcontrol/dev/t3c/run.sh
+CMD ${TC}/dev/t3c/run.sh
diff --git a/dev/t3c/run.sh b/dev/t3c/run.sh
index 9f1c2e36c6..e6e22a1f2f 100755
--- a/dev/t3c/run.sh
+++ b/dev/t3c/run.sh
@@ -18,9 +18,27 @@
 # under the License.
 
 set -o errexit
+set -o xtrace
 trap '[ $? -eq 0 ] && exit 0 || echo "Error on line ${LINENO} of ${0}"; exit 1' EXIT
 
 cd "$TC/tc-health-client"
+
+user=ats
+uid="$(stat -c%u "$TC")"
+gid="$(stat -c%g "$TC")"
+if [[ "$(id -u)" != "$uid" ]]; then
+	for dir in "${GOPATH}/bin" "${GOPATH}/pkg"; do
+		if [[ -e "$dir" ]] && [[ "$(stat -c%u "$dir")" -ne "$uid" || "$(stat -c%g "$dir")" -ne "$gid" ]] ; then
+			chown -R "${uid}:${gid}" "$dir"
+		fi
+	done
+
+	sed -Ei "s/^(${user}:.*:)([0-9]+:){2}(.*)/\1${uid}:${gid}:\3/" /etc/passwd
+	sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
+	chown -R "${uid}:${gid}" /usr/bin "/home/${user}" /etc/trafficserver /var/log/trafficserver /var/trafficserver
+	exec su "$user" -- "$0"
+fi
+
 go build --gcflags "all=-N -l" .
 
 cd "$TC/cache-config"
@@ -38,11 +56,11 @@ if [[ ! -f /usr/bin/tc-health-client ]]; then
 	ln -s "$TC/tc-health-client/tc-health-client" /usr/bin/
 fi
 
-su -c traffic_server ats &
+traffic_server &
 
 while inotifywait --exclude '.*(\.md|\.json|\.pl|\.rst|_test\.go|\.gitignore|__debug_bin|-logrotate|.service)$|^\./(build|t3c-check-refs/test-files|testing|t3util/testing|tm-health-client/(config|tmagent)/test_files)/.*' -e modify -r . ; do
 	T3C_PID="$(ps | grep t3c | grep -v grep | grep -v inotifywait | grep -v run.sh | tr -s ' ' | cut -d ' ' -f2)"
-	if [[ ! -z "$T3"]]; then
+	if [[ ! -z "$T3" ]]; then
 		echo "$T3C_PID" | xargs kill;
 	fi
 	# TODO: is it even necessary to restart ATS?
@@ -50,7 +68,7 @@ while inotifywait --exclude '.*(\.md|\.json|\.pl|\.rst|_test\.go|\.gitignore|__d
 		rm /var/trafficserver/server.lock;
 	fi
 	ps | grep traffic_server | grep -v grep | tr -s ' ' | cut -d ' ' -f2 | xargs kill
-	su -c traffic_server ats &
+	traffic_server &
 	# for whatever reason, without this the repeated call to inotifywait will
 	# sometimes lose track of th current directory. It spits out:
 	# Couldn't watch .: No such file or directory
diff --git a/dev/tpv2/Dockerfile b/dev/tpv2/Dockerfile
index c9c678e2ff..e4a8be7e96 100644
--- a/dev/tpv2/Dockerfile
+++ b/dev/tpv2/Dockerfile
@@ -20,14 +20,15 @@ RUN openssl genrsa -passout pass:x -out server.pass.key 2048 && \
 	openssl req -new -key server.key -out server.csr \
 		-subj "/C=US/ST=CO/L=Denver/O=Apache/OU=Traffic Control/CN=trafficops.dev.ciab.test" && \
 	openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt && \
-	openssl rand 32 | base64 > /aes.key
+	openssl rand 32 | base64 > /aes.key && \
+    chmod 644 /server.key /aes.key
 
 FROM node:16-alpine AS tpv2-dev
 
-ENV TC="/root/go/src/github.com/apache/trafficcontrol/"
-VOLUME /root/go/src/github.com/apache/trafficcontrol
+ENV TC="/go/src/github.com/apache/trafficcontrol"
+VOLUME $TC
 EXPOSE 443
 
 COPY --from=certbuilder /server.key /server.crt /
 
-CMD /root/go/src/github.com/apache/trafficcontrol/dev/tpv2/run.sh
+CMD ${TC}/dev/tpv2/run.sh
diff --git a/dev/tpv2/run.sh b/dev/tpv2/run.sh
index 35da81bda9..26f01eaf50 100755
--- a/dev/tpv2/run.sh
+++ b/dev/tpv2/run.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -16,5 +16,24 @@
 set -o errexit
 
 cd "$TC/experimental/traffic-portal"
+
+user=tpv2
+uid="$(stat -c%u "$TC")"
+gid="$(stat -c%g "$TC")"
+if [[ "$(id -u)" != "$uid" ]]; then
+	for dir in "${TC}/.npm" .angular node_modules; do
+		if [[ -e "$dir" ]] && [[ "$(stat -c%u "$dir")" -ne "$uid" || "$(stat -c%g "$dir")" -ne "$gid" ]] ; then
+			chown -R "${uid}:${gid}" "$dir"
+		fi
+	done
+
+	if ! adduser --disabled-password -u "$uid" "$user"; then
+		user="$(cat /etc/passwd | grep :x:${uid}: | cut -d: -f1)"
+	fi
+	sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
+	chown "${uid}:${gid}" /usr/bin
+	exec su "$user" -- "$0"
+fi
+
 npm ci --ignore-scripts
 ./node_modules/.bin/ng serve --ssl --ssl-cert /server.crt --ssl-key /server.key --watch --proxy-config "$TC/dev/tpv2/proxy.json" --port 443 --host "::0" --live-reload
diff --git a/dev/traffic_monitor/Dockerfile b/dev/traffic_monitor/Dockerfile
index 6c7428b79b..623f5487bd 100644
--- a/dev/traffic_monitor/Dockerfile
+++ b/dev/traffic_monitor/Dockerfile
@@ -14,11 +14,13 @@
 ARG GO_VERSION
 FROM golang:${GO_VERSION}-alpine AS trafficmonitor-dev
 
-ENV TC=/root/go/src/github.com/apache/trafficcontrol GOFLAGS="--buildvcs=false"
-VOLUME /root/go/src/github.com/apache/trafficcontrol
+ENV TC=/go/src/github.com/apache/trafficcontrol GOFLAGS="--buildvcs=false"
+VOLUME $TC
 EXPOSE 80 81
 
-RUN apk add --no-cache inotify-tools gcc libc-dev && go install github.com/go-delve/delve/cmd/dlv@latest && ln -s /root/go/bin/dlv /usr/bin/dlv
+RUN apk add --no-cache inotify-tools gcc libc-dev && \
+	go install github.com/go-delve/delve/cmd/dlv@latest && \
+	rm -rf $GOPATH/pkg/*
 RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
 
-CMD /root/go/src/github.com/apache/trafficcontrol/dev/traffic_monitor/run.sh
+CMD ${TC}/dev/traffic_monitor/run.sh
diff --git a/dev/traffic_monitor/run.sh b/dev/traffic_monitor/run.sh
index cd3b655ad6..0ce89e5e51 100755
--- a/dev/traffic_monitor/run.sh
+++ b/dev/traffic_monitor/run.sh
@@ -17,9 +17,24 @@
 # under the License.
 
 set -o errexit
+set -o xtrace
 trap '[ $? -eq 0 ] && exit 0 || echo "Error on line ${LINENO} of ${0}"; exit 1' EXIT
 
 cd "$TC/traffic_monitor"
+user=trafficmonitor
+uid="$(stat -c%u "$TC")"
+gid="$(stat -c%g "$TC")"
+if [[ "$(id -u)" != "$uid" ]]; then
+	for dir in "${GOPATH}/bin" "${GOPATH}/pkg"; do
+		if [[ -e "$dir" ]] && [[ "$(stat -c%u "$dir")" -ne "$uid" || "$(stat -c%g "$dir")" -ne "$gid" ]] ; then
+			chown -R "${uid}:${gid}" "$dir"
+		fi
+	done
+
+	adduser -Du"$uid" "$user"
+	sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
+	exec su "$user" -- "$0"
+fi
 
 dlv --accept-multiclient --continue --listen=:81 --headless --api-version=2 debug -- --opsCfg="$TC/dev/traffic_monitor/ops.config.json" --config="$TC/dev/traffic_monitor/tm.config.json" &
 
diff --git a/dev/traffic_monitor/tm.config.json b/dev/traffic_monitor/tm.config.json
index 3834cf6ac4..e778226b0f 100644
--- a/dev/traffic_monitor/tm.config.json
+++ b/dev/traffic_monitor/tm.config.json
@@ -12,7 +12,7 @@
 	"log_location_debug": "stdout",
 	"serve_read_timeout_ms": 86400000,
 	"serve_write_timeout_ms": 86400000,
-	"static_file_dir": "/root/go/src/github.com/apache/trafficcontrol/traffic_monitor/static/",
-	"crconfig_backup_file": "/root/go/src/github.com/apache/trafficcontrol/dev/traffic_monitor/snapshot.backup.json",
-	"tmconfig_backup_file": "/root/go/src/github.com/apache/trafficcontrol/dev/traffic_monitor/monitoring.snapshot.backup.json"
+	"static_file_dir": "/go/src/github.com/apache/trafficcontrol/traffic_monitor/static/",
+	"crconfig_backup_file": "/go/src/github.com/apache/trafficcontrol/dev/traffic_monitor/snapshot.backup.json",
+	"tmconfig_backup_file": "/go/src/github.com/apache/trafficcontrol/dev/traffic_monitor/monitoring.snapshot.backup.json"
 }
diff --git a/dev/traffic_ops/Dockerfile b/dev/traffic_ops/Dockerfile
index 195eab2856..5e68bf2ef3 100644
--- a/dev/traffic_ops/Dockerfile
+++ b/dev/traffic_ops/Dockerfile
@@ -20,22 +20,23 @@ RUN openssl genrsa -passout pass:x -out server.pass.key 2048 && \
 	openssl req -new -key server.key -out server.csr \
 		-subj "/C=US/ST=CO/L=Denver/O=Apache/OU=Traffic Control/CN=trafficops.dev.ciab.test" && \
 	openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt && \
-	openssl rand 32 | base64 > /aes.key
+	openssl rand 32 | base64 > /aes.key && \
+	chmod 644 /server.key /aes.key
 
 FROM golang:${GO_VERSION}-alpine AS trafficops-dev
 
-ENV TC="/root/go/src/github.com/apache/trafficcontrol/" GOFLAGS="--buildvcs=false"
-VOLUME /root/go/src/github.com/apache/trafficcontrol
+ENV TC="/go/src/github.com/apache/trafficcontrol" GOFLAGS="--buildvcs=false"
+VOLUME $TC
 ENV ADMIN="$TC/traffic_ops/app/db/admin"
 EXPOSE 443 6444
 
 COPY --from=certbuilder /server.key /server.crt /aes.key /
 RUN apk add --no-cache make inotify-tools postgresql-client gcc libc-dev && \
 	go install github.com/go-delve/delve/cmd/dlv@latest && \
-	ln -s /root/go/bin/dlv /usr/bin/dlv
+	rm -rf $GOPATH/pkg/*
 RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
 
 COPY .pgpass /root/.pgpass
 RUN chmod 0600 /root/.pgpass
 
-CMD /root/go/src/github.com/apache/trafficcontrol/dev/traffic_ops/run.sh
+CMD $TC/dev/traffic_ops/run.sh
diff --git a/dev/traffic_ops/run.sh b/dev/traffic_ops/run.sh
index 6da2320ebc..69ddecd350 100755
--- a/dev/traffic_ops/run.sh
+++ b/dev/traffic_ops/run.sh
@@ -17,14 +17,31 @@
 # under the License.
 
 set -o errexit
+set -o xtrace
 trap '[ $? -eq 0 ] && exit 0 || echo "Error on line ${LINENO} of ${0}"; exit 1' EXIT
 
+user=trafficops
+uid="$(stat -c%u "$TC")"
+gid="$(stat -c%g "$TC")"
+if [[ "$(id -u)" != "$uid" ]]; then
+	for dir in "${GOPATH}/bin" "${GOPATH}/pkg"; do
+		if [[ -e "$dir" ]] && [[ "$(stat -c%u "$dir")" -ne "$uid" || "$(stat -c%g "$dir")" -ne "$gid" ]] ; then
+			chown -R "${uid}:${gid}" "$dir"
+		fi
+	done
+
+	adduser -Du"$uid" "$user"
+	sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
+	exec su "$user" -- "$0"
+fi
+
+cd "$TC"
+
 while ! pg_isready -h db -p 5432 -d postgres; do
 	echo "waiting for db on postgresql://db:5432/postgres";
 	sleep 3;
 done
 
-cd "$TC"
 make traffic_ops/app/db/admin
 cd "$TC/dev/traffic_ops"
 
@@ -33,8 +50,10 @@ cd "$TC/dev/traffic_ops"
 "$ADMIN" -v -c ./traffic.vault.dbconf.yml -s "$TC/traffic_ops/app/db/trafficvault/create_tables.sql" -m "$TC/traffic_ops/app/db/trafficvault/migrations" reset
 "$ADMIN" -v -c ./traffic.vault.dbconf.yml -s "$TC/traffic_ops/app/db/trafficvault/create_tables.sql" -m "$TC/traffic_ops/app/db/trafficvault/migrations" upgrade
 
+
 psql -d 'postgres://traffic_ops:twelve12@db:5432/traffic_ops_development?sslmode=disable' -f ./seed.psql
 
+
 cd "$TC/traffic_ops/traffic_ops_golang"
 
 dlv --accept-multiclient --continue --listen=:6444 --headless --api-version=2 debug -- --cfg=../../dev/traffic_ops/cdn.json --dbcfg=../../dev/traffic_ops/db.config.json &
diff --git a/dev/traffic_portal/Dockerfile b/dev/traffic_portal/Dockerfile
index 546a2fc30c..62a87f4b6f 100644
--- a/dev/traffic_portal/Dockerfile
+++ b/dev/traffic_portal/Dockerfile
@@ -19,15 +19,16 @@ RUN openssl genrsa -passout pass:x -out server.pass.key 2048 && \
 	openssl req -new -key server.key -out server.csr \
 		-subj "/C=US/ST=CO/L=Denver/O=Apache/OU=Traffic Control/CN=trafficops.dev.ciab.test" && \
 	openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt && \
-	openssl rand 32 | base64 > /aes.key
+	openssl rand 32 | base64 > /aes.key && \
+    chmod 644 /server.key /aes.key
 
 FROM node:16-alpine AS trafficportal-dev
 
-ENV TC="/root/go/src/github.com/apache/trafficcontrol/"
-VOLUME /root/go/src/github.com/apache/trafficcontrol
+ENV TC="/go/src/github.com/apache/trafficcontrol"
+VOLUME $TC
 EXPOSE 443
 ENV TP_SERVER_CONFIG_FILE="$TC/dev/traffic_portal/config.js"
 
 COPY --from=certbuilder /server.key /server.crt /
 
-CMD /root/go/src/github.com/apache/trafficcontrol/dev/traffic_portal/run.sh
+CMD ${TC}/dev/traffic_portal/run.sh
diff --git a/dev/traffic_portal/config.js b/dev/traffic_portal/config.js
index dcca20abda..4ba146db27 100644
--- a/dev/traffic_portal/config.js
+++ b/dev/traffic_portal/config.js
@@ -31,7 +31,7 @@ module.exports = {
         base_url: 'https://trafficops:443/api/'
     },
     files: {
-        static: '/root/go/src/github.com/apache/trafficcontrol/traffic_portal/app/dist/public'
+        static: '/go/src/github.com/apache/trafficcontrol/traffic_portal/app/dist/public'
     },
     log: null,
     reject_unauthorized: 0
diff --git a/dev/traffic_portal/run.sh b/dev/traffic_portal/run.sh
index 6f45c18435..3874c71d76 100755
--- a/dev/traffic_portal/run.sh
+++ b/dev/traffic_portal/run.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -13,8 +13,27 @@
 #  limitations under the License.
 #
 
-set -o errexit
+set -o errexit -o nounset
 
 cd "$TC/traffic_portal"
+
+user=trafficportal
+uid="$(stat -c%u "$TC")"
+gid="$(stat -c%g "$TC")"
+if [[ "$(id -u)" != "$uid" ]]; then
+	for dir in "${TC}/.npm"  .[a-z]* app/dist app/dist/public node_modules; do
+		if [[ -e "$dir" ]] && [[ "$(stat -c%u "$dir")" -ne "$uid" || "$(stat -c%g "$dir")" -ne "$gid" ]] ; then
+			chown -R "${uid}:${gid}" "$dir"
+		fi
+	done
+
+	if ! adduser --disabled-password -u "$uid" "$user"; then
+		user="$(cat /etc/passwd | grep :x:${uid}: | cut -d: -f1)"
+	fi
+	sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
+	chown "${uid}:${gid}" /usr/bin
+	exec su "$user" -- "$0"
+fi
+
 npm ci
 ./node_modules/.bin/grunt
diff --git a/dev/traffic_router/run.sh b/dev/traffic_router/run.sh
index 9ec211f188..0e1907d519 100755
--- a/dev/traffic_router/run.sh
+++ b/dev/traffic_router/run.sh
@@ -16,20 +16,27 @@
 # specific language governing permissions and limitations
 # under the License.
 
-set -o errexit
-
-
-
+set -o errexit -o nounset
 
 cd "$TC/traffic_router"
+
 user=trafficrouter
-uid="$(stat -c%u .)"
-gid="$(stat -c%g .)"
-adduser -Du"$uid" "$user"
-sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
-chown -R "${uid}:${gid}" /opt
+uid="$(stat -c%u "$TC")"
+gid="$(stat -c%g "$TC")"
+if [[ "$(id -u)" != "$uid" ]]; then
+	for dir in "${TC}/.m2"  */target; do
+		if [[ -e "$dir" ]] && [[ "$(stat -c%u "$dir")" -ne "$uid" || "$(stat -c%g "$dir")" -ne "$gid" ]] ; then
+			chown -R "${uid}:${gid}" "$dir"
+		fi
+	done
+
+	adduser -Du"$uid" "$user"
+	sed -Ei "s/^(${user}:.*:)[0-9]+(:)$/\1${gid}\2/" /etc/group
+	chown -R "${uid}:${gid}" /opt
+	exec su "$user" -- "$0"
+fi
 
-su "$user" -- /usr/bin/mvn -Dmaven.test.skip=true compile package -P \!rpm-build
+mvn -Dmaven.test.skip=true compile package -P \!rpm-build
 
 cd "$TC/dev/traffic_router"
-exec su "$user" -- /opt/tomcat/bin/catalina.sh jpda run
+exec /opt/tomcat/bin/catalina.sh jpda run
diff --git a/docker-compose.yml b/docker-compose.yml
index cb5ce192c2..d9da0325cc 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -33,8 +33,10 @@ services:
         ports:
             - 6443:443
             - 6444:6444
+        sysctls:
+            - net.ipv4.ip_unprivileged_port_start=0
         volumes:
-            - .:/root/go/src/github.com/apache/trafficcontrol/
+            - .:/go/src/github.com/apache/trafficcontrol
 
     db:
         image: postgres:13.2-alpine
@@ -57,9 +59,11 @@ services:
         image: trafficportal-dev
         ports:
             - 444:443
+        sysctls:
+            - net.ipv4.ip_unprivileged_port_start=0
         volumes:
-            - .:/root/go/src/github.com/apache/trafficcontrol
-            - ./.npm:/root/.npm
+            - .:/go/src/github.com/apache/trafficcontrol
+            - ./.npm:/trafficportal/.npm
 
     tpv2:
         build:
@@ -72,8 +76,11 @@ services:
         image: tpv2-dev
         ports:
             - 443:443
+        sysctls:
+            - net.ipv4.ip_unprivileged_port_start=0
         volumes:
-            - .:/root/go/src/github.com/apache/trafficcontrol
+            - .:/go/src/github.com/apache/trafficcontrol
+            - ./.npm:/trafficportal/.npm
 
     trafficmonitor:
         build:
@@ -89,8 +96,10 @@ services:
         ports:
             - 80:80
             - 81:81
+        sysctls:
+            - net.ipv4.ip_unprivileged_port_start=0
         volumes:
-            - .:/root/go/src/github.com/apache/trafficcontrol
+            - .:/go/src/github.com/apache/trafficcontrol
 
     t3c:
         build:
@@ -107,8 +116,10 @@ services:
         ports:
             - 8080:80
             - 8081:8081
+        sysctls:
+            - net.ipv4.ip_unprivileged_port_start=0
         volumes:
-            - .:/root/go/src/github.com/apache/trafficcontrol
+            - .:/go/src/github.com/apache/trafficcontrol
 
     trafficrouter:
         build:
@@ -127,8 +138,11 @@ services:
             - 3333:3333
             - 2222:3443
             - 5005:5005
+        sysctls:
+            - net.ipv4.ip_unprivileged_port_start=0
         volumes:
             - .:/go/src/github.com/apache/trafficcontrol
+            - ./.m2:/home/trafficrouter/.m2
 networks:
     ciab:
         name: dev.ciab.test
diff --git a/traffic_ops/app/db/admin.go b/traffic_ops/app/db/admin.go
index 01529c8eae..50607739be 100644
--- a/traffic_ops/app/db/admin.go
+++ b/traffic_ops/app/db/admin.go
@@ -466,7 +466,6 @@ func seed() {
 	}
 	cmd := exec.Command("psql", "-h", hostIP, "-p", hostPort, "-d", dbName, "-U", dbUser, "-e", "-v", "ON_ERROR_STOP=1")
 	cmd.Stdin = bytes.NewBuffer(seedsBytes)
-	cmd.Env = append(os.Environ(), "PGPASSWORD="+dbPassword)
 	out, err := cmd.CombinedOutput()
 	fmt.Println(string(out))
 	if err != nil {
@@ -486,7 +485,6 @@ func loadSchema() {
 	}
 	cmd := exec.Command("psql", "-h", hostIP, "-p", hostPort, "-d", dbName, "-U", dbUser, "-e", "-v", "ON_ERROR_STOP=1")
 	cmd.Stdin = bytes.NewBuffer(schemaBytes)
-	cmd.Env = append(os.Environ(), "PGPASSWORD="+dbPassword)
 	out, err := cmd.CombinedOutput()
 	fmt.Println(string(out))
 	if err != nil {
@@ -505,7 +503,6 @@ func patch() {
 	}
 	cmd := exec.Command("psql", "-h", hostIP, "-p", hostPort, "-d", dbName, "-U", dbUser, "-e", "-v", "ON_ERROR_STOP=1")
 	cmd.Stdin = bytes.NewBuffer(patchesBytes)
-	cmd.Env = append(os.Environ(), "PGPASSWORD="+dbPassword)
 	out, err := cmd.CombinedOutput()
 	fmt.Printf(string(out))
 	if err != nil {
@@ -661,6 +658,10 @@ func main() {
 	if err := parseDBConfig(); err != nil {
 		die(err.Error())
 	}
+	if err := os.Setenv("PGPASSWORD", dbPassword); err != nil {
+		die("Setting PGPASSWORD: " + err.Error())
+	}
+
 	commands := make(map[string]func())
 
 	commands[cmdCreateDB] = createDB