fix: allow running as non-root (#40642)

## Description

Allows the Appsmith container to run as a non-root user, specified at
runtime through either docker-compose or Kubernetes pod security
context. I didn't specify the user in the `Dockerfile` because
environments like OpenShift choose a user at runtime, so it can't be
known at build time.

This needs to be followed by an update to docs and changes in the Helm
chart to finish it off, but that has a separate release cycle and this
needs to go ahead of that.

Ideally we would run as non-root by default, but since there's data
persisted on the filesystem automatically transitioning the default is
impossible without a lot of pain. This moves us in that direction and
enables it in the future if we go down that path.

Required to fix https://github.com/appsmithorg/appsmith/issues/38787

## Automation

/ok-to-test tags=""

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!WARNING]
> Tests have not run on the HEAD
50ba745c5bb7709c60ce5194437f921f1a95c980 yet
> <hr>Thu, 15 May 2025 15:56:31 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added support for user identity emulation when running as a non-root
user, improving compatibility in certain deployment environments.
- Prevented embedded database initialization when running as a non-root
user to ensure proper operation.

- **Chores**
- Installed additional system packages to the base image for enhanced
functionality.
- Optimized image size by consolidating and improving cleanup steps
during the build process.
- Updated base image and refined installation commands for improved
build consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Wyatt Walter 2025-05-28 11:49:48 -05:00 committed by GitHub
parent 3bcc8b0858
commit 2d21717059
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 44 additions and 16 deletions

View File

@ -21,6 +21,8 @@ RUN set -o xtrace \
supervisor curl nfs-common gnupg \
gettext \
ca-certificates \
libnss-wrapper \
git \
# Install MongoDB v6, Redis, PostgreSQL v14
&& curl -fsSL https://www.mongodb.org/static/pgp/server-6.0.asc | gpg --dearmor -o /usr/share/keyrings/mongodb-server-6.0.gpg \
&& echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list \
@ -28,7 +30,16 @@ RUN set -o xtrace \
&& curl --silent --show-error --location https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& apt update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes mongodb-org redis postgresql-14 \
&& apt-get clean
&& find /etc/redis -type d -exec chmod o+rx {} + -o -type f -exec chmod o+r {} + \
&& apt-get clean \
&& rm -rf \
/root/.cache \
/root/.npm \
/usr/local/share/doc \
/usr/share/doc \
/usr/share/man \
/var/lib/apt/lists/* \
/tmp/*
ENV PATH="/usr/lib/postgresql/14/bin:${PATH}"
@ -65,23 +76,20 @@ RUN set -o xtrace \
&& mkdir -p /opt/caddy \
&& version="$(curl --write-out '%{redirect_url}' 'https://github.com/caddyserver/caddy/releases/latest' | sed 's,.*/v,,')" \
&& curl --location "https://github.com/caddyserver/caddy/releases/download/v$version/caddy_${version}_linux_$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/').tar.gz" \
| tar -xz -C /opt/caddy
RUN mv /opt/caddy/caddy /opt/caddy/caddy_vanilla
| tar -xz -C /opt/caddy && \
mv /opt/caddy/caddy /opt/caddy/caddy_vanilla
COPY --from=caddybuilder /usr/bin/caddy /opt/caddy/caddy
# Clean up
RUN rm -rf \
/root/.cache \
/root/.npm \
/usr/local/share/doc \
/usr/share/doc \
/usr/share/man \
/var/lib/apt/lists/* \
/tmp/*
VOLUME [ "/appsmith-stacks" ]
ENV TMP="/tmp/appsmith"
ENV WWW_PATH="$TMP/www"
# libnss_wrapper.so is written to an architecture-specific directory, so we symlink to it in a common location to make it easier to activate
ENV NSS_WRAPPER_SYMLINK=/usr/local/lib/libnss_wrapper.so
RUN NSS_WRAPPER_LIB=$(find /usr/lib -name libnss_wrapper.so -type f 2>/dev/null | head -n1) && \
ln -sf "$NSS_WRAPPER_LIB" $NSS_WRAPPER_SYMLINK
# these env vars need to be set for NSS Wrapper to work but don't matter until LD_PRELOAD is set which is optionally done at runtime
ENV NSS_WRAPPER_PASSWD="${TMP}/passwd"
ENV NSS_WRAPPER_GROUP="${TMP}/group"

View File

@ -5,8 +5,6 @@ source pg-utils.sh
set -e
tlog "Running as: $(id)"
stacks_path=/appsmith-stacks
export APPSMITH_PG_DATABASE="appsmith"
@ -15,6 +13,23 @@ export MONGODB_TMP_KEY_PATH="$TMP/mongodb-key" # export for use in supervisor p
mkdir -pv "$SUPERVISORD_CONF_TARGET" "$WWW_PATH"
if [ "$(id -u)" != "0" ]; then
# if user is non-root setup nss_wrapper
# If this is a container restart, the files may already exist and we want them to remain read-only
if [[ ! -f /tmp/appsmith/passwd ]]; then
echo "appsmith:x:$(id -u):$(id -g):Appsmith:/opt/appsmith:/bin/bash" > /tmp/appsmith/passwd
chmod 444 /tmp/appsmith/passwd
fi
if [[ ! -f /tmp/appsmith/group ]]; then
echo "appsmith:x:$(id -g):" > /tmp/appsmith/group
chmod 444 /tmp/appsmith/group
fi
# NSS_WRAPPER_PASSWD, NSS_WRAPPER_GROUP, and NSS_WRAPPER_SYMLINK are set in Dockerfile
export LD_PRELOAD="$NSS_WRAPPER_SYMLINK"
fi
tlog "Running as: $(id)"
setup_proxy_variables() {
export NO_PROXY="${NO_PROXY-localhost,127.0.0.1}"
@ -429,6 +444,11 @@ check_redis_compatible_page_size() {
init_postgres() {
# Initialize embedded postgres by default; set APPSMITH_ENABLE_EMBEDDED_DB to 0, to use existing cloud postgres mockdb instance
if [[ ${APPSMITH_ENABLE_EMBEDDED_DB: -1} != 0 ]]; then
if [[ "$(id -u)" != "0" ]]; then
tlog "== When running as a non-root user embedded PostgreSQL cannot be used. Please use an external PostgreSQL instance instead." >&2
exit 1
fi
tlog "Checking initialized local postgres"
POSTGRES_DB_PATH="$stacks_path/data/postgres/main"