mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-08-29 15:06:26 +02:00
Optimized injection layer on lua base, as replace for nginx replace. Also optimized cloudflare cache deletion(no everytime for cleanup). Still CDN is required for logout mechanism via JS and Nextcloud deploy is buggy after changing from nginx to openresty. Propably some variable overwritte topic. Should be solved tomorrow.
This commit is contained in:
33
roles/srv-proxy-6-6-domain/tasks/cleanup.yml
Normal file
33
roles/srv-proxy-6-6-domain/tasks/cleanup.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
- name: "Lookup Cloudflare Zone ID for {{ domain }}"
|
||||
vars:
|
||||
cf_api_url: "https://api.cloudflare.com/client/v4/zones"
|
||||
ansible.builtin.uri:
|
||||
url: "{{ cf_api_url }}?name={{ domain | to_primary_domain }}"
|
||||
method: GET
|
||||
headers:
|
||||
Authorization: "Bearer {{ certbot_dns_api_token }}"
|
||||
Content-Type: "application/json"
|
||||
return_content: yes
|
||||
register: cf_zone_lookup
|
||||
when: dns_provider == "cloudflare"
|
||||
|
||||
- name: "Set fact cf_zone_id"
|
||||
set_fact:
|
||||
cf_zone_id: "{{ cf_zone_lookup.json.result[0].id }}"
|
||||
when:
|
||||
- dns_provider == "cloudflare"
|
||||
- cf_zone_lookup.json.result | length > 0
|
||||
|
||||
- name: "Purge everything from Cloudflare cache for domain {{ domain }}"
|
||||
ansible.builtin.uri:
|
||||
url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/purge_cache"
|
||||
method: POST
|
||||
headers:
|
||||
Authorization: "Bearer {{ certbot_dns_api_token }}"
|
||||
Content-Type: "application/json"
|
||||
body:
|
||||
purge_everything: true
|
||||
body_format: json
|
||||
return_content: yes
|
||||
register: cf_purge
|
||||
when: dns_provider == "cloudflare"
|
@@ -1,6 +1,9 @@
|
||||
# run_once_srv_proxy_6_6_domain: deactivated
|
||||
- name: Cleanup Domain
|
||||
include_tasks: cleanup.yml
|
||||
when: mode_cleanup | bool
|
||||
|
||||
- name: "include role for {{domain}} to receive certificates and do the modification routines"
|
||||
- name: "include role for {{ domain }} to receive certificates and do the modification routines"
|
||||
include_role:
|
||||
name: srv-web-7-6-composer
|
||||
|
||||
|
58
roles/srv-proxy-7-4-core/templates/location/README.md
Normal file
58
roles/srv-proxy-7-4-core/templates/location/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Nginx Location Templates
|
||||
|
||||
This directory contains Jinja2 templates for different Nginx `location` blocks, each designed to proxy and optimize different types of web traffic. These templates are used by the `srv-proxy-7-4-core` role to modularize and standardize reverse proxy configuration across a wide variety of applications.
|
||||
|
||||
---
|
||||
|
||||
## Overview of Files
|
||||
|
||||
### `html.conf.j2`
|
||||
- **Purpose:**
|
||||
Handles "normal" web traffic such as HTML pages, API endpoints, and general HTTP(S) requests.
|
||||
- **Features:**
|
||||
- Proxies requests to the backend service.
|
||||
- Optionally integrates with OAuth2 proxy for authentication.
|
||||
- Sets all necessary proxy headers.
|
||||
- Applies a Content Security Policy header.
|
||||
- Activates buffering for advanced features such as Lua-based string replacements.
|
||||
- Supports WebSocket upgrades for hybrid APIs.
|
||||
|
||||
---
|
||||
|
||||
### `ws.conf.j2`
|
||||
- **Purpose:**
|
||||
Handles WebSocket connections, enabling real-time features such as live updates or chats.
|
||||
- **Features:**
|
||||
- Sets all headers required for WebSocket upgrades.
|
||||
- Disables proxy buffering (required for WebSockets).
|
||||
- Uses `tcp_nodelay` for low latency.
|
||||
- Proxies traffic to the backend WebSocket server.
|
||||
|
||||
---
|
||||
|
||||
### `media.conf.j2`
|
||||
- **Purpose:**
|
||||
Proxies and caches static media files (images, icons, etc.).
|
||||
- **Features:**
|
||||
- Matches image file extensions (jpg, png, gif, webp, ico, svg, etc.).
|
||||
- Enables browser-side and proxy-side caching for efficient delivery.
|
||||
- Adds cache control headers and exposes the upstream cache status.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
These templates are intended for inclusion in larger Nginx configuration files via Jinja2.
|
||||
They modularize your configuration by separating HTML, WebSocket, and media proxying, allowing for clear, reusable, and maintainable reverse proxy logic.
|
||||
|
||||
- Use `html.conf.j2` for standard application HTTP/S endpoints.
|
||||
- Use `ws.conf.j2` for dedicated WebSocket endpoints.
|
||||
- Use `media.conf.j2` for efficient handling of static media content.
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Only enable WebSocket proxying (`ws.conf.j2`) for routes that actually require it, to avoid breaking buffering for standard HTTP.
|
||||
- Activate media proxying (`media.conf.j2`) if your application benefits from image caching at the proxy layer.
|
||||
- Keep templates modular for maintainability and scalability as your application grows.
|
2
roles/srv-proxy-7-4-core/templates/location/Todo.md
Normal file
2
roles/srv-proxy-7-4-core/templates/location/Todo.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# TODOS
|
||||
- ATM it seems like the media proxy isn't used. Propably it could make sense to activate it. -> Research it.
|
@@ -21,13 +21,16 @@ location {{location | default("/")}}
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# deactivate buffering
|
||||
proxy_buffering off;
|
||||
proxy_request_buffering off;
|
||||
# Activate buffering
|
||||
# Needs to be enabled, so that lua can do str replaces
|
||||
proxy_buffering on;
|
||||
proxy_request_buffering on;
|
||||
|
||||
# timeouts
|
||||
proxy_connect_timeout 1s;
|
||||
proxy_send_timeout 900s;
|
||||
proxy_read_timeout 900s;
|
||||
send_timeout 900s;
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/location.lua.j2'%}
|
||||
}
|
14
roles/srv-proxy-7-4-core/templates/location/ws.conf.j2
Normal file
14
roles/srv-proxy-7-4-core/templates/location/ws.conf.j2
Normal file
@@ -0,0 +1,14 @@
|
||||
location {{ location_ws }} {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_pass http://127.0.0.1:{{ ws_port }};
|
||||
|
||||
# Proxy buffering needs to be disabled for websockets.
|
||||
proxy_buffering off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
tcp_nodelay on;
|
||||
}
|
78
roles/srv-proxy-7-4-core/templates/vhost/README.md
Normal file
78
roles/srv-proxy-7-4-core/templates/vhost/README.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Nginx vHost Templates: Basic vs. WebSocket (ws_generic)
|
||||
|
||||
This directory provides two Nginx server templates for reverse proxying Dockerized applications behind Nginx:
|
||||
- `basic.conf.j2`
|
||||
- `ws_generic.conf.j2`
|
||||
|
||||
---
|
||||
|
||||
## When to Use Which Template?
|
||||
|
||||
### 1. `basic.conf.j2`
|
||||
**Use this template for standard HTTP/S applications.**
|
||||
It is optimized for typical web applications (e.g., static sites, PHP, Node.js, Django, etc.) that do **not** require persistent, bidirectional WebSocket connections.
|
||||
|
||||
- **Features:**
|
||||
- HTTP/2 support, TLS/SSL integration
|
||||
- Reverse proxy with buffering enabled (`proxy_buffering on`)
|
||||
- Allows advanced content filtering (e.g., via Lua body/headers)
|
||||
- Suitable for most REST APIs, web frontends, and admin panels
|
||||
|
||||
- **Pros:**
|
||||
- Enables HTML/body manipulation (for injecting snippets, analytics, CSP, etc.)
|
||||
- Optimized for efficient caching and GZIP compression
|
||||
- Good default for "normal" web traffic
|
||||
|
||||
- **Cons:**
|
||||
- **Not** suitable for WebSocket endpoints (buffering can break WS)
|
||||
- Slightly more latency for streaming data due to buffering
|
||||
|
||||
---
|
||||
|
||||
### 2. `ws_generic.conf.j2`
|
||||
**Use this template for applications requiring WebSocket support.**
|
||||
Designed for services (e.g., chat servers, real-time dashboards) needing fast, persistent connections using the WebSocket protocol.
|
||||
|
||||
- **Features:**
|
||||
- WebSocket-aware: `proxy_buffering off`, special upgrade headers
|
||||
- Supports standard HTTP/S traffic alongside WebSockets
|
||||
- Proper handling of connection upgrades and protocol switching
|
||||
|
||||
- **Pros:**
|
||||
- Required for all WebSocket endpoints
|
||||
- Allows instant, low-latency bidirectional traffic
|
||||
- Prevents data loss or connection drops due to proxy buffering
|
||||
|
||||
- **Cons:**
|
||||
- Disables body/content filtering and response manipulation
|
||||
- No buffering means less effective for caching/optimization
|
||||
- Not suitable for scenarios requiring Lua/JS content injection
|
||||
|
||||
---
|
||||
|
||||
## Summary Table
|
||||
|
||||
| Use Case | Template | Buffering | WebSocket? | Can Filter Content? |
|
||||
|--------------------------|---------------------|-----------|------------|--------------------|
|
||||
| Static/Classic Website | `basic.conf.j2` | On | No | Yes |
|
||||
| REST API | `basic.conf.j2` | On | No | Yes |
|
||||
| Real-Time Chat/App | `ws_generic.conf.j2`| Off | Yes | No |
|
||||
| Dashboard w/Live Data | `ws_generic.conf.j2`| Off | Yes | No |
|
||||
| Needs HTML Injection | `basic.conf.j2` | On | No | Yes |
|
||||
|
||||
---
|
||||
|
||||
## Good to Know
|
||||
|
||||
- **Never enable buffering for true WebSocket connections!**
|
||||
Use `proxy_buffering off;` (as in `ws_generic.conf.j2`) or connections may fail.
|
||||
- For most classic web applications, use the **basic template**.
|
||||
- For apps where you want to inject or modify HTML (e.g., analytics scripts), **only the basic template** supports this.
|
||||
|
||||
---
|
||||
|
||||
## Author & Project
|
||||
|
||||
By [Kevin Veen-Birkenbach](https://www.veen.world)
|
||||
Part of the [CyMaIS Project](https://s.veen.world/cymais)
|
||||
Licensed under the [CyMaIS NonCommercial License (CNCL)](https://s.veen.world/cncl)
|
@@ -6,7 +6,7 @@ server
|
||||
{% include 'roles/web-app-oauth2-proxy/templates/endpoint.conf.j2'%}
|
||||
{% endif %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% if proxy_extra_configuration is defined %}
|
||||
{# Additional Domain Specific Configuration #}
|
||||
@@ -15,9 +15,6 @@ server
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.logout', False) or domain == primary_domain %}
|
||||
{% include 'roles/web-svc-logout/templates/logout-proxy.conf.j2' %}
|
||||
{% endif %}
|
||||
{% if applications | get_app_conf(application_id, 'features.oauth2', False) %}
|
||||
{% set acl = applications | get_app_conf(application_id, 'oauth2_proxy.acl', False, {}) %}
|
||||
|
||||
@@ -25,38 +22,38 @@ server
|
||||
{# 1. Expose everything by default, then protect blacklisted paths #}
|
||||
{% set oauth2_proxy_enabled = false %}
|
||||
{% set location = "/" %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
|
||||
{% for loc in acl.blacklist %}
|
||||
{% set oauth2_proxy_enabled = true %}
|
||||
{% set location = loc %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
{% endfor %}
|
||||
|
||||
{% elif acl.whitelist is defined %}
|
||||
{# 2. Protect everything by default, then expose whitelisted paths #}
|
||||
{% set oauth2_proxy_enabled = true %}
|
||||
{% set location = "/" %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
|
||||
{% for loc in acl.whitelist %}
|
||||
{% set oauth2_proxy_enabled = false %}
|
||||
{% set location = loc %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
{% endfor %}
|
||||
|
||||
{% else %}
|
||||
{# 3. OAuth2 enabled but no (or empty) ACL — protect all #}
|
||||
{% set oauth2_proxy_enabled = true %}
|
||||
{% set location = "/" %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
{# 4. OAuth2 completely disabled — expose all #}
|
||||
{% set oauth2_proxy_enabled = false %}
|
||||
{% set location = "/" %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
{% endif %}
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,8 @@ server {
|
||||
server_name {{ domain }};
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2' %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2' %}
|
||||
|
||||
client_max_body_size {{ client_max_body_size | default('100m') }};
|
||||
keepalive_timeout 70;
|
||||
@@ -24,26 +25,10 @@ server {
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.logout', False) or domain == primary_domain %}
|
||||
{% include 'roles/web-svc-logout/templates/logout-proxy.conf.j2' %}
|
||||
{% endif %}
|
||||
|
||||
{% if ws_path is defined %}
|
||||
location {{ ws_path }} {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
|
||||
proxy_pass http://127.0.0.1:{{ ws_port }};
|
||||
proxy_buffering off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
tcp_nodelay on;
|
||||
}
|
||||
{% if location_ws is defined %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/ws.conf.j2' %}
|
||||
{% endif %}
|
||||
|
||||
error_page 500 501 502 503 504 /500.html;
|
||||
|
@@ -8,6 +8,9 @@ events
|
||||
http
|
||||
{
|
||||
include mime.types;
|
||||
|
||||
{# default_type application/octet-stream; If html filter does not work, this one needs to be used#}
|
||||
|
||||
default_type text/html;
|
||||
|
||||
{# caching #}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
- name: Create or update Cloudflare A-record for {{ item }}
|
||||
community.general.cloudflare_dns:
|
||||
api_token: "{{ cloudflare_api_token }}"
|
||||
api_token: "{{ certbot_dns_api_token }}"
|
||||
zone: "{{ item.split('.')[-2:] | join('.') }}"
|
||||
state: present
|
||||
type: A
|
||||
|
@@ -1,12 +1,22 @@
|
||||
{% set modifier_css_enabled = applications | get_app_conf(application_id, 'features.css', false) | bool %}
|
||||
{% if modifier_css_enabled %}
|
||||
{%- include 'roles/srv-web-7-7-inj-css/templates/location.conf.j2' -%}
|
||||
{% endif %}
|
||||
|
||||
lua_need_request_body on;
|
||||
|
||||
header_filter_by_lua_block {
|
||||
local ct = ngx.header.content_type or ""
|
||||
if ct:lower():find("^text/html") then
|
||||
ngx.ctx.is_html = true
|
||||
else
|
||||
ngx.ctx.is_html = false
|
||||
end
|
||||
}
|
||||
|
||||
body_filter_by_lua_block {
|
||||
-- initialize buffer
|
||||
-- only apply further processing if this is an HTML response
|
||||
if not ngx.ctx.is_html then
|
||||
return
|
||||
end
|
||||
|
||||
-- initialize or reuse the buffer
|
||||
ngx.ctx.buf = ngx.ctx.buf or {}
|
||||
local chunk, eof = ngx.arg[1], ngx.arg[2]
|
||||
|
||||
@@ -15,18 +25,22 @@ body_filter_by_lua_block {
|
||||
end
|
||||
|
||||
if not eof then
|
||||
-- drop intermediate chunks; we’ll emit only on eof
|
||||
ngx.arg[1] = nil
|
||||
return
|
||||
end
|
||||
|
||||
-- on eof: concatenate and reset buffer
|
||||
-- on eof: concatenate all buffered chunks
|
||||
local whole = table.concat(ngx.ctx.buf)
|
||||
ngx.ctx.buf = nil
|
||||
ngx.ctx.buf = nil -- clear buffer
|
||||
{# whole = string.gsub(whole, "</body>", "<!-- injected text2 -->\n</body>")
|
||||
ngx.arg[1] = whole #}
|
||||
|
||||
-- build head-injection snippets
|
||||
-- build a list of head-injection snippets
|
||||
local head_snippets = {}
|
||||
|
||||
{% for head_feature in ['css', 'matomo', 'port-ui-desktop', 'javascript', 'logout'] %}
|
||||
{# Deactivated 'logout' temporary due to chunk size. Needs an CDN. #}
|
||||
{% for head_feature in ['css', 'matomo', 'port-ui-desktop', 'javascript' ] %}
|
||||
{% if applications | get_app_conf(application_id, 'features.' ~ head_feature, false) | bool %}
|
||||
head_snippets[#head_snippets + 1] = [=[
|
||||
{%- include "roles/srv-web-7-7-inj-" ~ head_feature ~ "/templates/head_sub.j2" -%}
|
||||
@@ -34,19 +48,19 @@ body_filter_by_lua_block {
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
-- inject into </head>
|
||||
-- inject all collected snippets right before </head>
|
||||
local head_payload = table.concat(head_snippets, "\n") .. "</head>"
|
||||
whole = string.gsub(whole, "</head>", head_payload)
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.matomo', false) | bool %}
|
||||
-- build Matomo noscript tracking for body
|
||||
-- build Matomo noscript snippet for the body
|
||||
local body_matomo = [=[
|
||||
{%- include 'roles/srv-web-7-7-inj-matomo/templates/body_sub.j2' -%}
|
||||
]=]
|
||||
|
||||
-- inject before </body>
|
||||
-- inject it right before </body>
|
||||
whole = string.gsub(whole, "</body>", body_matomo)
|
||||
{% endif %}
|
||||
|
||||
-- finally send the modified HTML out
|
||||
ngx.arg[1] = whole
|
||||
}
|
||||
}
|
9
roles/srv-web-7-7-inj-compose/templates/server.conf.j2
Normal file
9
roles/srv-web-7-7-inj-compose/templates/server.conf.j2
Normal file
@@ -0,0 +1,9 @@
|
||||
{% set modifier_css_enabled = applications | get_app_conf(application_id, 'features.css', false) | bool %}
|
||||
{% if modifier_css_enabled %}
|
||||
{%- include 'roles/srv-web-7-7-inj-css/templates/location.conf.j2' -%}
|
||||
{% endif %}
|
||||
|
||||
{% set modifier_logout_enabled = applications | get_app_conf(application_id, 'features.logout', False) or domain == primary_domain %}
|
||||
{% if modifier_logout_enabled %}
|
||||
{% include 'roles/web-svc-logout/templates/logout-proxy.conf.j2' %}
|
||||
{% endif %}
|
@@ -85,7 +85,7 @@
|
||||
|
||||
// Initial scan
|
||||
scanAndPatch(document.querySelectorAll('*'));
|
||||
|
||||
{#
|
||||
// MutationObserver for dynamic content
|
||||
const observer = new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
@@ -97,4 +97,5 @@
|
||||
});
|
||||
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
#}
|
||||
})();
|
||||
|
63
roles/svc-prx-openresty/docs/CACHE.md
Normal file
63
roles/svc-prx-openresty/docs/CACHE.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Caching in OpenResty and Cloudflare
|
||||
|
||||
## Overview
|
||||
|
||||
When deploying OpenResty as a reverse proxy, content may be cached at multiple layers:
|
||||
|
||||
- **Local Proxy Cache:** If you configure Nginx/OpenResty with a cache zone (using directives like `proxy_cache`), responses can be stored locally on disk and served to future clients.
|
||||
- **Browser Cache:** Browsers cache responses based on HTTP headers like `Cache-Control` or `Expires`.
|
||||
- **CDN Cache (Cloudflare):** If your domain is proxied through Cloudflare, Cloudflare may cache your content at their edge servers and serve it from there, often without requests reaching your origin server.
|
||||
|
||||
## Troubleshooting Cache Issues
|
||||
|
||||
Caching can cause problems, especially when you update your web content or configuration but still receive outdated responses. Typical symptoms include:
|
||||
|
||||
- Changes to HTML/CSS/JS are not visible immediately.
|
||||
- Old redirects or headers persist even after config changes.
|
||||
- Assets do not update after a deployment.
|
||||
|
||||
If this happens, always consider all caching layers:
|
||||
1. **Browser:** Clear the browser cache or use a private window.
|
||||
2. **OpenResty:** If using a proxy cache, purge or clear the cache directory, or temporarily disable the cache zone.
|
||||
3. **Cloudflare:** Purge the CDN cache as described below.
|
||||
|
||||
## Purging Cloudflare Cache
|
||||
|
||||
Cloudflare aggressively caches static content by default. Even after you deploy new files or update your proxy configuration, users may continue to see cached versions until the cache expires.
|
||||
|
||||
### Manual Purge via Cloudflare Dashboard
|
||||
|
||||
1. Log into your Cloudflare dashboard at [https://dash.cloudflare.com](https://dash.cloudflare.com).
|
||||
2. Select your domain.
|
||||
3. Go to **Caching** → **Configuration**.
|
||||
4. Click **Purge Cache**.
|
||||
- Choose **Purge Everything** to delete all cached files (recommended after a deployment).
|
||||
- Or use **Custom Purge** to specify individual URLs.
|
||||
|
||||
### Purge with Cloudflare API
|
||||
|
||||
You can also purge the cache programmatically with Cloudflare’s API:
|
||||
|
||||
```bash
|
||||
curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/purge_cache" \
|
||||
-H "Authorization: Bearer <YOUR_API_TOKEN>" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data '{"purge_everything":true}'
|
||||
````
|
||||
|
||||
* Replace `<ZONE_ID>` with your Cloudflare Zone ID.
|
||||
* Replace `<YOUR_API_TOKEN>` with a valid API token with cache purge permissions.
|
||||
|
||||
To find your Zone ID, go to the overview page for your domain in the Cloudflare dashboard.
|
||||
**Note:** It can take a few seconds for the cache to be purged globally.
|
||||
|
||||
## Recommendations
|
||||
|
||||
* Always purge the Cloudflare cache after significant changes to your website or OpenResty/Nginx configuration.
|
||||
* If you use custom cache rules in OpenResty, consider providing cache-busting mechanisms (e.g., versioned URLs).
|
||||
* Test changes in a private/incognito window to rule out browser cache.
|
||||
|
||||
## Further Reading
|
||||
|
||||
* [Cloudflare Purge Cache Documentation](https://developers.cloudflare.com/cache/how-to/purge-cache/)
|
||||
* [Nginx/OpenResty Proxy Cache Guide](https://openresty.org/en/using-ngx_lua.html#caching)
|
@@ -3,13 +3,13 @@ server {
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/headers/content_security_policy.conf.j2' %}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
|
||||
{% set location = '^~ /cool/' %}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
application_id: "web-app-espocrm"
|
||||
database_type: "mariadb"
|
||||
ws_path: "/ws"
|
||||
location_ws: "/ws"
|
||||
ws_port: "{{ ports.localhost.websocket[application_id] }}"
|
||||
client_max_body_size: "100m"
|
||||
vhost_flavour: "ws_generic"
|
||||
|
@@ -11,7 +11,7 @@
|
||||
loop_var: domain
|
||||
vars:
|
||||
http_port: "{{ ports.localhost.http[application_id] }}"
|
||||
ws_path: "/api/v1/streaming"
|
||||
location_ws: "/api/v1/streaming"
|
||||
ws_port: "{{ ports.localhost.websocket[application_id] }}"
|
||||
client_max_body_size: "80m"
|
||||
vhost_flavour: "ws_generic"
|
||||
|
@@ -3,19 +3,16 @@ server {
|
||||
{# Could be that this is related to the set_fact use #}
|
||||
{% set domain = domains[application_id].synapse %}
|
||||
{% set http_port = ports.localhost.http['web-app-matrix_synapse'] %}
|
||||
{% set federation_port = ports.public.federation['web-app-matrix_synapse'] %}
|
||||
|
||||
server_name {{domains[application_id].synapse}};
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
# For the federation port
|
||||
listen 8448 ssl default_server;
|
||||
listen [::]:8448 ssl default_server;
|
||||
listen {{ federation_port }} ssl default_server;
|
||||
listen [::]:{{ federation_port }} ssl default_server;
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.logout', False) %}
|
||||
{% include 'roles/web-svc-logout/templates/logout-proxy.conf.j2' %}
|
||||
{% endif %}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
}
|
@@ -69,6 +69,9 @@ performance:
|
||||
memory_limit: "{{ ((ansible_memtotal_mb | int) / 30)|int }}M" # Dynamic set memory limit
|
||||
upload_limit: "5G" # Set upload limit to 5GB for big media files
|
||||
opcache_memory_consumption: "{{ ((ansible_memtotal_mb | int) / 30)|int }}M" # Dynamic set memory consumption
|
||||
|
||||
plugins_enabled: true # Implemented for speeding up testing and debugging process. For productive environments keep it true and steer the apps via the plugins config
|
||||
|
||||
plugins:
|
||||
# List for Nextcloud Plugin Routine
|
||||
# Decides if plugins should be activated or deactivated
|
||||
|
@@ -49,6 +49,7 @@
|
||||
vars:
|
||||
plugin_key: "{{ plugin_item.key }}"
|
||||
plugin_value: "{{ plugin_item.value }}"
|
||||
when: nextcloud_plugins_enabled
|
||||
|
||||
- name: Load system configuration
|
||||
include_tasks: 03_system.yml
|
||||
|
@@ -29,7 +29,7 @@ NEXTCLOUD_ADMIN_PASSWORD= "{{applications | get_app_conf(application_id, '
|
||||
|
||||
# Security
|
||||
|
||||
NEXTCLOUD_TRUSTED_DOMAINS= "{{ nextcloud_domains }}"
|
||||
NEXTCLOUD_TRUSTED_DOMAINS= "{{ domains[application_id] | select | join(',') }}"
|
||||
# Whitelist local docker gateway in Nextcloud to prevent brute-force throtteling
|
||||
TRUSTED_PROXIES= "{{ networks.internet.values() | select | join(',') }}"
|
||||
OVERWRITECLIURL= "{{ domains | get_url(application_id, web_protocol) }}"
|
||||
|
@@ -6,7 +6,8 @@ server
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
# Remove X-Powered-By, which is an information leak
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
|
||||
@@ -18,11 +19,7 @@ server
|
||||
client_body_buffer_size 400M;
|
||||
fastcgi_buffers 64 4K;
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.logout', False) %}
|
||||
{% include 'roles/web-svc-logout/templates/logout-proxy.conf.j2' %}
|
||||
{% endif %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
|
||||
location ^~ /.well-known {
|
||||
rewrite ^/\.well-known/host-meta\.json /public.php?service=host-meta-json last;
|
||||
|
@@ -6,6 +6,7 @@ container_port: 80
|
||||
# Database
|
||||
database_password: "{{ applications | get_app_conf(application_id, 'credentials.database_password', True)}}"
|
||||
database_type: "mariadb" # Database flavor
|
||||
nextcloud_plugins_enabled: "{{ applications | get_app_conf(application_id, 'plugins_enabled', True) }}"
|
||||
|
||||
# Networking
|
||||
domain: "{{ domains | get_domain(application_id) }}" # Public domain at which Nextcloud will be accessable
|
||||
@@ -23,15 +24,13 @@ nextcloud_control_node_plugin_tasks_directory: "{{role_path}}/tasks/plugins/"
|
||||
nextcloud_host_config_additives_directory: "{{ docker_compose.directories.volumes }}cymais/" # This folder is the path to which the additive configurations will be copied
|
||||
nextcloud_host_include_instructions_file: "{{ docker_compose.directories.volumes }}includes.php" # Path to the instruction file on the host. Responsible for loading the additional configurations
|
||||
|
||||
nextcloud_domains: "{{ domains | get_domain(application_id) }}" # This is wrong and should be optimized @todo implement support for multiple domains
|
||||
|
||||
# Docker
|
||||
|
||||
nextcloud_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
||||
|
||||
nextcloud_version: "{{ applications | get_app_conf(application_id, 'docker.services.nextcloud.version', True) }}"
|
||||
nextcloud_image: "{{ applications | get_app_conf(application_id, 'docker.services.nextcloud.image', True) }}"
|
||||
nextcloud_container: "{{ applications | get_app_conf(application_id, 'docker.services.nextcloud.name', True) }}"
|
||||
nextcloud_container: "{{ applications | get_app_conf(application_id, 'docker.services.nextcloud.name', True) }}"
|
||||
|
||||
nextcloud_proxy_name: "{{ applications | get_app_conf(application_id, 'docker.services.proxy.name', True) }}"
|
||||
nextcloud_proxy_image: "{{ applications | get_app_conf(application_id, 'docker.services.proxy.image', True) }}"
|
||||
|
@@ -3,7 +3,7 @@ server {
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/headers/content_security_policy.conf.j2' %}
|
||||
|
||||
@@ -11,35 +11,18 @@ server {
|
||||
# Application
|
||||
##
|
||||
|
||||
location @api {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
||||
client_max_body_size 100k; # default is 1M
|
||||
|
||||
proxy_connect_timeout 10m;
|
||||
proxy_send_timeout 10m;
|
||||
proxy_read_timeout 10m;
|
||||
send_timeout 10m;
|
||||
|
||||
#adapt
|
||||
proxy_pass http://127.0.0.1:{{ports.localhost.http[application_id]}};
|
||||
}
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.logout', False) %}
|
||||
{% include 'roles/web-svc-logout/templates/logout-proxy.conf.j2' %}
|
||||
{% endif %}
|
||||
{% set location = "@html" %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2' %}
|
||||
|
||||
location / {
|
||||
try_files /dev/null @api;
|
||||
try_files /dev/null {{ location }};
|
||||
}
|
||||
|
||||
location = /api/v1/videos/upload-resumable {
|
||||
client_max_body_size 0;
|
||||
proxy_request_buffering off;
|
||||
|
||||
try_files /dev/null @api;
|
||||
try_files /dev/null {{ location }};
|
||||
}
|
||||
|
||||
location ~ ^/api/v1/videos/(upload|([^/]+/studio/edit))$ {
|
||||
@@ -47,33 +30,25 @@ server {
|
||||
client_max_body_size 12G; # default is 1M
|
||||
add_header X-File-Maximum-Size 8G always; # inform backend of the set value in bytes before mime-encoding (x * 1.4 >= client_max_body_size)
|
||||
|
||||
try_files /dev/null @api;
|
||||
try_files /dev/null {{ location }};
|
||||
}
|
||||
|
||||
location ~ ^/api/v1/(videos|video-playlists|video-channels|users/me) {
|
||||
client_max_body_size 6M; # default is 1M
|
||||
add_header X-File-Maximum-Size 4M always; # inform backend of the set value in bytes before mime-encoding (x * 1.4 >= client_max_body_size)
|
||||
|
||||
try_files /dev/null @api;
|
||||
try_files /dev/null {{ location }};
|
||||
}
|
||||
|
||||
##
|
||||
# Websocket
|
||||
##
|
||||
|
||||
location @api_websocket {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_pass http://127.0.0.1:{{ports.localhost.http[application_id]}};
|
||||
}
|
||||
{% set location_ws = "@websocket" %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/ws.conf.j2' %}
|
||||
|
||||
location /socket.io {
|
||||
try_files /dev/null @api_websocket;
|
||||
try_files /dev/null {{ location_ws }};
|
||||
}
|
||||
|
||||
location /tracker/socket {
|
||||
@@ -81,6 +56,6 @@ server {
|
||||
# Don't close the websocket before then
|
||||
proxy_read_timeout 15m; # default is 60s
|
||||
|
||||
try_files /dev/null @api_websocket;
|
||||
try_files /dev/null {{ location_ws }};
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@ server
|
||||
{% include 'roles/web-app-oauth2-proxy/templates/endpoint.conf.j2'%}
|
||||
{% endif %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% if proxy_extra_configuration is defined %}
|
||||
{# Additional Domain Specific Configuration #}
|
||||
@@ -17,6 +17,6 @@ server
|
||||
|
||||
{% for path in syncope_paths.values() %}
|
||||
{% set location = web_protocol ~ '://' ~ domains | get_domain(application_id) ~ '/' ~ path ~ '/' %}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2'%}
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/location/html.conf.j2'%}
|
||||
{% endfor %}
|
||||
}
|
@@ -4,7 +4,7 @@ server
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/headers/content_security_policy.conf.j2' %}
|
||||
charset utf-8;
|
||||
@@ -15,6 +15,7 @@ server
|
||||
autoindex on; {# Enable directory listing #}
|
||||
autoindex_exact_size off; {# Display sizes in a human-readable format #}
|
||||
autoindex_localtime on; {# Show local time #}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/location.lua.j2' %}
|
||||
}
|
||||
|
||||
location /.well-known/ {
|
||||
|
@@ -4,7 +4,7 @@ server
|
||||
|
||||
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_header.j2' %}
|
||||
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.lua.j2'%}
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/server.conf.j2'%}
|
||||
|
||||
{% include 'roles/srv-proxy-7-4-core/templates/headers/content_security_policy.conf.j2' %}
|
||||
charset utf-8;
|
||||
@@ -13,6 +13,7 @@ server
|
||||
{
|
||||
root {{nginx.directories.data.html}};
|
||||
index index.html index.htm;
|
||||
{% include 'roles/srv-web-7-7-inj-compose/templates/location.lua.j2' %}
|
||||
}
|
||||
|
||||
location /.well-known/ {
|
||||
|
Reference in New Issue
Block a user