Create compose.stack.yaml

This commit is contained in:
perennial
2024-10-09 15:00:32 +11:00
parent d459fc9ce5
commit c7c24737de
3 changed files with 199 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
{
# General options
http_port 80
https_port 443
# Logging configuration
log {
output stdout
format console
}
}
# Main server block for caddy.localhost
caddy.localhost {
tls internal # Use Caddy's automatic HTTPS with internal CA
# Reverse proxy configuration (pick one or the other)
## With Varnish as a caching layer (recommended if using PixivFE's internal image proxy)
reverse_proxy varnish:80
## Bypass Varnish and send requests directly to PixivFE on port 8282
#reverse_proxy pixivfe:8282
# Header manipulation
header {
# Cross-Origin isolation headers
Cross-Origin-Embedder-Policy "require-corp"
Cross-Origin-Opener-Policy "same-origin"
Cross-Origin-Resource-Policy "same-origin"
}
}
+79
View File
@@ -0,0 +1,79 @@
### compose.stack.yaml
## Intended to provide replicate a production environment by placing a reverse proxy in front of PixivFE,
## with Varnish as caching layer (optional)
### Instructions:
## To run using a fresh build (this is probably what you want during development):
# docker compose -f compose.stack.yaml up --build
## To run using a cached build:
# docker compose -f compose.stack.yaml up
## To reload Caddy configuration without downtime:
# docker exec -w /etc/caddy caddy caddy reload
## To access pixivfe:
# Visit https://caddy.localhost/ in your browser
# and accept any security warnings shown (expected as Caddy uses self-signed certs by default)
services:
caddy:
container_name: caddy
image: caddy:2.8.4-alpine
restart: unless-stopped
ports:
- 80:80
- 443:443
networks:
internal: {}
volumes:
- type: bind
source: ./Caddyfile
target: /etc/caddy/Caddyfile
read_only: true
- caddy_data:/data
- caddy_config:/config
varnish:
container_name: varnish
image: varnish:7.5.0
restart: unless-stopped
networks:
internal: {}
volumes:
- type: bind
source: ./default.vcl
target: /etc/varnish/default.vcl
read_only: true
pixivfe:
container_name: pixivfe
hostname: pixivfe
image: vnpower/pixivfe:latest
build:
context: .
dockerfile: Dockerfile
init: true
networks:
internal: {}
env_file:
- path: .env
required: true
restart: unless-stopped
cap_drop:
- ALL
read_only: true
user: 10001:10001
security_opt:
- no-new-privileges:true
# Named volumes for persistent data
volumes:
caddy_data: {}
caddy_config: {}
# Network configuration
# Required for internal communication between the web server and PixivFE.
networks:
internal:
driver: bridge
+89
View File
@@ -0,0 +1,89 @@
vcl 4.1;
backend pixivfe {
.host = "pixivfe";
.port = "8282";
}
sub vcl_recv {
if (req.http.host == "caddy.localhost") {
set req.backend_hint = pixivfe;
# Step 1: Check for login status
if (req.http.cookie ~ "pixivfe-Token") {
set req.http.X-User-Logged-In = "true";
} else {
set req.http.X-User-Logged-In = "false";
}
# For logged-in users, include the token in the cache key
if (req.http.X-User-Logged-In == "true") {
set req.http.X-User-Token = regsub(req.http.cookie, ".*pixivfe-Token=([^;]+).*", "\1");
}
}
}
sub vcl_backend_response {
if (bereq.backend == pixivfe) {
# Step 2: Implement different caching strategies
# set grace to 1 minute globally
set beresp.grace = 1m;
## landing page; should be cached conservatively when it contains personalised content for logged in users, but be more aggressive for the shared page shown to anonymous visitors
if (bereq.url == "/") {
if (beresp.status == 200) {
if (bereq.http.X-User-Logged-In == "false") {
# Non-logged in users: cache for 8h
set beresp.ttl = 8h;
set beresp.http.Cache-Control = "public, max-age=28800";
} else {
# Logged in users: cache for 30 seconds, vary by user token
set beresp.ttl = 30s;
set beresp.uncacheable = false;
set beresp.http.Cache-Control = "private, max-age=30";
set beresp.http.Vary = "X-User-Token";
}
}
return (deliver);
}
## pages with user content that changes dynamically every request as per the Pixiv upstream; use a moderate caching strategy, we don't need to fetch new content *every* time
if (bereq.url ~ "^/discovery" || bereq.url ~ "^/discovery/novel" || bereq.url ~ "^/newest") {
if (beresp.status == 200) {
set beresp.ttl = 30s;
set beresp.uncacheable = false;
set beresp.http.Cache-Control = "public, max-age=30";
}
return (deliver);
}
## pages with user content that changes dynamically, but either over longer timeframes (ranking pages) or not appreciably (loading in under 100ms is probably more important than knowing the *exact* number of bookmarks a work has); we can be more aggressive
if (bereq.url ~ "^/ranking" || bereq.url ~ "^/rankingCalendar" || bereq.url ~ "^/artworks/" || bereq.url ~ "^/novel/" || bereq.url ~ "^/users/") {
if (beresp.status == 200) {
set beresp.ttl = 8h;
set beresp.http.Cache-Control = "public, max-age=28800";
}
return (deliver);
}
# proxied static media (images, short video, etc); a aggressive caching strategy is safe
if (bereq.url ~ "^/proxy/") {
if (beresp.status == 200) {
set beresp.ttl = 24h;
set beresp.http.Cache-Control = "public, max-age=31536000"; # 1 year
}
return (deliver);
}
# if nothing matches, be safe and dont cache anything
set beresp.http.Cache-Control = "private, no-store";
}
}
sub vcl_hash {
# Step 3: Include user token in hash for logged-in users
if (req.http.X-User-Logged-In == "true") {
hash_data(req.http.X-User-Token);
}
}