Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use sudo to call docker-build if we're not running as root. #373

Closed
wants to merge 8 commits into from
Closed
38 changes: 4 additions & 34 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,57 +16,25 @@ ENV BASEDIR=/usr/lib/unifi \
CERTNAME=cert.pem \
CERT_PRIVATE_NAME=privkey.pem \
CERT_IS_CHAIN=false \
GOSU_VERSION=1.10 \
BIND_PRIV=true \
RUNAS_UID0=true \
UNIFI_GID=999 \
UNIFI_UID=999

# Install gosu
# https://github.com/tianon/gosu/blob/master/INSTALL.md
# This should be integrated with the main run because it duplicates a lot of the steps there
# but for now while shoehorning gosu in it is seperate
RUN set -ex \
&& fetchDeps=' \
ca-certificates \
dirmngr \
gpg \
wget \
' \
&& apt-get update \
&& apt-get install -y --no-install-recommends $fetchDeps \
&& dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
&& wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" \
# verify the signature
&& export GNUPGHOME="$(mktemp -d)" \
&& for server in $(shuf -e ha.pool.sks-keyservers.net \
hkp://p80.pool.sks-keyservers.net:80 \
keyserver.ubuntu.com \
hkp://keyserver.ubuntu.com:80 \
pool.sks-keyservers.net) ; do \
gpg --keyserver "$server" --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 && break || : ; \
done \
&& gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
&& rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc \
&& chmod +x /usr/local/bin/gosu \
&& apt-get purge -y --auto-remove $fetchDeps \
&& rm -rf /var/lib/apt/lists/*

RUN mkdir -p /usr/unifi \
/usr/local/unifi/init.d \
/usr/unifi/init.d \
/usr/local/docker
COPY docker-entrypoint.sh /usr/local/bin/
COPY docker-healthcheck.sh /usr/local/bin/
COPY docker-build.sh /usr/local/bin/
COPY docker-permissions.sh /usr/local/bin/
COPY functions /usr/unifi/functions
COPY import_cert /usr/unifi/init.d/
COPY pre_build /usr/local/docker/pre_build
RUN chmod +x /usr/local/bin/docker-entrypoint.sh \
&& chmod +x /usr/unifi/init.d/import_cert \
&& chmod +x /usr/local/bin/docker-healthcheck.sh \
&& chmod +x /usr/local/bin/docker-build.sh \
&& chmod +x /usr/local/bin/docker-permissions.sh \
&& chmod -R +x /usr/local/docker/pre_build

# Push installing openjdk-8-jre first, so that the unifi package doesn't pull in openjdk-7-jre as a dependency? Else uncomment and just go with openjdk-7.
Expand All @@ -76,6 +44,8 @@ RUN set -ex \
&& useradd --no-log-init -r -u $UNIFI_UID -g $UNIFI_GID unifi \
&& /usr/local/bin/docker-build.sh "${PKGURL}"

RUN mkdir -p /unifi && chown unifi:unifi -R /unifi

VOLUME ["/unifi", "${RUNDIR}"]

EXPOSE 6789/tcp 8080/tcp 8443/tcp 8880/tcp 8843/tcp 3478/udp
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ Default: `8443`

This is the HTTPS port used by the Web interface.

### `UNIFI_STDOUT`

Default: `unset`

Controller outputs logs to stdout in addition to server.log

### `TZ`

TimeZone. (i.e America/Chicago)
Expand Down
9 changes: 9 additions & 0 deletions docker-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ addKey() {
return 1
}

if [ ! -f /usr/bin/sudo ]; then
apt-get update
apt-get install sudo
rm -rf /var/lib/apt/lists/*
echo "ALL ALL=(ALL) NOPASSWD:SETENV: /usr/local/bin/docker-build.sh" > /etc/sudoers.d/unifi-build
echo "ALL ALL=(ALL) NOPASSWD:SETENV: /usr/local/bin/docker-permissions.sh" > /etc/sudoers.d/unifi-permissions
fi

if [ "x${1}" == "x" ]; then
echo please pass PKGURL as an environment variable
exit 0
Expand Down Expand Up @@ -63,4 +71,5 @@ ln -s ${LOGDIR} ${OLOGDIR}
mkdir -p /var/cert ${CERTDIR}
ln -s ${CERTDIR} /var/cert/unifi

rm -rf /etc/sudoers.d/unifi-build
rm -rf "${0}"
46 changes: 15 additions & 31 deletions docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
. /usr/unifi/functions

if [ -x /usr/local/bin/docker-build.sh ]; then
/usr/local/bin/docker-build.sh "${PKGURL}"
if [[ $EUID -ne 0 ]]; then
sudo -E /usr/local/bin/docker-build.sh "${PKGURL}"
else
/usr/local/bin/docker-build.sh "${PKGURL}"
fi
fi

exit_handler() {
Expand Down Expand Up @@ -141,9 +145,10 @@ if [[ "$UNIFI_ECC_CERT" == "true" ]]; then
settings["unifi.https.ciphers"]="TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
fi

for key in "${!settings[@]}"; do
confSet "$confFile" "$key" "${settings[$key]}"
done
if [[ "$UNIFI_STDOUT" == "true" ]]; then
settings["unifi.logStdout"]="true"
fi

UNIFI_CMD="java ${JVM_OPTS} -jar ${BASEDIR}/lib/ace.jar start"

# controller writes to relative path logs/server.log
Expand All @@ -162,34 +167,13 @@ if [[ "${@}" == "unifi" ]]; then
mkdir -p "${dir}"
fi
done
if [ "${RUNAS_UID0}" == "true" ] || [ "${CUID}" != "0" ]; then
if [ "${CUID}" == 0 ]; then
log 'WARNING: Running UniFi in insecure (root) mode'
fi
${UNIFI_CMD} &
elif [ "${RUNAS_UID0}" == "false" ]; then
if [ "${BIND_PRIV}" == "true" ]; then
if setcap 'cap_net_bind_service=+ep' "${JAVA_HOME}/jre/bin/java"; then
sleep 1
else
log "ERROR: setcap failed, can not continue"
log "ERROR: You may either launch with -e BIND_PRIV=false and only use ports >1024"
log "ERROR: or run this container as root with -e RUNAS_UID0=true"
exit 1
fi
fi
if [ "$(id unifi -u)" != "${UNIFI_UID}" ] || [ "$(id unifi -g)" != "${UNIFI_GID}" ]; then
log "INFO: Changing 'unifi' UID to '${UNIFI_UID}' and GID to '${UNIFI_GID}'"
usermod -o -u ${UNIFI_UID} unifi && groupmod -o -g ${UNIFI_GID} unifi
fi
# Using a loop here so I can check more directories easily later
for dir in ${DIRS}; do
if [ "$(stat -c '%u' "${dir}")" != "${UNIFI_UID}" ]; then
chown -R "${UNIFI_UID}:${UNIFI_GID}" "${dir}"
fi
done
gosu unifi:unifi ${UNIFI_CMD} &
for key in "${!settings[@]}"; do
confSet "$confFile" "$key" "${settings[$key]}"
done
if [ $CUID != 0 ]; then
sudo -E UNIFI_UID=$(id -u) UNIFI_GID=$(id -g) /usr/local/bin/docker-permissions.sh
fi
${UNIFI_CMD} &
wait
log "WARN: unifi service process ended without being signaled? Check for errors in ${LOGDIR}." >&2
else
Expand Down
12 changes: 12 additions & 0 deletions docker-permissions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

DIRS="${RUNDIR} ${LOGDIR} ${DATADIR} ${BASEDIR}"

echo "Setting ownership of '${DIRS}' to ${UNIFI_UID}:${UNIFI_GID}"

# Using a loop here so I can check more directories easily later
for dir in ${DIRS}; do
if [ "$(stat -c '%u' "${dir}")" != "${UNIFI_UID}" ]; then
chown -R "${UNIFI_UID}:${UNIFI_GID}" "${dir}"
fi
done