added Copyparty
This commit is contained in:
@@ -39,6 +39,7 @@ handled separately — see [Exposing services](#exposing-services).
|
|||||||
| [audiobookshelf](audiobookshelf/) | 13378 | Audiobooks and podcasts, with per-user progress sync |
|
| [audiobookshelf](audiobookshelf/) | 13378 | Audiobooks and podcasts, with per-user progress sync |
|
||||||
| [cloudflare-tunnel](cloudflare-tunnel/) | — | Outbound connector. Exposes other services without opening a port |
|
| [cloudflare-tunnel](cloudflare-tunnel/) | — | Outbound connector. Exposes other services without opening a port |
|
||||||
| [codeserver](codeserver/) | 8443 | VS Code in a browser. Effectively a remote shell — read its README before exposing |
|
| [codeserver](codeserver/) | 8443 | VS Code in a browser. Effectively a remote shell — read its README before exposing |
|
||||||
|
| [copyparty](copyparty/) | 3923 | File server built for big/resumable transfers, WebDAV, media index |
|
||||||
| [filebrowser](filebrowser/) | 3672 | Web file manager for one directory tree (FileBrowser Quantum fork) |
|
| [filebrowser](filebrowser/) | 3672 | Web file manager for one directory tree (FileBrowser Quantum fork) |
|
||||||
| [jellyfin](jellyfin/) | 8096 | Media streaming. Also 7359/udp for auto-discovery |
|
| [jellyfin](jellyfin/) | 8096 | Media streaming. Also 7359/udp for auto-discovery |
|
||||||
| [openwebui](openwebui/) | 3033 | LLM chat UI. One `OWUI_TAG` switches between CPU, CUDA and bundled-Ollama |
|
| [openwebui](openwebui/) | 3033 | LLM chat UI. One `OWUI_TAG` switches between CPU, CUDA and bundled-Ollama |
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Copy to .env and adjust. .env is git-ignored; this file is not.
|
||||||
|
|
||||||
|
# ─── Required ───────────────────────────────────────────────────────
|
||||||
|
# Password for the account named in init/copyparty.conf. That config grants
|
||||||
|
# access to this account ONLY -- there is no anonymous access.
|
||||||
|
#
|
||||||
|
# openssl rand -base64 18
|
||||||
|
#
|
||||||
|
CP_PASSWORD=
|
||||||
|
|
||||||
|
# The directory to share. Bound to /w inside the container, which is what
|
||||||
|
# init/copyparty.conf serves at the webroot.
|
||||||
|
# Add `:ro` to the volume line in compose.yaml for a download-only server.
|
||||||
|
SHARE_PATH=/srv/downloads
|
||||||
|
|
||||||
|
# ─── Optional ───────────────────────────────────────────────────────
|
||||||
|
# Username. Change it here AND in the `accs:` block of init/copyparty.conf --
|
||||||
|
# the two must match or the account has no permissions.
|
||||||
|
#CP_USER=admin
|
||||||
|
|
||||||
|
# Index, thumbnails and copyparty's own config dir. Keeps state out of the
|
||||||
|
# shared folder. Back this up.
|
||||||
|
#DATA_PATH=./data
|
||||||
|
|
||||||
|
# The image runs as root unless told otherwise and reads no PUID/PGID; these
|
||||||
|
# feed Docker's `user:` directive. Must be able to read/write SHARE_PATH.
|
||||||
|
#PUID=1000
|
||||||
|
#PGID=1000
|
||||||
|
#TZ=Europe/Paris
|
||||||
|
|
||||||
|
#PORT=3923
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# copyparty
|
||||||
|
|
||||||
|
File server with an unusual amount packed in: resumable uploads, dedup, a media
|
||||||
|
index with thumbnails, share links, and WebDAV/FTP/SFTP/TFTP on the side. One
|
||||||
|
Python process, no database server.
|
||||||
|
|
||||||
|
Overlaps with [filebrowser](../filebrowser/) — that one is a tidy file manager,
|
||||||
|
this one is a transfer workhorse. Uploading 40 GB over a flaky connection is
|
||||||
|
where the difference shows.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
echo "CP_PASSWORD=$(openssl rand -base64 18)" >> .env
|
||||||
|
$EDITOR .env # set SHARE_PATH
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://<host>:3923` and log in as `admin` with that password.
|
||||||
|
|
||||||
|
## Ports
|
||||||
|
|
||||||
|
| Port | Proto | Purpose |
|
||||||
|
|------|-------|---------|
|
||||||
|
| 3923 | http | Web UI, WebDAV, and the API |
|
||||||
|
|
||||||
|
## Why it looks like this
|
||||||
|
|
||||||
|
**No anonymous access.** Upstream's example config grants `rw: *` — read *and
|
||||||
|
write* to anybody who can reach the port. That's a sensible LAN dropbox and a
|
||||||
|
poor default for anything else, so this config gives access to one named
|
||||||
|
account and nothing to the public. Verified: anonymous gets `403`, the account
|
||||||
|
gets `200`.
|
||||||
|
|
||||||
|
**The password is not in the config file.** copyparty's `[accounts]` section
|
||||||
|
takes `user: password` in plaintext, which is fine on your own disk but not in
|
||||||
|
a git repo. Accounts are passed as a command-line argument instead, so
|
||||||
|
`CP_PASSWORD` stays in `.env`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
command: ["-a", "${CP_USER:-admin}:${CP_PASSWORD:?...}"]
|
||||||
|
```
|
||||||
|
|
||||||
|
The username there must match the `accs:` block in
|
||||||
|
[`init/copyparty.conf`](init/copyparty.conf), or the account exists with no
|
||||||
|
permissions and every page looks empty.
|
||||||
|
|
||||||
|
**`XDG_CONFIG_HOME=/data`.** `/cfg` is mounted read-only, so without this
|
||||||
|
copyparty can't write its config directory and falls back to `/tmp` — logging a
|
||||||
|
warning most people scroll past. The consequence is that **the filekeys behind
|
||||||
|
every share link regenerate on each restart**, quietly breaking links you've
|
||||||
|
handed out.
|
||||||
|
|
||||||
|
**`hist: /data/hist`.** By default the index and thumbnail cache go into a
|
||||||
|
`.hist` directory *inside the folder you're sharing*. Redirecting it keeps your
|
||||||
|
media directory as you left it.
|
||||||
|
|
||||||
|
**The `ac` image.** Variants differ by what's bundled — `min` is the bare
|
||||||
|
server, `ac` adds ffmpeg for thumbnails and media tags, others add more. `ac` is
|
||||||
|
what the config's `e2ts` needs.
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- **Inline comments need two spaces before the `#`.** With one, the `#` and
|
||||||
|
everything after becomes part of the value. copyparty warns at startup rather
|
||||||
|
than failing, so it's easy to miss.
|
||||||
|
- **Share links bypass authentication by design.** That's the point of them,
|
||||||
|
but a leaked link is public access to that file.
|
||||||
|
- **`e2dsa` indexes on first start.** For a large share, expect the first boot
|
||||||
|
to churn; uploads are blocked while it runs and it says so in the log.
|
||||||
|
- **Back up `DATA_PATH`.** It holds the index and the filekeys that make share
|
||||||
|
links stable.
|
||||||
|
- **Version-check is opt-in.** Uncomment `vc-url` and `vc-exit` in the config
|
||||||
|
and copyparty refuses to start on a version with a known advisory — worth it
|
||||||
|
if you expose this.
|
||||||
|
|
||||||
|
## Exposing it
|
||||||
|
|
||||||
|
- [Reverse proxy with Caddy](../docs/reverse-proxy.md) — needed; the built-in
|
||||||
|
TLS uses a self-signed certificate.
|
||||||
|
- [Single sign-on with Authentik](../docs/authentik-sso.md) — copyparty has its
|
||||||
|
own accounts, so forward auth means two logins. Worth it anyway if this faces
|
||||||
|
the internet.
|
||||||
|
- [Cloudflare Tunnel](../cloudflare-tunnel/) — **think first.** Large uploads
|
||||||
|
are the reason to run copyparty, and the tunnel's ~100 MB body cap is exactly
|
||||||
|
what breaks.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Upstream: <https://github.com/9001/copyparty>
|
||||||
|
- The compose example this started from:
|
||||||
|
<https://github.com/9001/copyparty/blob/hovudstraum/docs/examples/docker/basic-docker-compose/docker-compose.yml>
|
||||||
|
- Image: <https://hub.docker.com/r/copyparty/ac>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
services:
|
||||||
|
copyparty:
|
||||||
|
# Variants differ by what's bundled: `min` is the bare server, `ac` adds
|
||||||
|
# ffmpeg for thumbnails and media tags, `iv`/`dj` add more. `ac` is the
|
||||||
|
# sensible default and what the config's e2ts flag needs.
|
||||||
|
image: copyparty/ac:1.20.21
|
||||||
|
container_name: copyparty
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# Runs as root unless told otherwise. It reads no PUID/PGID.
|
||||||
|
user: "${PUID:-1000}:${PGID:-1000}"
|
||||||
|
|
||||||
|
# The thumbnailer gets ~10s to finish after the stop signal.
|
||||||
|
stop_grace_period: 15s
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- TZ=${TZ:-Etc/UTC}
|
||||||
|
# Keeps log lines from being buffered.
|
||||||
|
- PYTHONUNBUFFERED=1
|
||||||
|
# Without this, copyparty cannot write its config dir (/cfg is read-only)
|
||||||
|
# and falls back to /tmp -- which silently regenerates the filekeys behind
|
||||||
|
# every share link on each restart.
|
||||||
|
- XDG_CONFIG_HOME=/data
|
||||||
|
# Replace NOPE with 2 to enable mimalloc: faster, roughly double the RAM.
|
||||||
|
- LD_PRELOAD=/usr/lib/libmimalloc-secure.so.NOPE
|
||||||
|
|
||||||
|
# Accounts live here, not in the committed config file. The name must match
|
||||||
|
# the one in init/copyparty.conf's `accs:` block.
|
||||||
|
command: ["-a", "${CP_USER:-admin}:${CP_PASSWORD:?set a password - the config grants access to this account only}"]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- ./init:/cfg:ro
|
||||||
|
# Index, thumbnails and copyparty's own config dir. Back this up.
|
||||||
|
- ${DATA_PATH:-./data}:/data
|
||||||
|
# What you're sharing. Add `:ro` for a download-only server.
|
||||||
|
- "${SHARE_PATH:?set SHARE_PATH to the directory you want to share}:/w"
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "${PORT:-3923}:3923"
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
# The "/._" suffix matches copyparty's default log filter, so the probe
|
||||||
|
# doesn't fill the log.
|
||||||
|
test: ["CMD-SHELL", "wget --spider -q 127.0.0.1:3923/?reset=/._"]
|
||||||
|
interval: 1m
|
||||||
|
timeout: 2s
|
||||||
|
retries: 5
|
||||||
|
start_period: 15s
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# copyparty configuration. Everything in /cfg is loaded by the image's own
|
||||||
|
# initcfg, which also sets `chdir: /w`.
|
||||||
|
#
|
||||||
|
# Not YAML despite appearances -- indentation matters, `key: value` for options
|
||||||
|
# that take one, bare words for flags.
|
||||||
|
#
|
||||||
|
# Inline comments need AT LEAST TWO SPACES before the `#`. With one space the
|
||||||
|
# `#` and everything after it becomes part of the value, and copyparty warns
|
||||||
|
# about it at startup rather than failing.
|
||||||
|
#
|
||||||
|
# No [accounts] section here on purpose: accounts are passed on the command
|
||||||
|
# line from .env, so no password is ever committed. See compose.yaml.
|
||||||
|
|
||||||
|
[global]
|
||||||
|
e2dsa # index files and scan the filesystem
|
||||||
|
e2ts # read media tags; needs the "ac" image, which has ffmpeg
|
||||||
|
|
||||||
|
# Keep the index out of the shared folder. Without this, copyparty creates
|
||||||
|
# a .hist directory inside whatever you are sharing.
|
||||||
|
hist: /data/hist
|
||||||
|
|
||||||
|
# ipa: lan # reject connections from outside the LAN
|
||||||
|
# df: 16 # refuse uploads when under 16 GB free
|
||||||
|
# grid # thumbnail grid by default
|
||||||
|
# theme: 2 # monokai
|
||||||
|
|
||||||
|
# Warn -- and with vc-exit, refuse to start -- if the running version has a
|
||||||
|
# known advisory. Off by default upstream; worth it for anything exposed.
|
||||||
|
# vc-url: https://api.copyparty.eu/advisories
|
||||||
|
# vc-exit
|
||||||
|
|
||||||
|
[/] # volume at the webroot
|
||||||
|
/w # serving /w, which compose binds to your SHARE_PATH
|
||||||
|
accs:
|
||||||
|
# Upstream's example uses `rw: *`, i.e. read-write for anonymous visitors.
|
||||||
|
# That is a reasonable LAN dropbox and a bad default for anything else, so
|
||||||
|
# only the account created in compose.yaml gets access here.
|
||||||
|
rwmda: admin # read-write-move-delete-admin
|
||||||
|
flags:
|
||||||
|
e2ds
|
||||||
Reference in New Issue
Block a user