From a012744e44f6ba9bad1b4ca7e92ae71e1304bb1e Mon Sep 17 00:00:00 2001 From: Schreiber Date: Mon, 4 May 2026 17:43:06 -0700 Subject: [PATCH 1/6] reset --- docker-compose.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 38ac189..0d7f5dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: - net env_file: sublime.env environment: - MANTIS_HOST_URL: "http://host.docker.internal:8000" + MANTIS_HOST_URL: "http://sublime_mantis:8000" sublime_redis: image: redis:6.2 restart: unless-stopped @@ -177,18 +177,6 @@ services: /usr/bin/mc ls myminio; exit 0; " - sublime_hydra: - image: sublimesec/hydra-cpu:dev - restart: unless-stopped - ports: - - "8200:8200" - networks: - - net - container_name: sublime_hydra - environment: - WORKERS: 2 - WEB_CONCURRENCY: 5 - KEEP_ALIVE: 2 sublime_localstack: container_name: sublime_localstack image: localstack/localstack:4.10.0 From 864b64a7316c41055f15e36553c838154b410ede Mon Sep 17 00:00:00 2001 From: Schreiber Date: Tue, 5 May 2026 08:45:42 -0700 Subject: [PATCH 2/6] fix --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0d7f5dd..282308e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: - net env_file: sublime.env environment: - MANTIS_HOST_URL: "http://sublime_mantis:8000" + MANTIS_HOST_URL: "http://host.docker.internal:8000" sublime_redis: image: redis:6.2 restart: unless-stopped From 7650c4190739588278b3be791f17ee2f0f39523c Mon Sep 17 00:00:00 2001 From: Schreiber Date: Tue, 5 May 2026 11:47:09 -0700 Subject: [PATCH 3/6] use different volume --- docker-compose.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 282308e..0a12340 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,19 +1,19 @@ services: - sublime_postgres: - image: postgres:13.2 + sublime_postgres: + image: postgres:13.2 restart: unless-stopped - container_name: sublime_postgres - environment: + container_name: sublime_postgres + environment: POSTGRES_USER: sublime POSTGRES_DB: mantis PGDATA: /data/postgres env_file: sublime.env - volumes: - - postgres:/data/postgres - ports: + volumes: + - postgres_e2e:/data/postgres # different volume than dev to avoid overwriting data + ports: - "5432:5432" - networks: - - net + networks: + - net sublime_dashboard: image: sublimesec/dashboard:dev restart: unless-stopped @@ -195,7 +195,7 @@ networks: net: driver: bridge volumes: - postgres: + postgres_e2e: logs: s3_data: localstack: From 2f32d6e7db65b426cfb1bd693cd4ba3233d3328b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 14 Sep 2026 22:39:41 +0000 Subject: [PATCH 4/6] Sync from 824a55c31f914af6b478a611c675552907eec82e --- .github/dependabot.yml | 14 ++ .github/workflows/docker-deploy-dev.yml | 14 +- .github/workflows/docker-tests.yml | 49 ---- .gitignore | 1 + LICENSE | 2 +- README.md | 29 ++- assets/sublime-logo.png | Bin 0 -> 32202 bytes docker-compose.yml | 292 +++++++++++++++++------- install-and-launch.sh | 12 +- nginx-custom-ssl/Dockerfile | 9 + nginx-custom-ssl/README.md | 12 + nginx-custom-ssl/certs/.keep | 0 nginx-custom-ssl/conf/nginx.conf | 57 +++++ nginx-custom-ssl/conf/ssl-params.conf | 20 ++ nginx-letsencrypt/Dockerfile | 2 +- nginx-letsencrypt/nginx.conf | 2 + nginx-letsencrypt/start.sh | 2 +- update-and-run.sh | 10 +- utils.sh | 5 + 19 files changed, 368 insertions(+), 164 deletions(-) create mode 100644 .github/dependabot.yml delete mode 100644 .github/workflows/docker-tests.yml create mode 100644 assets/sublime-logo.png create mode 100644 nginx-custom-ssl/Dockerfile create mode 100644 nginx-custom-ssl/README.md create mode 100644 nginx-custom-ssl/certs/.keep create mode 100644 nginx-custom-ssl/conf/nginx.conf create mode 100644 nginx-custom-ssl/conf/ssl-params.conf diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0414fe9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + cooldown: + default-days: 7 diff --git a/.github/workflows/docker-deploy-dev.yml b/.github/workflows/docker-deploy-dev.yml index 3d54b47..b475d7e 100644 --- a/.github/workflows/docker-deploy-dev.yml +++ b/.github/workflows/docker-deploy-dev.yml @@ -12,23 +12,25 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v2 + uses: actions/checkout@v6 + with: + persist-credentials: false - name: Login to DockerHub - uses: docker/login-action@v1 + uses: docker/login-action@v4.1.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v4 with: driver: docker - - name: Build letsencrypt - id: build-letsencrypt - uses: docker/build-push-action@v2 + - name: Build mantis + id: build-mantis + uses: docker/build-push-action@v7.1.0 with: push: true tags: sublimesec/nginx-letsencrypt:latest diff --git a/.github/workflows/docker-tests.yml b/.github/workflows/docker-tests.yml deleted file mode 100644 index 3134b37..0000000 --- a/.github/workflows/docker-tests.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Platform PR CI - -on: - push: - branches: [ "**" ] - workflow_dispatch: {} - -concurrency: - group: ${{ github.ref }} - cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} - -jobs: - tests: - name: Validate Platform Installation - runs-on: ubuntu-22.04 - - permissions: - id-token: write - contents: read - - steps: - - name: Checkout - uses: actions/checkout@v3 - - # main should never require private images - - name: Configure AWS Credentials - if: github.ref != 'refs/heads/main' - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: arn:aws:iam::948971135452:role/ci-sublime-platform-ecr-read - aws-region: us-east-1 - - - name: Login to Amazon ECR - if: github.ref != 'refs/heads/main' - uses: aws-actions/amazon-ecr-login@v2 - with: - registries: "948971135452" - - - name: Make ECR credentials available to sudo - if: github.ref != 'refs/heads/main' - run: sudo cp -r $HOME/.docker /root/ - - - name: Install Platform - run: | - interactive=false clone_platform=false ./install-and-launch.sh - - - name: Check Health - run: | - ./postflight_checks.sh diff --git a/.gitignore b/.gitignore index b3e9a4d..5333d47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ certbot.env sublime.env *.swp +.DS_Store diff --git a/LICENSE b/LICENSE index 90933c4..574d1b1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Sublime Security +Copyright (c) 2021-2026 Sublime Security Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index e18fce1..14ebf1e 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,43 @@ - Sublime Logo + Sublime Logo Sublime Platform ========== -by Sublime Security +by [Sublime Security](https://sublime.security/) Overview --------- -An open, adaptable email security platform for writing, running, and sharing custom detection and response rules to block phishing attacks, hunt for threats, and more. +A free and open platform for detecting and preventing email attacks like BEC, malware, and credential phishing. Gain visibility and control, hunt for advanced threats, and collaborate with the community. -Why? +Sublime uses Message Query Language (MQL), a domain-specific language purpose-built for describing behavior in email. MQL is email provider agnostic, enabling defenders to write, run, and share Detections-as-Code. + +Learn more about MQL: [Introduction to Message Query Language](https://sublime.security/blog/introduction-to-message-query-language-mql) + +Docker Usage & Caveats ---------- -Traditional email security is a one-size-fits-all black box. +This Docker deployment is intended for small-medium size deployments and for testing purposes ONLY (limited to 100 active mailboxes). For the best Sublime experience, we recommend the [AWS Cloud-native deployment](https://docs.sublime.security/docs/aws-cloudformation) or [Sublime Managed Cloud](https://docs.sublime.security/docs/sublime-managed), which can support any number of mailboxes, is resilient, and has the latest features. The docker deployment allows you to gain hands on experience, but will only receive best effort support (no long term support). + +[Learn more about feature restrictions for Docker Compose](https://docs.sublime.security/docs/docker-requirements-and-limitations) -The Sublime Platform **gives defenders control over their email environment** and uses an intuitive, interoperable, purpose-built domain-specific language (DSL). +The Sublime Platform Docker Compose ships as an entire setup. Modifying the docker-compose file or using our docker images within your own implementation is not supported. Setup ---------- ```console -curl -sL https://sublime.security/install.sh | sh +curl -sL https://raw.githubusercontent.com/sublime-security/sublime-platform/main/install-and-launch.sh | sh ``` [View Docker Quickstart](https://docs.sublimesecurity.com/docs/quickstart-docker) +[View other deployment methods](https://sublime.security/start) + Detection rules ---------- -Open-source detection rules are maintained in the [sublime-rules repo](https://github.com/sublime-security/sublime-rules). - +Open-source detection rules and links to community Feeds are maintained in the [sublime-rules repo](https://github.com/sublime-security/sublime-rules). Learn more ---------- -- [Sublime overview](https://sublime.security) - [Docs](https://docs.sublimesecurity.com) -- [Message Query Language (MQL) reference](https://docs.sublimesecurity.com/docs/message-query-language) - Sublime's DSL purpose-built for email analysis +- [API](https://docs.sublimesecurity.com/reference/introduction) - [Release log](https://new.sublimesecurity.com) +- [Message Query Language (MQL)](https://docs.sublimesecurity.com/docs/message-query-language) diff --git a/assets/sublime-logo.png b/assets/sublime-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a666a4825b37bdcdf153ad459e0cc2390c3b5f GIT binary patch literal 32202 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

