### 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._