From cb0aea56369b35bad41a24cfeecbf82d64e126cb Mon Sep 17 00:00:00 2001 From: Aram Akhavan Date: Sat, 13 Dec 2025 20:44:15 -0800 Subject: [PATCH 1/6] Add support for running rootless and with readonly filesystem --- bitwarden-lite/Dockerfile | 17 +++--- bitwarden-lite/docker-compose.yml | 10 +++- bitwarden-lite/entrypoint.sh | 60 +++++++++----------- bitwarden-lite/hbs/config.yaml | 4 +- bitwarden-lite/hbs/nginx-config.hbs | 3 + bitwarden-lite/nginx/nginx.conf | 15 +++-- bitwarden-lite/settings.env | 4 -- bitwarden-lite/supervisord/admin.ini | 4 +- bitwarden-lite/supervisord/api.ini | 4 +- bitwarden-lite/supervisord/events.ini | 4 +- bitwarden-lite/supervisord/icons.ini | 4 +- bitwarden-lite/supervisord/identity.ini | 4 +- bitwarden-lite/supervisord/nginx.ini | 2 +- bitwarden-lite/supervisord/notifications.ini | 4 +- bitwarden-lite/supervisord/scim.ini | 4 +- bitwarden-lite/supervisord/sso.ini | 4 +- bitwarden-lite/supervisord/supervisord.conf | 7 ++- 17 files changed, 79 insertions(+), 75 deletions(-) diff --git a/bitwarden-lite/Dockerfile b/bitwarden-lite/Dockerfile index 045b04c8..0537b1a2 100644 --- a/bitwarden-lite/Dockerfile +++ b/bitwarden-lite/Dockerfile @@ -236,16 +236,16 @@ RUN apk add --no-cache \ RUN mkdir -p /etc/bitwarden/attachments/send RUN mkdir -p /etc/bitwarden/data-protection RUN mkdir -p /etc/bitwarden/licenses -RUN mkdir -p /etc/bitwarden/logs RUN mkdir -p /etc/supervisor RUN mkdir -p /etc/supervisor.d -RUN mkdir -p /var/log/bitwarden -RUN mkdir -p /var/log/nginx/logs -RUN mkdir -p /etc/nginx/http.d -RUN mkdir -p /var/run/nginx -RUN mkdir -p /var/lib/nginx/tmp -RUN touch /var/run/nginx/nginx.pid -RUN mkdir -p /app +RUN mkdir -p /app/Identity +RUN mkdir -p /app/Sso +RUN mkdir -p /app/Web + +# Create soft links for files generated in the entrypoint +RUN ln -s /etc/bitwarden/identity.pfx /app/Identity/identity.pfx +RUN ln -s /etc/bitwarden/identity.pfx /app/Sso/identity.pfx +RUN ln -s /etc/bitwarden/app-id.json /app/Web/app-id.json # Copy all apps from dotnet-build stage WORKDIR /app @@ -287,6 +287,7 @@ RUN chmod +x /usr/local/bin/hbs COPY bitwarden-lite/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh +EXPOSE 8080 8443 VOLUME ["/etc/bitwarden"] WORKDIR /app diff --git a/bitwarden-lite/docker-compose.yml b/bitwarden-lite/docker-compose.yml index 1da80d4f..9e8e4674 100644 --- a/bitwarden-lite/docker-compose.yml +++ b/bitwarden-lite/docker-compose.yml @@ -7,13 +7,19 @@ services: env_file: - settings.env image: ${REGISTRY:-ghcr.io/bitwarden}/lite:${TAG:-2025.12.0} + user: 999:999 + tmpfs: /tmp + read_only: true + security_opt: + - no-new-privileges restart: always ports: - "80:8080" - "443:8443" volumes: + # The user specified above must have permissions + # for the bind mount on the host - bitwarden:/etc/bitwarden - - logs:/var/log/bitwarden # MariaDB Example db: @@ -50,6 +56,4 @@ services: # - data:/var/opt/mssql volumes: - bitwarden: - logs: data: diff --git a/bitwarden-lite/entrypoint.sh b/bitwarden-lite/entrypoint.sh index dd62f6c1..98f4ccd9 100755 --- a/bitwarden-lite/entrypoint.sh +++ b/bitwarden-lite/entrypoint.sh @@ -1,12 +1,14 @@ #!/bin/sh -# Set up user group -PGID="${PGID:-1000}" -addgroup -g $PGID bitwarden +if [[ "$(id -u)" == "0" ]]; then + # Set up user group + PGID="${PGID:-911}" + addgroup -g $PGID bitwarden -# Set up user -PUID="${PUID:-1000}" -adduser -D -H -u $PUID -G bitwarden bitwarden + # Set up user + PUID="${PUID:-911}" + adduser -D -H -u $PUID -G bitwarden bitwarden +fi # Translate environment variables for application settings VAULT_SERVICE_URI=https://${BW_DOMAIN:-localhost} @@ -49,20 +51,18 @@ if [ ! -f /etc/bitwarden/identity.pfx ]; then -subj "/CN=Bitwarden IdentityServer" \ -days 36500 + # identity.pfx is soft linked to the necessary locations in the Dockerfile openssl pkcs12 \ -export \ -out /etc/bitwarden/identity.pfx \ -inkey /etc/bitwarden/identity.key \ -in /etc/bitwarden/identity.crt \ - -passout pass:$globalSettings__identityServer__certificatePassword + -passout "pass:$globalSettings__identityServer__certificatePassword" rm /etc/bitwarden/identity.crt rm /etc/bitwarden/identity.key fi -cp /etc/bitwarden/identity.pfx /app/Identity/identity.pfx -cp /etc/bitwarden/identity.pfx /app/Sso/identity.pfx - # Generate SSL certificates if [ "$BW_ENABLE_SSL" = "true" ] && [ ! -f /etc/bitwarden/${BW_SSL_KEY:-ssl.key} ]; then TMP_OPENSSL_CONF="/tmp/openssl_san.cnf" @@ -74,8 +74,8 @@ if [ "$BW_ENABLE_SSL" = "true" ] && [ ! -f /etc/bitwarden/${BW_SSL_KEY:-ssl.key} -sha256 \ -nodes \ -days 36500 \ - -keyout /etc/bitwarden/${BW_SSL_KEY:-ssl.key} \ - -out /etc/bitwarden/${BW_SSL_CERT:-ssl.crt} \ + -keyout /etc/bitwarden/"${BW_SSL_KEY:-ssl.key}" \ + -out /etc/bitwarden/"${BW_SSL_CERT:-ssl.crt}" \ -reqexts SAN \ -extensions SAN \ -config "$TMP_OPENSSL_CONF" \ @@ -86,31 +86,23 @@ fi # Launch a loop to rotate nginx logs on a daily basis /bin/sh -c "/logrotate.sh loop >/dev/null 2>&1 &" -/usr/local/bin/hbs - -# Enable/Disable services -sed -i "s/autostart=true/autostart=${BW_ENABLE_ADMIN}/" /etc/supervisor.d/admin.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_API}/" /etc/supervisor.d/api.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_EVENTS}/" /etc/supervisor.d/events.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_ICONS}/" /etc/supervisor.d/icons.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_IDENTITY}/" /etc/supervisor.d/identity.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_NOTIFICATIONS}/" /etc/supervisor.d/notifications.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_SCIM}/" /etc/supervisor.d/scim.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_SSO}/" /etc/supervisor.d/sso.ini +# Create necessary directories +mkdir -p /etc/bitwarden/logs/supervisord +mkdir -p /etc/bitwarden/logs/nginx +mkdir -p /etc/bitwarden/nginx +mkdir -p /tmp/bitwarden -chown -R $PUID:$PGID \ - /app \ - /etc/bitwarden \ - /etc/nginx/http.d \ - /etc/supervisor \ - /etc/supervisor.d \ - /var/lib/nginx \ - /var/log \ - /var/run/nginx \ - /run +/usr/local/bin/hbs -if command -v su-exec >/dev/null 2>&1; then +if [[ "$(id -u)" == 0 ]]; then + find /etc/bitwarden ! -xtype l \( ! -gid "$PGID" -o ! -uid "$PUID" \) -exec chown "${PUID}:${PGID}" {} + exec su-exec $PUID:$PGID /usr/bin/supervisord else + FILES="$(find /etc/bitwarden ! -xtype l \( ! -gid "$(id -g)" -o ! -uid "$(id -u)" \))" + if [[ -n "$FILES" ]]; then + echo "The following files are not owned by the running user and may cause errors:" >&2 + echo "$FILES" >&2 + fi + exec /usr/bin/supervisord fi \ No newline at end of file diff --git a/bitwarden-lite/hbs/config.yaml b/bitwarden-lite/hbs/config.yaml index 2dc04a65..13fc4ad0 100644 --- a/bitwarden-lite/hbs/config.yaml +++ b/bitwarden-lite/hbs/config.yaml @@ -2,6 +2,6 @@ helper_categories: - String templates: - src: /etc/hbs/app-id.hbs - dest: /app/Web/app-id.json + dest: /etc/bitwarden/Web/app-id.json - src: /etc/hbs/nginx-config.hbs - dest: /etc/nginx/http.d/bitwarden.conf \ No newline at end of file + dest: /etc/bitwarden/nginx/bitwarden.conf \ No newline at end of file diff --git a/bitwarden-lite/hbs/nginx-config.hbs b/bitwarden-lite/hbs/nginx-config.hbs index 9beb4207..8470ca48 100644 --- a/bitwarden-lite/hbs/nginx-config.hbs +++ b/bitwarden-lite/hbs/nginx-config.hbs @@ -1,3 +1,6 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY BITWARDEN! +# CHANGES WILL BE OVERWRITTEN ON CONTAINER STARTUP! + server { listen {{{String.Coalesce env.BW_PORT_HTTP "8080"}}} default_server; listen [::]:{{{String.Coalesce env.BW_PORT_HTTP "8080"}}} default_server; diff --git a/bitwarden-lite/nginx/nginx.conf b/bitwarden-lite/nginx/nginx.conf index 93445e8a..b9104e3a 100644 --- a/bitwarden-lite/nginx/nginx.conf +++ b/bitwarden-lite/nginx/nginx.conf @@ -28,13 +28,20 @@ events { # Default error log file # (this is only used when you don't override error_log on a server{} level) -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx/nginx.pid; +error_log /etc/bitwarden/logs/nginx/error.log warn; +pid /tmp/bitwarden/nginx.pid; http { # Include proxy and server configuration. include /etc/nginx/proxy.conf; - include /etc/nginx/http.d/bitwarden.conf; + include /etc/bitwarden/nginx/bitwarden.conf; + + # Use /tmp/bitwarden for nginx temp files + client_body_temp_path /tmp/bitwarden/nginx 1 2; + fastcgi_temp_path /tmp/bitwarden/nginx-fastcgi; + proxy_temp_path /tmp/bitwarden/nginx-proxy; + uwsgi_temp_path /tmp/bitwarden/nginx-uwsgi; + scgi_temp_path /tmp/bitwarden/nginx-scgi; # Hide nginx version information. server_tokens off; @@ -62,7 +69,7 @@ http { # Default log file # (this is only used when you don't override access_log on a server{} level) - access_log /var/log/nginx/access.log main; + access_log /etc/bitwarden/logs/nginx/access.log main; # How long to allow each connection to stay idle; longer values are better # for each individual client, particularly for SSL, but means that worker diff --git a/bitwarden-lite/settings.env b/bitwarden-lite/settings.env index d86baa6c..e70e871d 100644 --- a/bitwarden-lite/settings.env +++ b/bitwarden-lite/settings.env @@ -23,10 +23,6 @@ BW_INSTALLATION_KEY=xxxxxxxxxxxx ##################### # Learn more here: https://bitwarden.com/help/environment-variables/ -# Container user ID/group ID -#PUID=1000 -#PGID=1000 - # Webserver ports #BW_PORT_HTTP=8080 #BW_PORT_HTTPS=8443 diff --git a/bitwarden-lite/supervisord/admin.ini b/bitwarden-lite/supervisord/admin.ini index 7e52170e..84f555a3 100644 --- a/bitwarden-lite/supervisord/admin.ini +++ b/bitwarden-lite/supervisord/admin.ini @@ -1,5 +1,5 @@ [program:admin] -autostart=true +autostart=%(ENV_BW_ENABLE_ADMIN)s autorestart=true command=/usr/bin/dotnet "Admin.dll" directory=/app/Admin @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5000" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/admin.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/admin.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/api.ini b/bitwarden-lite/supervisord/api.ini index f0081d99..a84d36db 100644 --- a/bitwarden-lite/supervisord/api.ini +++ b/bitwarden-lite/supervisord/api.ini @@ -1,5 +1,5 @@ [program:api] -autostart=true +autostart=%(ENV_BW_ENABLE_API)s autorestart=true command=/usr/bin/dotnet "Api.dll" directory=/app/Api @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5001" priority=2 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/api.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/api.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/events.ini b/bitwarden-lite/supervisord/events.ini index 4a772a59..80e5112b 100644 --- a/bitwarden-lite/supervisord/events.ini +++ b/bitwarden-lite/supervisord/events.ini @@ -1,5 +1,5 @@ [program:events] -autostart=true +autostart=%(ENV_BW_ENABLE_EVENTS)s autorestart=true command=/usr/bin/dotnet "Events.dll" directory=/app/Events @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5003" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/events.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/events.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/icons.ini b/bitwarden-lite/supervisord/icons.ini index dad58831..be7be324 100644 --- a/bitwarden-lite/supervisord/icons.ini +++ b/bitwarden-lite/supervisord/icons.ini @@ -1,5 +1,5 @@ [program:icons] -autostart=true +autostart=%(ENV_BW_ENABLE_ICONS)s autorestart=true command=/usr/bin/dotnet "Icons.dll" directory=/app/Icons @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5004" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/icons.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/icons.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/identity.ini b/bitwarden-lite/supervisord/identity.ini index cb0268f0..662c67ce 100644 --- a/bitwarden-lite/supervisord/identity.ini +++ b/bitwarden-lite/supervisord/identity.ini @@ -1,5 +1,5 @@ [program:identity] -autostart=true +autostart=%(ENV_BW_ENABLE_IDENTITY)s autorestart=true command=/usr/bin/dotnet "Identity.dll" directory=/app/Identity @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5005" priority=1 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/identity.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/identity.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/nginx.ini b/bitwarden-lite/supervisord/nginx.ini index bc52f3f9..98600d0d 100644 --- a/bitwarden-lite/supervisord/nginx.ini +++ b/bitwarden-lite/supervisord/nginx.ini @@ -4,4 +4,4 @@ autorestart=true command=nginx redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/nginx.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/nginx.log diff --git a/bitwarden-lite/supervisord/notifications.ini b/bitwarden-lite/supervisord/notifications.ini index e87c7e0d..29fae185 100644 --- a/bitwarden-lite/supervisord/notifications.ini +++ b/bitwarden-lite/supervisord/notifications.ini @@ -1,5 +1,5 @@ [program:notifications] -autostart=true +autostart=%(ENV_BW_ENABLE_NOTIFICATIONS)s autorestart=true command=/usr/bin/dotnet "Notifications.dll" directory=/app/Notifications @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5006" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/notifications.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/notifications.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/scim.ini b/bitwarden-lite/supervisord/scim.ini index f64d67d1..534017ff 100644 --- a/bitwarden-lite/supervisord/scim.ini +++ b/bitwarden-lite/supervisord/scim.ini @@ -1,5 +1,5 @@ [program:scim] -autostart=true +autostart=%(ENV_BW_ENABLE_SCIM)s autorestart=true command=/usr/bin/dotnet "Scim.dll" directory=/app/Scim @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5002" priority=4 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/scim.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/scim.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/sso.ini b/bitwarden-lite/supervisord/sso.ini index a0ba6577..1dc665bc 100644 --- a/bitwarden-lite/supervisord/sso.ini +++ b/bitwarden-lite/supervisord/sso.ini @@ -1,5 +1,5 @@ [program:sso] -autostart=true +autostart=%(ENV_BW_ENABLE_SSO)s autorestart=true command=/usr/bin/dotnet "Sso.dll" directory=/app/Sso @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5007" priority=4 redirect_stderr=true startsecs=15 -stdout_logfile=/var/log/bitwarden/sso.log +stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/sso.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/supervisord.conf b/bitwarden-lite/supervisord/supervisord.conf index 4cd6a8cb..51a84403 100644 --- a/bitwarden-lite/supervisord/supervisord.conf +++ b/bitwarden-lite/supervisord/supervisord.conf @@ -1,15 +1,16 @@ [unix_http_server] -file=/run/supervisord.sock ; the path to the socket file +file=/tmp/bitwarden/supervisord.sock ; the path to the socket file [supervisord] -logfile=/var/log/supervisord.log ; main log file; default $CWD/supervisord.log +logfile=/etc/bitwarden/logs/supervisord/supervisord.log ; main log file; default $CWD/supervisord.log nodaemon=true ; start in foreground if true; default false +pidfile=/tmp/bitwarden/supervisord.pid [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] -serverurl=unix:///run/supervisord.sock ; use a unix:// URL for a unix socket +serverurl=unix:///tmp/bitwarden/supervisord.sock ; use a unix:// URL for a unix socket [include] files = /etc/supervisor.d/*.ini From 72e2e88a9e2c22fd305f4e95fd0ecda69b5e61d5 Mon Sep 17 00:00:00 2001 From: Aram Akhavan Date: Sat, 13 Dec 2025 20:53:13 -0800 Subject: [PATCH 2/6] Fix shellcheck errors --- bitwarden-lite/entrypoint.sh | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/bitwarden-lite/entrypoint.sh b/bitwarden-lite/entrypoint.sh index 98f4ccd9..ff4fa88c 100755 --- a/bitwarden-lite/entrypoint.sh +++ b/bitwarden-lite/entrypoint.sh @@ -1,13 +1,13 @@ #!/bin/sh -if [[ "$(id -u)" == "0" ]]; then +if [ "$(id -u)" = "0" ]; then # Set up user group PGID="${PGID:-911}" - addgroup -g $PGID bitwarden + addgroup -g "$PGID" bitwarden # Set up user PUID="${PUID:-911}" - adduser -D -H -u $PUID -G bitwarden bitwarden + adduser -D -H -u "$PUID" -G bitwarden bitwarden fi # Translate environment variables for application settings @@ -20,23 +20,24 @@ INTERNAL_IDENTITY_KEY=$(openssl rand -hex 30) OIDC_IDENTITY_CLIENT_KEY=$(openssl rand -hex 30) DUO_AKEY=$(openssl rand -hex 30) -export globalSettings__baseServiceUri__vault=${globalSettings__baseServiceUri__vault:-$VAULT_SERVICE_URI} -export globalSettings__installation__id=$BW_INSTALLATION_ID -export globalSettings__installation__key=$BW_INSTALLATION_KEY -export globalSettings__internalIdentityKey=${globalSettings__internalIdentityKey:-$INTERNAL_IDENTITY_KEY} -export globalSettings__oidcIdentityClientKey=${globalSettings__oidcIdentityClientKey:-$OIDC_IDENTITY_CLIENT_KEY} -export globalSettings__duo__aKey=${globalSettings__duo__aKey:-$DUO_AKEY} +export globalSettings__baseServiceUri__vault="${globalSettings__baseServiceUri__vault:-$VAULT_SERVICE_URI}" +export globalSettings__installation__id="$BW_INSTALLATION_ID" +export globalSettings__installation__key="$BW_INSTALLATION_KEY" +export globalSettings__internalIdentityKey="${globalSettings__internalIdentityKey:-$INTERNAL_IDENTITY_KEY}" +export globalSettings__oidcIdentityClientKey="{globalSettings__oidcIdentityClientKey:-$OIDC_IDENTITY_CLIENT_KEY}" +export globalSettings__duo__aKey="${globalSettings__duo__aKey:-$DUO_AKEY}" +export globalSettings__identityServer__certificatePassword="${globalSettings__identityServer__certificatePassword:-$IDENTITY_SERVER_CERTIFICATE_PASSWORD}" -export globalSettings__databaseProvider=$BW_DB_PROVIDER -export globalSettings__mysql__connectionString=${globalSettings__mysql__connectionString:-$MYSQL_CONNECTION_STRING} -export globalSettings__postgreSql__connectionString=${globalSettings__postgreSql__connectionString:-$POSTGRESQL_CONNECTION_STRING} -export globalSettings__sqlServer__connectionString=${globalSettings__sqlServer__connectionString:-$SQLSERVER_CONNECTION_STRING} -export globalSettings__sqlite__connectionString=${globalSettings__sqlite__connectionString:-$SQLITE_CONNECTION_STRING} +export globalSettings__databaseProvider="$BW_DB_PROVIDER" +export globalSettings__mysql__connectionString="${globalSettings__mysql__connectionString:-$MYSQL_CONNECTION_STRING}" +export globalSettings__postgreSql__connectionString="${globalSettings__postgreSql__connectionString:-$POSTGRESQL_CONNECTION_STRING}" +export globalSettings__sqlServer__connectionString="${globalSettings__sqlServer__connectionString:-$SQLSERVER_CONNECTION_STRING}" +export globalSettings__sqlite__connectionString="${globalSettings__sqlite__connectionString:-$SQLITE_CONNECTION_STRING}" if [ "$BW_ENABLE_SSL" = "true" ]; then - export globalSettings__baseServiceUri__internalVault=https://localhost:${BW_PORT_HTTPS:-8443} + export globalSettings__baseServiceUri__internalVault="https://localhost:${BW_PORT_HTTPS:-8443}" else - export globalSettings__baseServiceUri__internalVault=http://localhost:${BW_PORT_HTTP:-8080} + export globalSettings__baseServiceUri__internalVault="http://localhost:${BW_PORT_HTTP:-8080}" fi # Generate Identity certificate @@ -64,10 +65,10 @@ if [ ! -f /etc/bitwarden/identity.pfx ]; then fi # Generate SSL certificates -if [ "$BW_ENABLE_SSL" = "true" ] && [ ! -f /etc/bitwarden/${BW_SSL_KEY:-ssl.key} ]; then +if [ "$BW_ENABLE_SSL" = "true" ] && [ ! -f /etc/bitwarden/"${BW_SSL_KEY:-ssl.key}" ]; then TMP_OPENSSL_CONF="/tmp/openssl_san.cnf" cat /usr/lib/ssl/openssl.cnf > "$TMP_OPENSSL_CONF" - printf "\n[SAN]\nsubjectAltName=DNS:${BW_DOMAIN:-localhost}\nbasicConstraints=CA:true\n" >> "$TMP_OPENSSL_CONF" + printf "\n[SAN]\nsubjectAltName=DNS:%s\nbasicConstraints=CA:true\n" "${BW_DOMAIN:-localhost}" >> "$TMP_OPENSSL_CONF" openssl req \ -x509 \ -newkey rsa:4096 \ @@ -94,12 +95,12 @@ mkdir -p /tmp/bitwarden /usr/local/bin/hbs -if [[ "$(id -u)" == 0 ]]; then +if [ "$(id -u)" = "0" ]; then find /etc/bitwarden ! -xtype l \( ! -gid "$PGID" -o ! -uid "$PUID" \) -exec chown "${PUID}:${PGID}" {} + - exec su-exec $PUID:$PGID /usr/bin/supervisord + exec su-exec "$PUID:$PGID" /usr/bin/supervisord else FILES="$(find /etc/bitwarden ! -xtype l \( ! -gid "$(id -g)" -o ! -uid "$(id -u)" \))" - if [[ -n "$FILES" ]]; then + if [ -n "$FILES" ]; then echo "The following files are not owned by the running user and may cause errors:" >&2 echo "$FILES" >&2 fi From 0b9cdb6f0ea0f6e9502ef5bcacc1eb3fff7ef6e0 Mon Sep 17 00:00:00 2001 From: Aram Akhavan Date: Sat, 20 Dec 2025 11:20:06 -0800 Subject: [PATCH 3/6] Update docker compose example --- bitwarden-lite/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitwarden-lite/docker-compose.yml b/bitwarden-lite/docker-compose.yml index 9e8e4674..b50f4b65 100644 --- a/bitwarden-lite/docker-compose.yml +++ b/bitwarden-lite/docker-compose.yml @@ -8,7 +8,7 @@ services: - settings.env image: ${REGISTRY:-ghcr.io/bitwarden}/lite:${TAG:-2025.12.0} user: 999:999 - tmpfs: /tmp + tmpfs: /tmp:rw,noexec,nosuid,nodev,size=512m read_only: true security_opt: - no-new-privileges From 921175c4d6ef80c01ec84b20ea1ce1a0212e04ec Mon Sep 17 00:00:00 2001 From: Aram Akhavan Date: Sat, 20 Dec 2025 12:50:20 -0800 Subject: [PATCH 4/6] Fix various issues preventing container startup --- bitwarden-lite/Dockerfile | 10 +++++----- bitwarden-lite/entrypoint.sh | 7 ++++--- bitwarden-lite/nginx/nginx.conf | 10 +++++++--- bitwarden-lite/supervisord/admin.ini | 2 +- bitwarden-lite/supervisord/api.ini | 2 +- bitwarden-lite/supervisord/events.ini | 2 +- bitwarden-lite/supervisord/icons.ini | 2 +- bitwarden-lite/supervisord/identity.ini | 2 +- bitwarden-lite/supervisord/nginx.ini | 2 +- bitwarden-lite/supervisord/notifications.ini | 2 +- bitwarden-lite/supervisord/scim.ini | 2 +- bitwarden-lite/supervisord/sso.ini | 2 +- 12 files changed, 25 insertions(+), 20 deletions(-) diff --git a/bitwarden-lite/Dockerfile b/bitwarden-lite/Dockerfile index 0537b1a2..388edaaa 100644 --- a/bitwarden-lite/Dockerfile +++ b/bitwarden-lite/Dockerfile @@ -242,11 +242,6 @@ RUN mkdir -p /app/Identity RUN mkdir -p /app/Sso RUN mkdir -p /app/Web -# Create soft links for files generated in the entrypoint -RUN ln -s /etc/bitwarden/identity.pfx /app/Identity/identity.pfx -RUN ln -s /etc/bitwarden/identity.pfx /app/Sso/identity.pfx -RUN ln -s /etc/bitwarden/app-id.json /app/Web/app-id.json - # Copy all apps from dotnet-build stage WORKDIR /app COPY --from=dotnet-build /app ./ @@ -254,6 +249,11 @@ COPY --from=dotnet-build /app ./ # Copy Web files from web-setup stage COPY --from=web-setup /tmp/build /app/Web +# Create soft links for files generated in the entrypoint +RUN ln -sf /etc/bitwarden/identity.pfx /app/Identity/identity.pfx +RUN ln -sf /etc/bitwarden/identity.pfx /app/Sso/identity.pfx +RUN ln -sf /etc/bitwarden/Web/app-id.json /app/Web/app-id.json + # Set up supervisord COPY bitwarden-lite/supervisord/*.ini /etc/supervisor.d/ COPY bitwarden-lite/supervisord/supervisord.conf /etc/supervisor/supervisord.conf diff --git a/bitwarden-lite/entrypoint.sh b/bitwarden-lite/entrypoint.sh index ff4fa88c..e2702e73 100755 --- a/bitwarden-lite/entrypoint.sh +++ b/bitwarden-lite/entrypoint.sh @@ -88,18 +88,19 @@ fi /bin/sh -c "/logrotate.sh loop >/dev/null 2>&1 &" # Create necessary directories -mkdir -p /etc/bitwarden/logs/supervisord mkdir -p /etc/bitwarden/logs/nginx +mkdir -p /etc/bitwarden/logs/supervisord mkdir -p /etc/bitwarden/nginx +mkdir -p /etc/bitwarden/Web mkdir -p /tmp/bitwarden /usr/local/bin/hbs if [ "$(id -u)" = "0" ]; then - find /etc/bitwarden ! -xtype l \( ! -gid "$PGID" -o ! -uid "$PUID" \) -exec chown "${PUID}:${PGID}" {} + + find /etc/bitwarden -follow ! -type l \( ! -group "$PGID" -o ! -user "$PUID" \) -exec chown "${PUID}:${PGID}" {} + exec su-exec "$PUID:$PGID" /usr/bin/supervisord else - FILES="$(find /etc/bitwarden ! -xtype l \( ! -gid "$(id -g)" -o ! -uid "$(id -u)" \))" + FILES="$(find /etc/bitwarden -follow ! -type l \( ! -group "$(id -g)" -o ! -user "$(id -u)" \))" if [ -n "$FILES" ]; then echo "The following files are not owned by the running user and may cause errors:" >&2 echo "$FILES" >&2 diff --git a/bitwarden-lite/nginx/nginx.conf b/bitwarden-lite/nginx/nginx.conf index b9104e3a..586a749c 100644 --- a/bitwarden-lite/nginx/nginx.conf +++ b/bitwarden-lite/nginx/nginx.conf @@ -1,6 +1,13 @@ # nginx Configuration File # http://wiki.nginx.org/Configuration +# Default error log file +# (this is only used when you don't override error_log on a server{} level) +# This is placed at the top because the compiled-in log path (/var/lib/nginx/logs/error.log) +# won't be writable in read-only containers. This ensures any errors during startup +# (e.g. configuration errors) will actually be written somewhere +error_log /etc/bitwarden/logs/nginx/error.log warn; + daemon off; # Run as a less privileged user for security reasons. @@ -26,9 +33,6 @@ events { worker_connections 8000; } -# Default error log file -# (this is only used when you don't override error_log on a server{} level) -error_log /etc/bitwarden/logs/nginx/error.log warn; pid /tmp/bitwarden/nginx.pid; http { diff --git a/bitwarden-lite/supervisord/admin.ini b/bitwarden-lite/supervisord/admin.ini index 84f555a3..aeac6425 100644 --- a/bitwarden-lite/supervisord/admin.ini +++ b/bitwarden-lite/supervisord/admin.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5000" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/admin.log +stdout_logfile=/etc/bitwarden/logs/supervisord/admin.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/api.ini b/bitwarden-lite/supervisord/api.ini index a84d36db..953e61ee 100644 --- a/bitwarden-lite/supervisord/api.ini +++ b/bitwarden-lite/supervisord/api.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5001" priority=2 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/api.log +stdout_logfile=/etc/bitwarden/logs/supervisord/api.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/events.ini b/bitwarden-lite/supervisord/events.ini index 80e5112b..1bba7f75 100644 --- a/bitwarden-lite/supervisord/events.ini +++ b/bitwarden-lite/supervisord/events.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5003" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/events.log +stdout_logfile=/etc/bitwarden/logs/supervisord/events.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/icons.ini b/bitwarden-lite/supervisord/icons.ini index be7be324..48b4415c 100644 --- a/bitwarden-lite/supervisord/icons.ini +++ b/bitwarden-lite/supervisord/icons.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5004" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/icons.log +stdout_logfile=/etc/bitwarden/logs/supervisord/icons.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/identity.ini b/bitwarden-lite/supervisord/identity.ini index 662c67ce..7f3cd355 100644 --- a/bitwarden-lite/supervisord/identity.ini +++ b/bitwarden-lite/supervisord/identity.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5005" priority=1 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/identity.log +stdout_logfile=/etc/bitwarden/logs/supervisord/identity.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/nginx.ini b/bitwarden-lite/supervisord/nginx.ini index 98600d0d..c0529a18 100644 --- a/bitwarden-lite/supervisord/nginx.ini +++ b/bitwarden-lite/supervisord/nginx.ini @@ -4,4 +4,4 @@ autorestart=true command=nginx redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/nginx.log +stdout_logfile=/etc/bitwarden/logs/supervisord/nginx.log diff --git a/bitwarden-lite/supervisord/notifications.ini b/bitwarden-lite/supervisord/notifications.ini index 29fae185..d501eb78 100644 --- a/bitwarden-lite/supervisord/notifications.ini +++ b/bitwarden-lite/supervisord/notifications.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5006" priority=3 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/notifications.log +stdout_logfile=/etc/bitwarden/logs/supervisord/notifications.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/scim.ini b/bitwarden-lite/supervisord/scim.ini index 534017ff..f7ff28e3 100644 --- a/bitwarden-lite/supervisord/scim.ini +++ b/bitwarden-lite/supervisord/scim.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5002" priority=4 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/scim.log +stdout_logfile=/etc/bitwarden/logs/supervisord/scim.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 diff --git a/bitwarden-lite/supervisord/sso.ini b/bitwarden-lite/supervisord/sso.ini index 1dc665bc..892eccbe 100644 --- a/bitwarden-lite/supervisord/sso.ini +++ b/bitwarden-lite/supervisord/sso.ini @@ -7,6 +7,6 @@ environment=ASPNETCORE_URLS="http://+:5007" priority=4 redirect_stderr=true startsecs=15 -stdout_logfile=/etc/bitwarden/logs/supervisord/bitwarden/sso.log +stdout_logfile=/etc/bitwarden/logs/supervisord/sso.log stdout_logfile_maxbytes=10485760 stdout_logfile_backups=5 From f72946ec4bc74c8108136decb5d8eb190c42c7ef Mon Sep 17 00:00:00 2001 From: Aram Akhavan Date: Mon, 19 Jan 2026 11:26:18 -0700 Subject: [PATCH 5/6] Update bitwarden-lite/entrypoint.sh Co-authored-by: gitclonebrian <235774926+gitclonebrian@users.noreply.github.com> --- bitwarden-lite/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bitwarden-lite/entrypoint.sh b/bitwarden-lite/entrypoint.sh index e2702e73..995dcb0b 100755 --- a/bitwarden-lite/entrypoint.sh +++ b/bitwarden-lite/entrypoint.sh @@ -24,7 +24,7 @@ export globalSettings__baseServiceUri__vault="${globalSettings__baseServiceUri__ export globalSettings__installation__id="$BW_INSTALLATION_ID" export globalSettings__installation__key="$BW_INSTALLATION_KEY" export globalSettings__internalIdentityKey="${globalSettings__internalIdentityKey:-$INTERNAL_IDENTITY_KEY}" -export globalSettings__oidcIdentityClientKey="{globalSettings__oidcIdentityClientKey:-$OIDC_IDENTITY_CLIENT_KEY}" +export globalSettings__oidcIdentityClientKey="${globalSettings__oidcIdentityClientKey:-$OIDC_IDENTITY_CLIENT_KEY}" export globalSettings__duo__aKey="${globalSettings__duo__aKey:-$DUO_AKEY}" export globalSettings__identityServer__certificatePassword="${globalSettings__identityServer__certificatePassword:-$IDENTITY_SERVER_CERTIFICATE_PASSWORD}" From 3f918f22eef7b24bf3e1d4c1ddfed1cc1395ce5a Mon Sep 17 00:00:00 2001 From: Aram Akhavan Date: Thu, 22 Jan 2026 12:20:01 -0800 Subject: [PATCH 6/6] Update bitwarden-lite/docker-compose.yml Co-authored-by: gitclonebrian <235774926+gitclonebrian@users.noreply.github.com> --- bitwarden-lite/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/bitwarden-lite/docker-compose.yml b/bitwarden-lite/docker-compose.yml index 50900709..9c46fd70 100644 --- a/bitwarden-lite/docker-compose.yml +++ b/bitwarden-lite/docker-compose.yml @@ -56,4 +56,5 @@ services: # - data:/var/opt/mssql volumes: + bitwarden: data: