diff --git a/.github/workflows/build-bitwarden-lite.yml b/.github/workflows/build-bitwarden-lite.yml index 0ed2c2f..43013c5 100644 --- a/.github/workflows/build-bitwarden-lite.yml +++ b/.github/workflows/build-bitwarden-lite.yml @@ -5,6 +5,8 @@ on: paths: - "bitwarden-lite/**" - ".github/workflows/build-bitwarden-lite.yml" + branches: + - main workflow_dispatch: inputs: self_host_repo_ref: @@ -165,66 +167,31 @@ jobs: echo "Using $IMAGE_TAG for build" echo "image_tag=${IMAGE_TAG}" >> "$GITHUB_OUTPUT" - - name: Log in to Azure - uses: bitwarden/gh-actions/azure-login@main - with: - subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - tenant_id: ${{ secrets.AZURE_TENANT_ID }} - client_id: ${{ secrets.AZURE_CLIENT_ID }} - - - name: Get Azure Key Vault secrets - id: get-kv-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@main - with: - keyvault: gh-org-bitwarden - secrets: "BW-GHAPP-ID,BW-GHAPP-KEY" - - - name: Log out from Azure - uses: bitwarden/gh-actions/azure-logout@main - - - name: Generate GH App token - uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0 - id: app-token - with: - app-id: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-ID }} - private-key: ${{ steps.get-kv-secrets.outputs.BW-GHAPP-KEY }} - permission-actions: read # for downloading workflow run artifacts - permission-contents: read # for checking out repos - - - name: Checkout server repo - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - repository: bitwarden/server - token: ${{ steps.app-token.outputs.token }} - ref: ${{ needs.setup.outputs.server_ref }} - path: "server" - persist-credentials: false - - - name: Download web client branch artifacts for dev builds - if: ${{ !inputs.use_latest_web_version }} - uses: bitwarden/gh-actions/download-artifacts@main - with: - github_token: ${{ steps.app-token.outputs.token }} - workflow: build-web.yml - workflow_conclusion: success - branch: ${{ needs.setup.outputs.web_ref }} - repo: bitwarden/clients - artifacts: "web-*-selfhosted-DEV.zip" - if_no_artifact_found: fail - - - name: Set web artifact path for dev builds - if: ${{ !inputs.use_latest_web_version }} - id: set-web-artifact-path - run: echo "path=$(find . -name "web-*-selfhosted-DEV.zip" | head -1)" >> "$GITHUB_OUTPUT" + - name: Generate web image tag + id: web-tag + env: + WEB_REF: ${{ needs.setup.outputs.web_ref }} + run: | + if [[ $WEB_REF =~ ^refs/tags/web-v(.+)$ ]]; then + WEB_TAG="${BASH_REMATCH[1]}" + else + WEB_TAG=$(echo "${WEB_REF#refs/heads/}" | \ + tr '[:upper:]' '[:lower:]' | \ + sed -E 's/[^a-z0-9._-]+/-/g; s/-+/-/g; s/^-+|-+$//g' | \ + cut -c1-128 | \ + sed -E 's/[.-]$//') + [[ "$WEB_TAG" == "main" ]] && WEB_TAG=dev + fi + echo "web_tag=${WEB_TAG}" >> "$GITHUB_OUTPUT" - name: Log build configuration env: - SERVER_REF: ${{ needs.setup.outputs.server_ref }} - WEB_REF: ${{ needs.setup.outputs.web_ref }} + SERVER_TAG: ${{ steps.tag.outputs.image_tag }} + WEB_TAG: ${{ steps.web-tag.outputs.web_tag }} run: | echo "### Build Configuration" >> $GITHUB_STEP_SUMMARY - echo "- Server: ${SERVER_REF}" >> $GITHUB_STEP_SUMMARY - echo "- Web: ${WEB_REF}" >> $GITHUB_STEP_SUMMARY + echo "- Server: ghcr.io/bitwarden/\*:${SERVER_TAG}" >> $GITHUB_STEP_SUMMARY + echo "- Web: ghcr.io/bitwarden/web:${WEB_TAG}" >> $GITHUB_STEP_SUMMARY - name: Build and push Docker image id: build-docker @@ -239,7 +206,10 @@ jobs: push: true tags: ghcr.io/bitwarden/lite:${{ steps.tag.outputs.image_tag }} build-args: | - WEB_ARTIFACT_PATH=${{ steps.set-web-artifact-path.outputs.path }} + SERVER_TAG=${{ steps.tag.outputs.image_tag }} + WEB_TAG=${{ steps.web-tag.outputs.web_tag }} + cache-from: type=gha + cache-to: type=gha,mode=min - name: Install Cosign uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 diff --git a/bitwarden-lite/Dockerfile b/bitwarden-lite/Dockerfile index 3d296b4..0a9349f 100644 --- a/bitwarden-lite/Dockerfile +++ b/bitwarden-lite/Dockerfile @@ -1,186 +1,23 @@ # syntax = docker/dockerfile:1.21 -############################################### -# Build stage # -############################################### -FROM --platform=$BUILDPLATFORM alpine:3.23 AS web-setup -ARG WEB_ARTIFACT_PATH - -# Add packages -RUN apk add --no-cache \ - curl \ - jq \ - unzip \ - git - -WORKDIR /tmp - -# Grab last tag/release of the 'web' client -RUN if [ -z "${WEB_ARTIFACT_PATH}" ]; then \ - git ls-remote --tags https://github.com/bitwarden/clients.git \ - | grep -E 'refs/tags/web-v[0-9]{4}\.([1-9]|1[0-2])\.[0-9]+' \ - | cut -d/ -f3 | sort -Vr | head -1 > tag.txt; \ - fi - -# Extract the version of the 'web' client -RUN if [ -z "${WEB_ARTIFACT_PATH}" ]; then \ - cat tag.txt | grep -o -E '[0-9]{4}\.([1-9]|1[0-2])\.[0-9]+' > version.txt; \ - fi - -# Download the built release artifact for the 'web' client -RUN if [ -z "${WEB_ARTIFACT_PATH}" ]; then \ - TAG=$(cat tag.txt) \ - && VERSION=$(cat version.txt) \ - && curl --proto "=https" -L https://github.com/bitwarden/clients/releases/download/$TAG/web-$VERSION-selfhosted-COMMERCIAL.zip -O; \ - fi - -# Copy provided web artifact if available -COPY ${WEB_ARTIFACT_PATH}* /tmp/ - -# Unzip the 'web' client to /tmp/build -RUN if [ -z "${WEB_ARTIFACT_PATH}" ]; then \ - VERSION=$(cat version.txt) \ - && unzip web-$VERSION-selfhosted-COMMERCIAL.zip; \ - else \ - unzip ${WEB_ARTIFACT_PATH} -d /tmp/; \ - fi +ARG SERVER_TAG=dev +ARG WEB_TAG=dev ############################################### -# Build stage # +# Web app stage # ############################################### -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine3.21 AS dotnet-build +FROM ghcr.io/bitwarden/web:${WEB_TAG} AS web-app -# Docker buildx supplies the value for this arg -ARG TARGETPLATFORM - -# Determine proper runtime value for .NET -# We put the value in a file to be read by later layers. -RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \ - RID=linux-musl-x64 ; \ - elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \ - RID=linux-musl-arm64 ; \ - elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \ - RID=linux-musl-arm ; \ - fi \ - && echo "RID=$RID" > /tmp/rid.txt - -# Add packages -RUN apk add --no-cache \ - npm - -# Copy csproj files as distinct layers -WORKDIR /source -COPY server/src/Admin/*.csproj ./src/Admin/ -COPY server/src/Api/*.csproj ./src/Api/ -COPY server/src/Events/*.csproj ./src/Events/ -COPY server/src/Icons/*.csproj ./src/Icons/ -COPY server/src/Identity/*.csproj ./src/Identity/ -COPY server/src/Notifications/*.csproj ./src/Notifications/ -COPY server/bitwarden_license/src/Sso/*.csproj ./bitwarden_license/src/Sso/ -COPY server/bitwarden_license/src/Scim/*.csproj ./bitwarden_license/src/Scim/ -COPY server/src/Core/*.csproj ./src/Core/ -COPY server/src/Infrastructure.Dapper/*.csproj ./src/Infrastructure.Dapper/ -COPY server/src/Infrastructure.EntityFramework/*.csproj ./src/Infrastructure.EntityFramework/ -COPY server/src/SharedWeb/*.csproj ./src/SharedWeb/ -COPY server/util/Migrator/*.csproj ./util/Migrator/ -COPY server/util/MySqlMigrations/*.csproj ./util/MySqlMigrations/ -COPY server/util/PostgresMigrations/*.csproj ./util/PostgresMigrations/ -COPY server/util/SqliteMigrations/*.csproj ./util/SqliteMigrations/ -COPY server/bitwarden_license/src/Commercial.Core/*.csproj ./bitwarden_license/src/Commercial.Core/ -COPY server/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/*.csproj ./bitwarden_license/src/Commercial.Infrastructure.EntityFramework/ -COPY server/Directory.Build.props . -COPY server/.editorconfig . -COPY server/global.json . - -# Restore Admin project dependencies and tools -WORKDIR /source/src/Admin -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Api project dependencies and tools -WORKDIR /source/src/Api -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Events project dependencies and tools -WORKDIR /source/src/Events -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Icons project dependencies and tools -WORKDIR /source/src/Icons -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Identity project dependencies and tools -WORKDIR /source/src/Identity -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Notifications project dependencies and tools -WORKDIR /source/src/Notifications -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Sso project dependencies and tools -WORKDIR /source/bitwarden_license/src/Sso -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Scim project dependencies and tools -WORKDIR /source/bitwarden_license/src/Scim -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Copy required project files -WORKDIR /source -COPY server/src/Admin/. ./src/Admin/ -COPY server/src/Api/. ./src/Api/ -COPY server/src/Events/. ./src/Events/ -COPY server/src/Icons/. ./src/Icons/ -COPY server/src/Identity/. ./src/Identity/ -COPY server/src/Notifications/. ./src/Notifications/ -COPY server/bitwarden_license/src/Sso/. ./bitwarden_license/src/Sso/ -COPY server/bitwarden_license/src/Scim/. ./bitwarden_license/src/Scim/ -COPY server/src/Core/. ./src/Core/ -COPY server/src/Infrastructure.Dapper/. ./src/Infrastructure.Dapper/ -COPY server/src/Infrastructure.EntityFramework/. ./src/Infrastructure.EntityFramework/ -COPY server/src/SharedWeb/. ./src/SharedWeb/ -COPY server/util/Migrator/. ./util/Migrator/ -COPY server/util/MySqlMigrations/. ./util/MySqlMigrations/ -COPY server/util/PostgresMigrations/. ./util/PostgresMigrations/ -COPY server/util/SqliteMigrations/. ./util/SqliteMigrations/ -COPY server/util/EfShared/. ./util/EfShared/ -COPY server/bitwarden_license/src/Commercial.Core/. ./bitwarden_license/src/Commercial.Core/ -COPY server/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/. ./bitwarden_license/src/Commercial.Infrastructure.EntityFramework/ -COPY server/.git/. ./.git/ - -# Build Admin app -WORKDIR /source/src/Admin -RUN npm install -RUN npm run build -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Admin --no-restore --no-self-contained -r $RID - -# Build Api app -WORKDIR /source/src/Api -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Api --no-restore --no-self-contained -r $RID - -# Build Events app -WORKDIR /source/src/Events -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Events --no-restore --no-self-contained -r $RID - -# Build Icons app -WORKDIR /source/src/Icons -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Icons --no-restore --no-self-contained -r $RID - -# Build Identity app -WORKDIR /source/src/Identity -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Identity --no-restore --no-self-contained -r $RID - -# Build Notifications app -WORKDIR /source/src/Notifications -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Notifications --no-restore --no-self-contained -r $RID - -# Build Sso app -WORKDIR /source/bitwarden_license/src/Sso -RUN npm install -RUN npm run build -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Sso --no-restore --no-self-contained -r $RID - -# Build Scim app -WORKDIR /source/bitwarden_license/src/Scim -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Scim --no-restore --no-self-contained -r $RID +############################################### +# Server app stages # +############################################### +FROM ghcr.io/bitwarden/admin:${SERVER_TAG} AS admin-app +FROM ghcr.io/bitwarden/api:${SERVER_TAG} AS api-app +FROM ghcr.io/bitwarden/events:${SERVER_TAG} AS events-app +FROM ghcr.io/bitwarden/icons:${SERVER_TAG} AS icons-app +FROM ghcr.io/bitwarden/identity:${SERVER_TAG} AS identity-app +FROM ghcr.io/bitwarden/notifications:${SERVER_TAG} AS notifications-app +FROM ghcr.io/bitwarden/scim:${SERVER_TAG} AS scim-app +FROM ghcr.io/bitwarden/sso:${SERVER_TAG} AS sso-app ############################################### # App stage # @@ -235,26 +72,34 @@ RUN apk add --no-cache \ gcompat # Create required directories -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 \ + /etc/bitwarden/attachments/send \ + /etc/bitwarden/data-protection \ + /etc/bitwarden/licenses \ + /etc/bitwarden/logs \ + /etc/supervisor \ + /etc/supervisor.d \ + /var/log/bitwarden \ + /var/log/nginx/logs \ + /etc/nginx/http.d \ + /var/run/nginx \ + /var/lib/nginx/tmp \ + /app \ + && touch /var/run/nginx/nginx.pid -# Copy all apps from dotnet-build stage +# Copy compiled apps from server images WORKDIR /app -COPY --from=dotnet-build /app ./ +COPY --from=admin-app /app /app/Admin +COPY --from=api-app /app /app/Api +COPY --from=events-app /app /app/Events +COPY --from=icons-app /app /app/Icons +COPY --from=identity-app /app /app/Identity +COPY --from=notifications-app /app /app/Notifications +COPY --from=scim-app /app /app/Scim +COPY --from=sso-app /app /app/Sso -# Copy Web files from web-setup stage -COPY --from=web-setup /tmp/build /app/Web +# Copy Web files from web-app stage +COPY --from=web-app /app /app/Web # Set up supervisord COPY bitwarden-lite/supervisord/*.ini /etc/supervisor.d/ diff --git a/bitwarden-lite/supervisord/admin.ini b/bitwarden-lite/supervisord/admin.ini index 7e52170..b8e128f 100644 --- a/bitwarden-lite/supervisord/admin.ini +++ b/bitwarden-lite/supervisord/admin.ini @@ -1,7 +1,7 @@ [program:admin] autostart=true autorestart=true -command=/usr/bin/dotnet "Admin.dll" +command=/app/Admin/Admin directory=/app/Admin environment=ASPNETCORE_URLS="http://+:5000" priority=3 diff --git a/bitwarden-lite/supervisord/api.ini b/bitwarden-lite/supervisord/api.ini index f0081d9..58aceff 100644 --- a/bitwarden-lite/supervisord/api.ini +++ b/bitwarden-lite/supervisord/api.ini @@ -1,7 +1,7 @@ [program:api] autostart=true autorestart=true -command=/usr/bin/dotnet "Api.dll" +command=/app/Api/Api directory=/app/Api environment=ASPNETCORE_URLS="http://+:5001" priority=2 diff --git a/bitwarden-lite/supervisord/events.ini b/bitwarden-lite/supervisord/events.ini index 4a772a5..824793d 100644 --- a/bitwarden-lite/supervisord/events.ini +++ b/bitwarden-lite/supervisord/events.ini @@ -1,7 +1,7 @@ [program:events] autostart=true autorestart=true -command=/usr/bin/dotnet "Events.dll" +command=/app/Events/Events directory=/app/Events environment=ASPNETCORE_URLS="http://+:5003" priority=3 diff --git a/bitwarden-lite/supervisord/icons.ini b/bitwarden-lite/supervisord/icons.ini index dad5883..68e8af0 100644 --- a/bitwarden-lite/supervisord/icons.ini +++ b/bitwarden-lite/supervisord/icons.ini @@ -1,7 +1,7 @@ [program:icons] autostart=true autorestart=true -command=/usr/bin/dotnet "Icons.dll" +command=/app/Icons/Icons directory=/app/Icons environment=ASPNETCORE_URLS="http://+:5004" priority=3 diff --git a/bitwarden-lite/supervisord/identity.ini b/bitwarden-lite/supervisord/identity.ini index cb0268f..e95eb4b 100644 --- a/bitwarden-lite/supervisord/identity.ini +++ b/bitwarden-lite/supervisord/identity.ini @@ -1,7 +1,7 @@ [program:identity] autostart=true autorestart=true -command=/usr/bin/dotnet "Identity.dll" +command=/app/Identity/Identity directory=/app/Identity environment=ASPNETCORE_URLS="http://+:5005" priority=1 diff --git a/bitwarden-lite/supervisord/notifications.ini b/bitwarden-lite/supervisord/notifications.ini index e87c7e0..dfc3b91 100644 --- a/bitwarden-lite/supervisord/notifications.ini +++ b/bitwarden-lite/supervisord/notifications.ini @@ -1,7 +1,7 @@ [program:notifications] autostart=true autorestart=true -command=/usr/bin/dotnet "Notifications.dll" +command=/app/Notifications/Notifications directory=/app/Notifications environment=ASPNETCORE_URLS="http://+:5006" priority=3 diff --git a/bitwarden-lite/supervisord/scim.ini b/bitwarden-lite/supervisord/scim.ini index f64d67d..c98766e 100644 --- a/bitwarden-lite/supervisord/scim.ini +++ b/bitwarden-lite/supervisord/scim.ini @@ -1,7 +1,7 @@ [program:scim] autostart=true autorestart=true -command=/usr/bin/dotnet "Scim.dll" +command=/app/Scim/Scim directory=/app/Scim environment=ASPNETCORE_URLS="http://+:5002" priority=4 diff --git a/bitwarden-lite/supervisord/sso.ini b/bitwarden-lite/supervisord/sso.ini index a0ba657..183a163 100644 --- a/bitwarden-lite/supervisord/sso.ini +++ b/bitwarden-lite/supervisord/sso.ini @@ -1,7 +1,7 @@ [program:sso] autostart=true autorestart=true -command=/usr/bin/dotnet "Sso.dll" +command=/app/Sso/Sso directory=/app/Sso environment=ASPNETCORE_URLS="http://+:5007" priority=4