diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 62bd7f8ce2..0fadfe55cf 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -51,7 +51,7 @@ body: label: BunkerWeb version description: What version of BunkerWeb are you running? placeholder: Version - value: 1.6.9 + value: 1.6.9~rc2 validations: required: true - type: dropdown diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index bb99bc2f83..b7f5cfeead 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,12 +36,12 @@ jobs: python -m pip install --no-cache-dir --require-hashes -r src/common/db/requirements.txt echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV - name: Initialize CodeQL - uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: languages: ${{ matrix.language }} config-file: ./.github/codeql.yml setup-python-dependencies: false - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/container-build.yml b/.github/workflows/container-build.yml index 906d14c318..766aa1d159 100644 --- a/.github/workflows/container-build.yml +++ b/.github/workflows/container-build.yml @@ -76,22 +76,22 @@ jobs: SSH_IP: ${{ secrets.ARM_SSH_IP }} SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }} - name: Setup Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 if: startsWith(inputs.CACHE_SUFFIX, 'arm') == false - name: Setup Buildx (ARM) - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 if: startsWith(inputs.CACHE_SUFFIX, 'arm') with: endpoint: ssh://root@arm platforms: linux/arm64,linux/arm/v7 - name: Login to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to ghcr if: inputs.PUSH == true - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -99,13 +99,13 @@ jobs: # Compute metadata - name: Extract metadata id: meta - uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: bunkerity/${{ inputs.IMAGE }} # Build cached image - name: Build image if: inputs.CACHE == true - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ${{ inputs.DOCKERFILE }} @@ -118,7 +118,7 @@ jobs: # Build non-cached image - name: Build image if: inputs.CACHE != true - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ${{ inputs.DOCKERFILE }} @@ -130,7 +130,7 @@ jobs: # Check OS vulnerabilities - name: Check OS vulnerabilities if: ${{ startsWith(inputs.CACHE_SUFFIX, 'arm') == false }} - uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0 + uses: aquasecurity/trivy-action@e368e328979b113139d6f9068e03accaed98a518 # v0.34.1 with: vuln-type: os skip-dirs: /root/.cargo diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index ddb6741510..776d233394 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -5,7 +5,6 @@ permissions: read-all on: push: branches: [dev] - workflow_dispatch: jobs: # Containers @@ -189,12 +188,12 @@ jobs: to: bunkerweb-all-in-one steps: - name: Login to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/doc-to-pdf.yml b/.github/workflows/doc-to-pdf.yml index 55546261d5..e9c4aab18f 100644 --- a/.github/workflows/doc-to-pdf.yml +++ b/.github/workflows/doc-to-pdf.yml @@ -23,7 +23,7 @@ jobs: - name: Install chromium run: sudo apt update && sudo apt install chromium-browser - name: Install node - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: node-version: 22 - name: Install puppeteer diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 9524d4d25a..56eb30e4b3 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -85,21 +85,21 @@ jobs: SSH_IP: ${{ secrets.ARM_SSH_IP }} SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }} - name: Setup Buildx - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 if: startsWith(env.ARCH, 'arm') == false - name: Setup Buildx (ARM) - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 if: startsWith(env.ARCH, 'arm') == true with: endpoint: ssh://root@arm platforms: linux/arm64,linux/arm/v7 - name: Login to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -107,7 +107,7 @@ jobs: # Build testing package image - name: Build package image if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui' || inputs.RELEASE == '1.5' - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . load: true @@ -119,7 +119,7 @@ jobs: # Build non-testing package image - name: Build package image if: inputs.RELEASE != 'testing' && inputs.RELEASE != 'dev' && inputs.RELEASE != 'ui' && inputs.RELEASE != '1.5' - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . load: true @@ -151,12 +151,12 @@ jobs: - name: Extract metadata if: inputs.TEST == true id: meta - uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: ghcr.io/bunkerity/${{ inputs.LINUX }}-tests:${{ inputs.RELEASE }} - name: Build test image if: inputs.TEST == true - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: tests/linux/Dockerfile-${{ inputs.LINUX }} diff --git a/.github/workflows/push-docker.yml b/.github/workflows/push-docker.yml index 602020247b..b7849cb8e2 100644 --- a/.github/workflows/push-docker.yml +++ b/.github/workflows/push-docker.yml @@ -35,12 +35,12 @@ jobs: - name: Check out repository code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Login to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -68,7 +68,7 @@ jobs: SSH_IP: ${{ secrets.ARM_SSH_IP }} SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }} - name: Setup Buildx (ARM) - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 with: endpoint: ssh://root@arm platforms: linux/arm64,linux/arm/v7 @@ -82,12 +82,12 @@ jobs: # Compute metadata - name: Extract metadata id: meta - uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0 + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: bunkerity/${{ inputs.IMAGE }} # Build and push - name: Build and push - uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ${{ inputs.DOCKERFILE }} diff --git a/.github/workflows/push-github.yml b/.github/workflows/push-github.yml index 1c0e6ee41d..0cd86d2dd1 100644 --- a/.github/workflows/push-github.yml +++ b/.github/workflows/push-github.yml @@ -24,7 +24,7 @@ jobs: # Get PDF doc - name: Get documentation if: inputs.VERSION != 'testing' - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf # Sanitize version (replace ~ with - for valid Git tag names) diff --git a/.github/workflows/push-packagecloud.yml b/.github/workflows/push-packagecloud.yml index 5a096a0acf..c431f8d10b 100644 --- a/.github/workflows/push-packagecloud.yml +++ b/.github/workflows/push-packagecloud.yml @@ -42,7 +42,7 @@ jobs: - name: Check out repository code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install ruby - uses: ruby/setup-ruby@4eb9f110bac952a8b68ecf92e3b5c7a987594ba6 # v1.292.0 + uses: ruby/setup-ruby@09a7688d3b55cf0e976497ff046b70949eeaccfd # v1.288.0 with: ruby-version: "3.0" - name: Install packagecloud @@ -81,7 +81,7 @@ jobs: echo "artifact=$ARTIFACT_NAME" >> $GITHUB_OUTPUT # Download packages (single generic step) - name: Download package artifact - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: ${{ env.ARTIFACT_NAME }} path: /tmp/${{ inputs.LINUX }} diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index f416b0eac2..eb98490e9a 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -25,6 +25,6 @@ jobs: results_format: sarif publish_results: true - name: "Upload SARIF results to code scanning" - uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: sarif_file: results.sarif diff --git a/.github/workflows/staging-delete-infra.yml b/.github/workflows/staging-delete-infra.yml index 62a4ffa784..f71bd11b25 100644 --- a/.github/workflows/staging-delete-infra.yml +++ b/.github/workflows/staging-delete-infra.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install terraform uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0 - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: tf-${{ inputs.TYPE }} path: /tmp diff --git a/.github/workflows/staging-tests.yml b/.github/workflows/staging-tests.yml index 46b904c92a..52f787e3fd 100644 --- a/.github/workflows/staging-tests.yml +++ b/.github/workflows/staging-tests.yml @@ -27,7 +27,7 @@ jobs: - name: Checkout source code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -43,7 +43,7 @@ jobs: - name: Install Terraform uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4.0.0 if: inputs.TYPE == 'k8s' - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: tf-k8s path: /tmp diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index dfe17b1b22..812849c265 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -5,7 +5,6 @@ permissions: read-all on: push: branches: [staging] - workflow_dispatch: jobs: # Build Docker images @@ -153,12 +152,12 @@ jobs: packages: write steps: - name: Login to Docker Hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/test-core-linux.yml b/.github/workflows/test-core-linux.yml index 196d56703d..a5e997a946 100644 --- a/.github/workflows/test-core-linux.yml +++ b/.github/workflows/test-core-linux.yml @@ -49,7 +49,7 @@ jobs: sudo chmod +x /usr/local/bin/geckodriver rm -f geckodriver.tar.gz - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/test-core.yml b/.github/workflows/test-core.yml index b630fa0cb9..642cc660c5 100644 --- a/.github/workflows/test-core.yml +++ b/.github/workflows/test-core.yml @@ -18,7 +18,7 @@ jobs: - name: Checkout source code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/tests-ui-linux.yml b/.github/workflows/tests-ui-linux.yml index c3ceae6e84..ae22a57558 100644 --- a/.github/workflows/tests-ui-linux.yml +++ b/.github/workflows/tests-ui-linux.yml @@ -49,7 +49,7 @@ jobs: sudo chmod +x /usr/local/bin/geckodriver rm -f geckodriver.tar.gz - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/tests-ui.yml b/.github/workflows/tests-ui.yml index 00232f953e..99b22108e4 100644 --- a/.github/workflows/tests-ui.yml +++ b/.github/workflows/tests-ui.yml @@ -17,7 +17,7 @@ jobs: - name: Checkout source code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Login to ghcr - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b2281f18bf..4e080faa48 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: hooks: - id: black name: Black Python Formatter - language_version: python3.10 + language_version: python3.9 - repo: local hooks: diff --git a/CHANGELOG.md b/CHANGELOG.md index fc13e3343d..fff52f69ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,59 +1,12 @@ # Changelog -## v1.6.10~rc1 - 2026/03/?? - -- [BUGFIX] Disable Gunicorn 25.1.0 control socket to prevent worker deadlock caused by fork in multi-threaded master process (UI, TMP-UI, API). -- [UI] Fix multiselect settings not correctly displaying or applying their values in the template editor and the service creation wizard. - -## v1.6.9 - 2026/03/13 - -- [SECURITY] Implement `SafeFileSystemCache` for Web UI session storage with token regeneration on privilege changes, preventing session fixation attacks. -- [SECURITY] Sanitize uploaded filenames in the Web UI to strip path separators, null bytes, and control characters, preventing path traversal attacks. -- [SECURITY] Add tar extraction path filtering in `Let's Encrypt` certificate handling to only allow expected directories, preventing path traversal. Add 300s timeout to certificate account registration. Use explicit whitelist for API environment variables. -- [SECURITY] Validate IP addresses and service names across all ban management endpoints (API, Lua, UI, CLI) to prevent invalid data injection. Fix Redis key parsing for service names containing underscores. -- [BUGFIX] Close local database connections before forking worker processes to prevent file descriptor leaks and connection pool corruption. -- [BUGFIX] Fix race condition in instance update logic by using direct SQL `UPDATE` statements instead of ORM session operations. -- [BUGFIX] Ensure thread safety when managing the session factory by moving instance update operations outside the synchronization lock. -- [BUGFIX] Handle empty or unreadable certificates gracefully in Let's Encrypt `retrieve_certificates` and `retrieve_certificates_info` functions to prevent crashes during certificate enumeration. -- [BUGFIX] Enhance error handling for missing server name in SSL certificate functions to avoid crashes when the server name is not yet configured. -- [BUGFIX] Improve backup cleanup logic when replacing destination files to correctly remove leftover backups after a successful replacement. -- [BUGFIX] Mark the Flask session as modified when adding flash messages to ensure session data is correctly persisted across redirects. -- [BUGFIX] Fix Domeneshop DNS provider in the `Let's Encrypt` plugin to use the correct credential keys and ensure proper certificate generation. -- [BUGFIX] Handle file-not-found and OS errors gracefully when archiving plugin UI pages in the database, and skip storing content when tar archiving fails to prevent corrupt data. -- [BUGFIX] Return false instead of a potentially incorrect result when version comparison encounters invalid version strings, preventing spurious update notifications. -- [BUGFIX] Validate gRPC host setting to only accept empty values or properly prefixed `grpc://` / `grpcs://` URIs. -- [BUGFIX] Properly close the database connection when the scheduler stops, and fix configuration generation flag to only reset after a successful reload. -- [BUGFIX] Add backup and rollback mechanism when deploying new configurations to BunkerWeb instances, preventing data loss if the file copy operation fails. -- [BUGFIX] Generate and deploy initial configuration on first start before running plugin jobs, ensuring API endpoints are available when jobs execute. -- [BUGFIX] Skip Content-Security-Policy header override in the antibot plugin when nonces are not available (e.g., HEAD requests), preventing malformed CSP headers. -- [UI] Add confetti animation and visual unlock effect when activating a PRO License Key in the Web UI. -- [UI] Fix service cloning to correctly strip the source service prefix from configuration keys, preventing settings from being ignored during import. -- [UI] Rate-limit worker restarts to prevent excessive restarts when multiple plugin reload triggers fire in quick succession. -- [UI] Fix crashes when CSRF validation or request teardown occurs outside a valid user context, improving stability during edge-case scenarios. -- [API] Add lifespan handler to properly close database connections on shutdown, preventing connection leaks. -- [DOCS] Update documentation and default configurations to remove the deprecated nightly CRS version and ensure full compatibility with CRS v4. -- [DOCS] Update Domeneshop DNS provider credential key names in documentation to match the corrected `client_token`/`client_secret` keys. -- [DOCS] Add documentation for the Cache PRO plugin covering response caching configuration and settings. -- [DEPS] Update coreruleset-v4 version to v4.24.1 - -## v1.6.9~rc4 - 2026/03/10 - -- [BUGFIX] Ensure script_nonce is available for security headers to prevent XSS attacks - -## v1.6.9~rc3 - 2026/03/06 +## v1.6.9 - 2026/03/?? - [BUGFIX] Fix issues with the new `multiselect` logic where a custom separator can be used, but the default one (space) was still used if the separator was empty, which caused issues with settings that had an empty string as a value. -- [BUGFIX] Fix issue with the failover not sending the failover configuration if the reload failed, which caused the failover configuration to not be applied until the next successful reload. -- [FEATURE] Add field value redaction in Let's Encrypt plugin and update ZeroSSL API key handling to avoid exposing sensitive information in logs and process arguments. (Except in TRACE level logs for debugging purposes) - [UI] Set `reuse_port` setting to `False` with gunicorn to avoid issues with workers not starting. - [UI] Tweak plugins headers style to avoid the text moving the buttons out of the page when the header is too long. -- [UI] Add `MAX_CONTENT_LENGTH` setting to configure the maximum upload size (defaults to 50 MB). -- [UI/API] Add `MAX_REQUESTS` setting to configure Gunicorn max requests before worker restart (defaults to 1000), with `UI_MAX_REQUESTS` / `API_MAX_REQUESTS` as optional overrides. - [API] Set `reuse_port` setting to `False` with gunicorn to avoid issues with workers not starting. -- [MISC] Enhance version comparison logic in update check -- [MISC] Enhance database connection management with configurable pool reset and session handling -- [MISC] Enhance database configuration options with `DATABASE_POOL_SIZE`, `DATABASE_POOL_MAX_OVERFLOW`, `DATABASE_POOL_TIMEOUT`, `DATABASE_POOL_RECYCLE`, `DATABASE_POOL_PRE_PING`, `DATABASE_POOL_RESET_ON_RETURN`, `DATABASE_RETRY_TIMEOUT`, `DATABASE_REQUEST_RETRY_ATTEMPTS` and `DATABASE_REQUEST_RETRY_DELAY` settings for improved performance, reliability and resilience of database interactions. -- [DEPS] Updated libmaxminddb version to v1.13.3 +- [DEPS] Updated libmaxminddb version to v1.13.2 - [DEPS] Updated luajit2 version to v2.1-20260227 - [DEPS] Update coreruleset-v4 version to v4.24.0 diff --git a/CLAUDE.md b/CLAUDE.md index df48acac04..109eba0751 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,72 +10,44 @@ BunkerWeb is an open-source Web Application Firewall (WAF) built on NGINX with a ### Core Components -- **BunkerWeb Core** (`src/bw/`, `src/common/core/`): NGINX-based reverse proxy with security modules in Lua (request-time) and Python (jobs). Entry point: `src/bw/lua/bunkerweb.lua`. -- **Scheduler** (`src/scheduler/`): Central orchestrator ("brain"). `main.py` runs the main loop; `JobScheduler.py` manages job execution with thread pools. Uses Python's `schedule` library. -- **Autoconf** (`src/autoconf/`): Listens for Docker/Swarm/Kubernetes events and dynamically reconfigures BunkerWeb. -- **API** (`src/api/`): FastAPI service with router-based architecture (`src/api/app/routers/` — auth, instances, services, configs, plugins, jobs). IP whitelist and rate limiting support. -- **Web UI** (`src/ui/`): Flask app using Blueprints for routing (`src/ui/app/routes/` — configs, plugins, jobs, logs, instances, profile, etc.). Uses Flask-Login for auth and Jinja2 templates. `dependencies.py` is the central dependency injection point providing DB, DATA, BW_CONFIG, BW_INSTANCES_UTILS. -- **Database** (`src/common/db/`): SQLAlchemy ORM with `model.py` defining all tables (Plugins, Settings, Services, Jobs, Custom_configs, Users, etc.). `Database.py` wraps high-level query methods. Supports SQLite (WAL mode), MariaDB, MySQL, PostgreSQL with QueuePool for connection pooling. +- **BunkerWeb Core** (`src/bw/`, `src/common/core/`): NGINX-based reverse proxy with security modules written in Lua and Python. Each security feature is a plugin with its own `plugin.json` configuration. +- **Scheduler** (`src/scheduler/`): Central orchestrator that manages configuration, executes jobs, generates NGINX configs, and acts as intermediary between components. This is the "brain" of BunkerWeb. +- **Autoconf** (`src/autoconf/`): Listens for Docker/Swarm/Kubernetes events and dynamically reconfigures BunkerWeb without container restarts. +- **API** (`src/api/`): FastAPI service for programmatic control of BunkerWeb instances. +- **Web UI** (`src/ui/`): Flask-based admin interface for managing instances, viewing blocked attacks, configuring settings, and monitoring jobs. +- **Database** (`src/common/db/`): Backend store (SQLite/MariaDB/MySQL/PostgreSQL) for configuration, metadata, cached files, and job execution state. ### Configuration Flow -1. Settings defined as environment variables (e.g., `USE_ANTIBOT=captcha`, `AUTO_LETS_ENCRYPT=yes`) +1. Settings are defined as environment variables (e.g., `USE_ANTIBOT=captcha`, `AUTO_LETS_ENCRYPT=yes`) 2. Scheduler reads settings from environment or database -3. **Configurator** (`src/common/gen/Configurator.py`) validates settings against `plugin.json` schemas with pre-compiled regex caches -4. **Templator** (`src/common/gen/Templator.py`) renders NGINX configs from Jinja2 templates (`src/common/confs/`) using ProcessPoolExecutor for parallel rendering -5. BunkerWeb instances reload with new configuration -6. In multisite mode, prefix settings with server name: `www.example.com_USE_ANTIBOT=captcha` -7. Multiple settings use numeric suffixes: `REVERSE_PROXY_URL_1=/api`, `REVERSE_PROXY_HOST_1=http://backend1` +3. Configurator/Templator (`src/common/gen/`) generates NGINX configuration files from templates (`src/common/confs/`) +4. BunkerWeb instances reload with new configuration +5. In multisite mode, prefix settings with server name: `www.example.com_USE_ANTIBOT=captcha` +6. Multiple settings use numeric suffixes: `REVERSE_PROXY_URL_1=/api`, `REVERSE_PROXY_HOST_1=http://backend1` ### Plugin System -Each core module in `src/common/core/*/` contains: +Each core module in `src/common/core/*/` is a plugin with: -- `plugin.json`: Metadata with settings schema (id, name, version, stream, settings with context/type/regex/default, jobs array with schedule/reload/async flags) -- `jobs/` folder: Python scripts for periodic tasks (e.g., downloading blocklists). Jobs specify `every` (once/minute/hour/day/week) and `reload` flag. +- `plugin.json`: Metadata, settings schema, validation regex +- Python jobs for periodic tasks (e.g., downloading blocklists) - Lua code for request-time processing -- `confs/` folder: NGINX configuration templates +- NGINX configuration templates -External plugins follow the same structure. - -### Lua Request Processing Pipeline - -The Lua runtime (`src/bw/lua/`) processes requests through plugin hooks at NGINX phases: access, header_filter, body_filter, log. Key files: - -- `plugin.lua`: Plugin loader and execution across phases -- `ctx.lua`: Per-request context management -- `datastore.lua`: Shared data persistence (shared dict backed) -- `cachestore.lua`: Request-level caching -- `clusterstore.lua`: Cluster-aware storage (Redis) - -### Core Plugins (src/common/core/) - -42 plugins organized by function: - -- **Auth**: antibot (CAPTCHA), authbasic, mtls, crowdsec -- **Threat Detection**: modsecurity (OWASP WAF), badbehavior, dnsbl, reversescan -- **Access Control**: whitelist, blacklist, greylist, country, limit (rate limiting) -- **SSL/TLS**: ssl, letsencrypt, customcert, selfsigned -- **Proxy & Routing**: reverseproxy, realip, redirect, grpc, php -- **Performance**: gzip, brotli, clientcache, redis -- **Headers & Content**: headers, cors, inject, robotstxt, securitytxt -- **Management**: sessions, metrics, backup, templates, bunkernet, ui, db, jobs - -### Shared Utilities (src/common/utils/) - -- `common_utils.py`: Docker secrets handling, hashing, version info, integration detection -- `logger.py`: Logging with syslog support -- `jobs.py`: Job helpers (atomic writes, file hashing, tar operations) -- `ApiCaller.py`: HTTP client for inter-component API calls +External plugins follow the same structure and can be installed via the Web UI or CLI. ## Development Commands ### Setup ```bash +# Install Python dependencies for a component pip install -r src/scheduler/requirements.txt pip install -r src/ui/requirements.txt pip install -r src/api/requirements.txt + +# Install pre-commit hooks pre-commit install ``` @@ -98,56 +70,69 @@ pre-commit run --all-files # Individual tools black . # Python formatting (160 char lines) -flake8 . # Python linting (ignores E266,E402,E501,E722,W503) +flake8 . # Python linting stylua . # Lua formatting -luacheck src/ # Lua linting (--std min) +luacheck src/ # Lua linting shellcheck scripts/*.sh # Shell script linting prettier --write "**/*.{js,ts,css,html,json,yaml,md}" # Frontend formatting -codespell # Spell checking -refurb # Python refactoring suggestions (excludes tests/) ``` -### Run Development Instance +### Documentation ```bash -# Full stack with UI + API (recommended) -docker compose -f misc/dev/docker-compose.ui.api.yml up -d +# Serve docs locally with live reload +mkdocs serve --watch + +# Build static docs +mkdocs build ``` -Dev compose files in `misc/dev/`: +### Run Development Instance -- `docker-compose.ui.api.yml` — Full stack (UI + API + core + MariaDB) — **recommended** -- `docker-compose.ui.yml` — UI only (no API) -- `docker-compose.all-in-one.yml` — Single container with all components -- `docker-compose.autoconf.yml` — Docker autoconf mode -- `docker-compose.wizard.yml` — Setup wizard +```bash +# Iso-prod environment with all components +docker compose -f misc/dev/docker-compose.ui.api.yml up -d -Dev credentials: UI `admin`/`P@ssw0rd`, API `admin`/`P@ssw0rd`, DB `bunkerweb`/`secret`. +# There are other compose files for different setups in misc/dev/ +``` -The dev compose mounts `src/ui/app/` and `src/api/app/` as read-only volumes, so UI and API code changes apply without rebuilding (restart the container to pick up changes). +## Code Organization -### Database Migrations +### Directory Structure -```bash -# Alembic migrations in src/common/db/alembic/ -# Separate version directories per DB type: mariadb_versions, mysql_versions, postgresql_versions, sqlite_versions -# Migration scripts also in src/common/db/alembic/ +``` +src/ +├── all-in-one/ # Single container with all components +├── api/ # FastAPI service +├── autoconf/ # Docker/Swarm/K8s event listener +├── bw/ # BunkerWeb core (NGINX + Lua runtime) +├── common/ # Shared code +│ ├── api/ # API client library +│ ├── cli/ # Command-line interface (bwcli) +│ ├── confs/ # NGINX configuration templates +│ ├── core/ # Core security plugins (each is a module) +│ ├── db/ # Database abstraction + Alembic migrations +│ ├── gen/ # Configuration generator (Configurator, Templator) +│ ├── helpers/ # Healthcheck scripts +│ └── utils/ # Shared utilities +├── deps/ # Third-party dependencies (NGINX modules, Lua libs) +├── linux/ # Linux package build scripts (deb/rpm) +├── scheduler/ # Job scheduler and orchestrator +└── ui/ # Web UI (Flask app) + +docs/ # MkDocs documentation +examples/ # Integration examples with tests.json +tests/ # Integration test suites +misc/ # Utilities and scripts ``` -## Key Files +### Key Files - `src/common/settings.json`: Master list of all core settings with validation rules -- `src/common/db/model.py`: SQLAlchemy ORM models for all tables -- `src/common/db/Database.py`: High-level database wrapper -- `src/common/gen/Configurator.py`: Settings validation engine -- `src/common/gen/Templator.py`: NGINX config renderer -- `src/scheduler/main.py`: Scheduler entry point -- `src/scheduler/JobScheduler.py`: Job execution orchestrator +- `src/scheduler/main.py`: Scheduler entry point, handles config generation and job execution - `src/ui/main.py`: Web UI entry point -- `src/ui/app/dependencies.py`: UI dependency injection (DB, DATA, BW_CONFIG) -- `src/api/app/core.py`: API entry point (imports all routers) - `src/bw/lua/bunkerweb.lua`: Main Lua runtime initialization -- `pyproject.toml`: Black config (160 char lines) +- `pyproject.toml`: Project metadata (Black config: 160 char lines) - `.pre-commit-config.yaml`: All linting/formatting rules ## Important Patterns @@ -159,36 +144,51 @@ The dev compose mounts `src/ui/app/` and `src/api/app/` as read-only volumes, so ### Security Modes -- `detect`: Log threats without blocking +- `detect`: Log threats without blocking (for testing/debugging false positives) - `block`: Actively block threats (default) ### Integration Modes -Set one of these to `yes`: `AUTOCONF_MODE`, `SWARM_MODE`, `KUBERNETES_MODE` +Set one of these to `yes`: -### Testing +- `AUTOCONF_MODE`: Docker autoconf (labels on containers) +- `SWARM_MODE`: Docker Swarm (labels on services) +- `KUBERNETES_MODE`: Kubernetes (Ingress resources) + +### Database Migrations + +Use Alembic for schema changes: ```bash -python3 tests/main.py docker # Docker integration tests -python3 tests/main.py autoconf # Autoconf tests -python3 tests/main.py swarm # Swarm tests -python3 tests/main.py kubernetes # Kubernetes tests -python3 tests/main.py linux debian # Linux tests (with distro) +# Located in src/common/db/alembic/ +# Separate version directories for: mariadb, mysql, postgresql, sqlite ``` -- Tests scan `examples/*/tests.json` for test scenarios (type: string/status, url, expected results) -- Real Docker environments with actual HTTP requests — tests verify observable behavior, not internals +## Testing Philosophy + +- Integration tests use real Docker environments with actual HTTP requests +- Each example has a `tests.json` defining test scenarios (HTTP status codes, response content, timing) +- Tests verify observable behavior, not internals +- For regressions, add a test case to the relevant example's `tests.json` + +## Configuration Best Practices + +- Never commit secrets (use `env/` templates for examples) +- Settings are validated against regex in `plugin.json` +- Custom NGINX configs go in designated directories or via Web UI +- ModSecurity custom rules follow the same pattern +- Multi-language UI translations in `src/ui/app/static/locales/` ## Key Conventions - Python: snake_case (modules/functions), PascalCase (classes), Black formatting at 160 chars - Lua: lowercase module names, descriptive function names, StyLua formatting - Shell: POSIX-compatible unless `#!/bin/bash` shebang, pass ShellCheck -- Commit messages: Conventional Commits (`feat:`, `fix:`, `docs:`) or ` - ...` format -- UI translations in `src/ui/app/static/locales/` +- Commit messages: Use Conventional Commits (`feat:`, `fix:`, `docs:`) or ` - ...` format ## External Resources -- Documentation: -- Official Plugins: -- Web UI Demo: +- Documentation: https://docs.bunkerweb.io +- Official Plugins: https://github.com/bunkerity/bunkerweb-plugins +- Web UI Demo: https://demo-ui.bunkerweb.io +- Discord: https://discord.com/invite/fTf46FmtyD diff --git a/README.md b/README.md index 0bcd493b9c..6e05411864 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- BunkerWeb logo + BunkerWeb logo

