Files
serverAppConfigs/serverAppConfigs-docs/Dankserver/Copyparty.md
T
Frank 8e1b00646f copyparty: read-only volume (no uploads); correct runbook anon-perms claim
-v /w::A granted anonymous full rwmda on the LAN (verified: anon PUT -> 201,
PROPFIND -> 207). New perms ::r:ra,dank: browse/download for anonymous
(required by the guarded files.franksdank.cloud chain), admin for dank,
no w/m/d for anyone. Runbook corrected with the --help-accounts semantics.
2026-08-31 16:37:38 -07:00

7.2 KiB

Copyparty

Copyparty is a lightweight file server and media streamer that runs as a single Python binary. It handles large payloads, media streaming, resumable uploads, directory browsing, and WebDAV from one process.

Host: Dankserver — Hostname: files.dankserver.local — Docs: https://github.com/9001/copyparty

Facts

Item Value
Latest version v1.20.21 (2026-08)
Image ghcr.io/9001/copyparty-ac:latest (ac = full edition; the bare copyparty:latest tag does not exist — ghcr answers 403 on the token request for nonexistent repos)
Port 3923 (host) → 3923 (container)
Volume bind mount the shared root directory
Auth Per-directory .cpy config files, HTTP basic auth, dirkeys, filekeys
Streaming HTTP range requests, HLS, WebDAV, WOPI (Office editing)
Docker editions dj (document + media), iv (image + video), v (video only)

Configuration

Command-line interface (ac edition)

The ac edition's entrypoint is /bin/ash /z/cpp.sh -c /z/initcfg — it parses a config file, then execs python3 -m copyparty "$@", so accounts and volumes are passed as argv flags, not env vars. COPAY_PASS/COPAY_MODE envs are not consumed by this image (zero COPAY_ references in the package). The deployed interface:

command: ["-a", "dank:${COPAY_PASS}", "-v", "/w::r:ra,dank"]

-a takes USER:PASS. -v takes src:dst:perm1:perm2:... (authoritative: python3 -m copyparty --help-accounts inside the image, v1.20.21): each perm field is <letters>[,user[,user...]] and a field with no username applies to every unauthenticated request. Letters: r read (list + download), w upload, m move, d delete, a admin (control panel, config reload), A = rwmda. (everything). Empty dst mounts at the basename of src → URL /w.

Read-only posture (2026-08-31): ::r = browse + download for anonymous (required: the guarded files.franksdank.cloud chain delivers authentik'd traffic to copyparty unauthenticated), :ra,dank = admin for the dank account. No w/m/d for anyone — uploads, moves, and deletes are rejected server-side over HTTP, PUT, and WebDAV alike. There is no dedicated "reject uploads" volflag; the perms field is the documented mechanism (--help-flags volflags only throttle/reshape uploads).

History: the pre-2026-08-31 flag -v /w::A was not "A for dank, nothing for anonymous" as an earlier revision of this page claimed — the bare A granted full read/write/delete to anyone reaching port 3923. Verified live the same day: anonymous GET /Movies/ → 200, PROPFIND / → 207, PUT → 201.

Configuration File Options

Copyparty reads its configuration from initcfg (or config in the /data directory). Key options:

  • use-bwrap: n — Disable bwrap sandboxing for ffmpeg (default in Docker). Set to y to enable.
  • shadowing //NULL — Full unmap of a volume from the filesystem.
  • Config env-var expansion: Use ${VAR} syntax in [global] section for environment variable substitution.

Docker Editions

Different editions bundle different libraries:

Edition Bundled Libraries Use Case
dj Document + image + video libraries Full-featured server
iv Image + video libraries Image and video focused
v Video only Transcoding only, minimal footprint

The iv edition is no longer available for arm32/armv6. Use dj for maximum compatibility.

Volumes

Live deployment: the whole LUKS array is served at URL /w (the ac edition takes its volume roots from argv plus chdir: /w in /z/initcfg, not from a /data convention). Access is read-only since 2026-08-31 (-v /w::r:ra,dank — see #Command-line interface (ac edition) above). The compose bind mount is /mnt/entropy:/w (host path → container path). Note the bind itself is still rw on disk — copyparty enforces read-only at the application layer, so local services (Jellyfin, Calibre) keep writing into the array directly.

Docker Compose

  copyparty:
    image: ghcr.io/9001/copyparty-ac:latest
    container_name: copyparty
    restart: unless-stopped
    command: ["-a", "dank:${COPAY_PASS}", "-v", "/w::r:ra,dank"]
    ports:
      - "3923:3923"
    volumes:
      - /mnt/entropy:/w
      - /opt/copyparty/cfg:/cfg
    healthcheck:
      test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:3923/')"]
      interval: 30s
      timeout: 10s
      retries: 3

${COPAY_PASS} is compose-time interpolation from dankserver/.env — the password lands in the container's argv, visible to anyone who can run podman inspect copyparty on the host.

Applying changes: scripts/deploy.sh deliberately does not touch the dankserver compose stack (host containers are not quadlet-managed there), so command: edits need a manual recreate on Dankserver:

cd /home/dank/serverAppConfigs/dankserver && podman-compose up -d --force-recreate copyparty

Same project (dankserver), only copyparty is recreated; a fresh container answers 000 for the first seconds while it mounts.

Healthcheck

A simple HTTP check on port 3923 works. The root path returns HTTP 200 with the directory listing.

WOPI Integration

Copyparty v1.20.9+ supports WOPI (Web Application Open Platform Interface) for editing Office documents in the web UI via Collabora Online. Enable with the --wopi-accs flag to limit WOPI access to specific paths.

Security Advisories

Version CVE Issue
v1.20.19 GHSA-phv8-wgjp-g4p9 FTP upload outside volume
v1.20.17 GHSA-x5pq-m9p8-f4vx dirkey/filekey confusion
v1.20.9 CVE-2026-27948 / GHSA-62cr-6wp5-q43h XSS via file upload

Upgrade to v1.20.19+ to cover all known CVEs. The dirkey fix (v1.20.17) matters if using both dirkeys and filekeys.

Gotchas

  • Large transfers: Disable TLS inside the app and let Caddy terminate TLS. This avoids double encryption overhead.
  • Dedicated share directory: Do not give Copyparty the whole disk. Mount only the intended share path.
  • Whole-disk share (live choice): this deployment does serve the whole 91 T array from /w. Since 2026-08-31 the volume is application-level read-only for every account, so no remote write path exists. But note: LAN-direct :3923 is unauthenticated browse/download (anonymous holds r) — Caddy + Anubis + authentik guard only files.franksdank.cloud, not the published port. Tighten to -v /w::r,dank if anonymous LAN reads become unacceptable. (Before 2026-08-31, -v /w::A made the array world-writable on the LAN — see #Command-line interface (ac edition).)
  • Upload tokens scoped per folder: Prevents accidental global write access.
  • CSP nonces (v1.20.17+): Security hardening for JavaScript execution. May break third-party JS plugins (--js-browser / --html-head).
  • Custom thumbnail extractors (v1.20.19+): New thumbex framework. Requires configuration in initcfg.

See Also