- /api/v1/media and /api/v2/media (and GET/PUT /api/v1/media/:id):
images go through libvips (NetVips, its native build bundled):
autorotated, every kind of metadata dropped (EXIF, GPS, XMP, IPTC,
comments), capped at 4096 px, with a 640 px preview and a blurhash
(own encoder, the reference algorithm); animated GIFs are re-encoded;
video and audio are remuxed by ffmpeg with -map_metadata -1, never
re-encoded, and a video gets a still preview. Files get random names
under /var/lib/privapub/media, outside the web root deploys replace, and
are served at /media/files with nosniff and a sandbox CSP.
- media_ids on create and edit (four at most, the persona's own, each used
once); notes carry them as Document attachments with alt text, blurhash,
focalPoint and size; inbound attachments were already kept.
- avatar and header uploads in update_credentials, cropped to 400x400 and
1500x500, federated with Update{Person}.
- Remote media reaches clients only through /media/proxy/{hmac}/{url},
fetched by the guarded client (no SVG, 40 MB cap) and cached outside the
served root, trimmed to 5 GB; foreign avatars and headers use it too, so
a client never contacts another server.
- MediaJanitor deletes uploads left unattached for a day.
- nginx accepts 100 MB bodies on the upload endpoints only (applied on Max).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
62 lines
1.6 KiB
Plaintext
62 lines
1.6 KiB
Plaintext
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name privapub.thepra.dev;
|
|
|
|
location ^~ /.well-known/acme-challenge/ {
|
|
root /var/www/acme;
|
|
default_type "text/plain";
|
|
}
|
|
|
|
location / {
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
listen 8444 ssl proxy_protocol;
|
|
listen [::]:443 ssl;
|
|
server_name privapub.thepra.dev;
|
|
http2 on;
|
|
|
|
include /etc/nginx/ssl.conf;
|
|
ssl_certificate /root/.acme.sh/privapub.thepra.dev_ecc/fullchain.cer;
|
|
ssl_certificate_key /root/.acme.sh/privapub.thepra.dev_ecc/privapub.thepra.dev.key;
|
|
include /etc/nginx/snippets/privapub-headers.conf;
|
|
|
|
access_log /var/log/nginx/privapub.thepra.dev.access.log;
|
|
error_log /var/log/nginx/privapub.thepra.dev.error.log;
|
|
|
|
client_max_body_size 2m;
|
|
|
|
location ^~ /.well-known/acme-challenge/ {
|
|
root /var/www/acme;
|
|
default_type "text/plain";
|
|
}
|
|
|
|
location ~ ^/api/v[12]/media$|^/api/v1/accounts/update_credentials$ {
|
|
client_max_body_size 100m;
|
|
proxy_request_buffering off;
|
|
proxy_pass http://127.0.0.1:6970;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Connection "";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:6970;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Connection "";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_read_timeout 60s;
|
|
}
|
|
}
|