diff --git a/bitwarden-lite/Dockerfile b/bitwarden-lite/Dockerfile index 045b04c8..388edaaa 100644 --- a/bitwarden-lite/Dockerfile +++ b/bitwarden-lite/Dockerfile @@ -236,16 +236,11 @@ 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 # Copy all apps from dotnet-build stage WORKDIR /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 @@ -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 ad3538c6..55c93d29 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:-2026.1.0} + user: 999:999 + tmpfs: /tmp:rw,noexec,nosuid,nodev,size=512m + 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: @@ -51,5 +57,4 @@ services: volumes: bitwarden: - logs: data: diff --git a/bitwarden-lite/entrypoint.sh b/bitwarden-lite/entrypoint.sh index dd62f6c1..995dcb0b 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} @@ -18,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 @@ -49,33 +52,31 @@ 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 +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 \ -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 +87,24 @@ 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/nginx +mkdir -p /etc/bitwarden/logs/supervisord +mkdir -p /etc/bitwarden/nginx +mkdir -p /etc/bitwarden/Web +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 - exec su-exec $PUID:$PGID /usr/bin/supervisord +if [ "$(id -u)" = "0" ]; then + 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 -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 + 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..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,15 +33,19 @@ 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 /var/log/nginx/error.log warn; -pid /var/run/nginx/nginx.pid; +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 +73,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 5812fccf..6dceb764 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..aeac6425 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/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..953e61ee 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/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..1bba7f75 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/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..48b4415c 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/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..7f3cd355 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/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..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=/var/log/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 e87c7e0d..d501eb78 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/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..f7ff28e3 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/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..892eccbe 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/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