a#)23gDe~{(tLQPfay~#BtmaeZ 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 TWK2N?0e|vuRHVx!O#=TP^sXBj literal 0 HcmV?d00001 diff --git a/docker-compose.yml b/docker-compose.yml index 0a12340..2c6d95f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,60 +1,44 @@ services: - sublime_postgres: - image: postgres:13.2 + sublime_postgres: + image: postgres:13.2 + command: -c 'max_connections=200' restart: unless-stopped - container_name: sublime_postgres - environment: + container_name: sublime_postgres + environment: POSTGRES_USER: sublime POSTGRES_DB: mantis PGDATA: /data/postgres env_file: sublime.env - volumes: - - postgres_e2e:/data/postgres # different volume than dev to avoid overwriting data - ports: - - "5432:5432" - networks: - - net + volumes: + - postgres_e2e:/data/postgres # different volume than dev-be to avoid overwriting data + networks: + - net + ports: + - 5432:5432 sublime_dashboard: image: sublimesec/dashboard:dev restart: unless-stopped container_name: sublime_dashboard ports: - - "0.0.0.0:3000:80" + - 0.0.0.0:3000:80 networks: - net env_file: sublime.env environment: - MANTIS_HOST_URL: "http://host.docker.internal:8000" + MANTIS_HOST_URL: http://host.docker.internal:8000 sublime_redis: image: redis:6.2 restart: unless-stopped container_name: sublime_redis command: redis-server --loglevel warning - ports: - - "6379:6379" networks: - net - sublime_nipper: - image: 948971135452.dkr.ecr.us-east-1.amazonaws.com/nipper-python-dev:dev - restart: unless-stopped - container_name: sublime_nipper - env_file: sublime.env ports: - - "8300:8000" - networks: - - net - environment: - NIPPER_BUCKET: "nipper-artifacts" - BUCKET_ENDPOINT_URL: "http://sublimes3:8110" - DD_TRACE_ENABLED: false - depends_on: - - sublime_create_buckets + - 6379:6379 sublime_strelka_frontend: image: sublimesec/strelka-frontend:0.3 restart: unless-stopped command: strelka-frontend - ports: - - "57314:57314" networks: - net volumes: @@ -64,6 +48,8 @@ services: - sublime_strelka_coordinator deploy: replicas: 1 + ports: + - 57314:57314 sublime_strelka_backend: image: sublimesec/strelka-backend:0.3 restart: unless-stopped @@ -96,93 +82,204 @@ services: networks: - net sublime_screenshot_service: - image: sublimesec/render-email-html:0.1 + image: sublimesec/render-email-html:0.2 restart: unless-stopped - ports: - - "8100:8100" environment: - S3_ENDPOINT=http://sublimes3:8110 - SCREENSHOT_BUCKET=email-screenshots - AWS_REGION=us-east-1 - DISABLE_DD=true container_name: sublime_screenshot_service - env_file: sublime.env networks: - net + ports: + - 8100:8100 + env_file: sublime.env depends_on: - sublime_create_buckets - sublime_azurite: - container_name: sublime_azurite - image: mcr.microsoft.com/azure-storage/azurite - restart: unless-stopped - networks: - - net - ports: - - "10000:10000" # Blob service - - "10001:10001" # Queue service - - "10002:10002" # Table service - volumes: - - azurite_data:/data - command: azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --location /data --skipApiVersionCheck - sublime_create_azure_blob_containers: - image: mcr.microsoft.com/azure-cli - depends_on: - - sublime_azurite + # cgr.dev/chainguard/minio has no shell, so anything needing one - fixing up volume + # ownership for minio's non-root UID, and writing MINIO_ROOT_USER/PASSWORD out to files from + # the AWS_* vars already in sublime.env - happens here instead, before minio itself starts. + sublimes3_init: + image: busybox + container_name: sublimes3_init networks: - net - environment: - AZURE_STORAGE_CONNECTION_STRING: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://sublime_azurite:10000/devstoreaccount1;" - command: > - bash -c " - az storage container create --name email-screenshots && - az storage container create --name events && - az storage container create --name message-storage && - az storage container create --name message-export && - az storage container create --name nipper-artifacts - " + env_file: sublime.env + volumes: + - s3_data:/data + - s3_creds:/creds + command: + - sh + - -c + - | + printf '%s' "$$AWS_ACCESS_KEY_ID" > /creds/root_user && printf '%s' "$$AWS_SECRET_ACCESS_KEY" > /creds/root_password && chmod 400 /creds/root_user /creds/root_password && chown -R 65532:65532 /creds /data # Keep this name as sublimes3 because underscores don't play nice with certain endpoint validation sublimes3: container_name: sublimes3 - image: minio/minio + image: cgr.dev/chainguard/minio:latest restart: unless-stopped networks: - net - ports: - - "8110:8110" volumes: - s3_data:/data + - s3_creds:/creds:ro + environment: + MINIO_ROOT_USER_FILE: /creds/root_user + MINIO_ROOT_PASSWORD_FILE: /creds/root_password + depends_on: + sublimes3_init: + condition: service_completed_successfully + command: + - server + - --address + - 0.0.0.0:8110 + - --console-address + - 0.0.0.0:8111 + - /data + ports: + - 8110:8110 + # cgr.dev/chainguard/minio-client has no shell, so it can't run `mc alias set` (which needs + # shell interpolation of the AWS_* secrets into CLI args), and we don't want that secret ever + # needing to land in sublime.env either. This throwaway busybox step hand-writes mc's + # config.json straight from the AWS_* vars already in sublime.env; chainguard's mc then just + # reads it via MC_CONFIG_DIR below. mc still needs to create its own share/certs scratch dirs + # under this path at runtime, so the volume can't be mounted read-only. + sublime_mc_config: + image: busybox + depends_on: + - sublimes3 + networks: + - net env_file: sublime.env - entrypoint: > - /bin/sh -c " - export MINIO_ROOT_USER=$$AWS_ACCESS_KEY_ID; - export MINIO_ROOT_PASSWORD=$$AWS_SECRET_ACCESS_KEY; - minio server --address 0.0.0.0:8110 --console-address 0.0.0.0:8111 /data; - " + volumes: + - mc_config:/config + command: + - sh + - -c + - | + cat > /config/config.json <&2; exit 1; fi; sleep 2; done + sublime_nipper: + image: 948971135452.dkr.ecr.us-east-1.amazonaws.com/nipper-python-dev:dev + restart: unless-stopped + container_name: sublime_nipper env_file: sublime.env - entrypoint: > - /bin/sh -c " - sleep 15; - /usr/bin/mc alias set myminio http://sublimes3:8110 $$AWS_ACCESS_KEY_ID $$AWS_SECRET_ACCESS_KEY; - /usr/bin/mc mb myminio/email-screenshots; - /usr/bin/mc mb myminio/events; - /usr/bin/mc mb myminio/message-storage; - /usr/bin/mc mb myminio/message-export; - /usr/bin/mc mb myminio/nipper-artifacts; - /usr/bin/mc ls myminio; - exit 0; - " + ports: + - 8300:8000 + networks: + - net + environment: + NIPPER_BUCKET: nipper-artifacts + BUCKET_ENDPOINT_URL: http://sublimes3:8110 + TIKA_ENDPOINT: http://sublime_tika:9998 + DD_TRACE_ENABLED: false + depends_on: + - sublime_create_buckets + - sublime_tika + sublime_tika: + image: apache/tika:3.3.1.0-full + restart: unless-stopped + container_name: sublime_tika + ports: + - 9998:9998 + networks: + - net + sublime_azurite: + container_name: sublime_azurite + image: mcr.microsoft.com/azure-storage/azurite + restart: unless-stopped + networks: + - net + ports: + - 10000:10000 # Blob service + - 10001:10001 # Queue service + - 10002:10002 # Table service + volumes: + - azurite_data:/data + command: azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0 --location /data --skipApiVersionCheck + sublime_create_azure_blob_containers: + image: mcr.microsoft.com/azure-cli + depends_on: + - sublime_azurite + networks: + - net + environment: + # Azurite's well-known, publicly documented emulator account key - not a real secret. + AZURE_STORAGE_CONNECTION_STRING: DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://sublime_azurite:10000/devstoreaccount1; + command: | + bash -c " az storage container create --name email-screenshots && az storage container create --name events && az storage container create --name message-storage && az storage container create --name message-export && az storage container create --name nipper-artifacts " sublime_localstack: container_name: sublime_localstack image: localstack/localstack:4.10.0 ports: - - "127.0.0.1:4566:4566" # LocalStack Gateway - - "127.0.0.1:4510-4559:4510-4559" # external services port range + - 127.0.0.1:4566:4566 # LocalStack Gateway + - 127.0.0.1:4510-4559:4510-4559 # external services port range networks: - net environment: @@ -190,13 +287,32 @@ services: - DEBUG=0 volumes: - localstack:/var/lib/localstack - + # docker compose up --wait treats any container it doesn't already expect to exit as failed the + # moment it exits, even with code 0 (https://github.com/docker/compose/issues/10596). Neither + # sublime_create_buckets nor sublime_create_azure_blob_containers has a dependent declared with + # condition: service_completed_successfully, so --wait has no way to know their exit is expected. + # This long-running sentinel supplies that dependent so --wait treats their completion as success. + sublime_storage_ready: + image: alpine:3.20 + command: + - tail + - -f + - /dev/null + networks: + - net + depends_on: + sublime_create_buckets: + condition: service_completed_successfully + sublime_create_azure_blob_containers: + condition: service_completed_successfully networks: net: driver: bridge volumes: - postgres_e2e: logs: s3_data: + s3_creds: + mc_config: localstack: azurite_data: + postgres_e2e: diff --git a/install-and-launch.sh b/install-and-launch.sh index b68692c..6021048 100755 --- a/install-and-launch.sh +++ b/install-and-launch.sh @@ -43,10 +43,10 @@ set -e # : ----------------------------------------- -: Branch - default: dev +: Branch - default: main : ----------------------------------------- -# By default, this script assumes that it should pull dependencies from branch `dev`. If you wish to get dependencies +# By default, this script assumes that it should pull dependencies from branch `main`. If you wish to get dependencies # from another branch, you can specify it here. # : curl -sL https://sublimesecurity.com/install.sh | remote_branch=custom-branch sh @@ -80,7 +80,7 @@ if [ -z "$interactive" ]; then # ascii art # credit: https://patorjk.com/ # font: Cyberlarge - cat </dev/null 2>&1; then - print_error "docker compose appears to be brought down. Will not proceed to avoid relaunching." + print_error "Sublime Platform appears to have been manually shut down. Will not proceed to avoid relaunching." + print_warning "If you wish to relaunch, please refer to the documentation here:" + print_warning "https://docs.sublimesecurity.com/docs/quickstart-docker#how-to-update" exit 0 fi fi @@ -23,7 +29,7 @@ if [ -z "$(git status --porcelain)" ]; then echo "git working dir clean. Proceeding with git updates." old_ref=$(git rev-parse HEAD) - git pull + logrun git pull new_ref=$(git rev-parse HEAD) if [ "${old_ref}" != "${new_ref}" ]; then diff --git a/utils.sh b/utils.sh index 982d534..5610818 100644 --- a/utils.sh +++ b/utils.sh @@ -48,3 +48,8 @@ print_info() { print_warning() { print_color "\n$1\n" "warning" } + +logrun() { + echo >&2 "+ $*" + "$@" +} From 33e2bd90e3e98f3c081c97f0aaefa5aadb13433d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 15 Sep 2026 15:29:02 +0000 Subject: [PATCH 5/6] Sync from e11d3865a36798aabbb5f23e03a2201bc8f9079a --- .github/workflows/docker-deploy-dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker-deploy-dev.yml b/.github/workflows/docker-deploy-dev.yml index b475d7e..a1d43ee 100644 --- a/.github/workflows/docker-deploy-dev.yml +++ b/.github/workflows/docker-deploy-dev.yml @@ -12,19 +12,19 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: persist-credentials: false - name: Login to DockerHub - uses: docker/login-action@v4.1.0 + uses: docker/login-action@v4.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v4 + uses: docker/setup-buildx-action@v4.1.0 with: driver: docker From dd98123a135e08aae9682ac5ff6319d289131890 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 16 Sep 2026 00:28:26 +0000 Subject: [PATCH 6/6] Sync from 43535a5629e0c8a6e952adffb2c0d4619e3e0d32 --- nginx-custom-ssl/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nginx-custom-ssl/README.md b/nginx-custom-ssl/README.md index 131be57..30256cd 100644 --- a/nginx-custom-ssl/README.md +++ b/nginx-custom-ssl/README.md @@ -6,7 +6,8 @@ To enable SSL with your custom certificate, follow the steps below: 1. Copy your certificate and key to certs/nginx.crt and certs/nginx.key 2. Edit conf/nginx.conf to update `__server_names__` to your domain or IP address -3. Perform any other configuration edits that you might need -4. Run `docker build -t sublime_nginx_custom_ssl .` -5. Run `cd ..` (back to sublime-platform directory) -6. Run `docker compose --profile nginx-custom-ssl up` +3. Configure the `sublime.env` file in the repository root for your domain, following [Configure Sublime](https://docs.sublime.security/docs/quickstart-docker#ssl). Do not include a port in `BASE_URL` or the other public URLs. +4. Perform any other configuration edits that you might need +5. Run `docker build -t sublime_nginx_custom_ssl .` +6. Run `cd ..` (back to sublime-platform directory) +7. Run `docker compose --profile nginx-custom-ssl up`