### Self-Hosted File Server with Tailscale, HTTPS & Systemd on Linux --- ## Table of Contents 1. [What is Copyparty?](#1-what-is-copyparty) 2. [Prerequisites](#2-prerequisites) 3. [File Structure](#3-file-structure) 4. [Configuration File](#4-configuration-file) 5. [Systemd Service](#5-systemd-service) 6. [Tailscale Integration](#6-tailscale-integration) 7. [HTTPS Setup](#7-https-setup) 8. [Managing the Service](#8-managing-the-service) 9. [Security Considerations](#9-security-considerations) 10. [Troubleshooting](#10-troubleshooting) --- ## 1. 📦 What is Copyparty? Copyparty is a lightweight, portable file server written in Python. It runs as a single script with no complex dependencies and provides a full-featured web interface for managing files remotely. **Key features:** - Web-based file upload and download with drag-and-drop - Built-in media player for audio and video streaming - Multiple user accounts with granular permission control - Resumable uploads and downloads - Runs on Linux, Windows, macOS, and Android **GitHub:** https://github.com/9001/copyparty --- ## 2. ✅ Prerequisites - Python 3.x installed (`python3 --version`) - `copyparty-sfx.py` downloaded from the [GitHub releases page](https://github.com/9001/copyparty/releases) - Tailscale installed and connected _(optional, for remote access)_ - `cfssl` installed _(optional, for self-signed HTTPS)_ --- ## 3. 📁 File Structure It is recommended to keep all copyparty-related files in one dedicated folder: ``` /home/username/Copyparty/ ├── copyparty-sfx.py # Main copyparty executable ├── copyparty.conf # Configuration file ├── copyparty.service # Systemd service file ├── copyparty.pem # TLS certificate (optional, for HTTPS) ├── renew-cert.sh # Certificate renewal script (optional) ├── Browse/ # Public read-only folder for guests └── Dump/ # Public upload folder for guests ``` Create the folders: ```bash mkdir -p ~/Copyparty/Browse mkdir -p ~/Copyparty/Dump ``` --- ## 4. ⚙️ Configuration File **Location:** `~/Copyparty/copyparty.conf` Below is a complete example configuration, followed by a detailed explanation of each section. ### Complete Config ```ini [global] i: 0.0.0.0 p: 3923 cert: /home/username/Copyparty/copyparty.pem # optional, for HTTPS [accounts] alice: StrongPassphraseHere [/] /home/username accs: rwmda: alice [/browse] /home/username/Copyparty/Browse accs: r: * rwmda: alice [/dump] /home/username/Copyparty/Dump accs: wG: * rwmda: alice flags: e2d fk: 4 ``` --- ### 4.1 Global Section ```ini [global] i: 0.0.0.0 p: 3923 cert: /home/username/Copyparty/copyparty.pem ``` |Option|Description| |---|---| |`i: 0.0.0.0`|Bind to all network interfaces (LAN, Tailscale, localhost) simultaneously| |`p: 3923`|Port to listen on. 3923 is copyparty's default| |`cert: /path/to/cert.pem`|_(Optional)_ Path to TLS certificate for HTTPS| > **Note:** Using `0.0.0.0` means you don't need to list individual IPs. Copyparty will automatically be available on every interface including Tailscale. --- ### 4.2 Accounts Section ```ini [accounts] alice: StrongPassphraseHere ``` Creates user accounts in the format `username: password`. Multiple accounts can be added, one per line. > **Security:** Use a strong passphrase with mixed characters, numbers, and symbols. This password protects access to your private folders. --- ### 4.3 Volumes (Folders) Each volume maps a URL path to a folder on disk and defines who can access it. **General format:** ```ini [/url-path] /path/to/folder/on/disk accs: permissions: username ``` #### Permission Reference |Permission|Meaning| |---|---| |`r`|Read — browse and download files| |`w`|Write — upload files| |`m`|Move — rename and move files| |`d`|Delete — delete files| |`a`|Admin — access the admin panel| |`G`|upGet — see only your own uploads (combine with `w` → `wG`)| |`*`|Wildcard — applies to all unauthenticated guests| --- #### Volume: Private Root (/) ```ini [/] /home/username accs: rwmda: alice ``` Serves the user's home folder. Only the named user has access — guests cannot see this volume at all. The user gets full read, write, move, delete, and admin permissions. > **Tip:** Instead of sharing the entire home folder, you can create individual volumes for specific folders (Downloads, Documents, Videos, etc.) for better security. See example below: ```ini [/downloads] /home/username/Downloads accs: rwmda: alice [/documents] /home/username/Documents accs: rwmda: alice ``` --- #### Volume: Browse (/browse) ```ini [/browse] /home/username/Copyparty/Browse accs: r: * rwmda: alice ``` A public read-only folder. Anyone (guests and the admin user) can browse and download files. Only the admin user can upload, move, or delete. Use this to share files publicly. --- #### Volume: Dump (/dump) ```ini [/dump] /home/username/Copyparty/Dump accs: wG: * rwmda: alice flags: e2d fk: 4 ``` A public upload folder. Guests can upload files and access only their own uploads via a unique filekey link. They cannot browse other users' files. |Flag|Description| |---|---| |`e2d`|Enables the uploads database. Required for `wG` (upGet) to work| |`fk: 4`|Enables filekeys, 4 characters long. Each upload gets a unique `?k=XXXX` key| > **How it works for guests:** After uploading, the guest receives a unique link like `/dump/filename.jpg?k=8TLN`. This is the only way to access the file later — the guest should save this link before navigating away. --- ## 5. 🚀 Systemd Service The systemd service ensures copyparty starts automatically at boot, before any user logs in. ### Complete Service File **Location:** `/etc/systemd/system/copyparty.service` ```ini [Unit] Description=Copyparty File Server After=network-online.target tailscaled.service Wants=network-online.target tailscaled.service [Service] Type=simple User=username Group=username WorkingDirectory=/home/username/Copyparty ExecStart=/usr/bin/python3 /home/username/Copyparty/copyparty-sfx.py \ -c /home/username/Copyparty/copyparty.conf ExecReload=/bin/kill -s USR1 $MAINPID Restart=on-failure RestartSec=5 StandardOutput=journal StandardError=journal # Security hardening ProtectClock=true ProtectControlGroups=true ProtectHostname=true ProtectKernelLogs=true ProtectKernelModules=true ProtectKernelTunables=true ProtectProc=invisible RemoveIPC=true RestrictNamespaces=true RestrictRealtime=true RestrictSUIDSGID=true [Install] WantedBy=multi-user.target ``` ### Explanation |Option|Description| |---|---| |`After=` / `Wants=`|Wait for network and Tailscale to be ready before starting| |`User=` / `Group=`|Run as your user account| |`ExecReload=`|Allows graceful config reload without full restart| |`Restart=on-failure`|Automatically restart if copyparty crashes| |Security hardening options|Restrict kernel-level access for the process| ### Installing the Service ```bash # Copy service file to systemd directory sudo cp ~/Copyparty/copyparty.service /etc/systemd/system/copyparty.service # Reload systemd and enable sudo systemctl daemon-reload sudo systemctl enable copyparty # auto-start on boot sudo systemctl start copyparty # start immediately # Verify it's running sudo systemctl status copyparty ``` --- ## 6. 🔒 Tailscale Integration Tailscale is a VPN built on WireGuard that creates a private encrypted network between your devices. Since copyparty binds to all interfaces (`0.0.0.0`), it is automatically available on your Tailscale IP — no extra configuration needed in copyparty itself. ### 🌐 Access URL Reference |Scenario|URL|Encryption| |---|---|---| |Home network (LAN)|`http://192.168.1.x:3923`|None (trusted network)| |Away from home, Tailscale on|`http://100.x.x.x:3923`|✅ WireGuard| |Via Tailscale domain|`https://hostname.tailnet.ts.net:3923`|✅ WireGuard + TLS| |Friend without Tailscale|`https://hostname.tailnet.ts.net`|✅ TLS via Funnel| > **Note:** Traffic over the Tailscale IP is already encrypted end-to-end by WireGuard, even when using plain HTTP. HTTPS over Tailscale is double-encrypted but not strictly necessary. --- ### 6.1 Tailscale Funnel _(Optional)_ Funnel exposes copyparty to the public internet through Tailscale's servers. Anyone with the URL can access it — no Tailscale installation required on their end. This is useful for friends who want to upload files remotely. **Requirements:** - Tailscale account (free plan supported) - HTTPS must be enabled (Funnel requires it) **Setup:** ```bash # 1. Enable Funnel for your node at: # https://login.tailscale.com/f/funnel?node=YOUR_NODE_ID # 2. Start Funnel in the background sudo tailscale funnel --bg 3923 # 3. Check status tailscale funnel status # 4. To disable tailscale funnel --https=443 off ``` Funnel config persists across reboots automatically. > **Speed note:** Funnel routes traffic through Tailscale's relay servers, so speed is limited by your home upload bandwidth. For fast transfers with trusted contacts, add them to your Tailscale network instead (see below). --- ### 6.3 Adding Trusted Users to Tailscale _(Optional)_ For people who need fast, direct access: 1. Go to https://login.tailscale.com/admin/users 2. Click **Invite users** and send the invite link 3. They install Tailscale and accept the invite 4. They can then access copyparty at `http://100.x.x.x:3923` > **Warning:** Adding someone to your Tailscale network gives them access to your entire private network, not just copyparty. Only invite trusted people. --- ## 7. 🔐 HTTPS Setup _(Optional)_ ### Option A — Tailscale Certificate (Recommended) If you are using Tailscale, you can get a valid TLS certificate for your Tailscale domain for free. This enables HTTPS with no browser warnings on any device. **Steps:** ```bash # 1. Enable HTTPS in Tailscale admin panel: # https://login.tailscale.com/admin/dns → Enable HTTPS Certificates # 2. Generate the certificate tailscale cert hostname.tailnet.ts.net # 3. Combine cert and key into one PEM file for copyparty cat hostname.tailnet.ts.net.crt hostname.tailnet.ts.net.key \ > ~/Copyparty/copyparty.pem # 4. Add to your config's [global] section: # cert: /home/username/Copyparty/copyparty.pem # 5. Restart copyparty sudo systemctl restart copyparty ``` > **Important:** Tailscale certificates expire every 90 days. Set a reminder to renew them. **Certificate Renewal Script:** Save this as `~/Copyparty/renew-cert.sh`: ```bash #!/bin/bash tailscale cert hostname.tailnet.ts.net cat hostname.tailnet.ts.net.crt hostname.tailnet.ts.net.key \ > /home/username/Copyparty/copyparty.pem sudo systemctl restart copyparty echo "Certificate renewed and copyparty restarted!" ``` ```bash chmod +x ~/Copyparty/renew-cert.sh # Run when cert expires (~every 90 days) ~/Copyparty/renew-cert.sh ``` --- ### Option B — Self-signed Certificate via cfssl _(Optional)_ Copyparty can automatically generate a self-signed certificate if `cfssl` is installed. ```bash # Download cfssl binaries from: # https://github.com/cloudflare/cfssl/releases/latest # Place cfssl, cfssljson, cfssl-certinfo in /usr/local/bin/ sudo chmod +x /usr/local/bin/cfssl* # Copyparty will auto-generate certs on next start sudo systemctl restart copyparty ``` > **Drawback:** Self-signed certs trigger browser security warnings on every device. You would need to manually install the generated `ca.pem` onto each device to suppress the warnings. The Tailscale cert option is generally preferable. --- ## 8. 🛠️ Managing the Service ### Start / Stop / Restart ```bash sudo systemctl start copyparty # start sudo systemctl stop copyparty # stop sudo systemctl restart copyparty # restart (required after config changes) sudo systemctl enable copyparty # enable auto-start on boot sudo systemctl disable copyparty # disable auto-start on boot ``` ### Viewing Logs ```bash sudo journalctl -u copyparty -f # live log (Ctrl+C to exit) sudo journalctl -u copyparty -n 100 # last 100 lines sudo journalctl -u copyparty -b # all logs since last boot sudo journalctl -u copyparty --since today # logs from today ``` > **Tip:** The `-f` (follow) flag streams logs in real time — identical to running copyparty manually in the terminal. ### Testing Config Before Restarting Always test your config manually before applying it via systemd to catch errors early: ```bash python3 ~/Copyparty/copyparty-sfx.py -c ~/Copyparty/copyparty.conf ``` --- ## 9. 🛡️ Security Considerations ### Strengths of This Setup - Strong passphrase protects all private volumes - Guests are sandboxed to `/browse` (read-only) and `/dump` (upload + own files only) - Tailscale Funnel only exposes guest-accessible volumes publicly - Systemd security hardening restricts kernel-level process access - HTTPS encrypts traffic on the Tailscale domain - WireGuard encrypts all Tailscale IP traffic ### Known Risks |Risk|Severity|Mitigation| |---|---|---| |Copyparty runs as your user account|Medium|Create a dedicated service user (advanced)| |LAN traffic is plain HTTP|Low|Trusted home network; use HTTPS URL for sensitive sessions| |Home folder served at root volume|Medium|Use a strong unique passphrase; consider serving specific folders instead| |Self-signed cert triggers browser warnings|Low|Use Tailscale cert instead| ### Password Best Practices - Use a passphrase of 3+ random words combined with numbers and special characters - Never reuse passwords from other services - Change it immediately if you suspect it was compromised - The password is stored in `copyparty.conf` — protect file permissions on it: ```bash chmod 600 ~/Copyparty/copyparty.conf ``` --- ## 10. 🔧 Troubleshooting #### ❌ Copyparty won't start Check logs for config syntax errors: ```bash sudo journalctl -u copyparty -n 50 ``` --- #### 🔒 HTTPS certificate errors The Tailscale cert may have expired (~90 day lifespan). Renew it: ```bash ~/Copyparty/renew-cert.sh ``` --- #### 📡 Can't access via Tailscale IP Verify Tailscale is connected and check your IP: ```bash tailscale status tailscale ip -4 ``` The service may need a restart after Tailscale reconnects: ```bash sudo systemctl restart copyparty ``` --- #### 🌍 Funnel not working Check current status and re-enable if needed: ```bash tailscale funnel status sudo tailscale funnel --bg 3923 ``` --- #### 📎 Guest can't find their upload The filekey link (`?k=XXXX`) shown after uploading is the **only** way back to the file. It must be saved or bookmarked before navigating away from the upload page. --- #### ⚙️ Config changes not taking effect A restart is always required after editing the config: ```bash sudo systemctl restart copyparty ``` --- _Guide covers Copyparty v1.20.x on Fedora Linux with systemd. Most steps apply to any systemd-based Linux distribution._