Storage AWS

copyparty 1.20.26 on AWS User Guide

| Product: copyparty 1.20.26 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and using the copyparty 1.20.26 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg file sharing and sync listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.

copyparty is an open source file server you use from a web browser. You can upload files and whole folders by dragging them onto the page (large uploads resume where they stopped if the connection drops), browse folders, download single files or a whole folder as a zip or tar archive, and mount the share as a network drive over WebDAV.

The cloudimg image locks copyparty down:

  • HTTPS from the first boot. nginx serves copyparty on port 443 with a certificate generated on your instance's first boot. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve are dropped.
  • A password unique to your instance, and no anonymous access. On first boot the image generates a random password for the admin account and writes it to /var/lib/cloudimg/copyparty-credentials.txt (root only). copyparty stores only a salted scrypt hash of it, with a salt generated on your instance. Visitors without the password can see the sign in page and nothing else: no file, no folder name, no upload.
  • Only the web interface and WebDAV. copyparty can also run FTP, SFTP, SMB and TFTP servers and announce itself on the local network (mDNS, SSDP). On this image all of them are off, and a check that runs before every start refuses a configuration that turns them on, listens beyond the instance itself, or grants anything to anonymous visitors.
  • No passwords in web addresses. copyparty accepts a password in the URL (?pw=). Such an address would end up in browser history and logs, so nginx refuses it, and the refused request is logged without its query string. Sign in with the login box, or use HTTP Basic authentication or a PW header from scripts.
  • Path traversal refused. Encoded slashes, dots and backslashes and .. segments in a path are refused by nginx before they reach copyparty, and copyparty never follows a link out of the shared folder.
  • Nothing else on the network. copyparty listens on 127.0.0.1:3923 only. The security group needs only 22, 80 and 443.
  • No service can reach the metadata service. copyparty and nginx are blocked from the EC2 instance metadata service at the kernel level, and the AMI requires IMDSv2.
  • Cross site protection. Another web site cannot make your signed in browser upload, move or delete files, or start a zip download of a folder.
  • Pinned, verified release. copyparty 1.20.26 is installed from the release published on PyPI, checked against its recorded hash file by file, and runs on Ubuntu's own Python 3.12 and Jinja2 packages, which Ubuntu security updates keep patched.
  • Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.

What is on the image: copyparty 1.20.26 (/opt/copyparty), Python 3.12 and Jinja2 from Ubuntu, nginx, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. Your files live in /srv/copyparty.

Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large

Prerequisites

  • An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
  • A security group that allows TCP 22 (SSH), TCP 443 (copyparty) and TCP 80 (redirects to HTTPS) from your own networks only.

Step 1: Launch the instance

In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick copyparty 1.20.26 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair, a security group as above, and a subnet. Your files are stored on the root volume; raise its size under Configure storage if you expect to keep a lot of data (or add a volume later, Step 10).

With the AWS CLI (replace the values in angle brackets):

aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
  --instance-type m5.large --key-name <your-key-pair> \
  --security-group-ids <your-security-group> --subnet-id <your-subnet> \
  --metadata-options HttpTokens=required,HttpEndpoint=enabled \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=copyparty}]'

Step 2: Connect to your instance

Version SSH user
copyparty 1.20.26 on Ubuntu 24.04 ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>

Step 3: Check the services

First boot generates the certificate, the password and copyparty's own keys, then copyparty and nginx start. It takes a few seconds:

systemctl is-active copyparty-firstboot copyparty-set-host copyparty nginx
active
active
active
active

Only SSH (22) and nginx (80, 443) listen on the network. copyparty listens on loopback port 3923, and the other two are Ubuntu's local DNS resolver:

sudo ss -lntp | awk 'NR>1 {print $4}' | sort -u
0.0.0.0:22
0.0.0.0:443
0.0.0.0:80
127.0.0.1:3923
127.0.0.53%lo:53
127.0.0.54:53
[::]:22
[::]:443
[::]:80

If nginx or copyparty is not active, first boot has not finished (or failed, in which case neither starts). Check systemctl status copyparty-firstboot and journalctl -u copyparty-firstboot.

Step 4: Get your URL and password