@@ -12,11 +12,9 @@
-
- GitRated rating

@@ -32,7 +30,7 @@ | 🧩 Templates | - 🛡️ Examples + 🛡️ Examples
💬 Chat | @@ -52,14 +50,14 @@ # BunkerWeb

- Overview banner + Overview banner

BunkerWeb is a next-generation, open-source Web Application Firewall (WAF). -Being a full-featured web server (based on [NGINX](https://nginx.org/) under the hood), it will protect your web services to make them "secure by default." BunkerWeb integrates seamlessly into your existing environments ([Linux](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#linux), [Docker](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#docker), [Swarm](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#swarm), [Kubernetes](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#kubernetes), …) as a reverse proxy and is fully configurable (don't panic, there is an [awesome web UI](https://docs.bunkerweb.io/1.6.9/web-ui/?utm_campaign=self&utm_source=github) if you don't like the CLI) to meet your own use cases. In other words, cybersecurity is no longer a hassle. +Being a full-featured web server (based on [NGINX](https://nginx.org/) under the hood), it will protect your web services to make them "secure by default." BunkerWeb integrates seamlessly into your existing environments ([Linux](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#linux), [Docker](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#docker), [Swarm](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#swarm), [Kubernetes](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#kubernetes), …) as a reverse proxy and is fully configurable (don't panic, there is an [awesome web UI](https://docs.bunkerweb.io/1.6.9~rc2/web-ui/?utm_campaign=self&utm_source=github) if you don't like the CLI) to meet your own use cases. In other words, cybersecurity is no longer a hassle. -BunkerWeb contains primary [security features](https://docs.bunkerweb.io/1.6.9/advanced/?utm_campaign=self&utm_source=github#security-tuning) as part of the core but can be easily extended with additional ones thanks to a [plugin system](https://docs.bunkerweb.io/1.6.9/plugins/?utm_campaign=self&utm_source=github). +BunkerWeb contains primary [security features](https://docs.bunkerweb.io/1.6.9~rc2/advanced/?utm_campaign=self&utm_source=github#security-tuning) as part of the core but can be easily extended with additional ones thanks to a [plugin system](https://docs.bunkerweb.io/1.6.9~rc2/plugins/?utm_campaign=self&utm_source=github). ## Why BunkerWeb? @@ -86,7 +84,7 @@ A non-exhaustive list of security features: - **Block known bad IPs** with external blacklists and DNSBL - And much more... -Learn more about the core security features in the [security tuning](https://docs.bunkerweb.io/1.6.9/advanced/?utm_campaign=self&utm_source=github#security-tuning) section of the documentation. +Learn more about the core security features in the [security tuning](https://docs.bunkerweb.io/1.6.9~rc2/advanced/?utm_campaign=self&utm_source=github#security-tuning) section of the documentation. ## Demo @@ -121,13 +119,13 @@ When using BunkerWeb, you have the choice of the version you want to use: open-s Whether it's enhanced security, an enriched user experience, or technical monitoring, the BunkerWeb PRO version allows you to fully benefit from BunkerWeb and meet your professional needs. -In the documentation or the user interface, PRO features are annotated with a crown crown pro icon to distinguish them from those integrated into the open-source version. +In the documentation or the user interface, PRO features are annotated with a crown crown pro icon to distinguish them from those integrated into the open-source version. You can upgrade from the open-source version to the PRO one easily and at any time. The process is straightforward: - Claim your [free trial on the BunkerWeb panel](https://panel.bunkerweb.io/store/bunkerweb-pro?utm_campaign=self&utm_source=doc) by using the `freetrial` promo code at checkout - Once connected to the client area, copy your PRO license key -- Paste your license key into BunkerWeb using the [web UI](https://docs.bunkerweb.io/1.6.9/web-ui/#upgrade-to-pro) or a [specific setting](https://docs.bunkerweb.io/1.6.9/features/#pro) +- Paste your license key into BunkerWeb using the [web UI](https://docs.bunkerweb.io/1.6.9~rc2/web-ui/#upgrade-to-pro) or a [specific setting](https://docs.bunkerweb.io/1.6.9~rc2/features/#pro) Do not hesitate to visit the [BunkerWeb panel](https://panel.bunkerweb.io/knowledgebase?utm_campaign=self&utm_source=doc) or [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=doc) if you have any questions regarding the PRO version. @@ -160,10 +158,10 @@ Community and social networks: # Concepts

- Concepts banner + Concepts banner

-You will find more information about the key concepts of BunkerWeb in the [documentation](https://docs.bunkerweb.io/1.6.9/concepts/?utm_campaign=self&utm_source=github). +You will find more information about the key concepts of BunkerWeb in the [documentation](https://docs.bunkerweb.io/1.6.9~rc2/concepts/?utm_campaign=self&utm_source=github). ## Integrations @@ -171,12 +169,12 @@ The first concept is the integration of BunkerWeb into the target environment. W The following integrations are officially supported: -- [Docker](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#docker) -- [Linux](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#linux) -- [Docker autoconf](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#docker-autoconf) -- [Kubernetes](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#kubernetes) -- [Swarm](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#swarm) -- [Microsoft Azure](https://docs.bunkerweb.io/1.6.9/integrations/?utm_campaign=self&utm_source=github#microsoft-azure) +- [Docker](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#docker) +- [Linux](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#linux) +- [Docker autoconf](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#docker-autoconf) +- [Kubernetes](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#kubernetes) +- [Swarm](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#swarm) +- [Microsoft Azure](https://docs.bunkerweb.io/1.6.9~rc2/integrations/?utm_campaign=self&utm_source=github#microsoft-azure) ## Settings @@ -206,7 +204,7 @@ When multisite mode is enabled, BunkerWeb will serve and protect multiple web ap ## Custom configurations -Because meeting all the use cases only using the settings is not an option (even with [external plugins](https://docs.bunkerweb.io/1.6.9/plugins/?utm_campaign=self&utm_source=github)), you can use custom configurations to solve your specific challenges. +Because meeting all the use cases only using the settings is not an option (even with [external plugins](https://docs.bunkerweb.io/1.6.9~rc2/plugins/?utm_campaign=self&utm_source=github)), you can use custom configurations to solve your specific challenges. Under the hood, BunkerWeb uses the notorious NGINX web server, that's why you can leverage its configuration system for your specific needs. Custom NGINX configurations can be included in different [contexts](https://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files/#contexts) like HTTP or server (all servers and/or specific server block). @@ -215,7 +213,7 @@ Another core component of BunkerWeb is the ModSecurity Web Application Firewall: ## Database

- Database model + Database model

The state of the current configuration of BunkerWeb is stored in a backend database which contains the following data: @@ -244,7 +242,7 @@ In other words, the scheduler is the brain of BunkerWeb.