Files
serverAppConfigs/serverAppConfigs-docs/Dankserver/Copyparty.md
Frank a5fe045b58 docs(vault): one fact, one owner — repair the doubled pages, single-source the facts
Structural repair:
- 13 pages were the same document twice (each exactly 2x its HEAD size),
  a second frontmatter block whose closing fence had been glued onto a body
  line by a frontmatter rewrite that re-read its own output. Un-doubled by
  cutting at the second frontmatter and keeping the copy whose body is a
  superset; the orphan census reports 0 lost tokens against HEAD.
- log.md: one entry per date, bare `## YYYY-MM-DD` headings, newest first —
  66 dated headings merged into 34, titles demoted to bold leads, every
  content line verified present. The file had been descending at the head
  and ascending at the tail.

Ownership moves:
- New `LLM/frank-medium.md` is the locator for the retired Dankserver
  endpoint: era windows quoted from each era page's own banner, no numbers
  restated, and the two unresolved date conflicts recorded instead of
  silently resolved. `frank-archon.md` links to it instead of restating the
  pre-rename window.
- The four Pipeline-Parallelism stubs (frontmatter only, no body) are gone;
  `Multi-Node Runtimes.md` owns runtime construction, launch, mixed-vendor
  verdicts and cross-split spec decode, and the four links that pointed at
  the stubs were repointed at it or at the drafter page.
- Authentik's three stub pages fold into `Authentik.md`, with the process
  detail and the outpost reference split out so the parent stays under the
  length hint.

Verified corrections (host census + live probe, 2026-10-19):
- The MXFP4 checkpoint two pages called the "on-disk rollback" is gone:
  /home/dank/models/ holds StillDeadcode, rad and tpl.jinja. Stated once, on
  the era page that owns that payload; the swap page now links to it.
- frank-medium-radiance-mxfp4: the 4.24/7 accept rate belongs to the DFlash2
  arm measured on the FP8 target, not to the MXFP4 era; the 3-family soak run
  census is kept once (155 requests) instead of twice (~120 and 155).
- Fleet shapes re-confirmed against the live endpoints before touching any
  page: 3x200000 fp8 KV, 2x200704, 2x262144.

Index rows are regenerated, not hand-carved. Net -1,849 vault lines.
2026-10-19 05:00:43 -07:00

8.7 KiB

type, description, tags, timestamp
type description tags timestamp
reference Copyparty is a lightweight file server and media streamer that runs as a single Python binary.
dankserver
copyparty
2026-09-03

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 — Access: files.franksdank.cloud guarded by the Anubis → Authentik chain (Caddy routes it post-auth to 192.168.0.235:3923); the published port itself stays unauthenticated on the LAN — Docs: https://github.com/9001/copyparty

Facts

Item Value
Running 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). Upstream latest v1.20.24 (2026-09-19); v1.20.21 at research time (2026-08)
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 via Volume=/mnt/entropy:/w:ro in the quadlet unit (Entropy Volume) — read-only at the mount level, so no containerized consumer can write into the array through this path regardless of account permissions. The ac edition takes its volume roots from argv (-v /w::r:ra,dank), not from a /data convention; see #Command-line interface (ac edition) above.

Docker Compose (reference — retired 2026-09-01; live deployment is the quadlet unit below)

  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_ACCOUNT}/${COPAY_PASSWORD} are never written into the unit: they live in the host-local /home/dank/Containers/copyparty/env (0600), loaded via [Service] EnvironmentFile= so systemd expands them into Exec=-a ${COPAY_ACCOUNT}:${COPAY_PASSWORD} at start. The password still lands in the container argv — visible to anyone who can run podman inspect copyparty on the host.

Deployment (Quadlet)

Since 2026-09-01: dankserver/copyparty/quadlet/copyparty.container → copyparty.service, deployed with ./scripts/deploy.sh dankserver --service copyparty. Cutover details:

  • v1 generator rejects Command= → the argv lives in Exec=.
  • No HealthCmd= — the v1 generator splits unquoted spaces in that key; self-healing is Restart=always.
  • PublishPort=3923:3923 — the first cutover dropped it (unit joined dankserver_appnet), copyparty answered inside the netns only; the published-port seam test now pins 3923 alongside 8085/8096/8083.
  • Config root moved /opt/copyparty → /home/dank/Containers/copyparty/cfg.
  • The deployer refuses to start the unit before the env file exists, so a missing seed cannot create an admin account with a garbage password.

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 Advisory CVE Issue
v1.20.19 GHSA-phv8-wgjp-g4p9 CVE-2026-104102 FTP upload outside the defined volumes (limited path traversal)
v1.20.17 GHSA-x5pq-m9p8-f4vx CVE-2026-70657 dirkey/filekey confusion
v1.20.9 GHSA-62cr-6wp5-q43h CVE-2026-27948 reflected XSS via the ?setck= URL parameter (not the upload path — the separate upload/DOM-XSS advisory is GHSA-m2jw-cj8v-937r)

Upgrade to v1.20.19+ to cover all known advisories. The dirkey fix (v1.20.17) matters if using both dirkeys and filekeys. Each row's patched version is the advisory's own first_patched_version.

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. The volume is mounted :ro in the unit AND the permission flags grant anonymous only r, so no remote write path exists at all now. 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) — and the mount was rw.)
  • 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

Citations