sudo cat /var/lib/cloudimg/copyparty-credentials.txt

The file is readable by root only:

# copyparty 1.20.26 on Ubuntu 24.04 - per-instance sign-in (written by copyparty-apply-credential, firstboot)
# This credential is unique to this instance; none was baked into the image. Keep this file secret.
COPYPARTY_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
COPYPARTY_USER=admin
COPYPARTY_PASS=<COPYPARTY_PASS>

The URL uses the instance's public DNS name from EC2 instance metadata. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too. To use your own DNS name, see Step 9.

The built in self test proves the whole chain from the command line: an anonymous visitor sees nothing, a wrong password is refused, the right one signs in, an upload, download and delete round trip works, and the refusals described in this guide hold:

sudo copyparty-selftest
SELFTEST-OK https 301 + /healthz + anonymous: no permissions, upload 401 + wrong password 403 + admin sign-in + upload/download/delete round trip + 403 cross-origin upload + 400 encoded and dot-segment traversal + 400 password in URL + 403 cross-site zip + 444 unknown host

Step 5: Sign in

Open the COPYPARTY_URL in your browser. The certificate is self signed, so your browser asks you to confirm it the first time. Before you accept it, compare the fingerprint your browser shows with the one on the instance (or install your own certificate, Step 9):

sudo openssl x509 -in /etc/ssl/copyparty/copyparty.crt -noout -fingerprint -sha256

copyparty shows its sign in page. It asks only for a password: copyparty recognises the account by its password. Enter the COPYPARTY_PASS from Step 4 and choose login.

The copyparty sign in page on cloudimg, asking for a password

Step 6: Upload, browse and download

After signing in you see the shared folder, /srv/copyparty on the instance, with a folder tree on the left. The top right corner shows the permissions of your account: read, write, move, delete and admin.

copyparty listing the shared folder with a reports folder, a text file and a Markdown file

To upload, open the rocket tab in the toolbar and drop files or whole folders onto the UPLOAD box (or click it to pick files). copyparty hashes each file in your browser and sends it in chunks; if the connection drops, upload the same file again and it continues where it stopped. Files you upload into a folder are listed there as soon as they finish.

A CSV file uploaded into the reports folder with copyparty's resumable uploader

Click a file to download or open it. The zip link next to a folder downloads the whole folder as one archive. The folder icon in the toolbar creates folders, and the menus on each file move, rename and delete.

HTML, SVG and Markdown files are shown as plain text rather than run as pages on your copyparty site (see Security notes for why, and how to change it).

copyparty also answers plain HTTP requests, which is handy for scripts. From the instance itself, with curl (the password goes into a private curl config file, never onto the command line):

F=/var/lib/cloudimg/copyparty-credentials.txt
H=$(sudo sed -n 's#^COPYPARTY_URL=https://\([^/]*\)/.*#\1#p' $F)
W=$(mktemp -d); chmod 700 "$W"
( umask 077; printf 'user = "admin:%s"\n' "$(sudo sed -n 's/^COPYPARTY_PASS=//p' $F)" > "$W/curl.cfg" )
printf 'Hello from cloudimg.\n' > "$W/hello.txt"
C=(curl -s -K "$W/curl.cfg" --resolve "$H:443:127.0.0.1" --cacert /etc/ssl/copyparty/copyparty.crt)
"${C[@]}" -H "Origin: https://$H" -o /dev/null -w 'PUT hello.txt -> HTTP %{http_code}\n' -T "$W/hello.txt" "https://$H/hello.txt"
"${C[@]}" "https://$H/hello.txt"
"${C[@]}" -H "Origin: https://$H" -o /dev/null -w 'DELETE hello.txt -> HTTP %{http_code}\n' -X DELETE "https://$H/hello.txt"
rm -rf "$W"
PUT hello.txt -> HTTP 201
Hello from cloudimg.
DELETE hello.txt -> HTTP 200

A request that changes files is refused with 403 when it carries another web site's Origin (a page elsewhere trying to use your signed in browser). Scripts that send no Origin header, or your instance's own address as in the example, are accepted. copyparty accepts the password as HTTP Basic authentication with any user name; admin is used throughout this guide.

