mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge pull request #677 from bunkerity/dev
Merge branch "dev" into branch "staging"
This commit is contained in:
commit
d1a0f66c98
214 changed files with 1830 additions and 3433 deletions
15
.gitattributes
vendored
Normal file
15
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Folders
|
||||
src/deps/src/** linguist-vendored
|
||||
src/common/core/modsecurity/files/** linguist-vendored
|
||||
src/ui/static/js/editor/** linguist-vendored
|
||||
src/ui/static/js/utils/purify/** linguist-vendored
|
||||
src/ui/static/webfonts/** linguist-vendored
|
||||
|
||||
# Files
|
||||
src/deps/misc/lua-pack.Makefile -linguist-vendored
|
||||
src/deps/misc/ngx_http_modsecurity_access.c -linguist-vendored
|
||||
src/ui/static/css/datepicker-foundation.css -linguist-vendored
|
||||
src/ui/static/css/flatpickr.css -linguist-vendored
|
||||
src/ui/static/css/flatpickr.dark.css -linguist-vendored
|
||||
src/ui/static/js/tsparticles.bundle.min.js -linguist-vendored
|
||||
src/ui/static/js/utils/flatpickr.js -linguist-vendored
|
||||
2
.github/workflows/beta.yml
vendored
2
.github/workflows/beta.yml
vendored
|
|
@ -131,7 +131,7 @@ jobs:
|
|||
versionrpm: ${{ steps.getversionrpm.outputs.versionrpm }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Get VERSION
|
||||
id: getversion
|
||||
run: echo "version=$(cat src/VERSION | tr -d '\n')" >> "$GITHUB_OUTPUT"
|
||||
|
|
|
|||
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
|
|
@ -19,13 +19,13 @@ jobs:
|
|||
language: ["python", "javascript"]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
config-file: ./.github/codeql.yml
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
|
|
|||
18
.github/workflows/container-build.yml
vendored
18
.github/workflows/container-build.yml
vendored
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Replace VERSION
|
||||
if: inputs.RELEASE == 'testing'
|
||||
run: ./misc/update-version.sh testing
|
||||
|
|
@ -61,22 +61,22 @@ jobs:
|
|||
SSH_IP: ${{ secrets.ARM_SSH_IP }}
|
||||
SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }}
|
||||
- name: Setup Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
if: inputs.CACHE_SUFFIX != 'arm'
|
||||
- name: Setup Buildx (ARM)
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
if: inputs.CACHE_SUFFIX == 'arm'
|
||||
with:
|
||||
endpoint: ssh://root@arm
|
||||
platforms: linux/arm64,linux/arm/v7,linux/arm/v6
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to ghcr
|
||||
if: inputs.PUSH == true
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -84,13 +84,13 @@ jobs:
|
|||
# Compute metadata
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
|
||||
with:
|
||||
images: bunkerity/${{ inputs.IMAGE }}
|
||||
# Build cached image
|
||||
- name: Build image
|
||||
if: inputs.CACHE == true
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.DOCKERFILE }}
|
||||
|
|
@ -103,7 +103,7 @@ jobs:
|
|||
# Build non-cached image
|
||||
- name: Build image
|
||||
if: inputs.CACHE != true
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.DOCKERFILE }}
|
||||
|
|
@ -115,7 +115,7 @@ jobs:
|
|||
# Check OS vulnerabilities
|
||||
- name: Check OS vulnerabilities
|
||||
if: ${{ inputs.CACHE_SUFFIX != 'arm' }}
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@69cbbc0cbbf6a2b0bab8dcf0e9f2d7ead08e87e4 # master
|
||||
with:
|
||||
vuln-type: os
|
||||
skip-dirs: /root/.cargo
|
||||
|
|
|
|||
2
.github/workflows/create-arm.yml
vendored
2
.github/workflows/create-arm.yml
vendored
|
|
@ -33,7 +33,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Get ARM availabilities
|
||||
id: availabilities
|
||||
uses: scaleway/action-scw@c718eca1fcb9fec1fb1433752d61599c6a0ad2e9
|
||||
|
|
|
|||
6
.github/workflows/dev-update-mmdb.yml
vendored
6
.github/workflows/dev-update-mmdb.yml
vendored
|
|
@ -5,14 +5,14 @@ permissions:
|
|||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 1 5 * *"
|
||||
- cron: "0 12 1 * *"
|
||||
|
||||
jobs:
|
||||
mmdb-update:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.BUNKERBOT_TOKEN }}
|
||||
|
|
@ -52,7 +52,7 @@ jobs:
|
|||
rm -f asn.mmdb country.mmdb
|
||||
gunzip asn.mmdb.gz country.mmdb.gz
|
||||
- name: Commit and push changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
uses: stefanzweifel/git-auto-commit-action@3ea6ae190baf489ba007f7c92608f33ce20ef04a # v4.16.0
|
||||
with:
|
||||
branch: dev
|
||||
commit_message: "Monthly mmdb update"
|
||||
|
|
|
|||
6
.github/workflows/dev.yml
vendored
6
.github/workflows/dev.yml
vendored
|
|
@ -88,7 +88,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/core/ -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
@ -126,12 +126,12 @@ jobs:
|
|||
packages: write
|
||||
steps:
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
8
.github/workflows/doc-to-pdf.yml
vendored
8
.github/workflows/doc-to-pdf.yml
vendored
|
|
@ -13,9 +13,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install doc requirements
|
||||
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
- name: Install chromium
|
||||
run: sudo apt install chromium-browser
|
||||
- name: Install node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install puppeteer
|
||||
|
|
@ -32,7 +32,7 @@ jobs:
|
|||
run: mkdocs serve & sleep 10
|
||||
- name: Run pdf script
|
||||
run: node docs/misc/pdf.js http://localhost:8000/print_page/ BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf 'BunkerWeb documentation v${{ inputs.VERSION }}'
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf
|
||||
path: BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf
|
||||
|
|
|
|||
20
.github/workflows/linux-build.yml
vendored
20
.github/workflows/linux-build.yml
vendored
|
|
@ -37,7 +37,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Replace VERSION
|
||||
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui'
|
||||
run: ./misc/update-version.sh ${{ inputs.RELEASE }}
|
||||
|
|
@ -70,21 +70,21 @@ jobs:
|
|||
SSH_IP: ${{ secrets.ARM_SSH_IP }}
|
||||
SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }}
|
||||
- name: Setup Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
if: startsWith(env.ARCH, 'arm') == false
|
||||
- name: Setup Buildx (ARM)
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
if: startsWith(env.ARCH, 'arm') == true
|
||||
with:
|
||||
endpoint: ssh://root@arm
|
||||
platforms: linux/arm64,linux/arm/v7,linux/arm/v6
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -92,7 +92,7 @@ jobs:
|
|||
# Build testing package image
|
||||
- name: Build package image
|
||||
if: inputs.RELEASE == 'testing' || inputs.RELEASE == 'dev' || inputs.RELEASE == 'ui'
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
load: true
|
||||
|
|
@ -104,7 +104,7 @@ jobs:
|
|||
# Build non-testing package image
|
||||
- name: Build package image
|
||||
if: inputs.RELEASE != 'testing' && inputs.RELEASE != 'dev'
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
load: true
|
||||
|
|
@ -127,7 +127,7 @@ jobs:
|
|||
scp -r root@arm:/root/package-${{ inputs.LINUX }} ./package-${{ inputs.LINUX }}
|
||||
env:
|
||||
LARCH: ${{ env.LARCH }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
with:
|
||||
name: package-${{ inputs.LINUX }}-${{ env.LARCH }}
|
||||
path: package-${{ inputs.LINUX }}/*.${{ inputs.PACKAGE }}
|
||||
|
|
@ -135,12 +135,12 @@ jobs:
|
|||
- name: Extract metadata
|
||||
if: inputs.TEST == true
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
|
||||
with:
|
||||
images: ghcr.io/bunkerity/${{ inputs.LINUX }}-tests:${{ inputs.RELEASE }}
|
||||
- name: Build test image
|
||||
if: inputs.TEST == true
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
file: tests/linux/Dockerfile-${{ inputs.LINUX }}
|
||||
|
|
|
|||
4
.github/workflows/push-doc.yml
vendored
4
.github/workflows/push-doc.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.BUNKERBOT_TOKEN }}
|
||||
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
run: |
|
||||
git config --global user.name "BunkerBot"
|
||||
git config --global user.email "bunkerbot@bunkerity.com"
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install doc requirements
|
||||
|
|
|
|||
12
.github/workflows/push-docker.yml
vendored
12
.github/workflows/push-docker.yml
vendored
|
|
@ -33,14 +33,14 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -56,19 +56,19 @@ jobs:
|
|||
SSH_IP: ${{ secrets.ARM_SSH_IP }}
|
||||
SSH_CONFIG: ${{ secrets.ARM_SSH_CONFIG }}
|
||||
- name: Setup Buildx (ARM)
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
|
||||
with:
|
||||
endpoint: ssh://root@arm
|
||||
platforms: linux/arm64,linux/arm/v7,linux/arm/v6
|
||||
# Compute metadata
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
|
||||
with:
|
||||
images: bunkerity/${{ inputs.IMAGE }}
|
||||
# Build and push
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
|
||||
with:
|
||||
context: .
|
||||
file: ${{ inputs.DOCKERFILE }}
|
||||
|
|
|
|||
12
.github/workflows/push-github.yml
vendored
12
.github/workflows/push-github.yml
vendored
|
|
@ -15,15 +15,15 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checkout
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
# Get PDF doc
|
||||
- name: Get documentation
|
||||
if: inputs.VERSION != 'testing'
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: BunkerWeb_documentation_v${{ inputs.VERSION }}.pdf
|
||||
# Create tag
|
||||
- uses: rickstaa/action-create-tag@v1
|
||||
- uses: rickstaa/action-create-tag@88dbf7ff6fe2405f8e8f6c6fdfd78829bc631f83 # v1.6.3
|
||||
name: Create tag
|
||||
if: inputs.VERSION != 'testing'
|
||||
with:
|
||||
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
message: "v${{ inputs.VERSION }}"
|
||||
force_push_tag: true
|
||||
# Create tag
|
||||
- uses: rickstaa/action-create-tag@v1
|
||||
- uses: rickstaa/action-create-tag@88dbf7ff6fe2405f8e8f6c6fdfd78829bc631f83 # v1.6.3
|
||||
name: Create tag
|
||||
if: inputs.VERSION == 'testing'
|
||||
with:
|
||||
|
|
@ -51,7 +51,7 @@ jobs:
|
|||
# Create release
|
||||
- name: Create release
|
||||
if: inputs.VERSION != 'testing'
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
||||
with:
|
||||
body: |
|
||||
Documentation : https://docs.bunkerweb.io/${{ inputs.VERSION }}/
|
||||
|
|
@ -75,7 +75,7 @@ jobs:
|
|||
# Create release
|
||||
- name: Create release
|
||||
if: inputs.VERSION == 'testing'
|
||||
uses: softprops/action-gh-release@v1
|
||||
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
||||
with:
|
||||
body: |
|
||||
**The testing version of BunkerWeb should not be used in production, please use the latest stable version instead.**
|
||||
|
|
|
|||
10
.github/workflows/push-packagecloud.yml
vendored
10
.github/workflows/push-packagecloud.yml
vendored
|
|
@ -40,20 +40,20 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Install ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
uses: ruby/setup-ruby@52b8784594ec115fd17094752708121dc5dabb47 # v1.154.0
|
||||
with:
|
||||
ruby-version: "3.0"
|
||||
- name: Install packagecloud
|
||||
run: gem install package_cloud
|
||||
# Download packages
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
if: inputs.LINUX != 'el'
|
||||
with:
|
||||
name: package-${{ inputs.LINUX }}-${{ inputs.PACKAGE_ARCH }}
|
||||
path: /tmp/${{ inputs.LINUX }}
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
if: inputs.LINUX == 'el'
|
||||
with:
|
||||
name: package-rhel-${{ inputs.PACKAGE_ARCH }}
|
||||
|
|
@ -70,7 +70,7 @@ jobs:
|
|||
# run: sudo apt install -y rename && rename 's/[0-9]\.[0-9]\.[0-9]/testing/' /tmp/${{ inputs.LINUX }}/*.${{ inputs.PACKAGE }}
|
||||
# Push package
|
||||
- name: Push package to packagecloud
|
||||
uses: danielmundi/upload-packagecloud@v1
|
||||
uses: danielmundi/upload-packagecloud@46cd0e61152bf952dbc0d1759e609d3d22649030 # v1
|
||||
with:
|
||||
PACKAGE-NAME: /tmp/${{ inputs.LINUX }}/*.${{ inputs.PACKAGE }}
|
||||
PACKAGECLOUD-USERNAME: bunkerity
|
||||
|
|
|
|||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
|
@ -139,7 +139,7 @@ jobs:
|
|||
versionrpm: ${{ steps.getversionrpm.outputs.versionrpm }}
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Get VERSION
|
||||
id: getversion
|
||||
run: echo "version=$(cat src/VERSION | tr -d '\n')" >> "$GITHUB_OUTPUT"
|
||||
|
|
|
|||
2
.github/workflows/rm-arm.yml
vendored
2
.github/workflows/rm-arm.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Delete ARM VM
|
||||
uses: scaleway/action-scw@c718eca1fcb9fec1fb1433752d61599c6a0ad2e9
|
||||
with:
|
||||
|
|
|
|||
6
.github/workflows/scorecards-analysis.yml
vendored
6
.github/workflows/scorecards-analysis.yml
vendored
|
|
@ -15,16 +15,16 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@v2.2.0
|
||||
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: "Upload SARIF results to code scanning"
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
|||
10
.github/workflows/staging-create-infra.yml
vendored
10
.github/workflows/staging-create-infra.yml
vendored
|
|
@ -23,14 +23,14 @@ jobs:
|
|||
run: ssh-keygen -b 2048 -t rsa -f ~/.ssh/id_rsa -q -N "" && ssh-keygen -f ~/.ssh/id_rsa -y > ~/.ssh/id_rsa.pub && echo -e "Host *\n StrictHostKeyChecking no" > ~/.ssh/ssh_config
|
||||
if: inputs.TYPE != 'k8s'
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Install terraform
|
||||
uses: hashicorp/setup-terraform@v2
|
||||
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3
|
||||
- name: Install kubectl
|
||||
uses: azure/setup-kubectl@v3
|
||||
uses: azure/setup-kubectl@901a10e89ea615cf61f57ac05cecdf23e7de06d8 # v3.2
|
||||
if: inputs.TYPE == 'k8s'
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
|
||||
if: inputs.TYPE != 'k8s'
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
|
@ -54,7 +54,7 @@ jobs:
|
|||
if: always()
|
||||
env:
|
||||
SECRET_KEY: ${{ secrets.SECRET_KEY }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
|
||||
if: always()
|
||||
with:
|
||||
name: tf-${{ inputs.TYPE }}
|
||||
|
|
|
|||
8
.github/workflows/staging-delete-infra.yml
vendored
8
.github/workflows/staging-delete-infra.yml
vendored
|
|
@ -20,10 +20,10 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Install terraform
|
||||
uses: hashicorp/setup-terraform@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 # v2.0.3
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: tf-${{ inputs.TYPE }}
|
||||
path: /tmp
|
||||
|
|
@ -34,7 +34,7 @@ jobs:
|
|||
tar xf /tmp/terraform.tar -C / && mkdir ~/.ssh && touch ~/.ssh/id_rsa.pub
|
||||
env:
|
||||
SECRET_KEY: ${{ secrets.SECRET_KEY }}
|
||||
- uses: azure/setup-kubectl@v3
|
||||
- uses: azure/setup-kubectl@901a10e89ea615cf61f57ac05cecdf23e7de06d8 # v3.2
|
||||
if: inputs.TYPE == 'k8s'
|
||||
# Remove infra
|
||||
- run: kubectl delete daemonsets,replicasets,services,deployments,pods,rc,ingress,statefulsets --all --all-namespaces --timeout=60s ; kubectl delete pvc --all --timeout=60s ; kubectl delete pv --all --timeout=60s
|
||||
|
|
|
|||
10
.github/workflows/staging-tests.yml
vendored
10
.github/workflows/staging-tests.yml
vendored
|
|
@ -25,9 +25,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -43,7 +43,7 @@ jobs:
|
|||
if: inputs.TYPE == 'swarm'
|
||||
- name: Install test dependencies
|
||||
run: pip3 install --no-cache-dir --require-hashes -r tests/requirements.txt
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
||||
with:
|
||||
name: tf-k8s
|
||||
path: /tmp
|
||||
|
|
@ -66,9 +66,9 @@ jobs:
|
|||
REG_USER: ${{ github.actor }}
|
||||
REG_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: inputs.TYPE == 'k8s'
|
||||
- uses: azure/setup-kubectl@v3
|
||||
- uses: azure/setup-kubectl@901a10e89ea615cf61f57ac05cecdf23e7de06d8 # v3.2
|
||||
if: inputs.TYPE == 'k8s'
|
||||
- uses: azure/setup-helm@v3
|
||||
- uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5
|
||||
if: inputs.TYPE == 'k8s'
|
||||
- name: Pull BW linux ubuntu test image
|
||||
if: inputs.TYPE == 'linux'
|
||||
|
|
|
|||
6
.github/workflows/staging.yml
vendored
6
.github/workflows/staging.yml
vendored
|
|
@ -89,7 +89,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- id: set-matrix
|
||||
run: |
|
||||
tests=$(find ./tests/core/ -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | jq -c --raw-input --slurp 'split("\n")| .[0:-1]')
|
||||
|
|
@ -174,12 +174,12 @@ jobs:
|
|||
packages: write
|
||||
steps:
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
8
.github/workflows/test-core-linux.yml
vendored
8
.github/workflows/test-core-linux.yml
vendored
|
|
@ -16,9 +16,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: "pip"
|
||||
|
|
@ -34,7 +34,7 @@ jobs:
|
|||
sudo chmod 755 /opt/firefox /opt/firefox/firefox
|
||||
rm -f firefox-setup.tar.bz2
|
||||
- name: Download geckodriver
|
||||
uses: nick-fields/retry@v2
|
||||
uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2.9.0
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 20
|
||||
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
sudo chmod +x /usr/local/bin/geckodriver
|
||||
rm -f geckodriver.tar.gz
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
4
.github/workflows/test-core.yml
vendored
4
.github/workflows/test-core.yml
vendored
|
|
@ -16,9 +16,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
8
.github/workflows/tests-ui-linux.yml
vendored
8
.github/workflows/tests-ui-linux.yml
vendored
|
|
@ -13,9 +13,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Set up Python 3.11
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@65d7f2d534ac1bc67fcd62888c5f4f3d2cb2b236 # v4.7.1
|
||||
with:
|
||||
python-version: "3.11"
|
||||
cache: "pip"
|
||||
|
|
@ -31,7 +31,7 @@ jobs:
|
|||
sudo chmod 755 /opt/firefox /opt/firefox/firefox
|
||||
rm -f firefox-setup.tar.bz2
|
||||
- name: Download geckodriver
|
||||
uses: nick-fields/retry@v2
|
||||
uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2.9.0
|
||||
with:
|
||||
max_attempts: 3
|
||||
timeout_minutes: 20
|
||||
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
sudo chmod +x /usr/local/bin/geckodriver
|
||||
rm -f geckodriver.tar.gz
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
4
.github/workflows/tests-ui.yml
vendored
4
.github/workflows/tests-ui.yml
vendored
|
|
@ -12,9 +12,9 @@ jobs:
|
|||
steps:
|
||||
# Prepare
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
|
||||
- name: Login to ghcr
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
|
|
@ -3,26 +3,52 @@
|
|||
exclude: (^LICENSE.md$|^src/VERSION$|^src/(bw/misc/root-ca.pem$|deps/src/|common/core/modsecurity/files|ui/static/js/(editor/|utils/purify/|tsparticles\.bundle\.min\.js))|\.(svg|drawio|patch\d?|ascii|tf|tftpl)$)
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: f71fa2c1f9cf5cb705f73dffe4b21f7c61470ba9 # frozen: v4.4.0
|
||||
hooks:
|
||||
- id: check-case-conflict
|
||||
- id: detect-private-key
|
||||
- id: end-of-file-fixer
|
||||
- id: requirements-txt-fixer
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
exclude: ^(mkdocs.yml|examples/bigbluebutton/docker-compose.yml)$
|
||||
args: ["--allow-multiple-documents"]
|
||||
- id: check-case-conflict
|
||||
|
||||
- repo: https://github.com/ambv/black
|
||||
rev: 23.9.1
|
||||
rev: e87737140f32d3cd7c44ede75f02dcd58e55820e # frozen: 23.9.1
|
||||
hooks:
|
||||
- id: black
|
||||
name: Black Python Formatter
|
||||
language_version: python3.9
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: fc260393cc4ec09f8fc0a5ba4437f481c8b55dc1 # frozen: v3.0.3
|
||||
hooks:
|
||||
- id: prettier
|
||||
name: Prettier Code Formatter
|
||||
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 10f4af6dbcf93456ba7df762278ae61ba3120dc6 # frozen: 6.1.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
name: Flake8 Python Linter
|
||||
args: ["--max-line-length=250", "--ignore=E266,E402,E722,W503"]
|
||||
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: 6e41aba91fb32e9feb741a6258eefeb9c6e4a482 # frozen: v2.2.6
|
||||
hooks:
|
||||
- id: codespell
|
||||
name: Codespell Spell Checker
|
||||
exclude: (^src/(common/core/.+/files|bw/loading)/.+.html|modsecurity-rules.conf.*)$
|
||||
entry: codespell --ignore-regex="(tabEl|Widgits)" --skip src/ui/static/js/utils/flatpickr.js,CHANGELOG.md
|
||||
language: python
|
||||
types: [text]
|
||||
|
||||
- repo: https://github.com/gitleaks/gitleaks
|
||||
rev: v8.18.0
|
||||
rev: b813e6fe08b87541cb77296359ba1b7a50a00c98 # frozen: v8.18.0
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
|
||||
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||
rev: v0.9.0
|
||||
rev: 3f77b826548d8dc2d26675f077361c92773b50a7 # frozen: v0.9.0
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ src/deps/src/
|
|||
mkdocs.yml
|
||||
CHANGELOG.md
|
||||
CONTRIBUTING.md
|
||||
CODE_OF_CONDUCT.md
|
||||
LICENSE.md
|
||||
README.md
|
||||
SECURITY.md
|
||||
|
|
|
|||
|
|
@ -7,9 +7,14 @@
|
|||
- [BUGFIX] Fix UI clearing configs folder at startup
|
||||
- [BUGFIX] Fix Database not clearing old services when not using multisite
|
||||
- [BUGFIX] Fix UI using the wrong database when generating the new config when using an external database
|
||||
- [BUGFIX] Small fixes on linux paths creating unnecessary folders
|
||||
- [BUGFIX] Fix ACME renewal fails on redirection enabled Service
|
||||
- [MISC] Updated core dependencies
|
||||
- [MISC] Updated self-signed job to regenerate the cert if the subject or the expiration date has changed
|
||||
- [MISC] Jobs that download files from urls will now remove old cached files if urls are empty
|
||||
- [MISC] Replaced gevent with gthread in UI for security reasons
|
||||
- [MISC] Add HTML sanitization when injecting code in pages in the UI
|
||||
- [MISC] Optimize the way the UI handles services creation and edition
|
||||
|
||||
## v1.5.2 - 2023/10/10
|
||||
|
||||
|
|
|
|||
|
|
@ -335,10 +335,10 @@ Please contact us at [contact@bunkerity.com](mailto:contact@bunkerity.com) if yo
|
|||
|
||||
## Community
|
||||
|
||||
To get free community support you can use the following medias :
|
||||
To get free community support you can use the following media :
|
||||
|
||||
* The #help channel of BunkerWeb in the [Discord server](https://discord.com/invite/fTf46FmtyD)
|
||||
* The help category of [GitHub dicussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
* The help category of [GitHub discussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
* The [/r/BunkerWeb](https://www.reddit.com/r/BunkerWeb) subreddit
|
||||
* The [Server Fault](https://serverfault.com/) and [Super User](https://superuser.com/) forums
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ Please contact us at [contact@bunkerity.com](mailto:contact@bunkerity.com) if yo
|
|||
|
||||
## Where to get community support ?
|
||||
|
||||
To get free community support, you can use the following medias :
|
||||
To get free community support, you can use the following media :
|
||||
|
||||
- The #help channel of BunkerWeb in the [Discord server](https://discord.com/invite/fTf46FmtyD)
|
||||
- The help category of [GitHub dicussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
- The help category of [GitHub discussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
- The [/r/BunkerWeb](https://www.reddit.com/r/BunkerWeb) subreddit
|
||||
- The [Server Fault](https://serverfault.com/) and [Super User](https://superuser.com/) forums
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Concepts
|
||||
|
||||
<figure markdown>
|
||||
{ align=center, width="600" }
|
||||
{ align=center, width="600" }
|
||||
</figure>
|
||||
|
||||
## Integrations
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ def print_md_table(settings) -> MarkdownTableWriter:
|
|||
f"`{setting}`",
|
||||
"" if data["default"] == "" else f"`{data['default']}`",
|
||||
data["context"],
|
||||
"no" if not "multiple" in data else "yes",
|
||||
"no" if "multiple" not in data else "yes",
|
||||
data["help"],
|
||||
]
|
||||
for setting, data in settings.items()
|
||||
|
|
@ -42,15 +42,19 @@ print(
|
|||
file=doc,
|
||||
)
|
||||
print(
|
||||
"This section contains the full list of settings supported by BunkerWeb. If you are not yet familiar with BunkerWeb, you should first read the [concepts](concepts.md) section of the documentation. Please follow the instructions for your own [integration](integrations.md) on how to apply the settings.\n",
|
||||
"This section contains the full list of settings supported by BunkerWeb."
|
||||
+ " If you are not yet familiar with BunkerWeb, you should first read the [concepts](concepts.md) section of the documentation."
|
||||
+ " Please follow the instructions for your own [integration](integrations.md) on how to apply the settings.\n",
|
||||
file=doc,
|
||||
)
|
||||
print(
|
||||
"As a general rule when multisite mode is enabled, if you want to apply settings with multisite context to a specific server, you will need to add the primary (first) server name as a prefix like `www.example.com_USE_ANTIBOT=captcha` or `myapp.example.com_USE_GZIP=yes` for example.\n",
|
||||
"As a general rule when multisite mode is enabled, if you want to apply settings with multisite context to a specific server, you will need to add the primary"
|
||||
+ " (first) server name as a prefix like `www.example.com_USE_ANTIBOT=captcha` or `myapp.example.com_USE_GZIP=yes` for example.\n",
|
||||
file=doc,
|
||||
)
|
||||
print(
|
||||
'When settings are considered as "multiple", it means that you can have multiple groups of settings for the same feature by adding numbers as suffix like `REVERSE_PROXY_URL_1=/subdir`, `REVERSE_PROXY_HOST_1=http://myhost1`, `REVERSE_PROXY_URL_2=/anotherdir`, `REVERSE_PROXY_HOST_2=http://myhost2`, ... for example.\n',
|
||||
'When settings are considered as "multiple", it means that you can have multiple groups of settings for the same feature by adding numbers as suffix like `REVERSE_PROXY_URL_1=/subdir`,'
|
||||
+ " `REVERSE_PROXY_HOST_1=http://myhost1`, `REVERSE_PROXY_URL_2=/anotherdir`, `REVERSE_PROXY_HOST_2=http://myhost2`, ... for example.\n",
|
||||
file=doc,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ The first step is to install the plugin by putting the plugin files inside the c
|
|||
When using the [Swarm integration](integrations.md#swarm), plugins must be written to the volume mounted on `/data/plugins` into the scheduler container.
|
||||
|
||||
!!! info "Swarm volume"
|
||||
Configuring a Swarm volume that will persist when the scheduler service is running on different nodes is not covered is in this documentation. We will assume that you have a shared folder mounted on `/shared` accross all nodes.
|
||||
Configuring a Swarm volume that will persist when the scheduler service is running on different nodes is not covered is in this documentation. We will assume that you have a shared folder mounted on `/shared` across all nodes.
|
||||
|
||||
The first thing to do is to create the plugins folder :
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ Some helpers modules provide common helpful helpers :
|
|||
- `self.logger` : print logs
|
||||
- `bunkerweb.utils` : various useful functions
|
||||
- `bunkerweb.datastore` : access the global shared data on one instance (key/value store)
|
||||
- `bunkerweb.clusterstore` : access a Redis data store shared beetween BunkerWeb instances (key/value store)
|
||||
- `bunkerweb.clusterstore` : access a Redis data store shared between BunkerWeb instances (key/value store)
|
||||
|
||||
To access the functions, you first need to **require** the modules :
|
||||
|
||||
|
|
|
|||
|
|
@ -2322,7 +2322,7 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
|
|||
!!! warning "Feature is in beta"
|
||||
This feature is not production-ready. Feel free to test it and report us any bug using [issues](https://github.com/bunkerity/bunkerweb/issues) in the GitHub repository.
|
||||
|
||||
By default, BunkerWeb will only listen on IPv4 adresses and won't use IPv6 for network communications. If you want to enable IPv6 support, you need to set `USE_IPV6=yes`. Please note that IPv6 configuration of your network and environment is out-of-the-scope of this documentation.
|
||||
By default, BunkerWeb will only listen on IPv4 addresses and won't use IPv6 for network communications. If you want to enable IPv6 support, you need to set `USE_IPV6=yes`. Please note that IPv6 configuration of your network and environment is out-of-the-scope of this documentation.
|
||||
|
||||
=== "Docker"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
# pip-compile --allow-unsafe --generate-hashes --strip-extras requirements.in
|
||||
#
|
||||
babel==2.12.1 \
|
||||
--hash=sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610 \
|
||||
--hash=sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455
|
||||
babel==2.13.0 \
|
||||
--hash=sha256:04c3e2d28d2b7681644508f836be388ae49e0cfe91465095340395b60d00f210 \
|
||||
--hash=sha256:fbfcae1575ff78e26c7449136f1abbefc3c13ce542eeb13d43d50d8b047216ec
|
||||
# via mkdocs-material
|
||||
certifi==2023.7.22 \
|
||||
--hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \
|
||||
|
|
@ -267,9 +267,9 @@ pathvalidate==3.2.0 \
|
|||
--hash=sha256:5e8378cf6712bff67fbe7a8307d99fa8c1a0cb28aa477056f8fc374f0dff24ad \
|
||||
--hash=sha256:cc593caa6299b22b37f228148257997e2fa850eea2daf7e4cc9205cef6908dee
|
||||
# via pytablewriter
|
||||
platformdirs==3.10.0 \
|
||||
--hash=sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d \
|
||||
--hash=sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d
|
||||
platformdirs==3.11.0 \
|
||||
--hash=sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3 \
|
||||
--hash=sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e
|
||||
# via mkdocs
|
||||
pygments==2.16.1 \
|
||||
--hash=sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692 \
|
||||
|
|
@ -353,95 +353,95 @@ pyyaml-env-tag==0.1 \
|
|||
--hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \
|
||||
--hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069
|
||||
# via mkdocs
|
||||
regex==2023.8.8 \
|
||||
--hash=sha256:0085da0f6c6393428bf0d9c08d8b1874d805bb55e17cb1dfa5ddb7cfb11140bf \
|
||||
--hash=sha256:06c57e14ac723b04458df5956cfb7e2d9caa6e9d353c0b4c7d5d54fcb1325c46 \
|
||||
--hash=sha256:09b7f4c66aa9d1522b06e31a54f15581c37286237208df1345108fcf4e050c18 \
|
||||
--hash=sha256:0c59122ceccb905a941fb23b087b8eafc5290bf983ebcb14d2301febcbe199c7 \
|
||||
--hash=sha256:1005c60ed7037be0d9dea1f9c53cc42f836188227366370867222bda4c3c6bd7 \
|
||||
--hash=sha256:14898830f0a0eb67cae2bbbc787c1a7d6e34ecc06fbd39d3af5fe29a4468e2c9 \
|
||||
--hash=sha256:14dc6f2d88192a67d708341f3085df6a4f5a0c7b03dec08d763ca2cd86e9f559 \
|
||||
--hash=sha256:1e7d84d64c84ad97bf06f3c8cb5e48941f135ace28f450d86af6b6512f1c9a71 \
|
||||
--hash=sha256:2162ae2eb8b079622176a81b65d486ba50b888271302190870b8cc488587d280 \
|
||||
--hash=sha256:22283c769a7b01c8ac355d5be0715bf6929b6267619505e289f792b01304d898 \
|
||||
--hash=sha256:239c3c2a339d3b3ddd51c2daef10874410917cd2b998f043c13e2084cb191684 \
|
||||
--hash=sha256:293352710172239bf579c90a9864d0df57340b6fd21272345222fb6371bf82b3 \
|
||||
--hash=sha256:2ae54a338191e1356253e7883d9d19f8679b6143703086245fb14d1f20196be9 \
|
||||
--hash=sha256:2e73e5243af12d9cd6a9d6a45a43570dbe2e5b1cdfc862f5ae2b031e44dd95a8 \
|
||||
--hash=sha256:2e9216e0d2cdce7dbc9be48cb3eacb962740a09b011a116fd7af8c832ab116ca \
|
||||
--hash=sha256:3026cbcf11d79095a32d9a13bbc572a458727bd5b1ca332df4a79faecd45281c \
|
||||
--hash=sha256:3611576aff55918af2697410ff0293d6071b7e00f4b09e005d614686ac4cd57c \
|
||||
--hash=sha256:3ae646c35cb9f820491760ac62c25b6d6b496757fda2d51be429e0e7b67ae0ab \
|
||||
--hash=sha256:3b8e6ea6be6d64104d8e9afc34c151926f8182f84e7ac290a93925c0db004bfd \
|
||||
--hash=sha256:3d370ff652323c5307d9c8e4c62efd1956fb08051b0e9210212bc51168b4ff56 \
|
||||
--hash=sha256:3f7454aa427b8ab9101f3787eb178057c5250478e39b99540cfc2b889c7d0586 \
|
||||
--hash=sha256:40f029d73b10fac448c73d6eb33d57b34607f40116e9f6e9f0d32e9229b147d7 \
|
||||
--hash=sha256:423adfa872b4908843ac3e7a30f957f5d5282944b81ca0a3b8a7ccbbfaa06103 \
|
||||
--hash=sha256:4873ef92e03a4309b3ccd8281454801b291b689f6ad45ef8c3658b6fa761d7ac \
|
||||
--hash=sha256:48c640b99213643d141550326f34f0502fedb1798adb3c9eb79650b1ecb2f177 \
|
||||
--hash=sha256:4ae594c66f4a7e1ea67232a0846649a7c94c188d6c071ac0210c3e86a5f92109 \
|
||||
--hash=sha256:4b694430b3f00eb02c594ff5a16db30e054c1b9589a043fe9174584c6efa8033 \
|
||||
--hash=sha256:51d8ea2a3a1a8fe4f67de21b8b93757005213e8ac3917567872f2865185fa7fb \
|
||||
--hash=sha256:54de2619f5ea58474f2ac211ceea6b615af2d7e4306220d4f3fe690c91988a61 \
|
||||
--hash=sha256:551ad543fa19e94943c5b2cebc54c73353ffff08228ee5f3376bd27b3d5b9800 \
|
||||
--hash=sha256:5543c055d8ec7801901e1193a51570643d6a6ab8751b1f7dd9af71af467538bb \
|
||||
--hash=sha256:5cd9cd7170459b9223c5e592ac036e0704bee765706445c353d96f2890e816c8 \
|
||||
--hash=sha256:5ec4b3f0aebbbe2fc0134ee30a791af522a92ad9f164858805a77442d7d18570 \
|
||||
--hash=sha256:67ecd894e56a0c6108ec5ab1d8fa8418ec0cff45844a855966b875d1039a2e34 \
|
||||
--hash=sha256:6ab2ed84bf0137927846b37e882745a827458689eb969028af8032b1b3dac78e \
|
||||
--hash=sha256:704f63b774218207b8ccc6c47fcef5340741e5d839d11d606f70af93ee78e4d4 \
|
||||
--hash=sha256:7098c524ba9f20717a56a8d551d2ed491ea89cbf37e540759ed3b776a4f8d6eb \
|
||||
--hash=sha256:7aed90a72fc3654fba9bc4b7f851571dcc368120432ad68b226bd593f3f6c0b7 \
|
||||
--hash=sha256:7ce606c14bb195b0e5108544b540e2c5faed6843367e4ab3deb5c6aa5e681208 \
|
||||
--hash=sha256:7eb95fe8222932c10d4436e7a6f7c99991e3fdd9f36c949eff16a69246dee2dc \
|
||||
--hash=sha256:80b80b889cb767cc47f31d2b2f3dec2db8126fbcd0cff31b3925b4dc6609dcdb \
|
||||
--hash=sha256:82cd0a69cd28f6cc3789cc6adeb1027f79526b1ab50b1f6062bbc3a0ccb2dbc3 \
|
||||
--hash=sha256:83215147121e15d5f3a45d99abeed9cf1fe16869d5c233b08c56cdf75f43a504 \
|
||||
--hash=sha256:88900f521c645f784260a8d346e12a1590f79e96403971241e64c3a265c8ecdb \
|
||||
--hash=sha256:91129ff1bb0619bc1f4ad19485718cc623a2dc433dff95baadbf89405c7f6b57 \
|
||||
--hash=sha256:920974009fb37b20d32afcdf0227a2e707eb83fe418713f7a8b7de038b870d0b \
|
||||
--hash=sha256:9233ac249b354c54146e392e8a451e465dd2d967fc773690811d3a8c240ac601 \
|
||||
--hash=sha256:941460db8fe3bd613db52f05259c9336f5a47ccae7d7def44cc277184030a116 \
|
||||
--hash=sha256:942f8b1f3b223638b02df7df79140646c03938d488fbfb771824f3d05fc083a8 \
|
||||
--hash=sha256:964b16dcc10c79a4a2be9f1273fcc2684a9eedb3906439720598029a797b46e6 \
|
||||
--hash=sha256:9691a549c19c22d26a4f3b948071e93517bdf86e41b81d8c6ac8a964bb71e5a6 \
|
||||
--hash=sha256:96979d753b1dc3b2169003e1854dc67bfc86edf93c01e84757927f810b8c3c93 \
|
||||
--hash=sha256:987b9ac04d0b38ef4f89fbc035e84a7efad9cdd5f1e29024f9289182c8d99e09 \
|
||||
--hash=sha256:988631b9d78b546e284478c2ec15c8a85960e262e247b35ca5eaf7ee22f6050a \
|
||||
--hash=sha256:9a96edd79661e93327cfeac4edec72a4046e14550a1d22aa0dd2e3ca52aec921 \
|
||||
--hash=sha256:9b7408511fca48a82a119d78a77c2f5eb1b22fe88b0d2450ed0756d194fe7a9a \
|
||||
--hash=sha256:9dd6082f4e2aec9b6a0927202c85bc1b09dcab113f97265127c1dc20e2e32495 \
|
||||
--hash=sha256:a2ad5add903eb7cdde2b7c64aaca405f3957ab34f16594d2b78d53b8b1a6a7d6 \
|
||||
--hash=sha256:a8c65c17aed7e15a0c824cdc63a6b104dfc530f6fa8cb6ac51c437af52b481c7 \
|
||||
--hash=sha256:aadf28046e77a72f30dcc1ab185639e8de7f4104b8cb5c6dfa5d8ed860e57236 \
|
||||
--hash=sha256:b076da1ed19dc37788f6a934c60adf97bd02c7eea461b73730513921a85d4235 \
|
||||
--hash=sha256:b2aeab3895d778155054abea5238d0eb9a72e9242bd4b43f42fd911ef9a13470 \
|
||||
--hash=sha256:b82edc98d107cbc7357da7a5a695901b47d6eb0420e587256ba3ad24b80b7d0b \
|
||||
--hash=sha256:b8a0ccc8f2698f120e9e5742f4b38dc944c38744d4bdfc427616f3a163dd9de5 \
|
||||
--hash=sha256:b993b6f524d1e274a5062488a43e3f9f8764ee9745ccd8e8193df743dbe5ee61 \
|
||||
--hash=sha256:bb34d1605f96a245fc39790a117ac1bac8de84ab7691637b26ab2c5efb8f228c \
|
||||
--hash=sha256:bd3366aceedf274f765a3a4bc95d6cd97b130d1dda524d8f25225d14123c01db \
|
||||
--hash=sha256:c12f6f67495ea05c3d542d119d270007090bad5b843f642d418eb601ec0fa7be \
|
||||
--hash=sha256:c662a4cbdd6280ee56f841f14620787215a171c4e2d1744c9528bed8f5816c96 \
|
||||
--hash=sha256:c884d1a59e69e03b93cf0dfee8794c63d7de0ee8f7ffb76e5f75be8131b6400a \
|
||||
--hash=sha256:ca339088839582d01654e6f83a637a4b8194d0960477b9769d2ff2cfa0fa36d2 \
|
||||
--hash=sha256:cd2b6c5dfe0929b6c23dde9624483380b170b6e34ed79054ad131b20203a1a63 \
|
||||
--hash=sha256:ce0f9fbe7d295f9922c0424a3637b88c6c472b75eafeaff6f910494a1fa719ef \
|
||||
--hash=sha256:cf0633e4a1b667bfe0bb10b5e53fe0d5f34a6243ea2530eb342491f1adf4f739 \
|
||||
--hash=sha256:cf9273e96f3ee2ac89ffcb17627a78f78e7516b08f94dc435844ae72576a276e \
|
||||
--hash=sha256:d909b5a3fff619dc7e48b6b1bedc2f30ec43033ba7af32f936c10839e81b9217 \
|
||||
--hash=sha256:d9b6627408021452dcd0d2cdf8da0534e19d93d070bfa8b6b4176f99711e7f90 \
|
||||
--hash=sha256:de35342190deb7b866ad6ba5cbcccb2d22c0487ee0cbb251efef0843d705f0d4 \
|
||||
--hash=sha256:e51c80c168074faa793685656c38eb7a06cbad7774c8cbc3ea05552d615393d8 \
|
||||
--hash=sha256:e6bd1e9b95bc5614a7a9c9c44fde9539cba1c823b43a9f7bc11266446dd568e3 \
|
||||
--hash=sha256:e7a9aaa5a1267125eef22cef3b63484c3241aaec6f48949b366d26c7250e0357 \
|
||||
--hash=sha256:e951d1a8e9963ea51efd7f150450803e3b95db5939f994ad3d5edac2b6f6e2b4 \
|
||||
--hash=sha256:e9941a4ada58f6218694f382e43fdd256e97615db9da135e77359da257a7168b \
|
||||
--hash=sha256:f0640913d2c1044d97e30d7c41728195fc37e54d190c5385eacb52115127b882 \
|
||||
--hash=sha256:f0ccf3e01afeb412a1a9993049cb160d0352dba635bbca7762b2dc722aa5742a \
|
||||
--hash=sha256:f2181c20ef18747d5f4a7ea513e09ea03bdd50884a11ce46066bb90fe4213675 \
|
||||
--hash=sha256:f2200e00b62568cfd920127782c61bc1c546062a879cdc741cfcc6976668dfcf \
|
||||
--hash=sha256:fcbdc5f2b0f1cd0f6a56cdb46fe41d2cce1e644e3b68832f3eeebc5fb0f7712e
|
||||
regex==2023.10.3 \
|
||||
--hash=sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a \
|
||||
--hash=sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07 \
|
||||
--hash=sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca \
|
||||
--hash=sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58 \
|
||||
--hash=sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54 \
|
||||
--hash=sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed \
|
||||
--hash=sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff \
|
||||
--hash=sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528 \
|
||||
--hash=sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9 \
|
||||
--hash=sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971 \
|
||||
--hash=sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14 \
|
||||
--hash=sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af \
|
||||
--hash=sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302 \
|
||||
--hash=sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec \
|
||||
--hash=sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597 \
|
||||
--hash=sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b \
|
||||
--hash=sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd \
|
||||
--hash=sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767 \
|
||||
--hash=sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f \
|
||||
--hash=sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6 \
|
||||
--hash=sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293 \
|
||||
--hash=sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be \
|
||||
--hash=sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41 \
|
||||
--hash=sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc \
|
||||
--hash=sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29 \
|
||||
--hash=sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964 \
|
||||
--hash=sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d \
|
||||
--hash=sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a \
|
||||
--hash=sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc \
|
||||
--hash=sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55 \
|
||||
--hash=sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af \
|
||||
--hash=sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930 \
|
||||
--hash=sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e \
|
||||
--hash=sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d \
|
||||
--hash=sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863 \
|
||||
--hash=sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c \
|
||||
--hash=sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f \
|
||||
--hash=sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e \
|
||||
--hash=sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d \
|
||||
--hash=sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368 \
|
||||
--hash=sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb \
|
||||
--hash=sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52 \
|
||||
--hash=sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8 \
|
||||
--hash=sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4 \
|
||||
--hash=sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac \
|
||||
--hash=sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e \
|
||||
--hash=sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2 \
|
||||
--hash=sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a \
|
||||
--hash=sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4 \
|
||||
--hash=sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa \
|
||||
--hash=sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533 \
|
||||
--hash=sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b \
|
||||
--hash=sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588 \
|
||||
--hash=sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0 \
|
||||
--hash=sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915 \
|
||||
--hash=sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841 \
|
||||
--hash=sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a \
|
||||
--hash=sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988 \
|
||||
--hash=sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292 \
|
||||
--hash=sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3 \
|
||||
--hash=sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c \
|
||||
--hash=sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f \
|
||||
--hash=sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420 \
|
||||
--hash=sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9 \
|
||||
--hash=sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f \
|
||||
--hash=sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0 \
|
||||
--hash=sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b \
|
||||
--hash=sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037 \
|
||||
--hash=sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b \
|
||||
--hash=sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee \
|
||||
--hash=sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c \
|
||||
--hash=sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b \
|
||||
--hash=sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353 \
|
||||
--hash=sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051 \
|
||||
--hash=sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039 \
|
||||
--hash=sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a \
|
||||
--hash=sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b \
|
||||
--hash=sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e \
|
||||
--hash=sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5 \
|
||||
--hash=sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf \
|
||||
--hash=sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94 \
|
||||
--hash=sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991 \
|
||||
--hash=sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711 \
|
||||
--hash=sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a \
|
||||
--hash=sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab \
|
||||
--hash=sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a \
|
||||
--hash=sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11 \
|
||||
--hash=sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48
|
||||
# via mkdocs-material
|
||||
requests==2.31.0 \
|
||||
--hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
|
||||
|
|
@ -465,16 +465,16 @@ tcolorpy==0.1.4 \
|
|||
--hash=sha256:d0926480aa5012f34877d69fc3b670f207dc165674e68ad07458fa6ee5b12724 \
|
||||
--hash=sha256:f0dceb1cb95e554cee63024b3cd2fd8d4628c568773de2d1e6b4f0478461901c
|
||||
# via pytablewriter
|
||||
typepy==1.3.1 \
|
||||
--hash=sha256:892566bff279368d63f02901aba0a3ce78cd7a319ec1f2bf6c8baab3520207a3 \
|
||||
--hash=sha256:dfc37b888d6eed8542208389efa60ec8454e06fd84b276b45b2e33897f9d7825
|
||||
typepy==1.3.2 \
|
||||
--hash=sha256:b69fd48b9f50cdb3809906eef36b855b3134ff66c8893a4f8580abddb0b39517 \
|
||||
--hash=sha256:d5d1022a424132622993800f1d2cd16cfdb691ac4e3b9c325f0fcb37799db1ae
|
||||
# via
|
||||
# dataproperty
|
||||
# pytablewriter
|
||||
# tabledata
|
||||
urllib3==2.0.5 \
|
||||
--hash=sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594 \
|
||||
--hash=sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e
|
||||
urllib3==2.0.6 \
|
||||
--hash=sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2 \
|
||||
--hash=sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564
|
||||
# via requests
|
||||
verspec==0.1.0 \
|
||||
--hash=sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 \
|
||||
|
|
|
|||
|
|
@ -284,4 +284,4 @@ If you have bots that need to access your website, the recommended way to avoid
|
|||
|
||||
## Timezone
|
||||
|
||||
When using container-based integrations, the timezone of the container may not match the one of the host machine. To resolve that, you can set the `TZ` environment variable to the timezone of your choice on your containers (e.g. `TZ=Europe/Paris`). You will find the list of timezone identifers [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List).
|
||||
When using container-based integrations, the timezone of the container may not match the one of the host machine. To resolve that, you can set the `TZ` environment variable to the timezone of your choice on your containers (e.g. `TZ=Europe/Paris`). You will find the list of timezone identifiers [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List).
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ services:
|
|||
REVERSE_PROXY_URL: "/"
|
||||
REVERSE_PROXY_HOST: "http://mydrupal"
|
||||
CUSTOM_CONF_MODSEC_CRS_drupal: 'SecAction "id:900130,phase:1,nolog,pass,t:none,setvar:tx.crs_exclusions_drupal=1"'
|
||||
# Onces the installation is done, you can remove these lines
|
||||
# Once the installation is done, you can remove these lines
|
||||
LIMIT_REQ_URL_1: "/core/install.php"
|
||||
LIMIT_REQ_RATE_1: "5r/s"
|
||||
labels:
|
||||
|
|
@ -75,6 +75,7 @@ volumes:
|
|||
bw-data:
|
||||
db-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
ipam:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ services:
|
|||
USE_REVERSE_PROXY: "yes"
|
||||
REVERSE_PROXY_URL: "/"
|
||||
REVERSE_PROXY_HOST: "http://myps"
|
||||
# Onces the installation is done, you can remove these lines
|
||||
# Once the installation is done, you can remove these lines
|
||||
LIMIT_REQ_URL_1: "/install/index.php"
|
||||
LIMIT_REQ_RATE_1: "8r/s"
|
||||
labels:
|
||||
|
|
@ -85,6 +85,7 @@ volumes:
|
|||
ps-data:
|
||||
db-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
ipam:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version: "3.5"
|
||||
version: "3.5"
|
||||
|
||||
services:
|
||||
bunkerweb:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ site_name: BunkerWeb
|
|||
site_url: https://docs.bunkerweb.io/
|
||||
repo_url: https://github.com/bunkerity/bunkerweb
|
||||
site_description: Make your web services secure by default.
|
||||
copyright: Bunkerity
|
||||
copyright: Copyright © <script>document.write(new Date().getFullYear())</script> Bunkerity
|
||||
#remote_branch: ?
|
||||
#remote_name: ?
|
||||
|
||||
|
|
@ -49,7 +49,6 @@ markdown_extensions:
|
|||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
|
||||
copyright: Copyright © <script>document.write(new Date().getFullYear())</script> Bunkerity
|
||||
extra:
|
||||
version:
|
||||
provider: mike
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ authors = [
|
|||
|
||||
[tool.black]
|
||||
py39 = true
|
||||
line-length = 250
|
||||
include = '\.pyi?$'
|
||||
exclude = '''
|
||||
/(
|
||||
| \.git
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from os import getenv
|
||||
from time import sleep
|
||||
from typing import Optional
|
||||
from copy import deepcopy
|
||||
|
||||
from ConfigCaller import ConfigCaller # type: ignore
|
||||
|
|
@ -25,13 +24,20 @@ class Config(ConfigCaller):
|
|||
"modsec",
|
||||
"modsec-crs",
|
||||
]
|
||||
self.__configs = {
|
||||
config_type: {} for config_type in self._supported_config_types
|
||||
}
|
||||
self.__configs = {config_type: {} for config_type in self._supported_config_types}
|
||||
self.__config = {}
|
||||
|
||||
self._db = Database(self.__logger)
|
||||
|
||||
def _update_settings(self):
|
||||
plugins = self._db.get_plugins()
|
||||
if not plugins:
|
||||
self.__logger.error("No plugins in database, can't update settings...")
|
||||
return
|
||||
self._settings = {}
|
||||
for plugin in plugins:
|
||||
self._settings.update(plugin["settings"])
|
||||
|
||||
def __get_full_env(self) -> dict:
|
||||
env_instances = {"SERVER_NAME": ""}
|
||||
for instance in self.__instances:
|
||||
|
|
@ -106,9 +112,7 @@ class Config(ConfigCaller):
|
|||
while True:
|
||||
curr_changes = self._db.check_changes()
|
||||
if isinstance(curr_changes, str):
|
||||
self.__logger.error(
|
||||
f"An error occurred when checking for changes in the database : {curr_changes}"
|
||||
)
|
||||
self.__logger.error(f"An error occurred when checking for changes in the database : {curr_changes}")
|
||||
elif not any(curr_changes.values()):
|
||||
break
|
||||
else:
|
||||
|
|
@ -134,9 +138,7 @@ class Config(ConfigCaller):
|
|||
|
||||
# save custom configs to database
|
||||
if "custom_configs" in changes:
|
||||
err = self._db.save_custom_configs(
|
||||
custom_configs, "autoconf", changed=False
|
||||
)
|
||||
err = self._db.save_custom_configs(custom_configs, "autoconf", changed=False)
|
||||
if err:
|
||||
success = False
|
||||
self.__logger.error(
|
||||
|
|
@ -146,8 +148,6 @@ class Config(ConfigCaller):
|
|||
# update changes in db
|
||||
ret = self._db.checked_changes(changes, value=True)
|
||||
if ret:
|
||||
self.__logger.error(
|
||||
f"An error occurred when setting the changes to checked in the database : {ret}"
|
||||
)
|
||||
self.__logger.error(f"An error occurred when setting the changes to checked in the database : {ret}")
|
||||
|
||||
return success
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from abc import abstractmethod
|
||||
from os import getenv
|
||||
from time import sleep
|
||||
from typing import Literal, Optional, Union
|
||||
from typing import Literal, Union
|
||||
|
||||
from Config import Config
|
||||
|
||||
|
|
@ -20,12 +20,8 @@ class Controller(Config):
|
|||
self._type = ctrl_type
|
||||
self._instances = []
|
||||
self._services = []
|
||||
self._configs = {
|
||||
config_type: {} for config_type in self._supported_config_types
|
||||
}
|
||||
self._logger = setup_logger(
|
||||
f"{self._type}-controller", getenv("LOG_LEVEL", "INFO")
|
||||
)
|
||||
self._configs = {config_type: {} for config_type in self._supported_config_types}
|
||||
self._logger = setup_logger(f"{self._type}-controller", getenv("LOG_LEVEL", "INFO"))
|
||||
|
||||
def wait(self, wait_time: int) -> list:
|
||||
all_ready = False
|
||||
|
|
@ -105,7 +101,7 @@ class Controller(Config):
|
|||
|
||||
def _is_service_present(self, server_name):
|
||||
for service in self._services:
|
||||
if not "SERVER_NAME" in service or not service["SERVER_NAME"]:
|
||||
if "SERVER_NAME" not in service or not service["SERVER_NAME"]:
|
||||
continue
|
||||
if server_name == service["SERVER_NAME"].strip().split(" ")[0]:
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ class DockerController(Controller):
|
|||
def __init__(self, docker_host):
|
||||
super().__init__("docker")
|
||||
self.__client = DockerClient(base_url=docker_host)
|
||||
self.__custom_confs_rx = re_compile(
|
||||
r"^bunkerweb.CUSTOM_CONF_(SERVER_HTTP|MODSEC_CRS|MODSEC)_(.+)$"
|
||||
)
|
||||
self.__custom_confs_rx = re_compile(r"^bunkerweb.CUSTOM_CONF_(SERVER_HTTP|MODSEC_CRS|MODSEC)_(.+)$")
|
||||
|
||||
def _get_controller_instances(self) -> List[Container]:
|
||||
return self.__client.containers.list(filters={"label": "bunkerweb.INSTANCE"})
|
||||
|
|
@ -27,10 +25,7 @@ class DockerController(Controller):
|
|||
instance = {}
|
||||
instance["name"] = controller_instance.name
|
||||
instance["hostname"] = controller_instance.name
|
||||
instance["health"] = (
|
||||
controller_instance.status == "running"
|
||||
and controller_instance.attrs["State"]["Health"]["Status"] == "healthy"
|
||||
)
|
||||
instance["health"] = controller_instance.status == "running" and controller_instance.attrs["State"]["Health"]["Status"] == "healthy"
|
||||
instance["env"] = {}
|
||||
for env in controller_instance.attrs["Config"]["Env"]:
|
||||
variable = env.split("=")[0]
|
||||
|
|
@ -53,9 +48,7 @@ class DockerController(Controller):
|
|||
def _get_static_services(self) -> List[dict]:
|
||||
services = []
|
||||
variables = {}
|
||||
for instance in self.__client.containers.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
for instance in self.__client.containers.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
if not instance.attrs or not instance.attrs.get("Config", {}).get("Env"):
|
||||
continue
|
||||
|
||||
|
|
@ -70,9 +63,7 @@ class DockerController(Controller):
|
|||
for variable, value in variables.items():
|
||||
prefix = variable.split("_")[0]
|
||||
real_variable = variable.replace(f"{prefix}_", "", 1)
|
||||
if prefix == server_name and self._is_setting_context(
|
||||
real_variable, "multisite"
|
||||
):
|
||||
if prefix == server_name and self._is_setting_context(real_variable, "multisite"):
|
||||
service[real_variable] = value
|
||||
services.append(service)
|
||||
return services
|
||||
|
|
@ -80,9 +71,7 @@ class DockerController(Controller):
|
|||
def get_configs(self) -> Dict[str, Dict[str, Any]]:
|
||||
configs = {config_type: {} for config_type in self._supported_config_types}
|
||||
# get site configs from labels
|
||||
for container in self.__client.containers.list(
|
||||
filters={"label": "bunkerweb.SERVER_NAME"}
|
||||
):
|
||||
for container in self.__client.containers.list(filters={"label": "bunkerweb.SERVER_NAME"}):
|
||||
labels = container.labels # type: ignore (labels is inside a container)
|
||||
if isinstance(labels, list):
|
||||
labels = {label: "" for label in labels}
|
||||
|
|
@ -100,9 +89,7 @@ class DockerController(Controller):
|
|||
result = self.__custom_confs_rx.search(variable)
|
||||
if result is None:
|
||||
continue
|
||||
configs[result.group(1).lower().replace("_", "-")][
|
||||
f"{server_name}/{result.group(2)}"
|
||||
] = value
|
||||
configs[result.group(1).lower().replace("_", "-")][f"{server_name}/{result.group(2)}"] = value
|
||||
return configs
|
||||
|
||||
def apply_config(self) -> bool:
|
||||
|
|
@ -117,16 +104,13 @@ class DockerController(Controller):
|
|||
self._set_autoconf_load_db()
|
||||
for _ in self.__client.events(decode=True, filters={"type": "container"}):
|
||||
try:
|
||||
self._update_settings()
|
||||
self._instances = self.get_instances()
|
||||
self._services = self.get_services()
|
||||
self._configs = self.get_configs()
|
||||
if not self.update_needed(
|
||||
self._instances, self._services, configs=self._configs
|
||||
):
|
||||
if not self.update_needed(self._instances, self._services, configs=self._configs):
|
||||
continue
|
||||
self._logger.info(
|
||||
"Caught Docker event, deploying new configuration ..."
|
||||
)
|
||||
self._logger.info("Caught Docker event, deploying new configuration ...")
|
||||
if not self.apply_config():
|
||||
self._logger.error("Error while deploying new configuration")
|
||||
else:
|
||||
|
|
@ -136,6 +120,4 @@ class DockerController(Controller):
|
|||
|
||||
self._set_autoconf_load_db()
|
||||
except:
|
||||
self._logger.error(
|
||||
f"Exception while processing events :\n{format_exc()}"
|
||||
)
|
||||
self._logger.error(f"Exception while processing events :\n{format_exc()}")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.11.5-alpine@sha256:cd311c6a0164f34a7edbf364e05258b07d66d3f7bc155139dcb9bef88a186ded AS builder
|
||||
FROM python:3.12.0-alpine@sha256:ae35274f417fc81ba6ee1fc84206e8517f28117566ee6a04a64f004c1409bdac AS builder
|
||||
|
||||
# Copy python requirements
|
||||
COPY src/deps/requirements.txt /tmp/requirements-deps.txt
|
||||
|
|
@ -34,7 +34,7 @@ COPY src/common/helpers helpers
|
|||
COPY src/common/settings.json settings.json
|
||||
COPY src/common/utils utils
|
||||
|
||||
FROM python:3.11.5-alpine@sha256:cd311c6a0164f34a7edbf364e05258b07d66d3f7bc155139dcb9bef88a186ded
|
||||
FROM python:3.12.0-alpine@sha256:ae35274f417fc81ba6ee1fc84206e8517f28117566ee6a04a64f004c1409bdac
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
|
|||
|
|
@ -19,21 +19,12 @@ class IngressController(Controller):
|
|||
self.__networkingv1 = client.NetworkingV1Api()
|
||||
|
||||
def _get_controller_instances(self) -> list:
|
||||
return [
|
||||
pod
|
||||
for pod in self.__corev1.list_pod_for_all_namespaces(watch=False).items
|
||||
if (
|
||||
pod.metadata.annotations
|
||||
and "bunkerweb.io/INSTANCE" in pod.metadata.annotations
|
||||
)
|
||||
]
|
||||
return [pod for pod in self.__corev1.list_pod_for_all_namespaces(watch=False).items if (pod.metadata.annotations and "bunkerweb.io/INSTANCE" in pod.metadata.annotations)]
|
||||
|
||||
def _to_instances(self, controller_instance) -> List[dict]:
|
||||
instance = {}
|
||||
instance["name"] = controller_instance.metadata.name
|
||||
instance["hostname"] = (
|
||||
controller_instance.status.pod_ip or controller_instance.metadata.name
|
||||
)
|
||||
instance["hostname"] = controller_instance.status.pod_ip or controller_instance.metadata.name
|
||||
health = False
|
||||
if controller_instance.status.conditions:
|
||||
for condition in controller_instance.status.conditions:
|
||||
|
|
@ -48,9 +39,7 @@ class IngressController(Controller):
|
|||
pod = container
|
||||
break
|
||||
if not pod:
|
||||
self._logger.warning(
|
||||
f"Missing container bunkerweb in pod {controller_instance.metadata.name}"
|
||||
)
|
||||
self._logger.warning(f"Missing container bunkerweb in pod {controller_instance.metadata.name}")
|
||||
else:
|
||||
for env in pod.env:
|
||||
instance["env"][env.name] = env.value or ""
|
||||
|
|
@ -159,10 +148,7 @@ class IngressController(Controller):
|
|||
services = []
|
||||
variables = {}
|
||||
for instance in self.__corev1.list_pod_for_all_namespaces(watch=False).items:
|
||||
if (
|
||||
not instance.metadata.annotations
|
||||
or not "bunkerweb.io/INSTANCE" in instance.metadata.annotations
|
||||
):
|
||||
if not instance.metadata.annotations or "bunkerweb.io/INSTANCE" not in instance.metadata.annotations:
|
||||
continue
|
||||
|
||||
pod = None
|
||||
|
|
@ -181,22 +167,15 @@ class IngressController(Controller):
|
|||
for variable, value in variables.items():
|
||||
prefix = variable.split("_")[0]
|
||||
real_variable = variable.replace(f"{prefix}_", "", 1)
|
||||
if prefix == server_name and self._is_setting_context(
|
||||
real_variable, "multisite"
|
||||
):
|
||||
if prefix == server_name and self._is_setting_context(real_variable, "multisite"):
|
||||
service[real_variable] = value
|
||||
services.append(service)
|
||||
return services
|
||||
|
||||
def get_configs(self) -> dict:
|
||||
configs = {config_type: {} for config_type in self._supported_config_types}
|
||||
for configmap in self.__corev1.list_config_map_for_all_namespaces(
|
||||
watch=False
|
||||
).items:
|
||||
if (
|
||||
not configmap.metadata.annotations
|
||||
or "bunkerweb.io/CONFIG_TYPE" not in configmap.metadata.annotations
|
||||
):
|
||||
for configmap in self.__corev1.list_config_map_for_all_namespaces(watch=False).items:
|
||||
if not configmap.metadata.annotations or "bunkerweb.io/CONFIG_TYPE" not in configmap.metadata.annotations:
|
||||
continue
|
||||
|
||||
config_type = configmap.metadata.annotations["bunkerweb.io/CONFIG_TYPE"]
|
||||
|
|
@ -212,16 +191,12 @@ class IngressController(Controller):
|
|||
continue
|
||||
config_site = ""
|
||||
if "bunkerweb.io/CONFIG_SITE" in configmap.metadata.annotations:
|
||||
if not self._is_service_present(
|
||||
configmap.metadata.annotations["bunkerweb.io/CONFIG_SITE"]
|
||||
):
|
||||
if not self._is_service_present(configmap.metadata.annotations["bunkerweb.io/CONFIG_SITE"]):
|
||||
self._logger.warning(
|
||||
f"Ignoring config {configmap.metadata.name} because {configmap.metadata.annotations['bunkerweb.io/CONFIG_SITE']} doesn't exist",
|
||||
)
|
||||
continue
|
||||
config_site = (
|
||||
f"{configmap.metadata.annotations['bunkerweb.io/CONFIG_SITE']}/"
|
||||
)
|
||||
config_site = f"{configmap.metadata.annotations['bunkerweb.io/CONFIG_SITE']}/"
|
||||
for config_name, config_data in configmap.data.items():
|
||||
configs[config_type][f"{config_site}{config_name}"] = config_data
|
||||
return configs
|
||||
|
|
@ -247,17 +222,16 @@ class IngressController(Controller):
|
|||
for _ in w.stream(what):
|
||||
self.__internal_lock.acquire()
|
||||
locked = True
|
||||
self._update_settings()
|
||||
self._instances = self.get_instances()
|
||||
self._services = self.get_services()
|
||||
self._configs = self.get_configs()
|
||||
if not self.update_needed(
|
||||
self._instances, self._services, configs=self._configs
|
||||
):
|
||||
if not self.update_needed(self._instances, self._services, configs=self._configs):
|
||||
self.__internal_lock.release()
|
||||
locked = False
|
||||
continue
|
||||
self._logger.info(
|
||||
f"Catched kubernetes event ({watch_type}), deploying new configuration ...",
|
||||
f"Caught kubernetes event ({watch_type}), deploying new configuration ...",
|
||||
)
|
||||
try:
|
||||
ret = self.apply_config()
|
||||
|
|
@ -308,10 +282,7 @@ class IngressController(Controller):
|
|||
def process_events(self):
|
||||
self._set_autoconf_load_db()
|
||||
watch_types = ("pod", "ingress", "configmap", "service")
|
||||
threads = [
|
||||
Thread(target=self.__watch, args=(watch_type,))
|
||||
for watch_type in watch_types
|
||||
]
|
||||
threads = [Thread(target=self.__watch, args=(watch_type,)) for watch_type in watch_types]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
|
|
|
|||
|
|
@ -26,9 +26,7 @@ class SwarmController(Controller):
|
|||
def _to_instances(self, controller_instance) -> List[dict]:
|
||||
instances = []
|
||||
instance_env = {}
|
||||
for env in controller_instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"][
|
||||
"Env"
|
||||
]:
|
||||
for env in controller_instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]:
|
||||
variable = env.split("=")[0]
|
||||
value = env.replace(f"{variable}=", "", 1)
|
||||
if self._is_setting(variable):
|
||||
|
|
@ -61,12 +59,8 @@ class SwarmController(Controller):
|
|||
def _get_static_services(self) -> List[dict]:
|
||||
services = []
|
||||
variables = {}
|
||||
for instance in self.__client.services.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
if not instance.attrs or not instance.attrs.get("Spec", {}).get(
|
||||
"TaskTemplate", {}
|
||||
).get("ContainerSpec", {}).get("Env"):
|
||||
for instance in self.__client.services.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
if not instance.attrs or not instance.attrs.get("Spec", {}).get("TaskTemplate", {}).get("ContainerSpec", {}).get("Env"):
|
||||
continue
|
||||
|
||||
for env in instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]:
|
||||
|
|
@ -80,9 +74,7 @@ class SwarmController(Controller):
|
|||
for variable, value in variables.items():
|
||||
prefix = variable.split("_")[0]
|
||||
real_variable = variable.replace(f"{prefix}_", "", 1)
|
||||
if prefix == server_name and self._is_setting_context(
|
||||
real_variable, "multisite"
|
||||
):
|
||||
if prefix == server_name and self._is_setting_context(real_variable, "multisite"):
|
||||
service[real_variable] = value
|
||||
services.append(service)
|
||||
return services
|
||||
|
|
@ -91,15 +83,8 @@ class SwarmController(Controller):
|
|||
configs = {}
|
||||
for config_type in self._supported_config_types:
|
||||
configs[config_type] = {}
|
||||
for config in self.__client.configs.list(
|
||||
filters={"label": "bunkerweb.CONFIG_TYPE"}
|
||||
):
|
||||
if (
|
||||
not config.name
|
||||
or not config.attrs
|
||||
or not config.attrs.get("Spec", {}).get("Labels", {})
|
||||
or not config.attrs.get("Spec", {}).get("Data", {})
|
||||
):
|
||||
for config in self.__client.configs.list(filters={"label": "bunkerweb.CONFIG_TYPE"}):
|
||||
if not config.name or not config.attrs or not config.attrs.get("Spec", {}).get("Labels", {}) or not config.attrs.get("Spec", {}).get("Data", {}):
|
||||
continue
|
||||
|
||||
config_type = config.attrs["Spec"]["Labels"]["bunkerweb.CONFIG_TYPE"]
|
||||
|
|
@ -111,19 +96,13 @@ class SwarmController(Controller):
|
|||
continue
|
||||
config_site = ""
|
||||
if "bunkerweb.CONFIG_SITE" in config.attrs["Spec"]["Labels"]:
|
||||
if not self._is_service_present(
|
||||
config.attrs["Spec"]["Labels"]["bunkerweb.CONFIG_SITE"]
|
||||
):
|
||||
if not self._is_service_present(config.attrs["Spec"]["Labels"]["bunkerweb.CONFIG_SITE"]):
|
||||
self._logger.warning(
|
||||
f"Ignoring config {config_name} because {config.attrs['Spec']['Labels']['bunkerweb.CONFIG_SITE']} doesn't exist",
|
||||
)
|
||||
continue
|
||||
config_site = (
|
||||
f"{config.attrs['Spec']['Labels']['bunkerweb.CONFIG_SITE']}/"
|
||||
)
|
||||
configs[config_type][f"{config_site}{config_name}"] = b64decode(
|
||||
config.attrs["Spec"]["Data"]
|
||||
)
|
||||
config_site = f"{config.attrs['Spec']['Labels']['bunkerweb.CONFIG_SITE']}/"
|
||||
configs[config_type][f"{config_site}{config_name}"] = b64decode(config.attrs["Spec"]["Data"])
|
||||
return configs
|
||||
|
||||
def apply_config(self) -> bool:
|
||||
|
|
@ -139,36 +118,27 @@ class SwarmController(Controller):
|
|||
locked = False
|
||||
error = False
|
||||
try:
|
||||
for _ in self.__client.events(
|
||||
decode=True, filters={"type": event_type}
|
||||
):
|
||||
for _ in self.__client.events(decode=True, filters={"type": event_type}):
|
||||
self.__internal_lock.acquire()
|
||||
locked = True
|
||||
try:
|
||||
self._update_settings()
|
||||
self._instances = self.get_instances()
|
||||
self._services = self.get_services()
|
||||
self._configs = self.get_configs()
|
||||
if not self.update_needed(
|
||||
self._instances, self._services, configs=self._configs
|
||||
):
|
||||
if not self.update_needed(self._instances, self._services, configs=self._configs):
|
||||
self.__internal_lock.release()
|
||||
locked = False
|
||||
continue
|
||||
self._logger.info(
|
||||
f"Catched Swarm event ({event_type}), deploying new configuration ..."
|
||||
)
|
||||
self._logger.info(f"Caught Swarm event ({event_type}), deploying new configuration ...")
|
||||
if not self.apply_config():
|
||||
self._logger.error(
|
||||
"Error while deploying new configuration"
|
||||
)
|
||||
self._logger.error("Error while deploying new configuration")
|
||||
else:
|
||||
self._logger.info(
|
||||
"Successfully deployed new configuration 🚀",
|
||||
)
|
||||
except:
|
||||
self._logger.error(
|
||||
f"Exception while processing Swarm event ({event_type}) :\n{format_exc()}"
|
||||
)
|
||||
self._logger.error(f"Exception while processing Swarm event ({event_type}) :\n{format_exc()}")
|
||||
self.__internal_lock.release()
|
||||
locked = False
|
||||
except:
|
||||
|
|
@ -187,10 +157,7 @@ class SwarmController(Controller):
|
|||
def process_events(self):
|
||||
self._set_autoconf_load_db()
|
||||
event_types = ("service", "config")
|
||||
threads = [
|
||||
Thread(target=self.__event, args=(event_type,))
|
||||
for event_type in event_types
|
||||
]
|
||||
threads = [Thread(target=self.__event, args=(event_type,)) for event_type in event_types]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
for thread in threads:
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@ from sys import exit as sys_exit, path as sys_path
|
|||
from traceback import format_exc
|
||||
from pathlib import Path
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("api",), ("db",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("api",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ log "ENTRYPOINT" "ℹ️" "Starting BunkerWeb v$(cat /usr/share/bunkerweb/VERSIO
|
|||
# trap SIGTERM and SIGINT
|
||||
function trap_exit() {
|
||||
# shellcheck disable=SC2317
|
||||
log "ENTRYPOINT" "ℹ️" "Catched stop operation, stopping nginx ..."
|
||||
log "ENTRYPOINT" "ℹ️" "Caught stop operation, stopping nginx ..."
|
||||
# shellcheck disable=SC2317
|
||||
nginx -s stop
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ trap "trap_exit" TERM INT QUIT
|
|||
# trap SIGHUP
|
||||
function trap_reload() {
|
||||
# shellcheck disable=SC2317
|
||||
log "ENTRYPOINT" "ℹ️" "Catched reload operation"
|
||||
log "ENTRYPOINT" "ℹ️" "Caught reload operation"
|
||||
# shellcheck disable=SC2317
|
||||
if [ -f /var/run/bunkerweb/nginx.pid ] ; then
|
||||
# shellcheck disable=SC2317
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -20,7 +20,7 @@ function plugin:initialize(id, ctx)
|
|||
end
|
||||
end
|
||||
self.is_request = multisite
|
||||
-- Store common objets
|
||||
-- Store common objects
|
||||
self.logger = logger:new(self.id)
|
||||
local use_redis, err = utils.get_variable("USE_REDIS", false)
|
||||
if not use_redis then
|
||||
|
|
|
|||
|
|
@ -64,17 +64,13 @@ class CLI(ApiCaller):
|
|||
if redis_host:
|
||||
redis_port = self.__variables.get("REDIS_PORT", "6379")
|
||||
if not redis_port.isdigit():
|
||||
self.__logger.error(
|
||||
f"REDIS_PORT is not a valid port number: {redis_port}, defaulting to 6379"
|
||||
)
|
||||
self.__logger.error(f"REDIS_PORT is not a valid port number: {redis_port}, defaulting to 6379")
|
||||
redis_port = "6379"
|
||||
redis_port = int(redis_port)
|
||||
|
||||
redis_db = self.__variables.get("REDIS_DB", "0")
|
||||
if not redis_db.isdigit():
|
||||
self.__logger.error(
|
||||
f"REDIS_DB is not a valid database number: {redis_db}, defaulting to 0"
|
||||
)
|
||||
self.__logger.error(f"REDIS_DB is not a valid database number: {redis_db}, defaulting to 0")
|
||||
redis_db = "0"
|
||||
redis_db = int(redis_db)
|
||||
|
||||
|
|
@ -83,18 +79,12 @@ class CLI(ApiCaller):
|
|||
try:
|
||||
redis_timeout = float(redis_timeout)
|
||||
except ValueError:
|
||||
self.__logger.error(
|
||||
f"REDIS_TIMEOUT is not a valid timeout: {redis_timeout}, defaulting to 1000 ms"
|
||||
)
|
||||
self.__logger.error(f"REDIS_TIMEOUT is not a valid timeout: {redis_timeout}, defaulting to 1000 ms")
|
||||
redis_timeout = 1000.0
|
||||
|
||||
redis_keepalive_pool = self.__variables.get(
|
||||
"REDIS_KEEPALIVE_POOL", "10"
|
||||
)
|
||||
redis_keepalive_pool = self.__variables.get("REDIS_KEEPALIVE_POOL", "10")
|
||||
if not redis_keepalive_pool.isdigit():
|
||||
self.__logger.error(
|
||||
f"REDIS_KEEPALIVE_POOL is not a valid number of connections: {redis_keepalive_pool}, defaulting to 10"
|
||||
)
|
||||
self.__logger.error(f"REDIS_KEEPALIVE_POOL is not a valid number of connections: {redis_keepalive_pool}, defaulting to 10")
|
||||
redis_keepalive_pool = "10"
|
||||
redis_keepalive_pool = int(redis_keepalive_pool)
|
||||
|
||||
|
|
@ -109,9 +99,7 @@ class CLI(ApiCaller):
|
|||
ssl=self.__variables.get("REDIS_SSL", "no") == "yes",
|
||||
)
|
||||
else:
|
||||
self.__logger.error(
|
||||
"USE_REDIS is set to yes but REDIS_HOST is not set, disabling redis"
|
||||
)
|
||||
self.__logger.error("USE_REDIS is set to yes but REDIS_HOST is not set, disabling redis")
|
||||
self.__use_redis = False
|
||||
|
||||
if not db_path.is_dir() or self.__integration not in (
|
||||
|
|
@ -143,9 +131,7 @@ class CLI(ApiCaller):
|
|||
return "autoconf"
|
||||
elif integration_path.is_file():
|
||||
return integration_path.read_text(encoding="utf-8").strip().lower()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
return "docker"
|
||||
|
||||
return "linux"
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ from os.path import join
|
|||
from sys import exit as sys_exit, path as sys_path
|
||||
from traceback import format_exc
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("api",), ("db",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("api",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -25,9 +22,7 @@ if __name__ == "__main__":
|
|||
subparsers = parser.add_subparsers(help="command", dest="command")
|
||||
|
||||
# Unban subparser
|
||||
parser_unban = subparsers.add_parser(
|
||||
"unban", help="remove a ban from the cache"
|
||||
)
|
||||
parser_unban = subparsers.add_parser("unban", help="remove a ban from the cache")
|
||||
parser_unban.add_argument("ip", type=str, help="IP address to unban")
|
||||
|
||||
# Ban subparser
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ from sys import exit as sys_exit, path as sys_path
|
|||
from traceback import format_exc
|
||||
from typing import Tuple
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("db",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -63,10 +60,7 @@ try:
|
|||
# Multisite case
|
||||
if getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
getenv(f"{first_server}_USE_BLACKLIST", getenv("USE_BLACKLIST", "yes"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_USE_BLACKLIST", getenv("USE_BLACKLIST", "yes")) == "yes":
|
||||
blacklist_activated = True
|
||||
break
|
||||
# Singlesite case
|
||||
|
|
@ -133,7 +127,7 @@ try:
|
|||
blacklist_path.joinpath(f"{kind}.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db(f"{kind}.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete {kind}.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete {kind}.list from cache : {err}")
|
||||
if all_fresh:
|
||||
_exit(0)
|
||||
|
||||
|
|
@ -152,9 +146,7 @@ try:
|
|||
resp = get(url, stream=True, timeout=10)
|
||||
|
||||
if resp.status_code != 200:
|
||||
logger.warning(
|
||||
f"Got status code {resp.status_code}, skipping..."
|
||||
)
|
||||
logger.warning(f"Got status code {resp.status_code}, skipping...")
|
||||
continue
|
||||
|
||||
iterable = resp.iter_lines()
|
||||
|
|
@ -203,9 +195,7 @@ try:
|
|||
status = 1
|
||||
except:
|
||||
status = 2
|
||||
logger.error(
|
||||
f"Exception while getting blacklist from {url} :\n{format_exc()}"
|
||||
)
|
||||
logger.error(f"Exception while getting blacklist from {url} :\n{format_exc()}")
|
||||
|
||||
except:
|
||||
status = 2
|
||||
|
|
|
|||
|
|
@ -32,10 +32,7 @@ try:
|
|||
# Multisite case
|
||||
if getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
getenv(f"{first_server}_USE_BUNKERNET", getenv("USE_BUNKERNET", "yes"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_USE_BUNKERNET", getenv("USE_BUNKERNET", "yes")) == "yes":
|
||||
bunkernet_activated = True
|
||||
break
|
||||
# Singlesite case
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ for deps_path in [
|
|||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
from bunkernet import register, ping, get_id
|
||||
from bunkernet import register, ping
|
||||
from Database import Database # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
from jobs import get_file_in_db, set_file_in_db, del_file_in_db
|
||||
from jobs import get_file_in_db, set_file_in_db, del_file_in_db # type: ignore
|
||||
|
||||
logger = setup_logger("BUNKERNET", getenv("LOG_LEVEL", "INFO"))
|
||||
exit_status = 0
|
||||
|
|
@ -38,10 +38,7 @@ try:
|
|||
servers = servers.split(" ")
|
||||
|
||||
for first_server in servers:
|
||||
if (
|
||||
getenv(f"{first_server}_USE_BUNKERNET", getenv("USE_BUNKERNET", "yes"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_USE_BUNKERNET", getenv("USE_BUNKERNET", "yes")) == "yes":
|
||||
bunkernet_activated = True
|
||||
break
|
||||
# Singlesite case
|
||||
|
|
@ -73,9 +70,7 @@ try:
|
|||
logger.info("Registering instance on BunkerNet API ...")
|
||||
ok, status, data = register()
|
||||
if not ok:
|
||||
logger.error(
|
||||
f"Error while sending register request to BunkerNet API : {data}"
|
||||
)
|
||||
logger.error(f"Error while sending register request to BunkerNet API : {data}")
|
||||
_exit(2)
|
||||
elif status == 429:
|
||||
logger.warning(
|
||||
|
|
@ -102,23 +97,17 @@ try:
|
|||
)
|
||||
_exit(2)
|
||||
elif data.get("result", "ko") != "ok":
|
||||
logger.error(
|
||||
f"Received error from BunkerNet API while sending register request : {data.get('data', {})}"
|
||||
)
|
||||
logger.error(f"Received error from BunkerNet API while sending register request : {data.get('data', {})}")
|
||||
_exit(2)
|
||||
bunkernet_id = data["data"]
|
||||
instance_id_path.write_text(bunkernet_id, encoding="utf-8")
|
||||
registered = True
|
||||
exit_status = 1
|
||||
logger.info(
|
||||
f"Successfully registered on BunkerNet API with instance id {data['data']}"
|
||||
)
|
||||
logger.info(f"Successfully registered on BunkerNet API with instance id {data['data']}")
|
||||
else:
|
||||
bunkernet_id = bunkernet_id or instance_id_path.read_bytes()
|
||||
bunkernet_id = bunkernet_id.decode()
|
||||
logger.info(
|
||||
f"Already registered on BunkerNet API with instance id {bunkernet_id}"
|
||||
)
|
||||
logger.info(f"Already registered on BunkerNet API with instance id {bunkernet_id}")
|
||||
|
||||
sleep(1)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ from requests import request as requests_request, ReadTimeout
|
|||
from typing import Literal, Optional, Tuple, Union
|
||||
|
||||
|
||||
def request(
|
||||
method: Union[Literal["POST"], Literal["GET"]], url: str, _id: Optional[str] = None
|
||||
) -> Tuple[bool, Optional[int], Union[str, dict]]:
|
||||
def request(method: Union[Literal["POST"], Literal["GET"]], url: str, _id: Optional[str] = None) -> Tuple[bool, Optional[int], Union[str, dict]]:
|
||||
data = {"integration": get_integration(), "version": get_version()}
|
||||
headers = {"User-Agent": f"BunkerWeb/{get_version()}"}
|
||||
if _id is not None:
|
||||
|
|
@ -51,19 +49,11 @@ def data() -> Tuple[bool, Optional[int], Union[str, dict]]:
|
|||
|
||||
|
||||
def get_id() -> str:
|
||||
return (
|
||||
Path(sep, "var", "cache", "bunkerweb", "bunkernet", "instance.id")
|
||||
.read_text(encoding="utf-8")
|
||||
.strip()
|
||||
)
|
||||
return Path(sep, "var", "cache", "bunkerweb", "bunkernet", "instance.id").read_text(encoding="utf-8").strip()
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
return (
|
||||
Path(sep, "usr", "share", "bunkerweb", "VERSION")
|
||||
.read_text(encoding="utf-8")
|
||||
.strip()
|
||||
)
|
||||
return Path(sep, "usr", "share", "bunkerweb", "VERSION").read_text(encoding="utf-8").strip()
|
||||
|
||||
|
||||
def get_integration() -> str:
|
||||
|
|
@ -78,9 +68,7 @@ def get_integration() -> str:
|
|||
return "autoconf"
|
||||
elif integration_path.is_file():
|
||||
return integration_path.read_text(encoding="utf-8").strip().lower()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
return "docker"
|
||||
|
||||
return "linux"
|
||||
|
|
|
|||
|
|
@ -26,28 +26,20 @@ logger = setup_logger("CUSTOM-CERT", getenv("LOG_LEVEL", "INFO"))
|
|||
db = None
|
||||
|
||||
|
||||
def check_cert(
|
||||
cert_path: str, key_path: str, first_server: Optional[str] = None
|
||||
) -> bool:
|
||||
def check_cert(cert_path: str, key_path: str, first_server: Optional[str] = None) -> bool:
|
||||
try:
|
||||
if not cert_path or not key_path:
|
||||
logger.warning(
|
||||
"Both variables CUSTOM_SSL_CERT and CUSTOM_SSL_KEY have to be set to use custom certificates"
|
||||
)
|
||||
logger.warning("Both variables CUSTOM_SSL_CERT and CUSTOM_SSL_KEY have to be set to use custom certificates")
|
||||
return False
|
||||
|
||||
cert_path: Path = Path(normpath(cert_path))
|
||||
key_path: Path = Path(normpath(key_path))
|
||||
|
||||
if not cert_path.is_file():
|
||||
logger.warning(
|
||||
f"Certificate file {cert_path} is not a valid file, ignoring the custom certificate"
|
||||
)
|
||||
logger.warning(f"Certificate file {cert_path} is not a valid file, ignoring the custom certificate")
|
||||
return False
|
||||
elif not key_path.is_file():
|
||||
logger.warning(
|
||||
f"Key file {key_path} is not a valid file, ignoring the custom certificate"
|
||||
)
|
||||
logger.warning(f"Key file {key_path} is not a valid file, ignoring the custom certificate")
|
||||
return False
|
||||
|
||||
cert_cache_path = Path(
|
||||
|
|
@ -66,9 +58,7 @@ def check_cert(
|
|||
if old_hash == cert_hash:
|
||||
return False
|
||||
|
||||
cached, err = cache_file(
|
||||
cert_path, cert_cache_path, cert_hash, db, delete_file=False
|
||||
)
|
||||
cached, err = cache_file(cert_path, cert_cache_path, cert_hash, db, delete_file=False)
|
||||
if not cached:
|
||||
logger.error(f"Error while caching custom-cert cert.pem file : {err}")
|
||||
|
||||
|
|
@ -86,9 +76,7 @@ def check_cert(
|
|||
key_hash = file_hash(key_path)
|
||||
old_hash = cache_hash(key_cache_path, db)
|
||||
if old_hash != key_hash:
|
||||
cached, err = cache_file(
|
||||
key_path, key_cache_path, key_hash, db, delete_file=False
|
||||
)
|
||||
cached, err = cache_file(key_path, key_cache_path, key_hash, db, delete_file=False)
|
||||
if not cached:
|
||||
logger.error(f"Error while caching custom-cert key.pem file : {err}")
|
||||
|
||||
|
|
@ -103,14 +91,10 @@ def check_cert(
|
|||
status = 0
|
||||
|
||||
try:
|
||||
Path(sep, "var", "cache", "bunkerweb", "customcert").mkdir(
|
||||
parents=True, exist_ok=True
|
||||
)
|
||||
Path(sep, "var", "cache", "bunkerweb", "customcert").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if getenv("USE_CUSTOM_SSL", "no") == "yes" and getenv("SERVER_NAME", "") != "":
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
cert_path = getenv("CUSTOM_SSL_CERT", "")
|
||||
key_path = getenv("CUSTOM_SSL_KEY", "")
|
||||
|
|
@ -131,16 +115,11 @@ try:
|
|||
servers = servers.split(" ")
|
||||
|
||||
for first_server in servers:
|
||||
if not first_server or (
|
||||
getenv(f"{first_server}_USE_CUSTOM_SSL", getenv("USE_CUSTOM_SSL", "no"))
|
||||
!= "yes"
|
||||
):
|
||||
if not first_server or (getenv(f"{first_server}_USE_CUSTOM_SSL", getenv("USE_CUSTOM_SSL", "no")) != "yes"):
|
||||
continue
|
||||
|
||||
if not db:
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
cert_path = getenv(f"{first_server}_CUSTOM_SSL_CERT", "")
|
||||
key_path = getenv(f"{first_server}_CUSTOM_SSL_KEY", "")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ from sys import exit as sys_exit, path as sys_path
|
|||
from traceback import format_exc
|
||||
from typing import Tuple
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("db",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -63,10 +60,7 @@ try:
|
|||
# Multisite case
|
||||
if getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
getenv(f"{first_server}_USE_GREYLIST", getenv("USE_GREYLIST", "no"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_USE_GREYLIST", getenv("USE_GREYLIST", "no")) == "yes":
|
||||
greylist_activated = True
|
||||
break
|
||||
# Singlesite case
|
||||
|
|
@ -117,7 +111,7 @@ try:
|
|||
greylist_path.joinpath(f"{kind}.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db(f"{kind}.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete {kind}.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete {kind}.list from cache : {err}")
|
||||
if all_fresh:
|
||||
_exit(0)
|
||||
|
||||
|
|
@ -136,9 +130,7 @@ try:
|
|||
resp = get(url, stream=True, timeout=10)
|
||||
|
||||
if resp.status_code != 200:
|
||||
logger.warning(
|
||||
f"Got status code {resp.status_code}, skipping..."
|
||||
)
|
||||
logger.warning(f"Got status code {resp.status_code}, skipping...")
|
||||
continue
|
||||
|
||||
iterable = resp.iter_lines()
|
||||
|
|
@ -187,9 +179,7 @@ try:
|
|||
status = 1
|
||||
except:
|
||||
status = 2
|
||||
logger.error(
|
||||
f"Exception while getting greylist from {url} :\n{format_exc()}"
|
||||
)
|
||||
logger.error(f"Exception while getting greylist from {url} :\n{format_exc()}")
|
||||
|
||||
except:
|
||||
status = 2
|
||||
|
|
|
|||
|
|
@ -114,9 +114,7 @@ try:
|
|||
with tar_open(fileobj=BytesIO(content), mode="r") as tar:
|
||||
tar.extractall(path=temp_dir)
|
||||
else:
|
||||
logger.error(
|
||||
f"Unknown file type for {plugin_url}, either zip or tar are supported, skipping..."
|
||||
)
|
||||
logger.error(f"Unknown file type for {plugin_url}, either zip or tar are supported, skipping...")
|
||||
continue
|
||||
except:
|
||||
logger.error(
|
||||
|
|
|
|||
|
|
@ -43,9 +43,7 @@ try:
|
|||
with lock:
|
||||
response = None
|
||||
try:
|
||||
response = get(
|
||||
"https://db-ip.com/db/download/ip-to-asn-lite", timeout=5
|
||||
)
|
||||
response = get("https://db-ip.com/db/download/ip-to-asn-lite", timeout=5)
|
||||
except RequestException:
|
||||
logger.warning("Unable to check if asn.mmdb is the latest version")
|
||||
|
||||
|
|
@ -59,14 +57,10 @@ try:
|
|||
_sha1.update(data)
|
||||
|
||||
if response.content.decode().find(_sha1.hexdigest()) != -1:
|
||||
logger.info(
|
||||
"asn.mmdb is already the latest version, skipping download..."
|
||||
)
|
||||
logger.info("asn.mmdb is already the latest version, skipping download...")
|
||||
dl_mmdb = False
|
||||
else:
|
||||
logger.warning(
|
||||
"Unable to check if asn.mmdb is the latest version, downloading it anyway..."
|
||||
)
|
||||
logger.warning("Unable to check if asn.mmdb is the latest version, downloading it anyway...")
|
||||
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,7 @@ try:
|
|||
with lock:
|
||||
response = None
|
||||
try:
|
||||
response = get(
|
||||
"https://db-ip.com/db/download/ip-to-country-lite", timeout=5
|
||||
)
|
||||
response = get("https://db-ip.com/db/download/ip-to-country-lite", timeout=5)
|
||||
except RequestException:
|
||||
logger.warning("Unable to check if country.mmdb is the latest version")
|
||||
|
||||
|
|
@ -59,14 +57,10 @@ try:
|
|||
_sha1.update(data)
|
||||
|
||||
if response.content.decode().find(_sha1.hexdigest()) != -1:
|
||||
logger.info(
|
||||
"country.mmdb is already the latest version, skipping download..."
|
||||
)
|
||||
logger.info("country.mmdb is already the latest version, skipping download...")
|
||||
dl_mmdb = False
|
||||
else:
|
||||
logger.warning(
|
||||
"Unable to check if country.mmdb is the latest version, downloading it anyway..."
|
||||
)
|
||||
logger.warning("Unable to check if country.mmdb is the latest version, downloading it anyway...")
|
||||
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
|
|
|
|||
|
|
@ -39,9 +39,7 @@ try:
|
|||
bw_integration = "Autoconf"
|
||||
elif integration_path.is_file():
|
||||
bw_integration = integration_path.read_text(encoding="utf-8").strip()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
bw_integration = "Docker"
|
||||
|
||||
token = getenv("CERTBOT_TOKEN", "")
|
||||
|
|
@ -49,9 +47,7 @@ try:
|
|||
|
||||
# Cluster case
|
||||
if bw_integration in ("Docker", "Swarm", "Kubernetes", "Autoconf"):
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
lock = Lock()
|
||||
|
||||
with lock:
|
||||
|
|
@ -69,9 +65,7 @@ try:
|
|||
)
|
||||
if not sent:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Can't send API request to {api.endpoint}/lets-encrypt/challenge : {err}"
|
||||
)
|
||||
logger.error(f"Can't send API request to {api.endpoint}/lets-encrypt/challenge : {err}")
|
||||
elif status != 200:
|
||||
status = 1
|
||||
logger.error(
|
||||
|
|
|
|||
|
|
@ -39,18 +39,14 @@ try:
|
|||
bw_integration = "Autoconf"
|
||||
elif integration_path.is_file():
|
||||
bw_integration = integration_path.read_text(encoding="utf-8").strip()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
bw_integration = "Docker"
|
||||
|
||||
token = getenv("CERTBOT_TOKEN", "")
|
||||
|
||||
# Cluster case
|
||||
if bw_integration in ("Docker", "Swarm", "Kubernetes", "Autoconf"):
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
lock = Lock()
|
||||
with lock:
|
||||
instances = db.get_instances()
|
||||
|
|
@ -60,14 +56,10 @@ try:
|
|||
f"http://{instance['hostname']}:{instance['port']}",
|
||||
host=instance["server_name"],
|
||||
)
|
||||
sent, err, status, resp = api.request(
|
||||
"DELETE", "/lets-encrypt/challenge", data={"token": token}
|
||||
)
|
||||
sent, err, status, resp = api.request("DELETE", "/lets-encrypt/challenge", data={"token": token})
|
||||
if not sent:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Can't send API request to {api.endpoint}/lets-encrypt/challenge : {err}"
|
||||
)
|
||||
logger.error(f"Can't send API request to {api.endpoint}/lets-encrypt/challenge : {err}")
|
||||
elif status != 200:
|
||||
status = 1
|
||||
logger.error(
|
||||
|
|
|
|||
|
|
@ -42,9 +42,7 @@ try:
|
|||
bw_integration = "Autoconf"
|
||||
elif integration_path.is_file():
|
||||
bw_integration = integration_path.read_text(encoding="utf-8").strip()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
bw_integration = "Docker"
|
||||
|
||||
token = getenv("CERTBOT_TOKEN", "")
|
||||
|
|
@ -64,9 +62,7 @@ try:
|
|||
tgz.seek(0, 0)
|
||||
files = {"archive.tar.gz": tgz}
|
||||
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
lock = Lock()
|
||||
|
||||
with lock:
|
||||
|
|
@ -77,19 +73,13 @@ try:
|
|||
host = instance["server_name"]
|
||||
api = API(endpoint, host=host)
|
||||
|
||||
sent, err, status, resp = api.request(
|
||||
"POST", "/lets-encrypt/certificates", files=files
|
||||
)
|
||||
sent, err, status, resp = api.request("POST", "/lets-encrypt/certificates", files=files)
|
||||
if not sent:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Can't send API request to {api.endpoint}/lets-encrypt/certificates : {err}"
|
||||
)
|
||||
logger.error(f"Can't send API request to {api.endpoint}/lets-encrypt/certificates : {err}")
|
||||
elif status != 200:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Error while sending API request to {api.endpoint}/lets-encrypt/certificates : status = {resp['status']}, msg = {resp['msg']}"
|
||||
)
|
||||
logger.error(f"Error while sending API request to {api.endpoint}/lets-encrypt/certificates : status = {resp['status']}, msg = {resp['msg']}")
|
||||
else:
|
||||
logger.info(
|
||||
f"Successfully sent API request to {api.endpoint}/lets-encrypt/certificates",
|
||||
|
|
@ -97,18 +87,12 @@ try:
|
|||
sent, err, status, resp = api.request("POST", "/reload")
|
||||
if not sent:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Can't send API request to {api.endpoint}/reload : {err}"
|
||||
)
|
||||
logger.error(f"Can't send API request to {api.endpoint}/reload : {err}")
|
||||
elif status != 200:
|
||||
status = 1
|
||||
logger.error(
|
||||
f"Error while sending API request to {api.endpoint}/reload : status = {resp['status']}, msg = {resp['msg']}"
|
||||
)
|
||||
logger.error(f"Error while sending API request to {api.endpoint}/reload : status = {resp['status']}, msg = {resp['msg']}")
|
||||
else:
|
||||
logger.info(
|
||||
f"Successfully sent API request to {api.endpoint}/reload"
|
||||
)
|
||||
logger.info(f"Successfully sent API request to {api.endpoint}/reload")
|
||||
# Linux case
|
||||
else:
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -24,15 +24,13 @@ for deps_path in [
|
|||
|
||||
from Database import Database # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
from jobs import get_file_in_db, set_file_in_db
|
||||
from jobs import get_file_in_db, set_file_in_db # type: ignore
|
||||
|
||||
logger = setup_logger("LETS-ENCRYPT.new", getenv("LOG_LEVEL", "INFO"))
|
||||
status = 0
|
||||
|
||||
|
||||
def certbot_new(
|
||||
domains: str, email: str, letsencrypt_path: Path, letsencrypt_job_path: Path
|
||||
) -> int:
|
||||
def certbot_new(domains: str, email: str, letsencrypt_path: Path, letsencrypt_job_path: Path) -> int:
|
||||
return run(
|
||||
[
|
||||
join(sep, "usr", "share", "bunkerweb", "deps", "python", "bin", "certbot"),
|
||||
|
|
@ -60,8 +58,7 @@ def certbot_new(
|
|||
+ (["--staging"] if getenv("USE_LETS_ENCRYPT_STAGING", "no") == "yes" else []),
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
env=environ.copy()
|
||||
| {"PYTHONPATH": join(sep, "usr", "share", "bunkerweb", "deps", "python")},
|
||||
env=environ.copy() | {"PYTHONPATH": join(sep, "usr", "share", "bunkerweb", "deps", "python")},
|
||||
).returncode
|
||||
|
||||
|
||||
|
|
@ -81,8 +78,7 @@ def certbot_check_domains(domains: list[str], letsencrypt_path: Path) -> int:
|
|||
stdout=PIPE,
|
||||
stderr=STDOUT,
|
||||
text=True,
|
||||
env=environ.copy()
|
||||
| {"PYTHONPATH": join(sep, "usr", "share", "bunkerweb", "deps", "python")},
|
||||
env=environ.copy() | {"PYTHONPATH": join(sep, "usr", "share", "bunkerweb", "deps", "python")},
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
logger.error(f"Error while checking certificates :\n{proc.stdout}")
|
||||
|
|
@ -91,10 +87,7 @@ def certbot_check_domains(domains: list[str], letsencrypt_path: Path) -> int:
|
|||
needed_domains = set(domains)
|
||||
for raw_domains in findall(r"^ Domains: (.*)$", proc.stdout, MULTILINE):
|
||||
current_domains = raw_domains.split(" ")
|
||||
if (
|
||||
current_domains[0] == first_needed_domain
|
||||
and set(current_domains) == needed_domains
|
||||
):
|
||||
if current_domains[0] == first_needed_domain and set(current_domains) == needed_domains:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
|
@ -108,10 +101,7 @@ try:
|
|||
use_letsencrypt = True
|
||||
elif getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
first_server
|
||||
and getenv(f"{first_server}_AUTO_LETS_ENCRYPT", "no") == "yes"
|
||||
):
|
||||
if first_server and getenv(f"{first_server}_AUTO_LETS_ENCRYPT", "no") == "yes":
|
||||
use_letsencrypt = True
|
||||
break
|
||||
|
||||
|
|
@ -123,12 +113,8 @@ try:
|
|||
letsencrypt_path = Path(sep, "var", "cache", "bunkerweb", "letsencrypt")
|
||||
letsencrypt_path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
letsencrypt_job_path = Path(
|
||||
sep, "usr", "share", "bunkerweb", "core", "letsencrypt", "jobs"
|
||||
)
|
||||
Path(sep, "var", "lib", "bunkerweb", "letsencrypt").mkdir(
|
||||
parents=True, exist_ok=True
|
||||
)
|
||||
letsencrypt_job_path = Path(sep, "usr", "share", "bunkerweb", "core", "letsencrypt", "jobs")
|
||||
Path(sep, "var", "lib", "bunkerweb", "letsencrypt").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Get env vars
|
||||
bw_integration = "Linux"
|
||||
|
|
@ -142,9 +128,7 @@ try:
|
|||
bw_integration = "Autoconf"
|
||||
elif integration_path.is_file():
|
||||
bw_integration = integration_path.read_text(encoding="utf-8").strip()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
bw_integration = "Docker"
|
||||
|
||||
# Extract letsencrypt folder if it exists in db
|
||||
|
|
@ -209,9 +193,7 @@ try:
|
|||
continue
|
||||
else:
|
||||
status = 1 if status == 0 else status
|
||||
logger.info(
|
||||
f"Certificate generation succeeded for domain(s) : {domains}"
|
||||
)
|
||||
logger.info(f"Certificate generation succeeded for domain(s) : {domains}")
|
||||
|
||||
# Singlesite case
|
||||
elif getenv("AUTO_LETS_ENCRYPT", "no") == "yes" and getenv("SERVER_NAME"):
|
||||
|
|
@ -243,9 +225,7 @@ try:
|
|||
logger.error(f"Certificate generation failed for domain(s) : {domains}")
|
||||
else:
|
||||
status = 1
|
||||
logger.info(
|
||||
f"Certificate generation succeeded for domain(s) : {domains}"
|
||||
)
|
||||
logger.info(f"Certificate generation succeeded for domain(s) : {domains}")
|
||||
|
||||
# Put new folder in cache
|
||||
bio = BytesIO()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from os import _exit, environ, getenv, listdir, sep
|
||||
from os import _exit, environ, getenv, sep
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
from subprocess import DEVNULL, STDOUT, run
|
||||
|
|
@ -23,7 +23,7 @@ for deps_path in [
|
|||
|
||||
from Database import Database # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
from jobs import get_file_in_db, set_file_in_db
|
||||
from jobs import get_file_in_db, set_file_in_db # type: ignore
|
||||
|
||||
|
||||
def renew(domain: str, letsencrypt_path: Path) -> int:
|
||||
|
|
@ -53,8 +53,7 @@ def renew(domain: str, letsencrypt_path: Path) -> int:
|
|||
],
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
env=environ.copy()
|
||||
| {"PYTHONPATH": join(sep, "usr", "share", "bunkerweb", "deps", "python")},
|
||||
env=environ.copy() | {"PYTHONPATH": join(sep, "usr", "share", "bunkerweb", "deps", "python")},
|
||||
check=False,
|
||||
).returncode
|
||||
|
||||
|
|
@ -69,10 +68,7 @@ try:
|
|||
use_letsencrypt = True
|
||||
elif getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
first_server
|
||||
and getenv(f"{first_server}_AUTO_LETS_ENCRYPT", "no") == "yes"
|
||||
):
|
||||
if first_server and getenv(f"{first_server}_AUTO_LETS_ENCRYPT", "no") == "yes":
|
||||
use_letsencrypt = True
|
||||
break
|
||||
|
||||
|
|
@ -83,9 +79,7 @@ try:
|
|||
# Create directory if it doesn't exist
|
||||
letsencrypt_path = Path(sep, "var", "cache", "bunkerweb", "letsencrypt")
|
||||
letsencrypt_path.mkdir(parents=True, exist_ok=True)
|
||||
Path(sep, "var", "lib", "bunkerweb", "letsencrypt").mkdir(
|
||||
parents=True, exist_ok=True
|
||||
)
|
||||
Path(sep, "var", "lib", "bunkerweb", "letsencrypt").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Get env vars
|
||||
bw_integration = "Linux"
|
||||
|
|
@ -99,9 +93,7 @@ try:
|
|||
bw_integration = "Autoconf"
|
||||
elif integration_path.is_file():
|
||||
bw_integration = integration_path.read_text(encoding="utf-8").strip()
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(
|
||||
encoding="utf-8"
|
||||
):
|
||||
elif os_release_path.is_file() and "Alpine" in os_release_path.read_text(encoding="utf-8"):
|
||||
bw_integration = "Docker"
|
||||
|
||||
# Extract letsencrypt folder if it exists in db
|
||||
|
|
@ -134,9 +126,7 @@ try:
|
|||
getenv("AUTO_LETS_ENCRYPT", "no"),
|
||||
)
|
||||
!= "yes"
|
||||
or not letsencrypt_path.joinpath(
|
||||
"etc", "live", first_server, "cert.pem"
|
||||
).exists()
|
||||
or not letsencrypt_path.joinpath("etc", "live", first_server, "cert.pem").exists()
|
||||
):
|
||||
continue
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -35,10 +35,7 @@ try:
|
|||
"AUTO_LETS_ENCRYPT",
|
||||
"GENERATE_SELF_SIGNED_SSL",
|
||||
):
|
||||
if (
|
||||
getenv(f"{first_server}_{check_var}", getenv(check_var, "no"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_{check_var}", getenv(check_var, "no")) == "yes":
|
||||
need_default_cert = True
|
||||
break
|
||||
if need_default_cert:
|
||||
|
|
@ -99,9 +96,7 @@ try:
|
|||
"Successfully generated self-signed certificate for default server",
|
||||
)
|
||||
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
cached, err = set_file_in_db(
|
||||
"cert.pem",
|
||||
|
|
@ -109,13 +104,9 @@ try:
|
|||
db,
|
||||
)
|
||||
if not cached:
|
||||
logger.error(
|
||||
f"Error while saving default-server-cert cert.pem file to db cache : {err}"
|
||||
)
|
||||
logger.error(f"Error while saving default-server-cert cert.pem file to db cache : {err}")
|
||||
else:
|
||||
logger.info(
|
||||
"Successfully saved default-server-cert cert.pem file to db cache"
|
||||
)
|
||||
logger.info("Successfully saved default-server-cert cert.pem file to db cache")
|
||||
|
||||
cached, err = set_file_in_db(
|
||||
"cert.key",
|
||||
|
|
@ -123,13 +114,9 @@ try:
|
|||
db,
|
||||
)
|
||||
if not cached:
|
||||
logger.error(
|
||||
f"Error while saving default-server-cert cert.key file to db cache : {err}"
|
||||
)
|
||||
logger.error(f"Error while saving default-server-cert cert.key file to db cache : {err}")
|
||||
else:
|
||||
logger.info(
|
||||
"Successfully saved default-server-cert cert.key file to db cache"
|
||||
)
|
||||
logger.info("Successfully saved default-server-cert cert.key file to db cache")
|
||||
else:
|
||||
logger.info(
|
||||
"Skipping generation of self-signed certificate for default server (already present)",
|
||||
|
|
|
|||
|
|
@ -23,9 +23,7 @@ logger = setup_logger("UPDATE-CHECK", getenv("LOG_LEVEL", "INFO"))
|
|||
status = 0
|
||||
|
||||
try:
|
||||
current_version = (
|
||||
f"v{Path('/usr/share/bunkerweb/VERSION').read_text(encoding='utf-8').strip()}"
|
||||
)
|
||||
current_version = f"v{Path('/usr/share/bunkerweb/VERSION').read_text(encoding='utf-8').strip()}"
|
||||
|
||||
response = get(
|
||||
"https://github.com/bunkerity/bunkerweb/releases/latest",
|
||||
|
|
|
|||
|
|
@ -52,10 +52,7 @@ try:
|
|||
servers = servers.split(" ")
|
||||
|
||||
for first_server in servers:
|
||||
if (
|
||||
getenv(f"{first_server}_USE_REAL_IP", getenv("USE_REAL_IP", "no"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_USE_REAL_IP", getenv("USE_REAL_IP", "no")) == "yes":
|
||||
realip_activated = True
|
||||
break
|
||||
|
||||
|
|
@ -84,7 +81,7 @@ try:
|
|||
tmp_realip_path.joinpath("combined.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db("combined.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete combined.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete combined.list from cache : {err}")
|
||||
logger.info("RealIP list is already in cache, skipping download...")
|
||||
_exit(0)
|
||||
|
||||
|
|
@ -118,9 +115,7 @@ try:
|
|||
i += 1
|
||||
except:
|
||||
status = 2
|
||||
logger.error(
|
||||
f"Exception while getting RealIP list from {url} :\n{format_exc()}"
|
||||
)
|
||||
logger.error(f"Exception while getting RealIP list from {url} :\n{format_exc()}")
|
||||
|
||||
tmp_realip_path.joinpath("combined.list").write_bytes(content)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
{% if REDIRECT_TO != "" +%}
|
||||
{% if REDIRECT_TO_REQUEST_URI == "yes" +%}
|
||||
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }}$request_uri;
|
||||
{% else +%}
|
||||
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }};
|
||||
{% endif %}
|
||||
location / {
|
||||
{% if REDIRECT_TO_REQUEST_URI == "yes" +%}
|
||||
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }}$request_uri;
|
||||
{% else +%}
|
||||
return {{ REDIRECT_TO_STATUS_CODE }} {{ REDIRECT_TO }};
|
||||
{% endif %}
|
||||
}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,7 @@ lock = Lock()
|
|||
status = 0
|
||||
|
||||
|
||||
def generate_cert(
|
||||
first_server: str, days: str, subj: str, self_signed_path: Path
|
||||
) -> Tuple[bool, int]:
|
||||
def generate_cert(first_server: str, days: str, subj: str, self_signed_path: Path) -> Tuple[bool, int]:
|
||||
if self_signed_path.joinpath(f"{first_server}.pem").is_file():
|
||||
if (
|
||||
run(
|
||||
|
|
@ -61,19 +59,10 @@ def generate_cert(
|
|||
self_signed_path.joinpath(f"{first_server}.pem").read_bytes(),
|
||||
default_backend(),
|
||||
)
|
||||
if sorted(
|
||||
attribute.rfc4514_string() for attribute in certificate.subject
|
||||
) != sorted(v for v in subj.split("/") if v):
|
||||
logger.warning(
|
||||
f"Subject of self-signed certificate for {first_server} is different from the one in the configuration, regenerating ..."
|
||||
)
|
||||
elif (
|
||||
certificate.not_valid_after - certificate.not_valid_before
|
||||
!= timedelta(days=int(days))
|
||||
):
|
||||
logger.warning(
|
||||
f"Expiration date of self-signed certificate for {first_server} is different from the one in the configuration, regenerating ..."
|
||||
)
|
||||
if sorted(attribute.rfc4514_string() for attribute in certificate.subject) != sorted(v for v in subj.split("/") if v):
|
||||
logger.warning(f"Subject of self-signed certificate for {first_server} is different from the one in the configuration, regenerating ...")
|
||||
elif certificate.not_valid_after - certificate.not_valid_before != timedelta(days=int(days)):
|
||||
logger.warning(f"Expiration date of self-signed certificate for {first_server} is different from the one in the configuration, regenerating ...")
|
||||
else:
|
||||
return True, 0
|
||||
|
||||
|
|
@ -154,9 +143,7 @@ try:
|
|||
continue
|
||||
|
||||
if not db:
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
ret, ret_status = generate_cert(
|
||||
first_server,
|
||||
|
|
@ -174,9 +161,7 @@ try:
|
|||
|
||||
# Singlesite case
|
||||
elif getenv("GENERATE_SELF_SIGNED_SSL", "no") == "yes" and getenv("SERVER_NAME"):
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False
|
||||
)
|
||||
db = Database(logger, sqlalchemy_string=getenv("DATABASE_URI", None), pool=False)
|
||||
|
||||
first_server = getenv("SERVER_NAME", "").split(" ")[0]
|
||||
ret, ret_status = generate_cert(
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ from sys import exit as sys_exit, path as sys_path
|
|||
from traceback import format_exc
|
||||
from typing import Tuple
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("db",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -63,14 +60,11 @@ try:
|
|||
# Multisite case
|
||||
if getenv("MULTISITE", "no") == "yes":
|
||||
for first_server in getenv("SERVER_NAME", "").split(" "):
|
||||
if (
|
||||
getenv(f"{first_server}_USE_WHITELIST", getenv("USE_WHITELIST", "no"))
|
||||
== "yes"
|
||||
):
|
||||
if getenv(f"{first_server}_USE_WHITELIST", getenv("USE_WHITELIST", "yes")) == "yes":
|
||||
whitelist_activated = True
|
||||
break
|
||||
# Singlesite case
|
||||
elif getenv("USE_WHITELIST", "no") == "yes":
|
||||
elif getenv("USE_WHITELIST", "yes") == "yes":
|
||||
whitelist_activated = True
|
||||
|
||||
if not whitelist_activated:
|
||||
|
|
@ -117,7 +111,7 @@ try:
|
|||
whitelist_path.joinpath(f"{kind}.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db(f"{kind}.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete {kind}.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete {kind}.list from cache : {err}")
|
||||
if all_fresh:
|
||||
_exit(0)
|
||||
|
||||
|
|
@ -136,9 +130,7 @@ try:
|
|||
resp = get(url, stream=True, timeout=10)
|
||||
|
||||
if resp.status_code != 200:
|
||||
logger.warning(
|
||||
f"Got status code {resp.status_code}, skipping..."
|
||||
)
|
||||
logger.warning(f"Got status code {resp.status_code}, skipping...")
|
||||
continue
|
||||
|
||||
iterable = resp.iter_lines()
|
||||
|
|
@ -187,9 +179,7 @@ try:
|
|||
status = 1
|
||||
except:
|
||||
status = 2
|
||||
logger.error(
|
||||
f"Exception while getting whitelist from {url} :\n{format_exc()}"
|
||||
)
|
||||
logger.error(f"Exception while getting whitelist from {url} :\n{format_exc()}")
|
||||
|
||||
except:
|
||||
status = 2
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -16,9 +16,7 @@ from sqlalchemy.orm import declarative_base, relationship
|
|||
from sqlalchemy.schema import UniqueConstraint
|
||||
|
||||
CONTEXTS_ENUM = Enum("global", "multisite", name="contexts_enum")
|
||||
SETTINGS_TYPES_ENUM = Enum(
|
||||
"password", "text", "check", "select", name="settings_types_enum"
|
||||
)
|
||||
SETTINGS_TYPES_ENUM = Enum("password", "text", "check", "select", name="settings_types_enum")
|
||||
METHODS_ENUM = Enum("ui", "scheduler", "autoconf", "manual", name="methods_enum")
|
||||
SCHEDULES_ENUM = Enum("once", "minute", "hour", "day", "week", name="schedules_enum")
|
||||
CUSTOM_CONFIGS_TYPES_ENUM = Enum(
|
||||
|
|
@ -57,9 +55,7 @@ class Plugins(Base):
|
|||
data = Column(LargeBinary(length=(2**32) - 1), nullable=True)
|
||||
checksum = Column(String(128), nullable=True)
|
||||
|
||||
settings = relationship(
|
||||
"Settings", back_populates="plugin", cascade="all, delete-orphan"
|
||||
)
|
||||
settings = relationship("Settings", back_populates="plugin", cascade="all, delete-orphan")
|
||||
jobs = relationship("Jobs", back_populates="plugin", cascade="all, delete-orphan")
|
||||
pages = relationship("Plugin_pages", back_populates="plugin", cascade="all")
|
||||
|
||||
|
|
@ -88,12 +84,8 @@ class Settings(Base):
|
|||
multiple = Column(String(128), nullable=True)
|
||||
|
||||
selects = relationship("Selects", back_populates="setting", cascade="all")
|
||||
services = relationship(
|
||||
"Services_settings", back_populates="setting", cascade="all"
|
||||
)
|
||||
global_value = relationship(
|
||||
"Global_values", back_populates="setting", cascade="all"
|
||||
)
|
||||
services = relationship("Services_settings", back_populates="setting", cascade="all")
|
||||
global_value = relationship("Global_values", back_populates="setting", cascade="all")
|
||||
plugin = relationship("Plugins", back_populates="settings")
|
||||
|
||||
|
||||
|
|
@ -118,12 +110,8 @@ class Services(Base):
|
|||
id = Column(String(64), primary_key=True)
|
||||
method = Column(METHODS_ENUM, nullable=False)
|
||||
|
||||
settings = relationship(
|
||||
"Services_settings", back_populates="service", cascade="all"
|
||||
)
|
||||
custom_configs = relationship(
|
||||
"Custom_configs", back_populates="service", cascade="all"
|
||||
)
|
||||
settings = relationship("Services_settings", back_populates="service", cascade="all")
|
||||
custom_configs = relationship("Custom_configs", back_populates="service", cascade="all")
|
||||
jobs_cache = relationship("Jobs_cache", back_populates="service", cascade="all")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
cryptography==41.0.4
|
||||
psycopg2-binary==2.9.8
|
||||
psycopg2-binary==2.9.9
|
||||
PyMySQL==1.1.0
|
||||
sqlalchemy==2.0.21
|
||||
|
|
|
|||
|
|
@ -83,133 +83,141 @@ cryptography==41.0.4 \
|
|||
--hash=sha256:e40211b4923ba5a6dc9769eab704bdb3fbb58d56c5b336d30996c24fcf12aadb \
|
||||
--hash=sha256:efc8ad4e6fc4f1752ebfb58aefece8b4e3c4cae940b0994d43649bdfce8d0d4f
|
||||
# via -r requirements.in
|
||||
greenlet==2.0.2 \
|
||||
--hash=sha256:03a8f4f3430c3b3ff8d10a2a86028c660355ab637cee9333d63d66b56f09d52a \
|
||||
--hash=sha256:0bf60faf0bc2468089bdc5edd10555bab6e85152191df713e2ab1fcc86382b5a \
|
||||
--hash=sha256:1087300cf9700bbf455b1b97e24db18f2f77b55302a68272c56209d5587c12d1 \
|
||||
--hash=sha256:18a7f18b82b52ee85322d7a7874e676f34ab319b9f8cce5de06067384aa8ff43 \
|
||||
--hash=sha256:18e98fb3de7dba1c0a852731c3070cf022d14f0d68b4c87a19cc1016f3bb8b33 \
|
||||
--hash=sha256:1a819eef4b0e0b96bb0d98d797bef17dc1b4a10e8d7446be32d1da33e095dbb8 \
|
||||
--hash=sha256:26fbfce90728d82bc9e6c38ea4d038cba20b7faf8a0ca53a9c07b67318d46088 \
|
||||
--hash=sha256:2780572ec463d44c1d3ae850239508dbeb9fed38e294c68d19a24d925d9223ca \
|
||||
--hash=sha256:283737e0da3f08bd637b5ad058507e578dd462db259f7f6e4c5c365ba4ee9343 \
|
||||
--hash=sha256:2d4686f195e32d36b4d7cf2d166857dbd0ee9f3d20ae349b6bf8afc8485b3645 \
|
||||
--hash=sha256:2dd11f291565a81d71dab10b7033395b7a3a5456e637cf997a6f33ebdf06f8db \
|
||||
--hash=sha256:30bcf80dda7f15ac77ba5af2b961bdd9dbc77fd4ac6105cee85b0d0a5fcf74df \
|
||||
--hash=sha256:32e5b64b148966d9cccc2c8d35a671409e45f195864560829f395a54226408d3 \
|
||||
--hash=sha256:36abbf031e1c0f79dd5d596bfaf8e921c41df2bdf54ee1eed921ce1f52999a86 \
|
||||
--hash=sha256:3a06ad5312349fec0ab944664b01d26f8d1f05009566339ac6f63f56589bc1a2 \
|
||||
--hash=sha256:3a51c9751078733d88e013587b108f1b7a1fb106d402fb390740f002b6f6551a \
|
||||
--hash=sha256:3c9b12575734155d0c09d6c3e10dbd81665d5c18e1a7c6597df72fd05990c8cf \
|
||||
--hash=sha256:3f6ea9bd35eb450837a3d80e77b517ea5bc56b4647f5502cd28de13675ee12f7 \
|
||||
--hash=sha256:4b58adb399c4d61d912c4c331984d60eb66565175cdf4a34792cd9600f21b394 \
|
||||
--hash=sha256:4d2e11331fc0c02b6e84b0d28ece3a36e0548ee1a1ce9ddde03752d9b79bba40 \
|
||||
--hash=sha256:5454276c07d27a740c5892f4907c86327b632127dd9abec42ee62e12427ff7e3 \
|
||||
--hash=sha256:561091a7be172ab497a3527602d467e2b3fbe75f9e783d8b8ce403fa414f71a6 \
|
||||
--hash=sha256:6c3acb79b0bfd4fe733dff8bc62695283b57949ebcca05ae5c129eb606ff2d74 \
|
||||
--hash=sha256:703f18f3fda276b9a916f0934d2fb6d989bf0b4fb5a64825260eb9bfd52d78f0 \
|
||||
--hash=sha256:7492e2b7bd7c9b9916388d9df23fa49d9b88ac0640db0a5b4ecc2b653bf451e3 \
|
||||
--hash=sha256:76ae285c8104046b3a7f06b42f29c7b73f77683df18c49ab5af7983994c2dd91 \
|
||||
--hash=sha256:7cafd1208fdbe93b67c7086876f061f660cfddc44f404279c1585bbf3cdc64c5 \
|
||||
--hash=sha256:7efde645ca1cc441d6dc4b48c0f7101e8d86b54c8530141b09fd31cef5149ec9 \
|
||||
--hash=sha256:8512a0c38cfd4e66a858ddd1b17705587900dd760c6003998e9472b77b56d417 \
|
||||
--hash=sha256:88d9ab96491d38a5ab7c56dd7a3cc37d83336ecc564e4e8816dbed12e5aaefc8 \
|
||||
--hash=sha256:8eab883b3b2a38cc1e050819ef06a7e6344d4a990d24d45bc6f2cf959045a45b \
|
||||
--hash=sha256:910841381caba4f744a44bf81bfd573c94e10b3045ee00de0cbf436fe50673a6 \
|
||||
--hash=sha256:9190f09060ea4debddd24665d6804b995a9c122ef5917ab26e1566dcc712ceeb \
|
||||
--hash=sha256:937e9020b514ceedb9c830c55d5c9872abc90f4b5862f89c0887033ae33c6f73 \
|
||||
--hash=sha256:94c817e84245513926588caf1152e3b559ff794d505555211ca041f032abbb6b \
|
||||
--hash=sha256:971ce5e14dc5e73715755d0ca2975ac88cfdaefcaab078a284fea6cfabf866df \
|
||||
--hash=sha256:9d14b83fab60d5e8abe587d51c75b252bcc21683f24699ada8fb275d7712f5a9 \
|
||||
--hash=sha256:9f35ec95538f50292f6d8f2c9c9f8a3c6540bbfec21c9e5b4b751e0a7c20864f \
|
||||
--hash=sha256:a1846f1b999e78e13837c93c778dcfc3365902cfb8d1bdb7dd73ead37059f0d0 \
|
||||
--hash=sha256:acd2162a36d3de67ee896c43effcd5ee3de247eb00354db411feb025aa319857 \
|
||||
--hash=sha256:b0ef99cdbe2b682b9ccbb964743a6aca37905fda5e0452e5ee239b1654d37f2a \
|
||||
--hash=sha256:b80f600eddddce72320dbbc8e3784d16bd3fb7b517e82476d8da921f27d4b249 \
|
||||
--hash=sha256:b864ba53912b6c3ab6bcb2beb19f19edd01a6bfcbdfe1f37ddd1778abfe75a30 \
|
||||
--hash=sha256:b9ec052b06a0524f0e35bd8790686a1da006bd911dd1ef7d50b77bfbad74e292 \
|
||||
--hash=sha256:ba2956617f1c42598a308a84c6cf021a90ff3862eddafd20c3333d50f0edb45b \
|
||||
--hash=sha256:bdfea8c661e80d3c1c99ad7c3ff74e6e87184895bbaca6ee8cc61209f8b9b85d \
|
||||
--hash=sha256:be4ed120b52ae4d974aa40215fcdfde9194d63541c7ded40ee12eb4dda57b76b \
|
||||
--hash=sha256:c4302695ad8027363e96311df24ee28978162cdcdd2006476c43970b384a244c \
|
||||
--hash=sha256:c48f54ef8e05f04d6eff74b8233f6063cb1ed960243eacc474ee73a2ea8573ca \
|
||||
--hash=sha256:c9c59a2120b55788e800d82dfa99b9e156ff8f2227f07c5e3012a45a399620b7 \
|
||||
--hash=sha256:cd021c754b162c0fb55ad5d6b9d960db667faad0fa2ff25bb6e1301b0b6e6a75 \
|
||||
--hash=sha256:d27ec7509b9c18b6d73f2f5ede2622441de812e7b1a80bbd446cb0633bd3d5ae \
|
||||
--hash=sha256:d4606a527e30548153be1a9f155f4e283d109ffba663a15856089fb55f933e47 \
|
||||
--hash=sha256:d5508f0b173e6aa47273bdc0a0b5ba055b59662ba7c7ee5119528f466585526b \
|
||||
--hash=sha256:d75209eed723105f9596807495d58d10b3470fa6732dd6756595e89925ce2470 \
|
||||
--hash=sha256:d967650d3f56af314b72df7089d96cda1083a7fc2da05b375d2bc48c82ab3f3c \
|
||||
--hash=sha256:db1a39669102a1d8d12b57de2bb7e2ec9066a6f2b3da35ae511ff93b01b5d564 \
|
||||
--hash=sha256:dbfcfc0218093a19c252ca8eb9aee3d29cfdcb586df21049b9d777fd32c14fd9 \
|
||||
--hash=sha256:e0f72c9ddb8cd28532185f54cc1453f2c16fb417a08b53a855c4e6a418edd099 \
|
||||
--hash=sha256:e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0 \
|
||||
--hash=sha256:ea9872c80c132f4663822dd2a08d404073a5a9b5ba6155bea72fb2a79d1093b5 \
|
||||
--hash=sha256:eff4eb9b7eb3e4d0cae3d28c283dc16d9bed6b193c2e1ace3ed86ce48ea8df19 \
|
||||
--hash=sha256:f82d4d717d8ef19188687aa32b8363e96062911e63ba22a0cff7802a8e58e5f1 \
|
||||
--hash=sha256:fc3a569657468b6f3fb60587e48356fe512c1754ca05a564f11366ac9e306526
|
||||
greenlet==3.0.0 \
|
||||
--hash=sha256:02a807b2a58d5cdebb07050efe3d7deaf915468d112dfcf5e426d0564aa3aa4a \
|
||||
--hash=sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c \
|
||||
--hash=sha256:0d3f83ffb18dc57243e0151331e3c383b05e5b6c5029ac29f754745c800f8ed9 \
|
||||
--hash=sha256:10b5582744abd9858947d163843d323d0b67be9432db50f8bf83031032bc218d \
|
||||
--hash=sha256:123910c58234a8d40eaab595bc56a5ae49bdd90122dde5bdc012c20595a94c14 \
|
||||
--hash=sha256:19834e3f91f485442adc1ee440171ec5d9a4840a1f7bd5ed97833544719ce10b \
|
||||
--hash=sha256:1d363666acc21d2c204dd8705c0e0457d7b2ee7a76cb16ffc099d6799744ac99 \
|
||||
--hash=sha256:211ef8d174601b80e01436f4e6905aca341b15a566f35a10dd8d1e93f5dbb3b7 \
|
||||
--hash=sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17 \
|
||||
--hash=sha256:2e7dcdfad252f2ca83c685b0fa9fba00e4d8f243b73839229d56ee3d9d219314 \
|
||||
--hash=sha256:334ef6ed8337bd0b58bb0ae4f7f2dcc84c9f116e474bb4ec250a8bb9bd797a66 \
|
||||
--hash=sha256:343675e0da2f3c69d3fb1e894ba0a1acf58f481f3b9372ce1eb465ef93cf6fed \
|
||||
--hash=sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c \
|
||||
--hash=sha256:38ad562a104cd41e9d4644f46ea37167b93190c6d5e4048fcc4b80d34ecb278f \
|
||||
--hash=sha256:3c0d36f5adc6e6100aedbc976d7428a9f7194ea79911aa4bf471f44ee13a9464 \
|
||||
--hash=sha256:3fd2b18432e7298fcbec3d39e1a0aa91ae9ea1c93356ec089421fabc3651572b \
|
||||
--hash=sha256:4a1a6244ff96343e9994e37e5b4839f09a0207d35ef6134dce5c20d260d0302c \
|
||||
--hash=sha256:4cd83fb8d8e17633ad534d9ac93719ef8937568d730ef07ac3a98cb520fd93e4 \
|
||||
--hash=sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362 \
|
||||
--hash=sha256:553d6fb2324e7f4f0899e5ad2c427a4579ed4873f42124beba763f16032959af \
|
||||
--hash=sha256:56867a3b3cf26dc8a0beecdb4459c59f4c47cdd5424618c08515f682e1d46692 \
|
||||
--hash=sha256:621fcb346141ae08cb95424ebfc5b014361621b8132c48e538e34c3c93ac7365 \
|
||||
--hash=sha256:63acdc34c9cde42a6534518e32ce55c30f932b473c62c235a466469a710bfbf9 \
|
||||
--hash=sha256:6512592cc49b2c6d9b19fbaa0312124cd4c4c8a90d28473f86f92685cc5fef8e \
|
||||
--hash=sha256:6672fdde0fd1a60b44fb1751a7779c6db487e42b0cc65e7caa6aa686874e79fb \
|
||||
--hash=sha256:6a5b2d4cdaf1c71057ff823a19d850ed5c6c2d3686cb71f73ae4d6382aaa7a06 \
|
||||
--hash=sha256:6a68d670c8f89ff65c82b936275369e532772eebc027c3be68c6b87ad05ca695 \
|
||||
--hash=sha256:6bb36985f606a7c49916eff74ab99399cdfd09241c375d5a820bb855dfb4af9f \
|
||||
--hash=sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04 \
|
||||
--hash=sha256:7709fd7bb02b31908dc8fd35bfd0a29fc24681d5cc9ac1d64ad07f8d2b7db62f \
|
||||
--hash=sha256:8060b32d8586e912a7b7dac2d15b28dbbd63a174ab32f5bc6d107a1c4143f40b \
|
||||
--hash=sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7 \
|
||||
--hash=sha256:813720bd57e193391dfe26f4871186cf460848b83df7e23e6bef698a7624b4c9 \
|
||||
--hash=sha256:831d6f35037cf18ca5e80a737a27d822d87cd922521d18ed3dbc8a6967be50ce \
|
||||
--hash=sha256:871b0a8835f9e9d461b7fdaa1b57e3492dd45398e87324c047469ce2fc9f516c \
|
||||
--hash=sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35 \
|
||||
--hash=sha256:96d9ea57292f636ec851a9bb961a5cc0f9976900e16e5d5647f19aa36ba6366b \
|
||||
--hash=sha256:9a812224a5fb17a538207e8cf8e86f517df2080c8ee0f8c1ed2bdaccd18f38f4 \
|
||||
--hash=sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51 \
|
||||
--hash=sha256:9de687479faec7db5b198cc365bc34addd256b0028956501f4d4d5e9ca2e240a \
|
||||
--hash=sha256:a048293392d4e058298710a54dfaefcefdf49d287cd33fb1f7d63d55426e4355 \
|
||||
--hash=sha256:aa15a2ec737cb609ed48902b45c5e4ff6044feb5dcdfcf6fa8482379190330d7 \
|
||||
--hash=sha256:abe1ef3d780de56defd0c77c5ba95e152f4e4c4e12d7e11dd8447d338b85a625 \
|
||||
--hash=sha256:ad6fb737e46b8bd63156b8f59ba6cdef46fe2b7db0c5804388a2d0519b8ddb99 \
|
||||
--hash=sha256:b1660a15a446206c8545edc292ab5c48b91ff732f91b3d3b30d9a915d5ec4779 \
|
||||
--hash=sha256:b505fcfc26f4148551826a96f7317e02c400665fa0883fe505d4fcaab1dabfdd \
|
||||
--hash=sha256:b822fab253ac0f330ee807e7485769e3ac85d5eef827ca224feaaefa462dc0d0 \
|
||||
--hash=sha256:bdd696947cd695924aecb3870660b7545a19851f93b9d327ef8236bfc49be705 \
|
||||
--hash=sha256:bdfaeecf8cc705d35d8e6de324bf58427d7eafb55f67050d8f28053a3d57118c \
|
||||
--hash=sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f \
|
||||
--hash=sha256:c3692ecf3fe754c8c0f2c95ff19626584459eab110eaab66413b1e7425cd84e9 \
|
||||
--hash=sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c \
|
||||
--hash=sha256:c94e4e924d09b5a3e37b853fe5924a95eac058cb6f6fb437ebb588b7eda79870 \
|
||||
--hash=sha256:cc3e2679ea13b4de79bdc44b25a0c4fcd5e94e21b8f290791744ac42d34a0353 \
|
||||
--hash=sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2 \
|
||||
--hash=sha256:d5539f6da3418c3dc002739cb2bb8d169056aa66e0c83f6bacae0cd3ac26b423 \
|
||||
--hash=sha256:d55db1db455c59b46f794346efce896e754b8942817f46a1bada2d29446e305a \
|
||||
--hash=sha256:e09dea87cc91aea5500262993cbd484b41edf8af74f976719dd83fe724644cd6 \
|
||||
--hash=sha256:e52a712c38e5fb4fd68e00dc3caf00b60cb65634d50e32281a9d6431b33b4af1 \
|
||||
--hash=sha256:e693e759e172fa1c2c90d35dea4acbdd1d609b6936115d3739148d5e4cd11947 \
|
||||
--hash=sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810 \
|
||||
--hash=sha256:f351479a6914fd81a55c8e68963609f792d9b067fb8a60a042c585a621e0de4f \
|
||||
--hash=sha256:f47932c434a3c8d3c86d865443fadc1fbf574e9b11d6650b656e602b1797908a
|
||||
# via sqlalchemy
|
||||
psycopg2-binary==2.9.8 \
|
||||
--hash=sha256:01f9731761f711e42459f87bd2ad5d744b9773b5dd05446f3b579a0f077e78e3 \
|
||||
--hash=sha256:0e3071c947bda6afc6fe2e7b64ebd64fb2cad1bc0e705a3594cb499291f2dfec \
|
||||
--hash=sha256:14f85ff2d5d826a7ce9e6c31e803281ed5a096789f47f52cb728c88f488de01b \
|
||||
--hash=sha256:15458c81b0d199ab55825007115f697722831656e6477a427783fe75c201c82b \
|
||||
--hash=sha256:19d40993701e39c49b50e75cd690a6af796d7e7210941ee0fe49cf12b25840e5 \
|
||||
--hash=sha256:1d669887df169a9b0c09e0f5b46891511850a9ddfcde3593408af9d9774c5c3a \
|
||||
--hash=sha256:1dbad789ebd1e61201256a19dc2e90fed4706bc966ccad4f374648e5336b1ab4 \
|
||||
--hash=sha256:1f279ba74f0d6b374526e5976c626d2ac3b8333b6a7b08755c513f4d380d3add \
|
||||
--hash=sha256:205cecdd81ff4f1ddd687ce7d06879b9b80cccc428d8d6ebf36fcba08bb6d361 \
|
||||
--hash=sha256:278ebd63ced5a5f3af5394cb75a9a067243eee21f42f0126c6f1cf85eaeb90f9 \
|
||||
--hash=sha256:3723c3f009e2b2771f2491b330edb7091846f1aad0c08fbbd9a1383d6a0c0841 \
|
||||
--hash=sha256:395c217156723fe21809dfe8f7a433c5bf8e9bce229944668e4ec709c37c5442 \
|
||||
--hash=sha256:3ae22a0fa5c516b84ddb189157fabfa3f12eded5d630e1ce260a18e1771f8707 \
|
||||
--hash=sha256:3b6928a502af71ca2ac9aad535e78c8309892ed3bfa7933182d4c760580c8af4 \
|
||||
--hash=sha256:3b6c607ecb6a9c245ebe162d63ccd9222d38efa3c858bbe38d32810b08b8f87e \
|
||||
--hash=sha256:3fd44b52bc9c74c1512662e8da113a1c55127adeeacebaf460babe766517b049 \
|
||||
--hash=sha256:4336afc0e81726350bd5863e3c3116d8c12aa7f457d3d0b3b3dc36137fec6feb \
|
||||
--hash=sha256:4879ee1d07a6b2c232ae6a74570f4788cd7a29b3cd38bc39bf60225b1d075c78 \
|
||||
--hash=sha256:4960c881471ca710b81a67ef148c33ee121c1f8e47a639cf7e06537fe9fee337 \
|
||||
--hash=sha256:4b8b2cdf3bce4dd91dc035fbff4eb812f5607dda91364dc216b0920b97b521c7 \
|
||||
--hash=sha256:4bfabbd7e70785af726cc0209e8e64b926abf91741eca80678b221aad9e72135 \
|
||||
--hash=sha256:4d6b592ecc8667e608b9e7344259fbfb428cc053df0062ec3ac75d8270cd5a9f \
|
||||
--hash=sha256:5262713988d97a9d4cd54b682dec4a413b87b76790e5b16f480450550d11a8f7 \
|
||||
--hash=sha256:54bf5c27bd5867a5fa5341fad29f0d5838e2fed617ef5346884baf8b8b16dd82 \
|
||||
--hash=sha256:565edaf9f691b17a7fdbabd368b5b3e67d0fdc8f7f6b52177c1d3289f4e763fd \
|
||||
--hash=sha256:59421806c1a0803ea7de9ed061d656c041a84db0da7e73266b98db4c7ba263da \
|
||||
--hash=sha256:59f45cca0765aabb52a5822c72d5ff2ec46a28b1c1702de90dc0d306ec5c2001 \
|
||||
--hash=sha256:5a0a6e4004697ec98035ff3b8dfc4dba8daa477b23ee891d831cd3cd65ace6be \
|
||||
--hash=sha256:5aa0c99c12075c593dcdccbb8a7aaa714b716560cc99ef9206f9e75b77520801 \
|
||||
--hash=sha256:5aef3296d44d05805e634dbbd2972aa8eb7497926dd86047f5e39a79c3ecc086 \
|
||||
--hash=sha256:5cbe1e19f59950afd66764e3c905ecee9f2aee9f8df2ef35af6f7948ad93f620 \
|
||||
--hash=sha256:5debcb23a052f3fb4c165789ea513b562b2fac0f0f4f53eaf3cf4dc648907ff8 \
|
||||
--hash=sha256:5f955fe6301b84b6fd13970a05f3640fbb62ca3a0d19342356585006c830e038 \
|
||||
--hash=sha256:6369f4bd4d27944498094dccced1ae7ca43376a59dbfe4c8b6a16e9e3dc3ccce \
|
||||
--hash=sha256:63ce1dccfd08d9c5341ac82d62aa04345bc4bf41b5e5b7b2c6c172a28e0eda27 \
|
||||
--hash=sha256:65403113ac3a4813a1409fb6a1e43c658b459cc8ed8afcc5f4baf02ec8be4334 \
|
||||
--hash=sha256:673eafbdaa4ed9f5164c90e191c3895cc5f866b9b379fdb59f3a2294e914d9bd \
|
||||
--hash=sha256:693a4e7641556f0b421a7d6c6a74058aead407d860ac1cb9d0bf25be0ca73de8 \
|
||||
--hash=sha256:6e1bb4eb0d9925d65dabaaabcbb279fab444ba66d73f86d4c07dfd11f0139c06 \
|
||||
--hash=sha256:6f5e70e40dae47a4dc7f8eb390753bb599b0f4ede314580e6faa3b7383695d19 \
|
||||
--hash=sha256:80451e6b6b7c486828d5c7ed50769532bbb04ec3a411f1e833539d5c10eb691c \
|
||||
--hash=sha256:8c84ff9682bc4520504c474e189b3de7c4a4029e529c8b775e39c95c33073767 \
|
||||
--hash=sha256:91719f53ed2a95ebecefac48d855d811cba9d9fe300acc162993bdfde9bc1c3b \
|
||||
--hash=sha256:9a971086db0069aef2fd22ccffb670baac427f4ee2174c4f5c7206254f1e6794 \
|
||||
--hash=sha256:aeb09db95f38e75ae04e947d283e07be34d03c4c2ace4f0b73dbb9143d506e67 \
|
||||
--hash=sha256:c68a2e1afb4f2a5bb4b7bb8f90298d21196ac1c66418523e549430b8c4b7cb1e \
|
||||
--hash=sha256:c7ff2b6a79a92b1b169b03bb91b41806843f0cdf6055256554495bffed1d496d \
|
||||
--hash=sha256:ccaa2ae03990cedde1f618ff11ec89fefa84622da73091a67b44553ca8be6711 \
|
||||
--hash=sha256:cf60c599c40c266a01c458e9c71db7132b11760f98f08233f19b3e0a2153cbf1 \
|
||||
--hash=sha256:d29efab3c5d6d978115855a0f2643e0ee8c6450dc536d5b4afec6f52ab99e99e \
|
||||
--hash=sha256:d4a19a3332f2ac6d093e60a6f1c589f97eb9f9de7e27ea80d67f188384e31572 \
|
||||
--hash=sha256:dc145a241e1f6381efb924bcf3e3462d6020b8a147363f9111eb0a9c89331ad7 \
|
||||
--hash=sha256:de85105c568dc5f0f0efe793209ba83e4675d53d00faffc7a7c7a8bea9e0e19a \
|
||||
--hash=sha256:e11373d8e4f1f46cf3065bf613f0df9854803dc95aa4a35354ffac19f8c52127 \
|
||||
--hash=sha256:e271ad6692d50d70ca75db3bd461bfc26316de78de8fe1f504ef16dcea8f2312 \
|
||||
--hash=sha256:e3142c7e51b92855cff300580de949e36a94ab3bfa8f353b27fe26535e9b3542 \
|
||||
--hash=sha256:e46b0f4683539965ce849f2c13fc53e323bb08d84d4ba2e4b3d976f364c84210 \
|
||||
--hash=sha256:e6ef615d48fa60361e57f998327046bd89679c25d06eee9e78156be5a7a76e03 \
|
||||
--hash=sha256:e7bdc94217ae20ad03b375a991e107a31814053bee900ad8c967bf82ef3ff02e \
|
||||
--hash=sha256:fc37de7e3a87f5966965fc874d33c9b68d638e6c3718fdf32a5083de563428b0
|
||||
psycopg2-binary==2.9.9 \
|
||||
--hash=sha256:03ef7df18daf2c4c07e2695e8cfd5ee7f748a1d54d802330985a78d2a5a6dca9 \
|
||||
--hash=sha256:0a602ea5aff39bb9fac6308e9c9d82b9a35c2bf288e184a816002c9fae930b77 \
|
||||
--hash=sha256:0c009475ee389757e6e34611d75f6e4f05f0cf5ebb76c6037508318e1a1e0d7e \
|
||||
--hash=sha256:0ef4854e82c09e84cc63084a9e4ccd6d9b154f1dbdd283efb92ecd0b5e2b8c84 \
|
||||
--hash=sha256:1236ed0952fbd919c100bc839eaa4a39ebc397ed1c08a97fc45fee2a595aa1b3 \
|
||||
--hash=sha256:143072318f793f53819048fdfe30c321890af0c3ec7cb1dfc9cc87aa88241de2 \
|
||||
--hash=sha256:15208be1c50b99203fe88d15695f22a5bed95ab3f84354c494bcb1d08557df67 \
|
||||
--hash=sha256:1873aade94b74715be2246321c8650cabf5a0d098a95bab81145ffffa4c13876 \
|
||||
--hash=sha256:18d0ef97766055fec15b5de2c06dd8e7654705ce3e5e5eed3b6651a1d2a9a152 \
|
||||
--hash=sha256:1ea665f8ce695bcc37a90ee52de7a7980be5161375d42a0b6c6abedbf0d81f0f \
|
||||
--hash=sha256:2293b001e319ab0d869d660a704942c9e2cce19745262a8aba2115ef41a0a42a \
|
||||
--hash=sha256:246b123cc54bb5361588acc54218c8c9fb73068bf227a4a531d8ed56fa3ca7d6 \
|
||||
--hash=sha256:275ff571376626195ab95a746e6a04c7df8ea34638b99fc11160de91f2fef503 \
|
||||
--hash=sha256:281309265596e388ef483250db3640e5f414168c5a67e9c665cafce9492eda2f \
|
||||
--hash=sha256:2d423c8d8a3c82d08fe8af900ad5b613ce3632a1249fd6a223941d0735fce493 \
|
||||
--hash=sha256:2e5afae772c00980525f6d6ecf7cbca55676296b580c0e6abb407f15f3706996 \
|
||||
--hash=sha256:30dcc86377618a4c8f3b72418df92e77be4254d8f89f14b8e8f57d6d43603c0f \
|
||||
--hash=sha256:31a34c508c003a4347d389a9e6fcc2307cc2150eb516462a7a17512130de109e \
|
||||
--hash=sha256:323ba25b92454adb36fa425dc5cf6f8f19f78948cbad2e7bc6cdf7b0d7982e59 \
|
||||
--hash=sha256:34eccd14566f8fe14b2b95bb13b11572f7c7d5c36da61caf414d23b91fcc5d94 \
|
||||
--hash=sha256:3a58c98a7e9c021f357348867f537017057c2ed7f77337fd914d0bedb35dace7 \
|
||||
--hash=sha256:3f78fd71c4f43a13d342be74ebbc0666fe1f555b8837eb113cb7416856c79682 \
|
||||
--hash=sha256:4154ad09dac630a0f13f37b583eae260c6aa885d67dfbccb5b02c33f31a6d420 \
|
||||
--hash=sha256:420f9bbf47a02616e8554e825208cb947969451978dceb77f95ad09c37791dae \
|
||||
--hash=sha256:4686818798f9194d03c9129a4d9a702d9e113a89cb03bffe08c6cf799e053291 \
|
||||
--hash=sha256:57fede879f08d23c85140a360c6a77709113efd1c993923c59fde17aa27599fe \
|
||||
--hash=sha256:60989127da422b74a04345096c10d416c2b41bd7bf2a380eb541059e4e999980 \
|
||||
--hash=sha256:68fc1f1ba168724771e38bee37d940d2865cb0f562380a1fb1ffb428b75cb692 \
|
||||
--hash=sha256:6e6f98446430fdf41bd36d4faa6cb409f5140c1c2cf58ce0bbdaf16af7d3f119 \
|
||||
--hash=sha256:729177eaf0aefca0994ce4cffe96ad3c75e377c7b6f4efa59ebf003b6d398716 \
|
||||
--hash=sha256:72dffbd8b4194858d0941062a9766f8297e8868e1dd07a7b36212aaa90f49472 \
|
||||
--hash=sha256:75723c3c0fbbf34350b46a3199eb50638ab22a0228f93fb472ef4d9becc2382b \
|
||||
--hash=sha256:77853062a2c45be16fd6b8d6de2a99278ee1d985a7bd8b103e97e41c034006d2 \
|
||||
--hash=sha256:78151aa3ec21dccd5cdef6c74c3e73386dcdfaf19bced944169697d7ac7482fc \
|
||||
--hash=sha256:7f01846810177d829c7692f1f5ada8096762d9172af1b1a28d4ab5b77c923c1c \
|
||||
--hash=sha256:804d99b24ad523a1fe18cc707bf741670332f7c7412e9d49cb5eab67e886b9b5 \
|
||||
--hash=sha256:8359bf4791968c5a78c56103702000105501adb557f3cf772b2c207284273984 \
|
||||
--hash=sha256:83791a65b51ad6ee6cf0845634859d69a038ea9b03d7b26e703f94c7e93dbcf9 \
|
||||
--hash=sha256:8532fd6e6e2dc57bcb3bc90b079c60de896d2128c5d9d6f24a63875a95a088cf \
|
||||
--hash=sha256:876801744b0dee379e4e3c38b76fc89f88834bb15bf92ee07d94acd06ec890a0 \
|
||||
--hash=sha256:8dbf6d1bc73f1d04ec1734bae3b4fb0ee3cb2a493d35ede9badbeb901fb40f6f \
|
||||
--hash=sha256:8f8544b092a29a6ddd72f3556a9fcf249ec412e10ad28be6a0c0d948924f2212 \
|
||||
--hash=sha256:911dda9c487075abd54e644ccdf5e5c16773470a6a5d3826fda76699410066fb \
|
||||
--hash=sha256:977646e05232579d2e7b9c59e21dbe5261f403a88417f6a6512e70d3f8a046be \
|
||||
--hash=sha256:9dba73be7305b399924709b91682299794887cbbd88e38226ed9f6712eabee90 \
|
||||
--hash=sha256:a148c5d507bb9b4f2030a2025c545fccb0e1ef317393eaba42e7eabd28eb6041 \
|
||||
--hash=sha256:a6cdcc3ede532f4a4b96000b6362099591ab4a3e913d70bcbac2b56c872446f7 \
|
||||
--hash=sha256:ac05fb791acf5e1a3e39402641827780fe44d27e72567a000412c648a85ba860 \
|
||||
--hash=sha256:b58b4710c7f4161b5e9dcbe73bb7c62d65670a87df7bcce9e1faaad43e715245 \
|
||||
--hash=sha256:b6356793b84728d9d50ead16ab43c187673831e9d4019013f1402c41b1db9b27 \
|
||||
--hash=sha256:b76bedd166805480ab069612119ea636f5ab8f8771e640ae103e05a4aae3e417 \
|
||||
--hash=sha256:bc7bb56d04601d443f24094e9e31ae6deec9ccb23581f75343feebaf30423359 \
|
||||
--hash=sha256:c2470da5418b76232f02a2fcd2229537bb2d5a7096674ce61859c3229f2eb202 \
|
||||
--hash=sha256:c332c8d69fb64979ebf76613c66b985414927a40f8defa16cf1bc028b7b0a7b0 \
|
||||
--hash=sha256:c6af2a6d4b7ee9615cbb162b0738f6e1fd1f5c3eda7e5da17861eacf4c717ea7 \
|
||||
--hash=sha256:c77e3d1862452565875eb31bdb45ac62502feabbd53429fdc39a1cc341d681ba \
|
||||
--hash=sha256:ca08decd2697fdea0aea364b370b1249d47336aec935f87b8bbfd7da5b2ee9c1 \
|
||||
--hash=sha256:ca49a8119c6cbd77375ae303b0cfd8c11f011abbbd64601167ecca18a87e7cdd \
|
||||
--hash=sha256:cb16c65dcb648d0a43a2521f2f0a2300f40639f6f8c1ecbc662141e4e3e1ee07 \
|
||||
--hash=sha256:d2997c458c690ec2bc6b0b7ecbafd02b029b7b4283078d3b32a852a7ce3ddd98 \
|
||||
--hash=sha256:d3f82c171b4ccd83bbaf35aa05e44e690113bd4f3b7b6cc54d2219b132f3ae55 \
|
||||
--hash=sha256:dc4926288b2a3e9fd7b50dc6a1909a13bbdadfc67d93f3374d984e56f885579d \
|
||||
--hash=sha256:ead20f7913a9c1e894aebe47cccf9dc834e1618b7aa96155d2091a626e59c972 \
|
||||
--hash=sha256:ebdc36bea43063116f0486869652cb2ed7032dbc59fbcb4445c4862b5c1ecf7f \
|
||||
--hash=sha256:ed1184ab8f113e8d660ce49a56390ca181f2981066acc27cf637d5c1e10ce46e \
|
||||
--hash=sha256:ee825e70b1a209475622f7f7b776785bd68f34af6e7a46e2e42f27b659b5bc26 \
|
||||
--hash=sha256:f7ae5d65ccfbebdfa761585228eb4d0df3a8b15cfb53bd953e713e09fbb12957 \
|
||||
--hash=sha256:f7fc5a5acafb7d6ccca13bfa8c90f8c51f13d8fb87d95656d3950f0158d3ce53 \
|
||||
--hash=sha256:f9b5571d33660d5009a8b3c25dc1db560206e2d2f89d3df1cb32d72c0d117d52
|
||||
# via -r requirements.in
|
||||
pycparser==2.21 \
|
||||
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
|
||||
|
|
|
|||
|
|
@ -57,14 +57,10 @@ class Configurator:
|
|||
def get_settings(self) -> Dict[str, Any]:
|
||||
return self.__settings
|
||||
|
||||
def get_plugins(
|
||||
self, _type: Union[Literal["core"], Literal["external"]]
|
||||
) -> List[Dict[str, Any]]:
|
||||
def get_plugins(self, _type: Union[Literal["core"], Literal["external"]]) -> List[Dict[str, Any]]:
|
||||
return self.__core_plugins if _type == "core" else self.__external_plugins
|
||||
|
||||
def get_plugins_settings(
|
||||
self, _type: Union[Literal["core"], Literal["external"]]
|
||||
) -> Dict[str, Any]:
|
||||
def get_plugins_settings(self, _type: Union[Literal["core"], Literal["external"]]) -> Dict[str, Any]:
|
||||
if _type == "core":
|
||||
plugins = self.__core_plugins
|
||||
else:
|
||||
|
|
@ -77,7 +73,7 @@ class Configurator:
|
|||
return plugins_settings
|
||||
|
||||
def __map_servers(self) -> Dict[str, List[str]]:
|
||||
if not self.__multisite or not "SERVER_NAME" in self.__variables:
|
||||
if not self.__multisite or "SERVER_NAME" not in self.__variables:
|
||||
return {}
|
||||
servers = {}
|
||||
for server_name in self.__variables["SERVER_NAME"].strip().split(" "):
|
||||
|
|
@ -96,11 +92,7 @@ class Configurator:
|
|||
f"Ignoring {server_name}_SERVER_NAME because regex is not valid",
|
||||
)
|
||||
else:
|
||||
names = (
|
||||
self.__variables[f"{server_name}_SERVER_NAME"]
|
||||
.strip()
|
||||
.split(" ")
|
||||
)
|
||||
names = self.__variables[f"{server_name}_SERVER_NAME"].strip().split(" ")
|
||||
|
||||
servers[server_name] = names
|
||||
return servers
|
||||
|
|
@ -132,9 +124,7 @@ class Configurator:
|
|||
|
||||
if _type == "external":
|
||||
plugin_content = BytesIO()
|
||||
with tar_open(
|
||||
fileobj=plugin_content, mode="w:gz", compresslevel=9
|
||||
) as tar:
|
||||
with tar_open(fileobj=plugin_content, mode="w:gz", compresslevel=9) as tar:
|
||||
tar.add(
|
||||
dirname(file),
|
||||
arcname=basename(dirname(file)),
|
||||
|
|
@ -170,10 +160,10 @@ class Configurator:
|
|||
lines = f.readlines()
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or not "=" in line:
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
splitted = line.split("=", 1)
|
||||
variables[splitted[0]] = splitted[1]
|
||||
split = line.split("=", 1)
|
||||
variables[split[0]] = split[1]
|
||||
return variables
|
||||
|
||||
def get_config(self) -> Dict[str, Any]:
|
||||
|
|
@ -268,9 +258,7 @@ class Configurator:
|
|||
if variable in target:
|
||||
return target, variable
|
||||
for real_var, settings in target.items():
|
||||
if "multiple" in settings and re_search(
|
||||
f"^{real_var}_[0-9]+$", variable
|
||||
):
|
||||
if "multiple" in settings and re_search(f"^{real_var}_[0-9]+$", variable):
|
||||
return target, real_var
|
||||
return None, variable
|
||||
|
||||
|
|
|
|||
|
|
@ -63,27 +63,19 @@ class Templator:
|
|||
templates.append(template)
|
||||
return templates
|
||||
|
||||
def __write_config(
|
||||
self, subpath: Optional[str] = None, config: Optional[Dict[str, Any]] = None
|
||||
):
|
||||
def __write_config(self, subpath: Optional[str] = None, config: Optional[Dict[str, Any]] = None):
|
||||
real_path = Path(self.__output, subpath or "", "variables.env")
|
||||
real_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
real_path.write_text(
|
||||
"\n".join(f"{k}={v}" for k, v in (config or self.__config).items())
|
||||
)
|
||||
real_path.write_text("\n".join(f"{k}={v}" for k, v in (config or self.__config).items()))
|
||||
|
||||
def __render_global(self):
|
||||
self.__write_config()
|
||||
templates = self.__find_templates(
|
||||
["global", "http", "stream", "default-server-http"]
|
||||
)
|
||||
templates = self.__find_templates(["global", "http", "stream", "default-server-http"])
|
||||
for template in templates:
|
||||
self.__render_template(template)
|
||||
|
||||
def __render_server(self, server: str):
|
||||
templates = self.__find_templates(
|
||||
["modsec", "modsec-crs", "server-http", "server-stream"]
|
||||
)
|
||||
templates = self.__find_templates(["modsec", "modsec-crs", "server-http", "server-stream"])
|
||||
if self.__config.get("MULTISITE", "no") == "yes":
|
||||
config = self.__config.copy()
|
||||
for variable, value in self.__config.items():
|
||||
|
|
|
|||
|
|
@ -12,10 +12,7 @@ from time import sleep
|
|||
from traceback import format_exc
|
||||
from typing import Any, Dict
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("api",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("api",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -72,9 +69,7 @@ if __name__ == "__main__":
|
|||
type=str,
|
||||
help="path to the file containing environment variables",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-linux-reload", action="store_true", help="disable linux reload"
|
||||
)
|
||||
parser.add_argument("--no-linux-reload", action="store_true", help="disable linux reload")
|
||||
args = parser.parse_args()
|
||||
|
||||
settings_path = Path(normpath(args.settings))
|
||||
|
|
@ -183,10 +178,7 @@ if __name__ == "__main__":
|
|||
)
|
||||
templator.render()
|
||||
|
||||
if (
|
||||
integration not in ("Autoconf", "Swarm", "Kubernetes", "Docker")
|
||||
and not args.no_linux_reload
|
||||
):
|
||||
if integration not in ("Autoconf", "Swarm", "Kubernetes", "Docker") and not args.no_linux_reload:
|
||||
retries = 0
|
||||
while not Path(sep, "var", "run", "bunkerweb", "nginx.pid").exists():
|
||||
if retries == 5:
|
||||
|
|
|
|||
|
|
@ -298,9 +298,9 @@ six==1.16.0 \
|
|||
# via
|
||||
# kubernetes
|
||||
# python-dateutil
|
||||
urllib3==1.26.16 \
|
||||
--hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \
|
||||
--hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14
|
||||
urllib3==1.26.17 \
|
||||
--hash=sha256:24d6a242c28d29af46c3fae832c36db3bbebcc533dd1bb549172cd739c82df21 \
|
||||
--hash=sha256:94a757d178c9be92ef5539b8840d48dc9cf1b2709c9d6b588232a055c524458b
|
||||
# via
|
||||
# docker
|
||||
# kubernetes
|
||||
|
|
|
|||
|
|
@ -10,10 +10,7 @@ from time import sleep
|
|||
from traceback import format_exc
|
||||
from typing import Any
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",), ("api",), ("db",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",), ("api",), ("db",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -24,9 +21,7 @@ from Database import Database # type: ignore
|
|||
from Configurator import Configurator
|
||||
from API import API # type: ignore
|
||||
|
||||
custom_confs_rx = re_compile(
|
||||
r"^([0-9a-z\.-]*)_?CUSTOM_CONF_(HTTP|SERVER_STREAM|STREAM|DEFAULT_SERVER_HTTP|SERVER_HTTP|MODSEC_CRS|MODSEC)_(.+)$"
|
||||
)
|
||||
custom_confs_rx = re_compile(r"^([0-9a-z\.-]*)_?CUSTOM_CONF_(HTTP|SERVER_STREAM|STREAM|DEFAULT_SERVER_HTTP|SERVER_HTTP|MODSEC_CRS|MODSEC)_(.+)$")
|
||||
|
||||
|
||||
def get_instance_configs_and_apis(instance: Any, db, _type="Docker"):
|
||||
|
|
@ -36,17 +31,13 @@ def get_instance_configs_and_apis(instance: Any, db, _type="Docker"):
|
|||
custom_confs = []
|
||||
apis = []
|
||||
|
||||
for var in (
|
||||
instance.attrs["Config"]["Env"]
|
||||
if _type == "Docker"
|
||||
else instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]
|
||||
):
|
||||
splitted = var.split("=", 1)
|
||||
if custom_confs_rx.match(splitted[0]):
|
||||
custom_conf = custom_confs_rx.search(splitted[0]).groups()
|
||||
for var in instance.attrs["Config"]["Env"] if _type == "Docker" else instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]:
|
||||
split = var.split("=", 1)
|
||||
if custom_confs_rx.match(split[0]):
|
||||
custom_conf = custom_confs_rx.search(split[0]).groups()
|
||||
custom_confs.append(
|
||||
{
|
||||
"value": f"# CREATED BY ENV\n{splitted[1]}",
|
||||
"value": f"# CREATED BY ENV\n{split[1]}",
|
||||
"exploded": (
|
||||
custom_conf[0],
|
||||
custom_conf[1],
|
||||
|
|
@ -54,18 +45,16 @@ def get_instance_configs_and_apis(instance: Any, db, _type="Docker"):
|
|||
),
|
||||
}
|
||||
)
|
||||
logger.info(
|
||||
f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}"
|
||||
)
|
||||
logger.info(f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}")
|
||||
else:
|
||||
tmp_config[splitted[0]] = splitted[1]
|
||||
tmp_config[split[0]] = split[1]
|
||||
|
||||
if not db and splitted[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=splitted[1], pool=False)
|
||||
elif splitted[0] == "API_HTTP_PORT":
|
||||
api_http_port = splitted[1]
|
||||
elif splitted[0] == "API_SERVER_NAME":
|
||||
api_server_name = splitted[1]
|
||||
if not db and split[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=split[1], pool=False)
|
||||
elif split[0] == "API_HTTP_PORT":
|
||||
api_http_port = split[1]
|
||||
elif split[0] == "API_SERVER_NAME":
|
||||
api_server_name = split[1]
|
||||
|
||||
apis.append(
|
||||
API(
|
||||
|
|
@ -168,9 +157,7 @@ if __name__ == "__main__":
|
|||
|
||||
# Check existences and permissions
|
||||
logger.info("Checking arguments ...")
|
||||
files = [settings_path] + (
|
||||
[Path(normpath(args.variables))] if args.variables else []
|
||||
)
|
||||
files = [settings_path] + ([Path(normpath(args.variables))] if args.variables else [])
|
||||
paths_rx = [core_path, plugins_path]
|
||||
for file in files:
|
||||
if not file.is_file():
|
||||
|
|
@ -217,19 +204,13 @@ if __name__ == "__main__":
|
|||
),
|
||||
}
|
||||
)
|
||||
logger.info(
|
||||
f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}"
|
||||
)
|
||||
logger.info(f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}")
|
||||
|
||||
db = Database(logger, config_files.get("DATABASE_URI", None), pool=False)
|
||||
else:
|
||||
docker_client = DockerClient(
|
||||
base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
|
||||
)
|
||||
docker_client = DockerClient(base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock"))
|
||||
|
||||
while not docker_client.containers.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
while not docker_client.containers.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
logger.info("Waiting for BunkerWeb instance ...")
|
||||
sleep(5)
|
||||
|
||||
|
|
@ -239,16 +220,14 @@ if __name__ == "__main__":
|
|||
custom_confs = []
|
||||
apis = []
|
||||
|
||||
for instance in docker_client.containers.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
for instance in docker_client.containers.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
for var in instance.attrs["Config"]["Env"]:
|
||||
splitted = var.split("=", 1)
|
||||
if custom_confs_rx.match(splitted[0]):
|
||||
custom_conf = custom_confs_rx.search(splitted[0]).groups()
|
||||
split = var.split("=", 1)
|
||||
if custom_confs_rx.match(split[0]):
|
||||
custom_conf = custom_confs_rx.search(split[0]).groups()
|
||||
custom_confs.append(
|
||||
{
|
||||
"value": f"# CREATED BY ENV\n{splitted[1]}",
|
||||
"value": f"# CREATED BY ENV\n{split[1]}",
|
||||
"exploded": (
|
||||
custom_conf[0],
|
||||
custom_conf[1],
|
||||
|
|
@ -256,20 +235,16 @@ if __name__ == "__main__":
|
|||
),
|
||||
}
|
||||
)
|
||||
logger.info(
|
||||
f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}"
|
||||
)
|
||||
logger.info(f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}")
|
||||
else:
|
||||
tmp_config[splitted[0]] = splitted[1]
|
||||
tmp_config[split[0]] = split[1]
|
||||
|
||||
if not db and splitted[0] == "DATABASE_URI":
|
||||
db = Database(
|
||||
logger, sqlalchemy_string=splitted[1], pool=False
|
||||
)
|
||||
elif splitted[0] == "API_HTTP_PORT":
|
||||
api_http_port = splitted[1]
|
||||
elif splitted[0] == "API_SERVER_NAME":
|
||||
api_server_name = splitted[1]
|
||||
if not db and split[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=split[1], pool=False)
|
||||
elif split[0] == "API_HTTP_PORT":
|
||||
api_http_port = split[1]
|
||||
elif split[0] == "API_SERVER_NAME":
|
||||
api_server_name = split[1]
|
||||
|
||||
apis.append(
|
||||
API(
|
||||
|
|
@ -319,9 +294,7 @@ if __name__ == "__main__":
|
|||
logger.info("Database tables initialized")
|
||||
|
||||
err = db.initialize_db(
|
||||
version=Path(sep, "usr", "share", "bunkerweb", "VERSION")
|
||||
.read_text()
|
||||
.strip(),
|
||||
version=Path(sep, "usr", "share", "bunkerweb", "VERSION").read_text().strip(),
|
||||
integration=integration,
|
||||
)
|
||||
|
||||
|
|
@ -344,9 +317,7 @@ if __name__ == "__main__":
|
|||
err = db.save_config(config_files, args.method, changed=False)
|
||||
|
||||
if err:
|
||||
logger.warning(
|
||||
f"Couldn't save config to database : {err}, config may not work as expected"
|
||||
)
|
||||
logger.warning(f"Couldn't save config to database : {err}, config may not work as expected")
|
||||
else:
|
||||
changes.append("config")
|
||||
logger.info("Config successfully saved to database")
|
||||
|
|
@ -355,9 +326,7 @@ if __name__ == "__main__":
|
|||
err1 = db.save_custom_configs(custom_confs, args.method, changed=False)
|
||||
|
||||
if err1:
|
||||
logger.warning(
|
||||
f"Couldn't save custom configs to database : {err1}, custom configs may not work as expected"
|
||||
)
|
||||
logger.warning(f"Couldn't save custom configs to database : {err1}, custom configs may not work as expected")
|
||||
else:
|
||||
changes.append("custom_configs")
|
||||
logger.info("Custom configs successfully saved to database")
|
||||
|
|
@ -377,9 +346,7 @@ if __name__ == "__main__":
|
|||
else:
|
||||
if "instances" not in changes:
|
||||
changes.append("instances")
|
||||
logger.info(
|
||||
f"Instance {endpoint_data[0]} successfully saved to database"
|
||||
)
|
||||
logger.info(f"Instance {endpoint_data[0]} successfully saved to database")
|
||||
else:
|
||||
err = db.add_instance(
|
||||
"127.0.0.1",
|
||||
|
|
@ -397,9 +364,7 @@ if __name__ == "__main__":
|
|||
# update changes in db
|
||||
ret = db.checked_changes(changes, value=True)
|
||||
if ret:
|
||||
logger.error(
|
||||
f"An error occurred when setting the changes to checked in the database : {ret}"
|
||||
)
|
||||
logger.error(f"An error occurred when setting the changes to checked in the database : {ret}")
|
||||
except SystemExit as e:
|
||||
sys_exit(e.code)
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@ from sys import path as sys_path
|
|||
from tarfile import open as tar_open
|
||||
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
||||
|
||||
for deps_path in [
|
||||
join(sep, "usr", "share", "bunkerweb", *paths)
|
||||
for paths in (("deps", "python"), ("utils",))
|
||||
]:
|
||||
for deps_path in [join(sep, "usr", "share", "bunkerweb", *paths) for paths in (("deps", "python"), ("utils",))]:
|
||||
if deps_path not in sys_path:
|
||||
sys_path.append(deps_path)
|
||||
|
||||
|
|
@ -46,10 +43,7 @@ class ApiCaller:
|
|||
config.load_incluster_config()
|
||||
corev1 = kube_client.CoreV1Api()
|
||||
for pod in corev1.list_pod_for_all_namespaces(watch=False).items:
|
||||
if (
|
||||
pod.metadata.annotations != None
|
||||
and "bunkerweb.io/INSTANCE" in pod.metadata.annotations
|
||||
):
|
||||
if pod.metadata.annotations is not None and "bunkerweb.io/INSTANCE" in pod.metadata.annotations:
|
||||
api_http_port = None
|
||||
api_server_name = None
|
||||
|
||||
|
|
@ -66,20 +60,14 @@ class ApiCaller:
|
|||
)
|
||||
)
|
||||
else:
|
||||
docker_client = DockerClient(
|
||||
base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock")
|
||||
)
|
||||
docker_client = DockerClient(base_url=getenv("DOCKER_HOST", "unix:///var/run/docker.sock"))
|
||||
|
||||
if bw_integration == "Swarm":
|
||||
for instance in docker_client.services.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
for instance in docker_client.services.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
api_http_port = None
|
||||
api_server_name = None
|
||||
|
||||
for var in instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"][
|
||||
"Env"
|
||||
]:
|
||||
for var in instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]:
|
||||
if var.startswith("API_HTTP_PORT="):
|
||||
api_http_port = var.replace("API_HTTP_PORT=", "", 1)
|
||||
elif var.startswith("API_SERVER_NAME="):
|
||||
|
|
@ -89,15 +77,12 @@ class ApiCaller:
|
|||
self.__apis.append(
|
||||
API(
|
||||
f"http://{instance.name}.{task['NodeID']}.{task['ID']}:{api_http_port or getenv('API_HTTP_PORT', '5000')}",
|
||||
host=api_server_name
|
||||
or getenv("API_SERVER_NAME", "bwapi"),
|
||||
host=api_server_name or getenv("API_SERVER_NAME", "bwapi"),
|
||||
)
|
||||
)
|
||||
return
|
||||
|
||||
for instance in docker_client.containers.list(
|
||||
filters={"label": "bunkerweb.INSTANCE"}
|
||||
):
|
||||
for instance in docker_client.containers.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
api_http_port = None
|
||||
api_server_name = None
|
||||
|
||||
|
|
@ -160,9 +145,7 @@ class ApiCaller:
|
|||
def send_files(self, path: str, url: str) -> bool:
|
||||
ret = True
|
||||
with BytesIO() as tgz:
|
||||
with tar_open(
|
||||
mode="w:gz", fileobj=tgz, dereference=True, compresslevel=3
|
||||
) as tf:
|
||||
with tar_open(mode="w:gz", fileobj=tgz, dereference=True, compresslevel=3) as tf:
|
||||
tf.add(path, arcname=".")
|
||||
tgz.seek(0, 0)
|
||||
files = {"archive.tar.gz": tgz}
|
||||
|
|
|
|||
|
|
@ -15,18 +15,10 @@ from logger import setup_logger
|
|||
class ConfigCaller:
|
||||
def __init__(self):
|
||||
self.__logger = setup_logger("Config", "INFO")
|
||||
self._settings = loads(
|
||||
Path(sep, "usr", "share", "bunkerweb", "settings.json").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
)
|
||||
for plugin in glob(
|
||||
join(sep, "usr", "share", "bunkerweb", "core", "*", "plugin.json")
|
||||
) + glob(join(sep, "etc", "bunkerweb", "plugins", "*", "plugin.json")):
|
||||
self._settings = loads(Path(sep, "usr", "share", "bunkerweb", "settings.json").read_text(encoding="utf-8"))
|
||||
for plugin in glob(join(sep, "usr", "share", "bunkerweb", "core", "*", "plugin.json")) + glob(join(sep, "etc", "bunkerweb", "plugins", "*", "plugin.json")):
|
||||
try:
|
||||
self._settings.update(
|
||||
loads(Path(plugin).read_text(encoding="utf-8"))["settings"]
|
||||
)
|
||||
self._settings.update(loads(Path(plugin).read_text(encoding="utf-8"))["settings"])
|
||||
except KeyError:
|
||||
self.__logger.error(
|
||||
f'Error while loading plugin metadata file at {plugin} : missing "settings" key',
|
||||
|
|
@ -39,23 +31,15 @@ class ConfigCaller:
|
|||
def _is_setting(self, setting) -> bool:
|
||||
return setting in self._settings
|
||||
|
||||
def _is_setting_context(
|
||||
self, setting: str, context: Union[Literal["global"], Literal["multisite"]]
|
||||
) -> bool:
|
||||
def _is_setting_context(self, setting: str, context: Union[Literal["global"], Literal["multisite"]]) -> bool:
|
||||
if self._is_setting(setting):
|
||||
return self._settings[setting]["context"] == context
|
||||
elif match(r"^.+_\d+$", setting):
|
||||
multiple_setting = "_".join(setting.split("_")[:-1])
|
||||
return (
|
||||
self._is_setting(multiple_setting)
|
||||
and self._settings[multiple_setting]["context"] == context
|
||||
and "multiple" in self._settings[multiple_setting]
|
||||
)
|
||||
return self._is_setting(multiple_setting) and self._settings[multiple_setting]["context"] == context and "multiple" in self._settings[multiple_setting]
|
||||
return False
|
||||
|
||||
def _full_env(
|
||||
self, env_instances: Dict[str, Any], env_services: Dict[str, Any]
|
||||
) -> Dict[str, Any]:
|
||||
def _full_env(self, env_instances: Dict[str, Any], env_services: Dict[str, Any]) -> Dict[str, Any]:
|
||||
full_env = {}
|
||||
# Fill with default values
|
||||
for k, v in self._settings.items():
|
||||
|
|
@ -63,11 +47,7 @@ class ConfigCaller:
|
|||
# Replace with instances values
|
||||
for k, v in env_instances.items():
|
||||
full_env[k] = v
|
||||
if (
|
||||
not self._is_setting_context(k, "global")
|
||||
and env_instances.get("MULTISITE", "no") == "yes"
|
||||
and env_instances.get("SERVER_NAME", "") != ""
|
||||
):
|
||||
if not self._is_setting_context(k, "global") and env_instances.get("MULTISITE", "no") == "yes" and env_instances.get("SERVER_NAME", "") != "":
|
||||
for server_name in env_instances["SERVER_NAME"].split(" "):
|
||||
full_env[f"{server_name}_{k}"] = v
|
||||
# Replace with services values
|
||||
|
|
|
|||
|
|
@ -70,9 +70,7 @@ def is_cached_file(
|
|||
return is_cached and cached_file
|
||||
|
||||
|
||||
def get_file_in_db(
|
||||
file: Union[str, Path], db, *, job_name: Optional[str] = None
|
||||
) -> Optional[bytes]:
|
||||
def get_file_in_db(file: Union[str, Path], db, *, job_name: Optional[str] = None) -> Optional[bytes]:
|
||||
cached_file = db.get_job_cache_file(
|
||||
job_name or basename(getsourcefile(_getframe(1))).replace(".py", ""),
|
||||
normpath(file),
|
||||
|
|
@ -98,8 +96,7 @@ def set_file_in_db(
|
|||
service_id,
|
||||
name,
|
||||
content,
|
||||
job_name=job_name
|
||||
or basename(getsourcefile(_getframe(1))).replace(".py", ""),
|
||||
job_name=job_name or basename(getsourcefile(_getframe(1))).replace(".py", ""),
|
||||
checksum=checksum,
|
||||
)
|
||||
|
||||
|
|
@ -113,9 +110,7 @@ def set_file_in_db(
|
|||
def del_file_in_db(name: str, db) -> Tuple[bool, str]:
|
||||
ret, err = True, "success"
|
||||
try:
|
||||
db.delete_job_cache(
|
||||
name, job_name=basename(getsourcefile(_getframe(1))).replace(".py", "")
|
||||
)
|
||||
db.delete_job_cache(name, job_name=basename(getsourcefile(_getframe(1))).replace(".py", ""))
|
||||
except:
|
||||
return False, f"exception :\n{format_exc()}"
|
||||
return ret, err
|
||||
|
|
@ -145,9 +140,7 @@ def bytes_hash(bio: BufferedReader) -> str:
|
|||
|
||||
def cache_hash(cache: Union[str, Path], db=None) -> Optional[str]:
|
||||
with suppress(BaseException):
|
||||
return loads(Path(normpath(f"{cache}.md")).read_text(encoding="utf-8")).get(
|
||||
"checksum", None
|
||||
)
|
||||
return loads(Path(normpath(f"{cache}.md")).read_text(encoding="utf-8")).get("checksum", None)
|
||||
if db:
|
||||
cached_file = db.get_job_cache_file(
|
||||
basename(getsourcefile(_getframe(1))).replace(".py", ""),
|
||||
|
|
|
|||
|
|
@ -30,24 +30,12 @@ basicConfig(
|
|||
level=default_level,
|
||||
)
|
||||
|
||||
getLogger("sqlalchemy.orm.mapper.Mapper").setLevel(
|
||||
default_level if default_level != INFO else WARNING
|
||||
)
|
||||
getLogger("sqlalchemy.orm.relationships.RelationshipProperty").setLevel(
|
||||
default_level if default_level != INFO else WARNING
|
||||
)
|
||||
getLogger("sqlalchemy.orm.strategies.LazyLoader").setLevel(
|
||||
default_level if default_level != INFO else WARNING
|
||||
)
|
||||
getLogger("sqlalchemy.pool.impl.QueuePool").setLevel(
|
||||
default_level if default_level != INFO else WARNING
|
||||
)
|
||||
getLogger("sqlalchemy.pool.impl.NullPool").setLevel(
|
||||
default_level if default_level != INFO else WARNING
|
||||
)
|
||||
getLogger("sqlalchemy.engine.Engine").setLevel(
|
||||
default_level if default_level != INFO else WARNING
|
||||
)
|
||||
getLogger("sqlalchemy.orm.mapper.Mapper").setLevel(default_level if default_level != INFO else WARNING)
|
||||
getLogger("sqlalchemy.orm.relationships.RelationshipProperty").setLevel(default_level if default_level != INFO else WARNING)
|
||||
getLogger("sqlalchemy.orm.strategies.LazyLoader").setLevel(default_level if default_level != INFO else WARNING)
|
||||
getLogger("sqlalchemy.pool.impl.QueuePool").setLevel(default_level if default_level != INFO else WARNING)
|
||||
getLogger("sqlalchemy.pool.impl.NullPool").setLevel(default_level if default_level != INFO else WARNING)
|
||||
getLogger("sqlalchemy.engine.Engine").setLevel(default_level if default_level != INFO else WARNING)
|
||||
|
||||
# Edit the default levels of the logging module
|
||||
addLevelName(CRITICAL, "🚨")
|
||||
|
|
|
|||
|
|
@ -181,9 +181,9 @@ toposort==1.10 \
|
|||
--hash=sha256:bfbb479c53d0a696ea7402601f4e693c97b0367837c8898bc6471adfca37a6bd \
|
||||
--hash=sha256:cbdbc0d0bee4d2695ab2ceec97fe0679e9c10eab4b2a87a9372b929e70563a87
|
||||
# via pip-compile-multi
|
||||
urllib3==2.0.5 \
|
||||
--hash=sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594 \
|
||||
--hash=sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e
|
||||
urllib3==2.0.6 \
|
||||
--hash=sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2 \
|
||||
--hash=sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564
|
||||
# via requests
|
||||
wheel==0.41.2 \
|
||||
--hash=sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985 \
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
--license agpl3
|
||||
--version %VERSION%
|
||||
--architecture x86_64
|
||||
--depends bash --depends epel-release --depends python39 --depends 'nginx = 1:1.24.0-1.el8.ngx' --depends libcurl-devel --depends libxml2 --depends yajl --depends lmdb-libs --depends GeoIP-devel --depends file-libs --depends net-tools --depends gd --depends sudo --depends procps --depends lsof --depends brotli --depends openssl
|
||||
--depends bash --depends epel-release --depends python39 --depends 'nginx = 1:1.24.0-1.el8.ngx' --depends libcurl-devel --depends libxml2 --depends yajl --depends lmdb-libs --depends GeoIP-devel --depends file-libs --depends net-tools --depends gd --depends sudo --depends procps --depends lsof --depends brotli --depends openssl --depends libpq
|
||||
--description "BunkerWeb %VERSION% for CentOS Stream 8"
|
||||
--url "https://www.bunkerweb.io"
|
||||
--maintainer "Bunkerity <contact at bunkerity dot com>"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
--license agpl3
|
||||
--version %VERSION%
|
||||
--architecture %ARCH%
|
||||
--depends bash --depends python3 --depends procps --depends python3-pip --depends 'nginx = 1.24.0-1~bullseye' --depends libcurl4 --depends libgeoip-dev --depends libxml2 --depends libyajl2 --depends libmagic1 --depends net-tools --depends sudo --depends lsof
|
||||
--depends bash --depends python3 --depends procps --depends python3-pip --depends 'nginx = 1.24.0-1~bullseye' --depends libcurl4 --depends libgeoip-dev --depends libxml2 --depends libyajl2 --depends libmagic1 --depends net-tools --depends sudo --depends lsof --depends libpq5
|
||||
--description "BunkerWeb %VERSION% for Debian 11"
|
||||
--url "https://www.bunkerweb.io"
|
||||
--maintainer "Bunkerity <contact at bunkerity dot com>"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
--license agpl3
|
||||
--version %VERSION%
|
||||
--architecture %ARCH%
|
||||
--depends bash --depends python3 --depends 'nginx = 1:1.24.0-1.fc38' --depends libcurl-devel --depends libxml2 --depends yajl --depends lmdb-libs --depends geoip-devel --depends gd --depends sudo --depends procps --depends lsof --depends nginx-mod-stream --depends pcre
|
||||
--depends bash --depends python3 --depends 'nginx = 1:1.24.0-1.fc38' --depends libcurl-devel --depends libxml2 --depends yajl --depends lmdb-libs --depends geoip-devel --depends gd --depends sudo --depends procps --depends lsof --depends nginx-mod-stream --depends pcre --depends libpq
|
||||
--description "BunkerWeb %VERSION% for Fedora 38"
|
||||
--url "https://www.bunkerweb.io"
|
||||
--maintainer "Bunkerity <contact at bunkerity dot com>"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
--license agpl3
|
||||
--version %VERSION%
|
||||
--architecture %ARCH%
|
||||
--depends bash --depends python39 --depends 'nginx = 1:1.24.0-1.el8.ngx' --depends libcurl-devel --depends libxml2 --depends yajl --depends file-libs --depends net-tools --depends gd --depends sudo --depends procps --depends lsof --depends geoip
|
||||
--depends bash --depends python39 --depends 'nginx = 1:1.24.0-1.el8.ngx' --depends libcurl-devel --depends libxml2 --depends yajl --depends file-libs --depends net-tools --depends gd --depends sudo --depends procps --depends lsof --depends geoip --depends libpq
|
||||
--description "BunkerWeb %VERSION% for RHEL 8"
|
||||
--url "https://www.bunkerweb.io"
|
||||
--maintainer "Bunkerity <contact at bunkerity dot com>"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
--license agpl3
|
||||
--version %VERSION%
|
||||
--architecture %ARCH%
|
||||
--depends bash --depends python3 --depends python3-pip --depends 'nginx = 1.24.0-1~jammy' --depends libcurl4 --depends libgeoip-dev --depends libxml2 --depends libyajl2 --depends libmagic1 --depends net-tools --depends sudo --depends procps --depends lsof
|
||||
--depends bash --depends python3 --depends python3-pip --depends 'nginx = 1.24.0-1~jammy' --depends libcurl4 --depends libgeoip-dev --depends libxml2 --depends libyajl2 --depends libmagic1 --depends net-tools --depends sudo --depends procps --depends lsof --depends libpq5
|
||||
--description "BunkerWeb %VERSION% for Ubuntu 22.04"
|
||||
--url "https://www.bunkerweb.io"
|
||||
--maintainer "Bunkerity <contact at bunkerity dot com>"
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ function reload()
|
|||
log "SYSTEMCTL" "ℹ️" "BunkerWeb service reloaded ..."
|
||||
}
|
||||
|
||||
# List of differents args
|
||||
# List of different args
|
||||
case $1 in
|
||||
"start")
|
||||
start
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
FROM python:3.11.5-alpine@sha256:cd311c6a0164f34a7edbf364e05258b07d66d3f7bc155139dcb9bef88a186ded AS builder
|
||||
FROM python:3.12.0-alpine@sha256:ae35274f417fc81ba6ee1fc84206e8517f28117566ee6a04a64f004c1409bdac AS builder
|
||||
|
||||
# Install python dependencies
|
||||
RUN apk add --no-cache --virtual .build-deps g++ gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev openssl-dev cargo postgresql-dev
|
||||
|
||||
# Copy python requirements
|
||||
COPY src/deps/requirements.txt /tmp/requirements-deps.txt
|
||||
|
|
@ -12,9 +15,6 @@ RUN mkdir -p deps/python && \
|
|||
cat /tmp/req/requirements.txt* > deps/requirements.txt && \
|
||||
rm -rf /tmp/req
|
||||
|
||||
# Install python dependencies
|
||||
RUN apk add --no-cache --virtual .build-deps g++ gcc musl-dev jpeg-dev zlib-dev libffi-dev cairo-dev pango-dev gdk-pixbuf-dev openssl-dev cargo postgresql-dev
|
||||
|
||||
# Install python requirements
|
||||
RUN export MAKEFLAGS="-j$(nproc)" && \
|
||||
pip install --no-cache-dir --ignore-installed --require-hashes -r /tmp/requirements-deps.txt && \
|
||||
|
|
@ -38,7 +38,7 @@ COPY src/common/utils utils
|
|||
COPY src/scheduler scheduler
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM python:3.11.5-alpine@sha256:cd311c6a0164f34a7edbf364e05258b07d66d3f7bc155139dcb9bef88a186ded
|
||||
FROM python:3.12.0-alpine@sha256:ae35274f417fc81ba6ee1fc84206e8517f28117566ee6a04a64f004c1409bdac
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
@ -49,7 +49,7 @@ COPY --from=builder --chown=0:101 /usr/share/bunkerweb /usr/share/bunkerweb
|
|||
WORKDIR /usr/share/bunkerweb
|
||||
|
||||
# Add scheduler user, drop bwcli, install runtime dependencies, create data folders and set permissions
|
||||
RUN apk add --no-cache bash libgcc libstdc++ openssl libmagic && \
|
||||
RUN apk add --no-cache bash libgcc libstdc++ libpq openssl libmagic && \
|
||||
ln -s /usr/local/bin/python3 /usr/bin/python3 && \
|
||||
addgroup -g 101 scheduler && \
|
||||
adduser -h /var/cache/nginx -g scheduler -s /bin/sh -G scheduler -D -H -u 101 scheduler && \
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue