A root exports one of its personas (a job) as Mastodon's account archive, so other servers' importers read it: the actor with its public key only, its own posts and boosts with their media, likes, bookmarks and Mastodon's CSV files, plus PrivaPub's filters, followed hashtags, notification policy, pins, scheduled and located posts; nothing of its root, its siblings, its keys or anyone's token. A ticket link downloads it, for a week. An archive (PrivaPub's or Mastodon's) uploaded in pieces is imported into a persona in a job, the parts the root picks, with progress and a stop. SafeArchive refuses links, escaping paths, duplicates, bombs and oversized items, and reads the outbox one item at a time. Imported posts are delivered to no one, put in no home and notify nobody, yet show on the profile, outbox, hashtags and search; back home a post keeps its id, from another actor it gets one of its date and ImportedFromURI, so importing twice changes nothing. Relationships go through the existing services; located, scheduled and likes only when asked; followers never. tools/pasture/scenarios/persona-archive.sh imports mastouser's real Mastodon archive (156 posts, 24 pictures) into a persona Mastodon follows: Mastodon receives none of it, and a second import changes nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
104 lines
3.3 KiB
Plaintext
104 lines
3.3 KiB
Plaintext
# backup uploads: a few pieces a second at most, per address
|
|
limit_req_zone $binary_remote_addr zone=privapub_backup_uploads:1m rate=120r/m;
|
|
|
|
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;
|
|
}
|
|
|
|
# the administrator's backups and the personas' archives (owner decision 2026-10-07): a download streams a whole one for
|
|
# as long as it takes; an upload arrives in pieces of at most 32 MB, unbuffered
|
|
location ~ ^/clientapi/(admin/backups|persona/archive)/download/ {
|
|
proxy_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 3600s;
|
|
proxy_send_timeout 3600s;
|
|
}
|
|
location ~ ^/clientapi/(admin/backups|persona/archive)/uploads {
|
|
client_max_body_size 40m;
|
|
proxy_request_buffering off;
|
|
limit_req zone=privapub_backup_uploads burst=30 nodelay;
|
|
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 ^~ /media/proxy/ {
|
|
proxy_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 600s;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|