Step 7: Mount the share over WebDAV

copyparty speaks WebDAV on the same HTTPS address, with the same password, so you can mount the share as a drive or sync it with tools such as rclone. From the instance, a WebDAV listing of the shared folder:

F=/var/lib/cloudimg/copyparty-credentials.txt
H=$(sudo sed -n 's#^COPYPARTY_URL=https://\([^/]*\)/.*#\1#p' $F)
W=$(mktemp -d); chmod 700 "$W"
( umask 077; printf 'user = "admin:%s"\n' "$(sudo sed -n 's/^COPYPARTY_PASS=//p' $F)" > "$W/curl.cfg" )
curl -s -K "$W/curl.cfg" --resolve "$H:443:127.0.0.1" --cacert /etc/ssl/copyparty/copyparty.crt -X PROPFIND -H 'Depth: 1' -o /dev/null -w 'PROPFIND / -> HTTP %{http_code}\n' "https://$H/"
rm -rf "$W"
PROPFIND / -> HTTP 207

With rclone on your own computer (it asks for the password and stores it obscured in its own configuration; with the self signed certificate add --no-check-certificate, or install your own certificate first, Step 9):

rclone config create copyparty webdav url https://<your-copyparty-host>/ vendor owncloud user admin --obscure pass <COPYPARTY_PASS>
rclone ls copyparty:

