mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge pull request #995 from bunkerity/dev
Merge branch "dev" into branch "staging"
This commit is contained in:
commit
b8217fe436
61 changed files with 301 additions and 282 deletions
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
|
|
@ -35,12 +35,12 @@ jobs:
|
|||
python -m pip install --no-cache-dir --require-hashes -r src/common/db/requirements.txt
|
||||
echo "CODEQL_PYTHON=$(which python)" >> $GITHUB_ENV
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7
|
||||
uses: github/codeql-action/init@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
config-file: ./.github/codeql.yml
|
||||
setup-python-dependencies: false
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7
|
||||
uses: github/codeql-action/analyze@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
|
|
|||
2
.github/workflows/scorecards-analysis.yml
vendored
2
.github/workflows/scorecards-analysis.yml
vendored
|
|
@ -25,6 +25,6 @@ jobs:
|
|||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: "Upload SARIF results to code scanning"
|
||||
uses: github/codeql-action/upload-sarif@3ab4101902695724f9365a384f86c1074d94e18c # v3.24.7
|
||||
uses: github/codeql-action/upload-sarif@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
|
|
|||
22
README.md
22
README.md
|
|
@ -84,13 +84,29 @@ Learn more about the core security features in the [security tuning](https://doc
|
|||
|
||||
A demo website protected with BunkerWeb is available at [demo.bunkerweb.io](https://demo.bunkerweb.io/?utm_campaign=self&utm_source=github). Feel free to visit it and perform some security tests.
|
||||
|
||||
## PRO version
|
||||
|
||||
When using BunkerWeb you have the choice of the version you want to use : open-source or PRO.
|
||||
|
||||
Whether it's enhanced security, an enriched user experience, or technical supervision, the BunkerWeb PRO version will allow you to fully benefit from BunkerWeb and respond to your professional needs.
|
||||
|
||||
Be it in the documentation or the user interface, the PRO features are annotated with a crown <img src="https://docs.bunkerweb.io/1.5.6/assets/img/pro-icon.svg" alt="crow pro icon" height="32px" width="32px"> to distinguish them from those integrated into the open-source version.
|
||||
|
||||
You can upgrade from the open-source version to the PRO one easily and at any time you want. The process is pretty straightforward :
|
||||
|
||||
- Claim your [free trial on the BunkerWeb panel](https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc)
|
||||
- Once connected to the client area, copy your PRO license key
|
||||
- Paste your private key into BunkerWeb using the [web UI](https://docs.bunkerweb.io/1.5.6/web-ui/#upgrade-to-pro) or [specific setting](https://docs.bunkerweb.io/1.5.6/settings/#pro)
|
||||
|
||||
Do not hesitate to visit the [BunkerWeb panel](https://panel.bunkerweb.io/knowledgebase?utm_campaign=self&utm_source=doc) or [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=doc) if you have any question regarding the PRO version.
|
||||
|
||||
## Professional services
|
||||
|
||||
Maximize your BunkerWeb experience by getting professional services directly from the maintainers of the project. Whether you require technical support, personalized consulting, or development services, we stand ready to assist you in fortifying the security of your web services.
|
||||
Get the most of BunkerWeb by getting professional services directly from the maintainers of the project. From technical support to tailored consulting and development, we are here to assist you in the security of your web services.
|
||||
|
||||
You will find more information by visiting the [BunkerWeb Panel](https://panel.bunkerweb.io/?utm_campaign=self&utm_source=github), our dedicated platform for professional services.
|
||||
You will find more information by visiting the [BunkerWeb Panel](https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc), our dedicated platform for professional services.
|
||||
|
||||
Don't hesitate to [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=github) if you have any question, we will be more than happy to respond to your needs.
|
||||
Don't hesitate to [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=doc) if you have any question, we will be more than happy to respond to your needs.
|
||||
|
||||
## Ecosystem, community and resources
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,23 @@ To delve deeper into the core security features, we invite you to explore the [s
|
|||
|
||||
A demo website protected with BunkerWeb is available at [demo.bunkerweb.io](https://demo.bunkerweb.io/?utm_campaign=self&utm_source=doc). Feel free to visit it and perform some security tests.
|
||||
|
||||
## Professional services
|
||||
## PRO version
|
||||
|
||||
### Support panel
|
||||
When using BunkerWeb you have the choice of the version you want to use : open-source or PRO.
|
||||
|
||||
Whether it's enhanced security, an enriched user experience, or technical supervision, the BunkerWeb PRO version will allow you to fully benefit from BunkerWeb and respond to your professional needs.
|
||||
|
||||
Be it in the documentation or the user interface, the PRO features are annotated with a crown <img src="assets/img/pro-icon.svg" alt="crow pro icon" height="32px" width="32px"> to distinguish them from those integrated into the open-source version.
|
||||
|
||||
You can upgrade from the open-source version to the PRO one easily and at any time you want. The process is pretty straightforward :
|
||||
|
||||
- Claim your [free trial on the BunkerWeb panel](https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc)
|
||||
- Once connected to the client area, copy your PRO license key
|
||||
- Paste your private key into BunkerWeb using the [web UI](web-ui.md#upgrade-to-pro) or [specific setting](settings.md#pro)
|
||||
|
||||
Do not hesitate to visit the [BunkerWeb panel](https://panel.bunkerweb.io/knowledgebase?utm_campaign=self&utm_source=doc) or [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=doc) if you have any question regarding the PRO version.
|
||||
|
||||
## Professional services
|
||||
|
||||
Get the most of BunkerWeb by getting professional services directly from the maintainers of the project. From technical support to tailored consulting and development, we are here to assist you in the security of your web services.
|
||||
|
||||
|
|
@ -69,18 +83,6 @@ You will find more information by visiting the [BunkerWeb Panel](https://panel.b
|
|||
|
||||
Don't hesitate to [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=doc) if you have any question, we will be more than happy to respond to your needs.
|
||||
|
||||
### Pro version
|
||||
|
||||
BunkerWeb has a pro version to further improve the security of your applications and make managing them faster and easier (email reporting, more settings options...).
|
||||
|
||||
We have centralised version management and support within the panel for greater ease of use.
|
||||
|
||||
More detailed information about this version can be found [by visiting our website.](https://www.bunkerweb.io/#services?utm_campaign=self&utm_source=doc)
|
||||
|
||||
If you're interested, upgrade to the pro version in just a few clicks, [following the steps here.](https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc#pro)
|
||||
|
||||
Note that in the documentation, it will be mentioned when a feature is for the pro version.
|
||||
|
||||
## Ecosystem, community and resources
|
||||
|
||||
Official websites, tools and resources about BunkerWeb :
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import zipfile
|
|||
import shutil
|
||||
from contextlib import suppress
|
||||
|
||||
|
||||
def print_md_table(settings) -> MarkdownTableWriter:
|
||||
writer = MarkdownTableWriter(
|
||||
headers=["Setting", "Default", "Context", "Multiple", "Description"],
|
||||
|
|
@ -27,7 +26,6 @@ def print_md_table(settings) -> MarkdownTableWriter:
|
|||
)
|
||||
return writer
|
||||
|
||||
|
||||
def stream_support(support) -> str:
|
||||
md = "STREAM support "
|
||||
if support == "no":
|
||||
|
|
@ -38,6 +36,8 @@ def stream_support(support) -> str:
|
|||
md += ":warning:"
|
||||
return md
|
||||
|
||||
def pro_title(title: str) -> str:
|
||||
return f"## {title} <img src='/assets/img/pro-icon.svg' alt='crow pro icon' height='32px' width='32px'>\n"
|
||||
|
||||
doc = StringIO()
|
||||
|
||||
|
|
@ -70,8 +70,7 @@ with open("src/common/settings.json", "r") as f:
|
|||
print(print_md_table(loads(f.read())), file=doc)
|
||||
print(file=doc)
|
||||
|
||||
# Print core settings
|
||||
print("## Core settings\n", file=doc)
|
||||
# Get core plugins
|
||||
core_settings = {}
|
||||
for core in glob("src/common/core/*/plugin.json"):
|
||||
with open(core, "r") as f:
|
||||
|
|
@ -80,60 +79,30 @@ for core in glob("src/common/core/*/plugin.json"):
|
|||
if len(core_plugin["settings"]) > 0:
|
||||
core_settings[core_plugin["name"]] = core_plugin
|
||||
|
||||
for name, data in dict(sorted(core_settings.items())).items():
|
||||
print(f"### {data['name']}\n", file=doc)
|
||||
print(f"{stream_support(data['stream'])}\n", file=doc)
|
||||
print(f"{data['description']}\n", file=doc)
|
||||
print(print_md_table(data["settings"]), file=doc)
|
||||
|
||||
|
||||
def pro_title(head_num: str, title: str) -> str:
|
||||
markdown_header = "##" if head_num == "2" else "###"
|
||||
return f"""
|
||||
{markdown_header} {title}
|
||||
|
||||
<div style="display:flex; align-items:center">
|
||||
<h{head_num} data-custom-header id="{title.lower().replace(" ", "-")}">{title}</h{head_num}>
|
||||
|
||||
<svg style="height:1.25rem; width:1.25rem; margin-top: 0.70rem; margin-left: 0.5rem"
|
||||
viewBox="0 0 48 46"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path style="fill:#eab308" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
|
||||
<path style="fill:#eab308" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
|
||||
</svg>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
# Read VERSION as file with permissions to read from src/
|
||||
# Get PRO plugins
|
||||
with open("src/VERSION", "r") as f:
|
||||
version = f.read().strip()
|
||||
|
||||
# Get zip file from https://assets.bunkerity.com/bw-pro/preview/v{version}
|
||||
url = f"https://assets.bunkerity.com/bw-pro/preview/v{version}.zip"
|
||||
|
||||
# Download zip
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
Path(f"v{version}.zip").write_bytes(response.content)
|
||||
|
||||
# Unzip file
|
||||
with zipfile.ZipFile(f"v{version}.zip", "r") as zip_ref:
|
||||
zip_ref.extractall(f"v{version}")
|
||||
|
||||
# Print pro settings
|
||||
print("## Pro plugins", file=doc)
|
||||
pro_settings = {}
|
||||
for pro in glob(f"v{version}/*/plugin.json"):
|
||||
with open(pro, "r") as f:
|
||||
with suppress(Exception):
|
||||
pro_plugin = loads(f.read())
|
||||
if len(pro_plugin["settings"]) > 0:
|
||||
pro_settings[pro_plugin["name"]] = pro_plugin
|
||||
core_settings[pro_plugin["name"]] = pro_plugin
|
||||
core_settings[pro_plugin["name"]]["is_pro"] = True
|
||||
|
||||
for name, data in dict(sorted(pro_settings.items())).items():
|
||||
print(pro_title("3", data["name"]), file=doc)
|
||||
# Print plugins and their settings
|
||||
for name, data in dict(sorted(core_settings.items())).items():
|
||||
pro_crown = ""
|
||||
if "is_pro" in data:
|
||||
pro_crown = f" <img src='/assets/img/pro-icon.svg' alt='crow pro icon' height='32px' width='32px'> (PRO)\n"
|
||||
print(f"## {data['name']}{pro_crown}\n", file=doc)
|
||||
print(f"{stream_support(data['stream'])}\n", file=doc)
|
||||
print(f"{data['description']}\n", file=doc)
|
||||
print(print_md_table(data["settings"]), file=doc)
|
||||
|
|
|
|||
|
|
@ -2426,17 +2426,3 @@ By default, BunkerWeb will only listen on IPv4 addresses and won't use IPv6 for
|
|||
|
||||
...
|
||||
```
|
||||
|
||||
## And now ?
|
||||
|
||||
This quickstart is just a tiny fraction of the functionality that BunkerWeb has to offer. Be curious and see what else BunkerWeb has to offer.
|
||||
|
||||
You can take a detailed look at the many [plugins and settings available](settings.md) in this solution.
|
||||
|
||||
Details on the use of certain plugins can also be found on the [security tuning page.](security-tuning.md)
|
||||
|
||||
For simplified use of the solution, don't hesitate to [try out the web UI.](web-ui.md)
|
||||
|
||||
Please note that **BunkerWeb comes in both free and pro versions**, with pro features indicated to avoid confusion.
|
||||
|
||||
If you'd like to find out more about the pro version, and use the solution to the full, [visit the panel.](https://panel.bunkerweb.io/?utm_campaign=self&utm_source=doc#pro)
|
||||
|
|
|
|||
173
docs/settings.md
173
docs/settings.md
|
|
@ -52,9 +52,7 @@ STREAM support :warning:
|
|||
|`TIMERS_LOG_LEVEL` |`debug` |global |no |Log level for timers. |
|
||||
|
||||
|
||||
## Core settings
|
||||
|
||||
### Antibot
|
||||
## Antibot
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -74,7 +72,7 @@ Bot detection by using a challenge.
|
|||
|`ANTIBOT_TIME_RESOLVE` |`60` |multisite|no |Maximum time (in seconds) clients have to resolve the challenge. Once this time has passed, a new challenge will be generated.|
|
||||
|`ANTIBOT_TIME_VALID` |`86400` |multisite|no |Maximum validity time of solved challenges. Once this time has passed, clients will need to resolve a new one. |
|
||||
|
||||
### Auth basic
|
||||
## Auth basic
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -88,7 +86,7 @@ Enforce login before accessing a resource or the whole site using HTTP basic aut
|
|||
|`AUTH_BASIC_PASSWORD`|`changeme` |multisite|no |Password |
|
||||
|`AUTH_BASIC_TEXT` |`Restricted area`|multisite|no |Text to display |
|
||||
|
||||
### Bad behavior
|
||||
## Bad behavior
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -102,7 +100,7 @@ Ban IP generating too much 'bad' HTTP status code in a period of time.
|
|||
|`BAD_BEHAVIOR_THRESHOLD` |`10` |multisite|no |Maximum number of 'bad' HTTP status codes within the period of time before IP is banned. |
|
||||
|`BAD_BEHAVIOR_COUNT_TIME` |`60` |multisite|no |Period of time (in seconds) during which we count 'bad' HTTP status codes. |
|
||||
|
||||
### Blacklist
|
||||
## Blacklist
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -133,7 +131,7 @@ Deny access based on internal and external IP/network/rDNS/ASN blacklists.
|
|||
|`BLACKLIST_IGNORE_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to ignore in the blacklist. |
|
||||
|`BLACKLIST_IGNORE_URI_URLS` | |global |no |List of URLs, separated with spaces, containing URI to ignore in the blacklist. |
|
||||
|
||||
### Brotli
|
||||
## Brotli
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -146,7 +144,7 @@ Compress HTTP requests with the brotli algorithm.
|
|||
|`BROTLI_MIN_LENGTH`|`1000` |multisite|no |Minimum length for brotli compression. |
|
||||
|`BROTLI_COMP_LEVEL`|`6` |multisite|no |The compression level of the brotli algorithm. |
|
||||
|
||||
### BunkerNet
|
||||
## BunkerNet
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -157,7 +155,7 @@ Share threat data with other BunkerWeb instances via BunkerNet.
|
|||
|`USE_BUNKERNET` |`yes` |multisite|no |Activate BunkerNet feature. |
|
||||
|`BUNKERNET_SERVER`|`https://api.bunkerweb.io`|global |no |Address of the BunkerNet API.|
|
||||
|
||||
### CORS
|
||||
## CORS
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -177,7 +175,7 @@ Cross-Origin Resource Sharing.
|
|||
|`CORS_ALLOW_HEADERS` |`DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range`|multisite|no |Value of the Access-Control-Allow-Headers header. |
|
||||
|`CORS_DENY_REQUEST` |`yes` |multisite|no |Deny request and don't send it to backend if Origin is not allowed.|
|
||||
|
||||
### Client cache
|
||||
## Client cache
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -190,7 +188,7 @@ Manage caching for clients.
|
|||
|`CLIENT_CACHE_ETAG` |`yes` |multisite|no |Send the HTTP ETag header for static resources. |
|
||||
|`CLIENT_CACHE_CONTROL` |`public, max-age=15552000` |multisite|no |Value of the Cache-Control HTTP header. |
|
||||
|
||||
### Country
|
||||
## Country
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -201,7 +199,7 @@ Deny access based on the country of the client IP.
|
|||
|`BLACKLIST_COUNTRY`| |multisite|no |Deny access if the country of the client is in the list (ISO 3166-1 alpha-2 format separated with spaces). |
|
||||
|`WHITELIST_COUNTRY`| |multisite|no |Deny access if the country of the client is not in the list (ISO 3166-1 alpha-2 format separated with spaces).|
|
||||
|
||||
### Custom HTTPS certificate
|
||||
## Custom HTTPS certificate
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -215,7 +213,7 @@ Choose custom certificate for HTTPS.
|
|||
|`CUSTOM_SSL_CERT_DATA`| |multisite|no |Certificate data encoded in base64. |
|
||||
|`CUSTOM_SSL_KEY_DATA` | |multisite|no |Key data encoded in base64. |
|
||||
|
||||
### DB
|
||||
## DB
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -226,7 +224,7 @@ Integrate easily the Database.
|
|||
|`DATABASE_URI` |`sqlite:////var/lib/bunkerweb/db.sqlite3`|global |no |The database URI, following the sqlalchemy format.|
|
||||
|`DATABASE_LOG_LEVEL`|`warning` |global |no |The level to use for database logs. |
|
||||
|
||||
### DNSBL
|
||||
## DNSBL
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -237,7 +235,7 @@ Deny access based on external DNSBL servers.
|
|||
|`USE_DNSBL` |`yes` |multisite|no |Activate DNSBL feature.|
|
||||
|`DNSBL_LIST`|`bl.blocklist.de problems.dnsbl.sorbs.net sbl.spamhaus.org xbl.spamhaus.org`|global |no |List of DNSBL servers. |
|
||||
|
||||
### Errors
|
||||
## Errors
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -248,7 +246,7 @@ Manage default error pages
|
|||
|`ERRORS` | |multisite|no |List of HTTP error code and corresponding error pages, separated with spaces (404=/my404.html 403=/errors/403.html ...).|
|
||||
|`INTERCEPTED_ERROR_CODES`|`400 401 403 404 405 413 429 500 501 502 503 504`|multisite|no |List of HTTP error code intercepted by BunkerWeb |
|
||||
|
||||
### Greylist
|
||||
## Greylist
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -269,7 +267,7 @@ Allow access while keeping security features based on internal and external IP/n
|
|||
|`GREYLIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to put into the greylist. |
|
||||
|`GREYLIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to put into the greylist. |
|
||||
|
||||
### Gzip
|
||||
## Gzip
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -282,7 +280,7 @@ Compress HTTP requests with the gzip algorithm.
|
|||
|`GZIP_MIN_LENGTH`|`1000` |multisite|no |Minimum length for gzip compression. |
|
||||
|`GZIP_COMP_LEVEL`|`5` |multisite|no |The compression level of the gzip algorithm. |
|
||||
|
||||
### HTML injection
|
||||
## HTML injection
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -292,7 +290,7 @@ Inject custom HTML code before the </body> tag.
|
|||
|-------------|-------|---------|--------|------------------------|
|
||||
|`INJECT_BODY`| |multisite|no |The HTML code to inject.|
|
||||
|
||||
### Headers
|
||||
## Headers
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -315,19 +313,36 @@ Manage HTTP headers sent to clients.
|
|||
|`X_CONTENT_TYPE_OPTIONS` |`nosniff` |multisite|no |Value for the X-Content-Type-Options header. |
|
||||
|`X_XSS_PROTECTION` |`1; mode=block` |multisite|no |Value for the X-XSS-Protection header. |
|
||||
|
||||
### Let's Encrypt
|
||||
## Let's Encrypt
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
Automatic creation, renewal and configuration of Let's Encrypt certificates.
|
||||
|
||||
| Setting |Default| Context |Multiple| Description |
|
||||
|--------------------------|-------|---------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`AUTO_LETS_ENCRYPT` |`no` |multisite|no |Activate automatic Let's Encrypt mode. |
|
||||
|`EMAIL_LETS_ENCRYPT` | |multisite|no |Email used for Let's Encrypt notification and in certificate. |
|
||||
|`USE_LETS_ENCRYPT_STAGING`|`no` |multisite|no |Use the staging environment for Let’s Encrypt certificate generation. Useful when you are testing your deployments to avoid being rate limited in the production environment.|
|
||||
| Setting |Default| Context |Multiple| Description |
|
||||
|--------------------------|-------|---------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`AUTO_LETS_ENCRYPT` |`no` |multisite|no |Activate automatic Let's Encrypt mode. |
|
||||
|`EMAIL_LETS_ENCRYPT` | |multisite|no |Email used for Let's Encrypt notification and in certificate. |
|
||||
|`USE_LETS_ENCRYPT_STAGING`|`no` |multisite|no |Use the staging environment for Let’s Encrypt certificate generation. Useful when you are testing your deployments to avoid being rate limited in the production environment.|
|
||||
|
||||
### Limit
|
||||
## Let's Encrypt DNS <img src='/assets/img/pro-icon.svg' alt='crow pro icon' height='32px' width='32px'> (PRO)
|
||||
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
Automatic creation, renewal and configuration of Let's Encrypt certificates using DNS challenges.
|
||||
|
||||
| Setting | Default | Context |Multiple| Description |
|
||||
|----------------------------------|---------|---------|--------|---------------------------------------------------------------------------------------|
|
||||
|`AUTO_LETS_ENCRYPT_DNS` |`no` |multisite|no |Activate automatic Let's Encrypt DNS. |
|
||||
|`LETS_ENCRYPT_DNS_EMAIL` | |multisite|no |The email address to use for Let's Encrypt notifications. |
|
||||
|`USE_LETS_ENCRYPT_DNS_STAGING` |`no` |multisite|no |Use the Let's Encrypt staging environment. |
|
||||
|`LETS_ENCRYPT_DNS_PROVIDER` | |multisite|no |The DNS provider to use for DNS challenges. |
|
||||
|`USE_LETS_ENCRYPT_DNS_WILDCARD` |`yes` |multisite|no |Create wildcard certificates for all domains using DNS challenges. |
|
||||
|`LETS_ENCRYPT_DNS_PROPAGATION` |`default`|multisite|no |The time to wait for DNS propagation in seconds. |
|
||||
|`LETS_ENCRYPT_DNS_CREDENTIAL_ITEM`| |multisite|yes |Configuration item that will be added to the credentials.ini file for the DNS provider.|
|
||||
|
||||
## Limit
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -343,7 +358,7 @@ Limit maximum number of requests and connections.
|
|||
|`LIMIT_CONN_MAX_HTTP2` |`100` |multisite|no |Maximum number of streams per IP when using HTTP/2 protocol. |
|
||||
|`LIMIT_CONN_MAX_STREAM`|`10` |multisite|no |Maximum number of connections per IP when using stream. |
|
||||
|
||||
### Metrics
|
||||
## Metrics
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -355,7 +370,7 @@ Metrics collection and retrieve.
|
|||
|`METRICS_MEMORY_SIZE` |`16m` |global |no |Size of the internal storage for metrics. |
|
||||
|`METRICS_MAX_BLOCKED_REQUESTS`|`100` |global |no |Maximum number of blocked requests to store (per worker).|
|
||||
|
||||
### Miscellaneous
|
||||
## Miscellaneous
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -382,7 +397,7 @@ Miscellaneous settings.
|
|||
|`DENY_HTTP_STATUS` |`403` |global |no |HTTP status code to send when the request is denied (403 or 444). When using 444, BunkerWeb will close the connection. |
|
||||
|`SEND_ANONYMOUS_REPORT` |`yes` |global |no |Send anonymous report to BunkerWeb maintainers. |
|
||||
|
||||
### ModSecurity
|
||||
## ModSecurity
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -397,7 +412,19 @@ Management of the ModSecurity WAF.
|
|||
|`MODSECURITY_SEC_RULE_ENGINE` |`On` |multisite|no |SecRuleEngine directive of ModSecurity. |
|
||||
|`MODSECURITY_SEC_AUDIT_LOG_PARTS`|`ABCFHZ` |multisite|no |SecAuditLogParts directive of ModSecurity.|
|
||||
|
||||
### PHP
|
||||
## Monitoring <img src='/assets/img/pro-icon.svg' alt='crow pro icon' height='32px' width='32px'> (PRO)
|
||||
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
BunkerWeb monitoring pro system. This plugin is a prerequisite for some other plugins.
|
||||
|
||||
| Setting |Default| Context |Multiple| Description |
|
||||
|------------------------------|-------|---------|--------|---------------------------------------------|
|
||||
|`USE_MONITORING` |`yes` |multisite|no |Enable monitoring of BunkerWeb. |
|
||||
|`MONITORING_METRICS_DICT_SIZE`|`10M` |global |no |Size of the dict to store monitoring metrics.|
|
||||
|
||||
## PHP
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -410,7 +437,7 @@ Manage local or remote PHP-FPM.
|
|||
|`LOCAL_PHP` | |multisite|no |Path to the PHP-FPM socket file. |
|
||||
|`LOCAL_PHP_PATH` | |multisite|no |Root folder containing files in the local PHP-FPM instance. |
|
||||
|
||||
### Pro
|
||||
## Pro
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -420,7 +447,23 @@ Pro settings for the Pro version of BunkerWeb.
|
|||
|-----------------|-------|-------|--------|-------------------------------------------------|
|
||||
|`PRO_LICENSE_KEY`| |global |no |The License Key for the Pro version of BunkerWeb.|
|
||||
|
||||
### Real IP
|
||||
## Prometheus exporter <img src='/assets/img/pro-icon.svg' alt='crow pro icon' height='32px' width='32px'> (PRO)
|
||||
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
Prometheus exporter for BunkerWeb
|
||||
|
||||
| Setting | Default |Context|Multiple| Description |
|
||||
|-------------------------------|-----------------------------------------------------|-------|--------|------------------------------------------------------------------------|
|
||||
|`USE_PROMETHEUS_EXPORTER` |`no` |global |no |Enable the Prometheus export. |
|
||||
|`PROMETHEUS_EXPORTER_IP` |`0.0.0.0` |global |no |Listening IP of the Prometheus exporter. |
|
||||
|`PROMETHEUS_EXPORTER_PORT` |`9113` |global |no |Listening port of the Prometheus exporter. |
|
||||
|`PROMETHEUS_EXPORTER_DICT_SIZE`|`10M` |global |no |Size of the dict to store Prometheus metrics. |
|
||||
|`PROMETHEUS_EXPORTER_ALLOW_IP` |`127.0.0.0/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16`|global |no |List of IP/networks allowed to contact the Prometheus exporter endpoint.|
|
||||
|`PROMETHEUS_EXPORTER_URL` |`/metrics` |global |no |HTTP URL of the Prometheus exporter. |
|
||||
|
||||
## Real IP
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -435,7 +478,7 @@ Get real IP of clients when BunkerWeb is behind a reverse proxy / load balancer.
|
|||
|`REAL_IP_HEADER` |`X-Forwarded-For` |multisite|no |HTTP header containing the real IP or special value proxy_protocol for PROXY protocol. |
|
||||
|`REAL_IP_RECURSIVE` |`yes` |multisite|no |Perform a recursive search in the header container IP address. |
|
||||
|
||||
### Redirect
|
||||
## Redirect
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -447,7 +490,7 @@ Manage HTTP redirects.
|
|||
|`REDIRECT_TO_REQUEST_URI`|`no` |multisite|no |Append the requested URI to the redirect address.|
|
||||
|`REDIRECT_TO_STATUS_CODE`|`301` |multisite|no |Status code to send to client when redirecting. |
|
||||
|
||||
### Redis
|
||||
## Redis
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -471,7 +514,29 @@ Redis server configuration when using BunkerWeb in cluster mode.
|
|||
|`REDIS_SENTINEL_PASSWORD`| |global |no |Redis sentinel password. |
|
||||
|`REDIS_SENTINEL_MASTER` | |global |no |Redis sentinel master name. |
|
||||
|
||||
### Reverse proxy
|
||||
## Reporting <img src='/assets/img/pro-icon.svg' alt='crow pro icon' height='32px' width='32px'> (PRO)
|
||||
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
Regular reporting of important data from BunkerWeb (global, attacks, bans, requests, reasons, AS...). Monitoring pro plugin needed to work.
|
||||
|
||||
| Setting |Default |Context|Multiple| Description |
|
||||
|------------------------------|--------|-------|--------|----------------------------------------------------------------------------------------------------------------------------------|
|
||||
|`USE_REPORTING` |`no` |global |no |Enable the reporting feature. |
|
||||
|`REPORTING_USE_SMTP` |`no` |global |no |Enable the send report with email(s). |
|
||||
|`REPORTING_USE_WEBHOOK` |`no` |global |no |Enable the send report with webhook. |
|
||||
|`REPORTING_SCHEDULE` |`weekly`|global |no |The time between sending two reports. |
|
||||
|`REPORTING_WEBHOOK_URLS` | |global |no |List of webhooks URLs to receive the report in PDF format (separated by spaces) |
|
||||
|`REPORTING_SMTP_EMAILS` | |global |no |List of emails to receive the report in HTML format (separated by spaces) |
|
||||
|`REPORTING_SMTP_HOST` | |global |no |Host server used for SMTP sending. |
|
||||
|`REPORTING_SMTP_FROM_EMAIL` | |global |no |The email address used to send the message. Notice that 2FA must be disabled for this email address. |
|
||||
|`REPORTING_SMTP_FROM_USER` | |global |no |The user authentication value for sending via the from email address. |
|
||||
|`REPORTING_SMTP_FROM_PASSWORD`| |global |no |The password authentication value for sending via the from email address. |
|
||||
|`REPORTING_SMTP_PORT` |`465` |global |no |The port used for SMTP. Please note that there are different standards depending on the type of connection (SSL = 465, TLS = 587).|
|
||||
|`REPORTING_SMTP_SSL` |`SSL` |global |no |Determine whether or not you want a secure connection for SMTP. |
|
||||
|
||||
## Reverse proxy
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -507,7 +572,7 @@ Manage reverse proxy configurations.
|
|||
|`REVERSE_PROXY_INCLUDES` | |multisite|yes |Additional configuration to include in the location block, separated with spaces. |
|
||||
|`REVERSE_PROXY_CUSTOM_HOST` | |multisite|no |Override Host header sent to upstream server. |
|
||||
|
||||
### Reverse scan
|
||||
## Reverse scan
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -519,7 +584,7 @@ Scan clients ports to detect proxies or servers.
|
|||
|`REVERSE_SCAN_PORTS` |`22 80 443 3128 8000 8080`|multisite|no |List of port to scan when using reverse scan feature. |
|
||||
|`REVERSE_SCAN_TIMEOUT`|`500` |multisite|no |Specify the maximum timeout (in ms) when scanning a port. |
|
||||
|
||||
### Self-signed certificate
|
||||
## Self-signed certificate
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -531,7 +596,7 @@ Generate self-signed certificate.
|
|||
|`SELF_SIGNED_SSL_EXPIRY` |`365` |multisite|no |Self-signed certificate expiry in days. |
|
||||
|`SELF_SIGNED_SSL_SUBJ` |`/CN=www.example.com/`|multisite|no |Self-signed certificate subject. |
|
||||
|
||||
### Sessions
|
||||
## Sessions
|
||||
|
||||
STREAM support :white_check_mark:
|
||||
|
||||
|
|
@ -547,7 +612,7 @@ Management of session used by other plugins.
|
|||
|`SESSIONS_CHECK_IP` |`yes` |global |no |Destroy session if IP address is different than original one. |
|
||||
|`SESSIONS_CHECK_USER_AGENT`|`yes` |global |no |Destroy session if User-Agent is different than original one. |
|
||||
|
||||
### UI
|
||||
## UI
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
|
|
@ -558,7 +623,7 @@ Integrate easily the BunkerWeb UI.
|
|||
|`USE_UI` |`no` |multisite|no |Use UI |
|
||||
|`UI_HOST`| |global |no |Address of the web UI used for initial setup|
|
||||
|
||||
### Whitelist
|
||||
## Whitelist
|
||||
|
||||
STREAM support :warning:
|
||||
|
||||
|
|
@ -579,31 +644,3 @@ Allow access based on internal and external IP/network/rDNS/ASN whitelists.
|
|||
|`WHITELIST_URI` | |multisite|no |List of URI (PCRE regex), separated with spaces, to whitelist. |
|
||||
|`WHITELIST_URI_URLS` | |global |no |List of URLs, separated with spaces, containing bad URI to whitelist. |
|
||||
|
||||
## Pro plugins
|
||||
|
||||
### Prometheus exporter
|
||||
|
||||
<div style="display:flex; align-items:center">
|
||||
<h3 data-custom-header id="prometheus-exporter">Prometheus exporter</h3>
|
||||
|
||||
<svg style="height:1.25rem; width:1.25rem; margin-top: 0.70rem; margin-left: 0.5rem"
|
||||
viewBox="0 0 48 46"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path style="fill:#eab308" d="M43.218 28.2327L43.6765 23.971C43.921 21.6973 44.0825 20.1957 43.9557 19.2497L44 19.25C46.071 19.25 47.75 17.5711 47.75 15.5C47.75 13.4289 46.071 11.75 44 11.75C41.929 11.75 40.25 13.4289 40.25 15.5C40.25 16.4366 40.5935 17.2931 41.1613 17.9503C40.346 18.4535 39.2805 19.515 37.6763 21.1128C36.4405 22.3438 35.8225 22.9593 35.1333 23.0548C34.7513 23.1075 34.3622 23.0532 34.0095 22.898C33.373 22.6175 32.9485 21.8567 32.0997 20.335L27.6262 12.3135C27.1025 11.3747 26.6642 10.5889 26.2692 9.95662C27.89 9.12967 29 7.44445 29 5.5C29 2.73857 26.7615 0.5 24 0.5C21.2385 0.5 19 2.73857 19 5.5C19 7.44445 20.11 9.12967 21.7308 9.95662C21.3358 10.589 20.8975 11.3746 20.3738 12.3135L15.9002 20.335C15.0514 21.8567 14.627 22.6175 13.9905 22.898C13.6379 23.0532 13.2487 23.1075 12.8668 23.0548C12.1774 22.9593 11.5595 22.3438 10.3238 21.1128C8.71968 19.515 7.6539 18.4535 6.83882 17.9503C7.4066 17.2931 7.75 16.4366 7.75 15.5C7.75 13.4289 6.07107 11.75 4 11.75C1.92893 11.75 0.25 13.4289 0.25 15.5C0.25 17.5711 1.92893 19.25 4 19.25L4.04428 19.2497C3.91755 20.1957 4.07905 21.6973 4.32362 23.971L4.782 28.2327C5.03645 30.5982 5.24802 32.849 5.50717 34.875H42.4928C42.752 32.849 42.9635 30.5982 43.218 28.2327Z" fill="#1C274C" />
|
||||
<path style="fill:#eab308" d="M21.2803 45.5H26.7198C33.8098 45.5 37.3545 45.5 39.7198 43.383C40.7523 42.4588 41.4057 40.793 41.8775 38.625H6.1224C6.59413 40.793 7.24783 42.4588 8.2802 43.383C10.6454 45.5 14.1903 45.5 21.2803 45.5Z" fill="#1C274C" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
STREAM support :x:
|
||||
|
||||
Prometheus export for BunkerWeb
|
||||
|
||||
| Setting | Default |Context|Multiple| Description |
|
||||
|-------------------------------|-----------------------------------------------------|-------|--------|------------------------------------------------------------------------|
|
||||
|`USE_PROMETHEUS_EXPORTER` |`no` |global |no |Enable the Prometheus export. |
|
||||
|`PROMETHEUS_EXPORTER_IP` |`0.0.0.0` |global |no |Listening IP of the Prometheus exporter. |
|
||||
|`PROMETHEUS_EXPORTER_PORT` |`9113` |global |no |Listening port of the Prometheus exporter. |
|
||||
|`PROMETHEUS_EXPORTER_DICT_SIZE`|`10M` |global |no |Size of the dict to store Prometheus metrics. |
|
||||
|`PROMETHEUS_EXPORTER_ALLOW_IP` |`127.0.0.1/8 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16`|global |no |List of IP/networks allowed to contact the Prometheus exporter endpoint.|
|
||||
|`PROMETHEUS_EXPORTER_URL` |`/metrics` |global |no |HTTP URL of the Prometheus exporter. |
|
||||
|
|
|
|||
|
|
@ -721,15 +721,20 @@ Review your final BunkerWeb UI URL and then click on the `Setup` button. Once th
|
|||
|
||||
## Account management
|
||||
|
||||
You can change the username, password needed and manage two-factor authentication by **accessing the account page** of the web UI from the menu.
|
||||
|
||||
You need to click on `manage account` inside the sidebar menu.
|
||||
You can access the account management page by clicking on `manage account` inside the sidebar menu :
|
||||
|
||||
<figure markdown>
|
||||
{ align=center, width="350" }
|
||||
<figcaption>Account page access from menu</figcaption>
|
||||
</figure>
|
||||
|
||||
### Upgrade to PRO
|
||||
|
||||
!!! info "What is BunkerWeb PRO ?"
|
||||
BunkerWeb PRO is an enhanced version of BunkerWeb open-source. Whether it's enhanced security, an enriched user experience, or technical supervision, the BunkerWeb PRO version will allow you to fully benefit from BunkerWeb and respond to your professional needs. Do not hesitate to visit the [BunkerWeb panel](https://panel.bunkerweb.io/knowledgebase?utm_campaign=self&utm_source=doc) or [contact us](https://panel.bunkerweb.io/contact.php?utm_campaign=self&utm_source=doc) if you have any question regarding the PRO version.
|
||||
|
||||
TODO : screenshots
|
||||
|
||||
### Username / Password
|
||||
|
||||
!!! warning "Lost password/username"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e as builder
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c as builder
|
||||
|
||||
# Install python dependencies
|
||||
RUN apk add --no-cache build-base libffi-dev postgresql-dev
|
||||
|
|
@ -26,7 +26,7 @@ COPY src/common/helpers helpers
|
|||
COPY src/common/settings.json settings.json
|
||||
COPY src/common/utils utils
|
||||
|
||||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
@ -56,7 +56,7 @@ RUN apk add --no-cache bash && \
|
|||
chmod 660 INTEGRATION
|
||||
|
||||
# Fix CVEs
|
||||
RUN apk add --no-cache "libexpat>=2.6.0-r0"
|
||||
# There are no CVEs to fix for this image
|
||||
|
||||
VOLUME /data
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM nginx:1.24.0-alpine-slim@sha256:9cec4fd40a4e5156b4f4f555ee44a597491b6e8b91380c32b63ed45a4053a763 AS builder
|
||||
FROM nginx:1.24.0-alpine-slim@sha256:927eec798eb41b53f9e446aef26482ce4ade9008645ff13608c682cfe66b9503 AS builder
|
||||
|
||||
# Install temporary requirements for the dependencies
|
||||
RUN apk add --no-cache bash autoconf libtool automake geoip-dev g++ gcc curl-dev libxml2-dev pcre-dev make linux-headers musl-dev gd-dev gnupg brotli-dev openssl-dev patch readline-dev yajl yajl-dev yajl-tools py3-pip
|
||||
|
|
@ -42,7 +42,7 @@ COPY src/common/utils utils
|
|||
COPY src/VERSION VERSION
|
||||
COPY misc/*.ascii misc/
|
||||
|
||||
FROM nginx:1.24.0-alpine-slim@sha256:9cec4fd40a4e5156b4f4f555ee44a597491b6e8b91380c32b63ed45a4053a763
|
||||
FROM nginx:1.24.0-alpine-slim@sha256:927eec798eb41b53f9e446aef26482ce4ade9008645ff13608c682cfe66b9503
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
@ -53,7 +53,7 @@ COPY --from=builder --chown=0:101 /usr/share/bunkerweb /usr/share/bunkerweb
|
|||
WORKDIR /usr/share/bunkerweb
|
||||
|
||||
# Install runtime dependencies, pypi packages, move bwcli, create data folders and set permissions
|
||||
RUN apk add --no-cache openssl pcre bash python3 yajl geoip libxml2 libgd && \
|
||||
RUN apk add --no-cache openssl pcre bash python3 yajl geoip libxml2 libgd curl && \
|
||||
cp helpers/bwcli /usr/bin/ && \
|
||||
mkdir -p /etc/bunkerweb /var/tmp/bunkerweb /var/run/bunkerweb /var/log/bunkerweb /var/www/html && \
|
||||
mkdir -p /data/cache && ln -s /data/cache /var/cache/bunkerweb && \
|
||||
|
|
@ -68,7 +68,7 @@ RUN apk add --no-cache openssl pcre bash python3 yajl geoip libxml2 libgd && \
|
|||
ln -s /proc/1/fd/1 /var/log/bunkerweb/access.log
|
||||
|
||||
# Fix CVEs
|
||||
RUN apk add --no-cache "curl>=8.5.0-r0" "libcurl>=8.5.0-r0" "libcrypto3>=3.0.12-r4" "libexpat>=2.6.0-r0" "libssl3>=3.0.12-r4" "libwebp>=1.2.4-r3" "libx11>=1.8.7-r0" "nghttp2-libs>=1.51.0-r2"
|
||||
# There are no CVEs to fix for this image
|
||||
|
||||
EXPOSE 8080/tcp 8443/tcp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from hashlib import sha256
|
||||
from io import BytesIO
|
||||
from os import getenv, listdir, chmod, sep
|
||||
from os.path import basename, join, normpath
|
||||
from os import getenv, sep
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
from stat import S_IEXEC
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from threading import Lock
|
||||
from uuid import uuid4
|
||||
from glob import glob
|
||||
from json import JSONDecodeError, loads
|
||||
from shutil import copytree, rmtree
|
||||
from tarfile import open as tar_open
|
||||
|
|
@ -31,17 +29,18 @@ for deps_path in [
|
|||
from magic import Magic
|
||||
from requests import get
|
||||
|
||||
from common_utils import bytes_hash # type: ignore
|
||||
from Database import Database # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
|
||||
|
||||
EXTERNAL_PLUGINS_DIR = Path(sep, "etc", "bunkerweb", "plugins")
|
||||
TMP_DIR = Path(sep, "var", "tmp", "bunkerweb", "plugins")
|
||||
LOGGER = setup_logger("Jobs.download-plugins", getenv("LOG_LEVEL", "INFO"))
|
||||
status = 0
|
||||
|
||||
|
||||
def install_plugin(plugin_dir: str, db) -> bool:
|
||||
plugin_path = Path(plugin_dir)
|
||||
def install_plugin(plugin_path: Path, db) -> bool:
|
||||
plugin_file = plugin_path.joinpath("plugin.json")
|
||||
|
||||
if not plugin_file.is_file():
|
||||
|
|
@ -55,8 +54,10 @@ def install_plugin(plugin_dir: str, db) -> bool:
|
|||
LOGGER.error(f"Skipping installation of plugin {plugin_path.name} (plugin.json is not valid)")
|
||||
return False
|
||||
|
||||
new_plugin_path = EXTERNAL_PLUGINS_DIR.joinpath(metadata["id"])
|
||||
|
||||
# Don't go further if plugin is already installed
|
||||
if EXTERNAL_PLUGINS_DIR.joinpath(metadata["id"], "plugin.json").is_file():
|
||||
if new_plugin_path.is_dir():
|
||||
old_version = None
|
||||
|
||||
for plugin in db.get_plugins(_type="external"):
|
||||
|
|
@ -65,22 +66,19 @@ def install_plugin(plugin_dir: str, db) -> bool:
|
|||
break
|
||||
|
||||
if old_version == metadata["version"]:
|
||||
LOGGER.warning(
|
||||
f"Skipping installation of plugin {metadata['id']} (version {metadata['version']} already installed)",
|
||||
)
|
||||
LOGGER.warning(f"Skipping installation of plugin {metadata['id']} (version {metadata['version']} already installed)")
|
||||
return False
|
||||
|
||||
LOGGER.warning(
|
||||
f"Plugin {metadata['id']} is already installed but version {metadata['version']} is different from database ({old_version}), updating it...",
|
||||
f"Plugin {metadata['id']} is already installed but version {metadata['version']} is different from database ({old_version}), updating it..."
|
||||
)
|
||||
rmtree(EXTERNAL_PLUGINS_DIR.joinpath(metadata["id"]), ignore_errors=True)
|
||||
rmtree(new_plugin_path, ignore_errors=True)
|
||||
|
||||
# Copy the plugin
|
||||
copytree(plugin_dir, join(sep, "etc", "bunkerweb", "plugins", metadata["id"]))
|
||||
copytree(plugin_path, new_plugin_path)
|
||||
# Add u+x permissions to jobs files
|
||||
for job_file in glob(join(sep, "etc", "bunkerweb", "plugins", "jobs", "*")):
|
||||
st = Path(job_file).stat()
|
||||
chmod(job_file, st.st_mode | S_IEXEC)
|
||||
for job_file in new_plugin_path.joinpath("jobs").glob("*"):
|
||||
job_file.chmod(job_file.stat().st_mode | S_IEXEC)
|
||||
LOGGER.info(f"Plugin {metadata['id']} installed")
|
||||
return True
|
||||
|
||||
|
|
@ -101,7 +99,7 @@ try:
|
|||
# Download Plugin file
|
||||
try:
|
||||
if plugin_urls.startswith("file://"):
|
||||
content = Path(normpath(plugin_urls[7:])).read_bytes()
|
||||
content = Path(plugin_urls[7:]).read_bytes()
|
||||
else:
|
||||
content = b""
|
||||
resp = get(
|
||||
|
|
@ -120,16 +118,14 @@ try:
|
|||
if chunk:
|
||||
content += chunk
|
||||
except:
|
||||
LOGGER.error(
|
||||
f"Exception while downloading plugin(s) from {plugin_url} :\n{format_exc()}",
|
||||
)
|
||||
LOGGER.error(f"Exception while downloading plugin(s) from {plugin_url} :\n{format_exc()}")
|
||||
status = 2
|
||||
continue
|
||||
|
||||
# Extract it to tmp folder
|
||||
temp_dir = join(sep, "var", "tmp", "bunkerweb", "plugins", str(uuid4()))
|
||||
temp_dir = TMP_DIR.joinpath(str(uuid4()))
|
||||
try:
|
||||
Path(temp_dir).mkdir(parents=True, exist_ok=True)
|
||||
temp_dir.mkdir(parents=True, exist_ok=True)
|
||||
file_type = Magic(mime=True).from_buffer(content)
|
||||
|
||||
if file_type == "application/zip":
|
||||
|
|
@ -157,12 +153,12 @@ try:
|
|||
|
||||
# Install plugins
|
||||
try:
|
||||
for plugin_dir in glob(join(temp_dir, "*")):
|
||||
for plugin_path in temp_dir.rglob("**/plugin.json"):
|
||||
try:
|
||||
if install_plugin(plugin_dir, db):
|
||||
if install_plugin(plugin_path.parent, db):
|
||||
plugin_nbr += 1
|
||||
except FileExistsError:
|
||||
LOGGER.warning(f"Skipping installation of plugin {basename(plugin_dir)} (already installed)")
|
||||
LOGGER.warning(f"Skipping installation of plugin {plugin_path.parent.name} (already installed)")
|
||||
except:
|
||||
LOGGER.error(f"Exception while installing plugin(s) from {plugin_url} :\n{format_exc()}")
|
||||
status = 2
|
||||
|
|
@ -173,34 +169,30 @@ try:
|
|||
|
||||
external_plugins = []
|
||||
external_plugins_ids = []
|
||||
for plugin in listdir(EXTERNAL_PLUGINS_DIR):
|
||||
path = EXTERNAL_PLUGINS_DIR.joinpath(plugin)
|
||||
if not path.joinpath("plugin.json").is_file():
|
||||
LOGGER.warning(f"Plugin {plugin} is not valid, deleting it...")
|
||||
rmtree(path, ignore_errors=True)
|
||||
for plugin_path in EXTERNAL_PLUGINS_DIR.glob("*"):
|
||||
if not plugin_path.joinpath("plugin.json").is_file():
|
||||
LOGGER.warning(f"Plugin {plugin_path.name} is not valid, deleting it...")
|
||||
rmtree(plugin_path, ignore_errors=True)
|
||||
continue
|
||||
|
||||
plugin_file = loads(path.joinpath("plugin.json").read_text(encoding="utf-8"))
|
||||
plugin_file = loads(plugin_path.joinpath("plugin.json").read_text(encoding="utf-8"))
|
||||
|
||||
with BytesIO() as plugin_content:
|
||||
with tar_open(fileobj=plugin_content, mode="w:gz", compresslevel=9) as tar:
|
||||
tar.add(path, arcname=path.name)
|
||||
tar.add(plugin_path, arcname=plugin_path.name)
|
||||
plugin_content.seek(0)
|
||||
value = plugin_content.getvalue()
|
||||
|
||||
plugin_file.update(
|
||||
{
|
||||
"type": "external",
|
||||
"page": False,
|
||||
"page": plugin_path.joinpath("ui").is_dir(),
|
||||
"method": "scheduler",
|
||||
"data": value,
|
||||
"checksum": sha256(value).hexdigest(),
|
||||
"checksum": bytes_hash(value, algorithm="sha256"),
|
||||
}
|
||||
)
|
||||
|
||||
if "ui" in listdir(path):
|
||||
plugin_file["page"] = True
|
||||
|
||||
external_plugins.append(plugin_file)
|
||||
external_plugins_ids.append(plugin_file["id"])
|
||||
|
||||
|
|
@ -214,9 +206,7 @@ try:
|
|||
err = db.update_external_plugins(external_plugins)
|
||||
|
||||
if err:
|
||||
LOGGER.error(
|
||||
f"Couldn't update external plugins to database: {err}",
|
||||
)
|
||||
LOGGER.error(f"Couldn't update external plugins to database: {err}")
|
||||
|
||||
status = 1
|
||||
LOGGER.info("External plugins downloaded and installed")
|
||||
|
|
@ -227,7 +217,7 @@ except:
|
|||
status = 2
|
||||
LOGGER.error(f"Exception while running download-plugins.py :\n{format_exc()}")
|
||||
|
||||
for plugin_tmp in glob(join(sep, "var", "tmp", "bunkerweb", "plugins", "*")):
|
||||
for plugin_tmp in TMP_DIR.glob("*"):
|
||||
rmtree(plugin_tmp, ignore_errors=True)
|
||||
|
||||
sys_exit(status)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from datetime import datetime
|
||||
from hashlib import sha256
|
||||
from io import BytesIO
|
||||
from os import getenv, listdir, chmod, sep
|
||||
from os import getenv, sep
|
||||
from os.path import join
|
||||
from pathlib import Path
|
||||
from stat import S_IEXEC
|
||||
from sys import exit as sys_exit, path as sys_path
|
||||
from threading import Lock
|
||||
from uuid import uuid4
|
||||
from glob import glob
|
||||
from json import JSONDecodeError, loads
|
||||
from json import JSONDecodeError, load, loads
|
||||
from shutil import copytree, rmtree
|
||||
from tarfile import open as tar_open
|
||||
from traceback import format_exc
|
||||
|
|
@ -25,7 +23,7 @@ from requests import get
|
|||
|
||||
from Database import Database # type: ignore
|
||||
from logger import setup_logger # type: ignore
|
||||
from common_utils import get_os_info, get_integration, get_version # type: ignore
|
||||
from common_utils import bytes_hash, get_os_info, get_integration, get_version # type: ignore
|
||||
|
||||
API_ENDPOINT = "https://api.bunkerweb.io"
|
||||
PREVIEW_ENDPOINT = "https://assets.bunkerity.com/bw-pro/preview"
|
||||
|
|
@ -43,7 +41,8 @@ status = 0
|
|||
def clean_pro_plugins(db) -> None:
|
||||
LOGGER.debug("Cleaning up Pro plugins...")
|
||||
# Clean Pro plugins
|
||||
rmtree(PRO_PLUGINS_DIR.joinpath("*"), ignore_errors=True)
|
||||
for plugin in PRO_PLUGINS_DIR.glob("*"):
|
||||
rmtree(plugin, ignore_errors=True)
|
||||
# Update database
|
||||
db.update_external_plugins([], _type="pro")
|
||||
|
||||
|
|
@ -62,8 +61,10 @@ def install_plugin(plugin_path: Path, db, preview: bool = True) -> bool:
|
|||
LOGGER.error(f"Skipping installation of {'preview version of ' if preview else ''}Pro plugin {plugin_path.name} (plugin.json is not valid)")
|
||||
return False
|
||||
|
||||
new_plugin_path = PRO_PLUGINS_DIR.joinpath(metadata["id"])
|
||||
|
||||
# Don't go further if plugin is already installed
|
||||
if PRO_PLUGINS_DIR.joinpath(metadata["id"], "plugin.json").is_file():
|
||||
if new_plugin_path.is_dir():
|
||||
old_version = None
|
||||
|
||||
for plugin in db.get_plugins(_type="pro"):
|
||||
|
|
@ -80,14 +81,13 @@ def install_plugin(plugin_path: Path, db, preview: bool = True) -> bool:
|
|||
LOGGER.warning(
|
||||
f"{'Preview version of ' if preview else ''}Pro plugin {metadata['id']} is already installed but version {metadata['version']} is different from database ({old_version}), updating it..."
|
||||
)
|
||||
rmtree(PRO_PLUGINS_DIR.joinpath(metadata["id"]), ignore_errors=True)
|
||||
rmtree(new_plugin_path, ignore_errors=True)
|
||||
|
||||
# Copy the plugin
|
||||
copytree(plugin_path, PRO_PLUGINS_DIR.joinpath(metadata["id"]))
|
||||
copytree(plugin_path, new_plugin_path)
|
||||
# Add u+x permissions to jobs files
|
||||
for job_file in glob(PRO_PLUGINS_DIR.joinpath(metadata["id"], "jobs", "*").as_posix()):
|
||||
st = Path(job_file).stat()
|
||||
chmod(job_file, st.st_mode | S_IEXEC)
|
||||
for job_file in new_plugin_path.joinpath("jobs").glob("*"):
|
||||
job_file.chmod(job_file.stat().st_mode | S_IEXEC)
|
||||
LOGGER.info(f"✅ {'Preview version of ' if preview else ''}Pro plugin {metadata['id']} (version {metadata['version']}) installed successfully!")
|
||||
return True
|
||||
|
||||
|
|
@ -167,13 +167,19 @@ try:
|
|||
if metadata["is_pro"]:
|
||||
LOGGER.info("🚀 Your BunkerWeb Pro license is valid, checking if there are new or updated Pro plugins...")
|
||||
|
||||
resp = get(f"{API_ENDPOINT}/pro/download", headers=headers, json=data, timeout=5, allow_redirects=True)
|
||||
resp = get(f"{API_ENDPOINT}/pro/download", headers=headers, json=data, timeout=5, stream=True, allow_redirects=True)
|
||||
|
||||
if resp.status_code == 403:
|
||||
LOGGER.error(f"Access denied to {API_ENDPOINT}/pro - please check your BunkerWeb Pro access at https://panel.bunkerweb.io/")
|
||||
error = True
|
||||
if resp.headers.get("Content-Type", "") == "application/json":
|
||||
resp_data = resp.json()
|
||||
resp_data = {}
|
||||
with BytesIO() as resp_content:
|
||||
for chunk in resp.iter_content(chunk_size=8192):
|
||||
resp_content += chunk
|
||||
resp_content.seek(0)
|
||||
resp_data = load(resp_content)
|
||||
|
||||
if resp_data.get("action") == "clean":
|
||||
metadata = default_metadata.copy()
|
||||
db.set_pro_metadata(metadata)
|
||||
|
|
@ -200,7 +206,7 @@ try:
|
|||
message = "No BunkerWeb Pro license key provided"
|
||||
LOGGER.warning(f"{message}, only checking if there are new or updated preview versions of Pro plugins...")
|
||||
|
||||
resp = get(f"{PREVIEW_ENDPOINT}/v{data['version']}.zip", timeout=5, allow_redirects=True)
|
||||
resp = get(f"{PREVIEW_ENDPOINT}/v{data['version']}.zip", timeout=5, stream=True, allow_redirects=True)
|
||||
|
||||
if resp.status_code == 404:
|
||||
LOGGER.error(f"Couldn't find Pro plugins for BunkerWeb version {data['version']} at {PREVIEW_ENDPOINT}/v{data['version']}.zip")
|
||||
|
|
@ -220,7 +226,11 @@ try:
|
|||
sys_exit(status)
|
||||
resp.raise_for_status()
|
||||
|
||||
with BytesIO(resp.content) as plugin_content:
|
||||
with BytesIO() as plugin_content:
|
||||
for chunk in resp.iter_content(chunk_size=8192):
|
||||
plugin_content.write(chunk)
|
||||
plugin_content.seek(0)
|
||||
|
||||
with ZipFile(plugin_content) as zf:
|
||||
zf.extractall(path=temp_dir)
|
||||
|
||||
|
|
@ -245,34 +255,30 @@ try:
|
|||
|
||||
pro_plugins = []
|
||||
pro_plugins_ids = []
|
||||
for plugin in listdir(PRO_PLUGINS_DIR):
|
||||
path = PRO_PLUGINS_DIR.joinpath(plugin)
|
||||
if not path.joinpath("plugin.json").is_file():
|
||||
LOGGER.warning(f"Plugin {plugin} is not valid, deleting it...")
|
||||
rmtree(path, ignore_errors=True)
|
||||
for plugin_path in PRO_PLUGINS_DIR.glob("*"):
|
||||
if not plugin_path.joinpath("plugin.json").is_file():
|
||||
LOGGER.warning(f"Plugin {plugin_path.name} is not valid, deleting it...")
|
||||
rmtree(plugin_path, ignore_errors=True)
|
||||
continue
|
||||
|
||||
plugin_file = loads(path.joinpath("plugin.json").read_text(encoding="utf-8"))
|
||||
plugin_file = loads(plugin_path.joinpath("plugin.json").read_text(encoding="utf-8"))
|
||||
|
||||
with BytesIO() as plugin_content:
|
||||
with tar_open(fileobj=plugin_content, mode="w:gz", compresslevel=9) as tar:
|
||||
tar.add(path, arcname=path.name)
|
||||
tar.add(plugin_path, arcname=plugin_path.name)
|
||||
plugin_content.seek(0)
|
||||
value = plugin_content.getvalue()
|
||||
|
||||
plugin_file.update(
|
||||
{
|
||||
"type": "pro",
|
||||
"page": False,
|
||||
"page": plugin_path.joinpath("ui").is_dir(),
|
||||
"method": "scheduler",
|
||||
"data": value,
|
||||
"checksum": sha256(value).hexdigest(),
|
||||
"checksum": bytes_hash(value, algorithm="sha256"),
|
||||
}
|
||||
)
|
||||
|
||||
if "ui" in listdir(path):
|
||||
plugin_file["page"] = True
|
||||
|
||||
pro_plugins.append(plugin_file)
|
||||
pro_plugins_ids.append(plugin_file["id"])
|
||||
|
||||
|
|
@ -298,7 +304,7 @@ except:
|
|||
status = 2
|
||||
LOGGER.error(f"Exception while running download-pro-plugins.py :\n{format_exc()}")
|
||||
|
||||
for plugin_tmp in glob(TMP_DIR.joinpath("*").as_posix()):
|
||||
for plugin_tmp in TMP_DIR.glob("*"):
|
||||
rmtree(plugin_tmp, ignore_errors=True)
|
||||
|
||||
sys_exit(status)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e as builder
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c as builder
|
||||
|
||||
# Install python dependencies
|
||||
RUN apk add --no-cache build-base libffi-dev postgresql-dev
|
||||
|
|
@ -30,7 +30,7 @@ COPY src/common/utils utils
|
|||
COPY src/scheduler scheduler
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
@ -64,7 +64,7 @@ COPY --chown=root:scheduler --chmod=770 src/bw/misc/asn.mmdb /var/tmp/bunkerweb/
|
|||
COPY --chown=root:scheduler --chmod=770 src/bw/misc/country.mmdb /var/tmp/bunkerweb/country.mmdb
|
||||
|
||||
# Fix CVEs
|
||||
RUN apk add --no-cache "libexpat>=2.6.0-r0"
|
||||
# There are no CVEs to fix for this image
|
||||
|
||||
VOLUME /data
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e as builder
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c as builder
|
||||
|
||||
# Install python dependencies
|
||||
RUN apk add --no-cache build-base libffi-dev postgresql-dev
|
||||
|
|
@ -28,7 +28,7 @@ COPY src/common/helpers helpers
|
|||
COPY src/ui ui
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
@ -56,7 +56,7 @@ RUN apk add --no-cache bash libmagic && \
|
|||
ln -s /proc/1/fd/2 /var/log/bunkerweb/ui.log
|
||||
|
||||
# Fix CVEs
|
||||
RUN apk add --no-cache "libexpat>=2.6.0-r0"
|
||||
# There are no CVEs to fix for this image
|
||||
|
||||
VOLUME /data
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ loglevel = "info"
|
|||
proc_name = "bunkerweb-ui"
|
||||
preload_app = True
|
||||
reuse_port = True
|
||||
pidfile = join(sep, "var", "run", "bunkerweb", "ui.pid")
|
||||
worker_tmp_dir = join(sep, "dev", "shm")
|
||||
tmp_upload_dir = join(sep, "var", "tmp", "bunkerweb", "ui")
|
||||
worker_class = "gthread"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from contextlib import suppress
|
||||
from math import floor
|
||||
from os import _exit, getenv, listdir, sep, urandom
|
||||
from os import _exit, getenv, getpid, listdir, sep, urandom
|
||||
from os.path import basename, dirname, join
|
||||
from secrets import choice
|
||||
from string import ascii_letters, digits
|
||||
|
|
@ -180,6 +180,7 @@ elif getenv("ADMIN_USERNAME") and getenv("ADMIN_PASSWORD"):
|
|||
stop(1)
|
||||
|
||||
app.logger.info("Database is ready")
|
||||
Path(sep, "var", "run", "bunkerweb", "ui.pid").write_text(str(getpid()), encoding="utf-8")
|
||||
Path(sep, "var", "tmp", "bunkerweb", "ui.healthy").write_text("ok", encoding="utf-8")
|
||||
bw_version = Path(sep, "usr", "share", "bunkerweb", "VERSION").read_text(encoding="utf-8").strip()
|
||||
|
||||
|
|
@ -1038,11 +1039,9 @@ def global_config():
|
|||
),
|
||||
).start()
|
||||
|
||||
try:
|
||||
with suppress(BaseException):
|
||||
if config["PRO_LICENSE_KEY"]["value"] != variables["PRO_LICENSE_KEY"]:
|
||||
flash("Checking license key to upgrade.", "success")
|
||||
except:
|
||||
pass
|
||||
|
||||
return redirect(
|
||||
url_for(
|
||||
|
|
|
|||
|
|
@ -110,7 +110,11 @@ class News {
|
|||
document
|
||||
.querySelector("[data-news-container]")
|
||||
.insertAdjacentHTML("afterbegin", cleanHTML);
|
||||
document.querySelector(`.blog-click-${news.slug}`).addEventListener("click", function () { window.open(`${BASE_URL}/blog/post/${news.slug}`, '_blank') });
|
||||
document.querySelectorAll(`.blog-click-${news.slug}`).forEach((slug) => {
|
||||
slug.addEventListener("click", function () {
|
||||
window.open(`${BASE_URL}/blog/post/${news.slug}`, "_blank");
|
||||
});
|
||||
});
|
||||
document.querySelectorAll(".blog-click-tag").forEach((tag) => {
|
||||
tag.target = "_blank";
|
||||
});
|
||||
|
|
|
|||
4
src/ui/static/js/utils/purify/purify.min.js
vendored
4
src/ui/static/js/utils/purify/purify.min.js
vendored
File diff suppressed because one or more lines are too long
1
src/ui/static/js/utils/purify/src/license_header
vendored
Normal file
1
src/ui/static/js/utils/purify/src/license_header
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/*! @license DOMPurify VERSION | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/VERSION/LICENSE */
|
||||
8
src/ui/static/js/utils/purify/src/purify.js
vendored
8
src/ui/static/js/utils/purify/src/purify.js
vendored
|
|
@ -162,6 +162,7 @@ function createDOMPurify(window = getGlobal()) {
|
|||
ARIA_ATTR,
|
||||
IS_SCRIPT_OR_DATA,
|
||||
ATTR_WHITESPACE,
|
||||
CUSTOM_ELEMENT,
|
||||
} = EXPRESSIONS;
|
||||
|
||||
let { IS_ALLOWED_URI } = EXPRESSIONS;
|
||||
|
|
@ -909,7 +910,10 @@ function createDOMPurify(window = getGlobal()) {
|
|||
root.ownerDocument || root,
|
||||
root,
|
||||
// eslint-disable-next-line no-bitwise
|
||||
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT,
|
||||
NodeFilter.SHOW_ELEMENT |
|
||||
NodeFilter.SHOW_COMMENT |
|
||||
NodeFilter.SHOW_TEXT |
|
||||
NodeFilter.SHOW_PROCESSING_INSTRUCTION,
|
||||
null
|
||||
);
|
||||
};
|
||||
|
|
@ -1189,7 +1193,7 @@ function createDOMPurify(window = getGlobal()) {
|
|||
* @returns {boolean} Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
||||
*/
|
||||
const _isBasicCustomElement = function (tagName) {
|
||||
return tagName !== 'annotation-xml' && tagName.indexOf('-') > 0;
|
||||
return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
1
src/ui/static/js/utils/purify/src/regexp.js
vendored
1
src/ui/static/js/utils/purify/src/regexp.js
vendored
|
|
@ -14,3 +14,4 @@ export const ATTR_WHITESPACE = seal(
|
|||
/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
||||
);
|
||||
export const DOCTYPE_NAME = seal(/^html$/i);
|
||||
export const CUSTOM_ELEMENT = seal(/^[a-z][a-z\d]*(-[a-z\d]+)+$/i);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ terraform {
|
|||
required_providers {
|
||||
scaleway = {
|
||||
source = "scaleway/scaleway"
|
||||
version = "2.37.0"
|
||||
version = "2.38.2"
|
||||
}
|
||||
kubectl = {
|
||||
source = "gavinbunney/kubectl"
|
||||
|
|
@ -10,7 +10,7 @@ terraform {
|
|||
}
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "2.26.0"
|
||||
version = "2.27.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.12.2-alpine3.19@sha256:1a0501213b470de000d8432b3caab9d8de5489e9443c2cc7ccaa6b0aa5c3148e
|
||||
FROM python:3.12.2-alpine3.19@sha256:25a82f6f8b720a6a257d58e478a0a5517448006e010c85273f4d9c706819478c
|
||||
|
||||
# Install firefox and geckodriver
|
||||
RUN apk add --no-cache --virtual .build-deps curl grep zip wget && \
|
||||
|
|
|
|||
Loading…
Reference in a new issue