On Linux, davfs2 mounts it as a folder (sudo mount -t davfs https://<your-copyparty-host>/ /mnt/copyparty). Windows and macOS can map it as a network drive too, but both insist on a certificate they trust, so install a certificate from a public authority first (Step 9).

Step 8: Change the password

To replace the password with a new random one (written to the credentials file; the old one stops working at once, and every signed in browser has to sign in again):

sudo copyparty-set-password

To choose your own (16 to 128 printable characters, no spaces, :, ,, # or \), pass it on standard input so it never appears in your shell history or the process list:

read -rs NEWPASS && printf '%s\n' "$NEWPASS" | sudo copyparty-set-password --stdin; unset NEWPASS

Step 9: Use your own host name and certificate

Point a DNS record at the instance (an Elastic IP keeps the address across stop and start), then tell copyparty its name. This mints a new self signed certificate for that name, updates the nginx host rule and the cross site guards, and keeps the name across reboots:

sudo copyparty-set-hostname files.example.com

To use a certificate from a public authority instead, replace /etc/ssl/copyparty/copyparty.crt (full chain) and /etc/ssl/copyparty/copyparty.key (mode 0600, owned by root) with your own and run sudo systemctl reload nginx. Running copyparty-set-hostname again later would replace them with a new self signed pair.

Without your own name, each boot checks the instance's names: after a stop and start that changed the public address, the next boot issues a new certificate and updates the URL in the credentials file for the new name. Nothing changes on a boot where the names are the same.

Step 10: Where your files live, settings and backups

copyparty shares /srv/copyparty, owned by the copyparty service user, and nothing outside it. Its own state (indexes, sessions and keys) is in /var/lib/copyparty. To keep files on their own EBS volume, attach and format the volume, stop the service (sudo systemctl stop copyparty), copy the folder over and mount the volume at /srv/copyparty (add it to /etc/fstab with nofail), then make sure the mount point is owned by copyparty:copyparty with mode 0750 and start the service again.

The simplest complete backup is an EBS snapshot (or AWS Backup on the instance). For a file level copy:

sudo tar -czf /root/copyparty-files-backup.tar.gz -C /srv copyparty

The settings are in /etc/copyparty/copyparty.conf (the server and the shared folder) and /etc/copyparty/accounts.conf (the salt and the password hash, written by copyparty-set-password). Both are owned by root and only readable by the service. After editing, apply the change with:

sudo systemctl restart copyparty

copyparty-config-check runs before every start and keeps copyparty from starting with a setting this image keeps off: listening beyond 127.0.0.1, FTP, SFTP, SMB, TFTP, network discovery, identity provider headers, automatic sign in by IP address, changes through plain links, an anonymous permission or a password stored in clear text. Run it yourself after an edit to see what it would refuse:

sudo -u copyparty /usr/local/sbin/copyparty-config-check

The in browser reload cfg button of copyparty's control panel is switched off for the same reason: a restart always runs the check first. The copyparty documentation describes more folders, accounts and per folder options; a new account's password must be stored as a hash made with the same salt, for example:

sudo bash -c 'T=$(mktemp -d); printf "[global]\n  ah-salt: %s\n" "$(sed -nE "s/^ *ah-salt: *//p" /etc/copyparty/accounts.conf)" > $T/s.conf; read -rs PW; printf "%s\n" "$PW" | env -i PATH=/usr/bin:/bin HOME=$T XDG_CONFIG_HOME=$T /opt/copyparty/bin/copyparty -c $T/s.conf --ah-alg scrypt --ah-gen - 2>/dev/null | tail -1; rm -rf $T'

Step 11: Check persistence and updates

Every service is enabled, so copyparty returns after a reboot or a stop and start, and unattended security upgrades keep the operating system, Python, Jinja2 and nginx patched:

systemctl is-enabled copyparty copyparty-set-host nginx unattended-upgrades
enabled
enabled
enabled
enabled

Security notes

  • No shared secret ships in the image. No password, password hash, salt, session key or TLS key exists until your instance's first boot generates them, and neither nginx nor copyparty starts before that has finished.
  • No anonymous access. Only the admin account has any permission. Without the password, copyparty shows its sign in page and a page of client settings, and nothing about your files, over the web interface and over WebDAV alike. copyparty locks out an address for a day after nine wrong passwords within an hour; the address is the one nginx sees, so one client cannot lock out others.
  • Uploaded web pages do not run. HTML, SVG and Markdown files are shown as text (copyparty's no-html option), so a file someone uploads cannot run script as your copyparty site. If you want copyparty to render Markdown and HTML, remove the no-html line from /etc/copyparty/copyparty.conf and restart; only do that if you trust everyone who can upload.
  • Only one way in. FTP, SFTP, SMB, TFTP, mDNS and SSDP are off and refused by the configuration check, copyparty listens on loopback only, and the copyparty build on the image has the private key it ships for its own TLS mode removed (this image uses nginx for TLS).
  • Cross site requests are refused. Uploads, moves, deletes, zip and tar downloads and copyparty's settings links are refused when they come from another web site. Because of this a zip link pasted into the address bar is refused too; start downloads from the copyparty page. A file whose name contains a backslash cannot be opened through the web interface.
  • WebDAV with Windows. copyparty answers lock requests from the Windows WebDAV client even without a password (Windows hangs otherwise); the answer creates and changes nothing.
  • No access to the metadata service. copyparty and nginx run with a kernel level block on the EC2 instance metadata address.
  • Restrict 22/tcp to your management network, and 80/443 to the networks that use copyparty.

Architecture summary

Component Detail
Application copyparty 1.20.26 (MIT) on Ubuntu's Python 3.12, /opt/copyparty, copyparty.service as user copyparty, 127.0.0.1:3923
Web server nginx on 443 (HTTPS, per instance certificate in /etc/ssl/copyparty), 80 redirects to HTTPS, /healthz for load balancer checks
Files /srv/copyparty; copyparty's state in /var/lib/copyparty (the only paths the service can write)
Configuration /etc/copyparty/copyparty.conf and /etc/copyparty/accounts.conf (root owned, read only to the service), checked before every start
Credentials /var/lib/cloudimg/copyparty-credentials.txt, mode 0600, root only
Helpers copyparty-selftest, copyparty-set-password, copyparty-set-hostname, copyparty-config-check (in /usr/local/sbin)
First boot copyparty-firstboot.service; host name and certificate check on every later boot copyparty-set-host.service
Ports 22 SSH, 80 redirect, 443 copyparty (web interface and WebDAV)
Base image Ubuntu 24.04 LTS, fully patched, unattended security upgrades enabled, IMDSv2 required

Support

cloudimg images come with 24/7 support. Email support@cloudimg.co.uk with your AWS account ID and the instance ID. For copyparty itself, see the copyparty project on GitHub and its documentation.