### Docker Swarm Usage # Docker Swarm Usage ## Healthcheck The [Docker Image](../Dockerfile) includes a health check with the following options: ``` --interval=30s ``` > Specifies the time interval to run the health check. \ > In this case, the health check is performed every 30 seconds.
``` --timeout=10s ``` > Specifies the amount of time to wait for a response from the \"HEALTHCHECK\" command. \ > If the response does not arrive within 10 seconds, the health check fails.
``` --start-period=5s ``` > Specifies the amount of time to wait before starting the health check process. \ > In this case, the health check process will begin 5 seconds after the container is started.
``` --retries=3 ``` > Specifies the number of times Docker should retry the health check \ > before considering the container to be unhealthy.
The CMD instruction is used to define the command that will be run as part of the health check. \ In this case, the command is `wget --quiet --tries=1 --spider http://localhost:3000/ || exit 1`. \ This command will attempt to connect to `http://localhost:3000/` \ and if it fails it will exit with a status code of `1`. \ If this command returns a status code other than `0`, the health check fails. Overall, this \"HEALTHCHECK\" instruction is defining a health check process \ that runs every 30 seconds, and waits up to 10 seconds for a response, \ begins 5 seconds after the container is started, and retries up to 3 times. \ The health check attempts to connect to http://localhost:3000/ \ and will considers the container unhealthy if unable to connect. --- ### Faq # Frequently Asked Questions
Help! I can't install the PWA!
Here is a good guide on how to install PWAs on different platforms: \ https://www.cdc.gov/niosh/mining/tools/installpwa.html **Chromium-based browser on Desktop (Chrome, Edge, Vivaldi, Brave, etc.)** \ Easily install PairDrop PWA on your desktop by clicking the install-button in the top-right corner while on [pairdrop.net](https://pairdrop.net). Example on how to install a pwa with Edge **Desktop Firefox** \ On Firefox, PWAs are installable via [this browser extensions](https://addons.mozilla.org/de/firefox/addon/pwas-for-firefox/) **Android** \ PWAs are installable only by using Google Chrome or Samsung Browser: 1. Visit [pairdrop.net](https://pairdrop.net) 2. Click _Install_ on the installation pop-up or use the three-dot-menu and click on _Add to Home screen_ 3. Click _Add_ on the pop-up **iOS** \ PWAs are installable only by using Safari: 1. Visit [pairdrop.net](https://pairdrop.net) 2. Click on the share icon 3. Click _Add to Home Screen_ 4. Click _Add_ in the top right corner
**Self-Hosted Instance?** \ To be able to install the PWA from a self-hosted instance, the connection needs to be [established through HTTPS](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Installable_PWAs). See [this host your own section](https://github.com/schlagmichdoch/PairDrop/blob/master/docs/host-your-own.md#testing-pwa-related-features) for more info.
Shortcuts?
Available shortcuts: - Send a message with `CTRL + ENTER` - Close all "Send" and "Pair" dialogs by pressing `Esc`. - Copy a received message to the clipboard with `CTRL/⌘ + C`. - Accept file-transfer requests with `Enter` and decline with `Esc`.
How to save images directly to the gallery on iOS?
~~Apparently, iOS does not allow images shared from a website to be saved to the gallery directly.~~ ~~It simply does not offer that option for images shared from a website.~~ ~~iOS Shortcuts saves the day:~~ \ I created a simple iOS shortcut that takes your photos and saves them to your gallery: https://routinehub.co/shortcut/13988/ Update: \ Apparently, this was only a bug that is fixed in recent iOS version (https://github.com/WebKit/WebKit/pull/13111). \ If you use an older affected iOS version this might still be of use. \ Luckily, you can now simply use `Save Image`/`Save X Images` 🎉
Is it possible to send files or text directly from the "Context" or "Share" menu?
Yes, it finally is. * [Send files directly from the "Context" menu on Windows](/docs/how-to.md#send-files-directly-from-context-menu-on-windows) * [Send directly from the "Share" menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios) * [Send directly from the "Share" menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android)
Is it possible to send files or text directly via CLI?
Yes. * [Send directly from a command-line interface](/docs/how-to.md#send-directly-via-command-line-interface)
Are there any third-party Apps?
These third-party apps are compatible with PairDrop: 1. [Snapdrop Android App](https://github.com/fm-sys/snapdrop-android) 2. [Snapdrop for Firefox (Addon)](https://github.com/ueen/SnapdropFirefoxAddon) 3. Feel free to make one :)
What about the connection? Is it a P2P connection directly from device to device or is there any third-party-server?
It uses a WebRTC peer-to-peer connection. WebRTC needs a signaling server that is only used to establish a connection. The server is not involved in the file transfer. If the devices are on the same network, none of your files are ever sent to any server. If your devices are paired and behind a NAT, the PairDrop TURN Server is used to route your files and messages. See the [Technical Documentation](technical-documentation.md#encryption-webrtc-stun-and-turn) to learn more about STUN, TURN and WebRTC. If you host your own instance and want to support devices that do not support WebRTC, you can [start the PairDrop instance with an activated WebSocket fallback](https://github.com/schlagmichdoch/PairDrop/blob/master/docs/host-your-own.md#websocket-fallback-for-vpn).
What about privacy? Will files be saved on third-party servers?
Files are sent directly between peers. PairDrop doesn't even use a database. If curious, study [the signaling server](https://github.com/schlagmichdoch/PairDrop/blob/master/server/ws-server.js). WebRTC encrypts the files in transit. If the devices are on the same network, none of your files are ever sent to any server. If your devices are paired and behind a NAT, the PairDrop TURN Server is used to route your files and messages. See the [Technical Documentation](technical-documentation.md#encryption-webrtc-stun-and-turn) to learn more about STUN, TURN and WebRTC.
What about security? Are my files encrypted while sent between the computers?
Yes. Your files are sent using WebRTC, encrypting them in transit. Still you have to trust the PairDrop server. To ensure the connection is secure and there is no [MITM](https://en.m.wikipedia.org/wiki/Man-in-the-middle_attack) there is a plan to make PairDrop zero trust by encrypting the signaling and implementing a verification process. See [issue #180](https://github.com/schlagmichdoch/PairDrop/issues/180) to keep updated.
Transferring many files with paired devices takes too long
Naturally, if traffic needs to be routed through the TURN server because your devices are behind different NATs, transfer speed decreases. You can open a hotspot on one of your devices to bridge the connection, which omits the need of the TURN server. - [How to open a hotspot on Windows](https://support.microsoft.com/en-us/windows/use-your-windows-pc-as-a-mobile-hotspot-c89b0fad-72d5-41e8-f7ea-406ad9036b85#WindowsVersion=Windows_11) - [How to open a hotspot on macOS](https://support.apple.com/guide/mac-help/share-internet-connection-mac-network-users-mchlp1540/mac) - [Library to open a hotspot on Linux](https://github.com/lakinduakash/linux-wifi-hotspot) You can also use mobile hotspots on phones to do that. Then, all data should be sent directly between devices and not use your data plan.
Why don't you implement feature xyz?
Snapdrop and PairDrop are a study in radical simplicity. The user interface is insanely simple. Features are chosen very carefully because complexity grows quadratically since every feature potentially interferes with each other feature. We focus very narrowly on a single use case: instant file transfer. Not facilitating optimal edge-cases means better flow for average users. Don't be sad. We may decline your feature request for the sake of simplicity. Read *Insanely Simple: The Obsession that Drives Apple's Success*, and/or *Thinking, Fast and Slow* to learn more.
PairDrop is awesome. How can I support it?
* [Buy me a coffee](https://www.buymeacoffee.com/pairdrop) to pay for the domain and the server, and support libre software. * [File bugs, give feedback, submit suggestions](https://github.com/schlagmichdoch/pairdrop/issues) * Share PairDrop on social media. * Fix bugs and create a pull request. * Do some security analysis and make suggestions. * Participate in [active discussions](https://github.com/schlagmichdoch/PairDrop/discussions)
How does it work?
[See here for info about the technical implementation](/docs/technical-documentation.md)
[< Back](/README.md) --- ### Host Your Own # Deployment Notes ## TURN server for Internet Transfer Beware that you have to host your own TURN server to enable transfers between different networks. Follow [this guide](https://gabrieltanner.org/blog/turn-server/) to either install coturn directly on your system (Step 1) or deploy it via Docker (Step 5). You can use the `docker-compose-coturn.yml` in this repository. See [Coturn and PairDrop via Docker Compose](#coturn-and-pairdrop-via-docker-compose). Alternatively, use a free, pre-configured TURN server like [OpenRelay](https://www.metered.ca/tools/openrelay/)
## PairDrop via HTTPS On some browsers PairDrop must be served over TLS in order for some features to work properly. These may include: - Copying an incoming message via the 'copy' button - Installing PairDrop as PWA - Persistent pairing of devices - Changing of the display name - Notifications Naturally, this is also recommended to increase security.
## Deployment with Docker The easiest way to get PairDrop up and running is by using Docker. ### Docker Image from Docker Hub ```bash docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 lscr.io/linuxserver/pairdrop ``` > This image is hosted by [linuxserver.io](https://linuxserver.io). For more information visit https://hub.docker.com/r/linuxserver/pairdrop
### Docker Image from GitHub Container Registry (ghcr.io) ```bash docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 ghcr.io/schlagmichdoch/pairdrop ```
### Docker Image self-built #### Build the image ```bash docker build --pull . -f Dockerfile -t pairdrop ``` > A GitHub action is set up to do this step automatically at the release of new versions. > > `--pull` ensures always the latest node image is used. #### Run the image ```bash docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 -it pairdrop ``` > You must use a server proxy to set the `X-Forwarded-For` header > to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > To prevent bypassing the proxy by reaching the docker container directly, > `127.0.0.1` is specified in the run command.
### Flags Set options by using the following flags in the `docker run` command: #### Port ```bash -p 127.0.0.1:8080:3000 ``` > Specify the port used by the docker image > > - 3000 -> `-p 127.0.0.1:3000:3000` > - 8080 -> `-p 127.0.0.1:8080:3000` #### Set Environment Variables via Docker Environment Variables are set directly in the `docker run` command: \ e.g. `docker run -p 127.0.0.1:3000:3000 -it pairdrop -e DEBUG_MODE="true"` Overview of available Environment Variables are found [here](#environment-variables). Example: ```bash docker run -d \ --name=pairdrop \ --restart=unless-stopped \ -p 127.0.0.1:3000:3000 \ -e PUID=1000 \ -e PGID=1000 \ -e WS_SERVER=false \ -e WS_FALLBACK=false \ -e RTC_CONFIG=false \ -e RATE_LIMIT=false \ -e DEBUG_MODE=false \ -e TZ=Etc/UTC \ lscr.io/linuxserver/pairdrop ```
## Deployment with Docker Compose Here's an example docker compose file: ```yaml version: "3" services: pairdrop: image: "lscr.io/linuxserver/pairdrop:latest" container_name: pairdrop restart: unless-stopped environment: - PUID=1000 # UID to run the application as - PGID=1000 # GID to run the application as - WS_FALLBACK=false # Set to true to enable websocket fallback if the peer to peer WebRTC connection is not available to the client. - RATE_LIMIT=false # Set to true to limit clients to 1000 requests per 5 min. - RTC_CONFIG=false # Set to the path of a file that specifies the STUN/TURN servers. - DEBUG_MODE=false # Set to true to debug container and peer connections. - TZ=Etc/UTC # Time Zone ports: - "127.0.0.1:3000:3000" # Web UI ``` Run the compose file with `docker compose up -d`. > You must use a server proxy to set the `X-Forwarded-For` header > to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > To prevent bypassing the proxy by reaching the Docker container > directly, `127.0.0.1` is specified in the `ports` argument.
## Deployment with Node.js Clone this repository and enter the folder ```bash git clone https://github.com/schlagmichdoch/PairDrop.git && cd PairDrop ``` Install all dependencies with NPM: ```bash npm install ``` Start the server with: ```bash npm start ``` > By default, the node server listens on port 3000.
### Options / Flags These are some flags only reasonable when deploying via Node.js #### Port ```bash PORT=3000 ``` > Default: `3000` > > Environment variable to specify the port used by the Node.js server \ > e.g. `PORT=3010 npm start` #### Local Run ```bash npm start -- --localhost-only ``` > Only allow connections from localhost. > > You must use a server proxy to set the `X-Forwarded-For` header > to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > Use this when deploying PairDrop with node to prevent > bypassing the reverse proxy by reaching the Node.js server directly. #### Automatic restart on error ```bash npm start -- --auto-restart ``` > Restarts server automatically on error #### Production (autostart and rate-limit) ```bash npm run start:prod ``` > shortcut for `RATE_LIMIT=5 npm start -- --auto-restart` #### Production (autostart, rate-limit, localhost-only) ```bash npm run start:prod -- --localhost-only ``` > To prevent connections to the node server from bypassing \ > the proxy server you should always use "--localhost-only" on production. #### Set Environment Variables via Node.js To specify environment variables set them in the run command in front of `npm start`. The syntax is different on Unix and Windows. On Unix based systems ```bash PORT=3000 RTC_CONFIG="rtc_config.json" npm start ``` On Windows ```bash $env:PORT=3000 RTC_CONFIG="rtc_config.json"; npm start ``` Overview of available Environment Variables are found [here](#environment-variables).
## Environment Variables ### Debug Mode ```bash DEBUG_MODE="true" ``` > Default: `false` > > Logs the used environment variables for debugging. > > Prints debugging information about the connecting peers IP addresses. > > This is quite useful to check whether the [#HTTP-Server](#http-server) > is configured correctly, so the auto-discovery feature works correctly. > Otherwise, all clients discover each other mutually, independently of their network status. > > If this flag is set to `"true"` each peer that connects to the PairDrop server will produce a log to STDOUT like this: > > ``` > ----DEBUGGING-PEER-IP-START---- > remoteAddress: ::ffff:172.17.0.1 > x-forwarded-for: 19.117.63.126 > cf-connecting-ip: undefined > PairDrop uses: 19.117.63.126 > IP is private: false > if IP is private, '127.0.0.1' is used instead > ----DEBUGGING-PEER-IP-END---- > ``` > > If the IP address "PairDrop uses" matches the public IP address of the client device, everything is set up correctly. \ > To find out the public IP address of the client device visit https://whatsmyip.com/. > > To preserve your clients' privacy: \ > **Never use this environment variable in production!**
### Rate limiting requests ```bash RATE_LIMIT=1 ``` > Default: `false` > > Limits clients to 1000 requests per 5 min > > "If you are behind a proxy/load balancer (usually the case with most hosting services, e.g. Heroku, Bluemix, AWS ELB, > Render, Nginx, Cloudflare, Akamai, Fastly, Firebase Hosting, Rackspace LB, Riverbed Stingray, etc.), the IP address of > the request might be the IP of the load balancer/reverse proxy (making the rate limiter effectively a global one and > blocking all requests once the limit is reached) or undefined." > (See: https://express-rate-limit.mintlify.app/guides/troubleshooting-proxy-issues) > > To find the correct number to use for this setting: > > 1. Start PairDrop with `DEBUG_MODE=True` and `RATE_LIMIT=1` > 2. Make a `get` request to `/ip` of the PairDrop instance (e.g. `https://pairdrop-example.net/ip`) > 3. Check if the IP address returned in the response matches your public IP address (find out by visiting e.g. https://whatsmyip.com/) > 4. You have found the correct number if the IP addresses match. If not, then increase `RATE_LIMIT` by one and redo 1. - 4. > > e.g. on Render you must use RATE_LIMIT=5
### IPv6 Localization ```bash IPV6_LOCALIZE=4 ``` > Default: `false` > > To enable Peer Auto-Discovery among IPv6 peers, you can specify a reduced number of segments \ > of the client IPv6 address to be evaluated as the peer's IP. \ > This can be especially useful when using Cloudflare as a proxy. > > The flag must be set to an **integer** between `1` and `7`. \ > The number represents the number of IPv6 [hextets](https://en.wikipedia.org/wiki/IPv6#Address_representation) \ > to match the client IP against. The most common value would be `4`, \ > which will group peers within the same `/64` subnet.
### Websocket Fallback (for VPN) ```bash WS_FALLBACK=true ``` > Default: `false` > > Provides PairDrop to clients with an included websocket fallback \ > if the peer to peer WebRTC connection is not available to the client. > > This is not used on the official https://pairdrop.net website, > but you can activate it on your self-hosted instance.\ > This is especially useful if you connect to your instance via a VPN (as most VPN services block WebRTC completely in > order to hide your real IP address). ([Read more here](https://privacysavvy.com/security/safe-browsing/disable-webrtc-chrome-firefox-safari-opera-edge/)). > > **Warning:** \ > All traffic sent between devices using this fallback > is routed through the server and therefor not peer to peer! > > Beware that the traffic routed via this fallback is readable by the server. \ > Only ever use this on instances you can trust. > > Additionally, beware that all traffic using this fallback debits the servers data plan.
### Specify STUN/TURN Servers ```bash RTC_CONFIG="rtc_config.json" ``` > Default: `false` > > Specify the STUN/TURN servers PairDrop clients use by setting \ > `RTC_CONFIG` to a JSON file including the configuration. \ > You can use `rtc_config_example.json` as a starting point. > > To host your own TURN server you can follow this guide: https://gabrieltanner.org/blog/turn-server/ > Alternatively, use a free, pre-configured TURN server like [OpenRelay](<[url](https://www.metered.ca/tools/openrelay/)>) > > Default configuration: > > ```json > { > "sdpSemantics": "unified-plan", > "iceServers": [ > { > "urls": "stun:stun.l.google.com:19302" > } > ] > } > ```
You can host an instance that uses another signaling server This can be useful if you don't want to trust the client files that are hosted on another instance but still want to connect to devices that use https://pairdrop.net. ### Specify Signaling Server ```bash SIGNALING_SERVER="pairdrop.net" ``` > Default: `false` > > By default, clients connecting to your instance use the signaling server of your instance to connect to other devices. > > By using `SIGNALING_SERVER`, you can host an instance that uses another signaling server. > > This can be useful if you want to ensure the integrity of the client files and don't want to trust the client files that are hosted on another PairDrop instance but still want to connect to devices that use the other instance. > E.g. host your own client files under *pairdrop.your-domain.com* but use the official signaling server under *pairdrop.net* > This way devices connecting to *pairdrop.your-domain.com* and *pairdrop.net* can discover each other. > > Beware that the version of your PairDrop server must be compatible with the version of the signaling server. > > `SIGNALING_SERVER` must be a valid url without the protocol prefix. > Examples of valid values: `pairdrop.net`, `pairdrop.your-domain.com:3000`, `your-domain.com/pairdrop`
### Customizable buttons for the _About PairDrop_ page ```bash DONATION_BUTTON_ACTIVE=true DONATION_BUTTON_LINK="https://www.buymeacoffee.com/pairdrop" DONATION_BUTTON_TITLE="Buy me a coffee" TWITTER_BUTTON_ACTIVE=true TWITTER_BUTTON_LINK="https://twitter.com/account" TWITTER_BUTTON_TITLE="Find me on Twitter" MASTODON_BUTTON_ACTIVE=true MASTODON_BUTTON_LINK="https://mastodon.social/account" MASTODON_BUTTON_TITLE="Find me on Mastodon" BLUESKY_BUTTON_ACTIVE=true BLUESKY_BUTTON_LINK="https://bsky.app/profile/account" BLUESKY_BUTTON_TITLE="Find me on Bluesky" CUSTOM_BUTTON_ACTIVE=true CUSTOM_BUTTON_LINK="https://your-custom-social-network.net/account" CUSTOM_BUTTON_TITLE="Find me on this custom social network" PRIVACYPOLICY_BUTTON_ACTIVE=true PRIVACYPOLICY_BUTTON_LINK="https://link-to-your-privacy-policy.net" PRIVACYPOLICY_BUTTON_TITLE="Open our privacy policy" ``` > Default: unset > > By default, clients will show the default button configuration: GitHub, BuyMeACoffee, Twitter, and FAQ on GitHub. > > The GitHub and FAQ on GitHub buttons are essential, so they are always shown. > > The other buttons can be customized: > > * `*_BUTTON_ACTIVE`: set this to `true` to show a natively hidden button or to `false` to hide a normally shown button > * `*_BUTTON_LINK`: set this to any URL to overwrite the href attribute of the button > * `*_BUTTON_TITLE`: set this to overwrite the hover title of the button. This will prevent the title from being translated.
## Healthcheck > The Docker Image hosted on `ghcr.io` and the self-built Docker Image include a healthcheck. > > Read more about [Docker Swarm Usage](docker-swarm-usage.md#docker-swarm-usage).
## HTTP-Server When running PairDrop, the `X-Forwarded-For` header has to be set by a proxy. \ Otherwise, all clients will be mutually visible. To check if your setup is configured correctly [use the environment variable `DEBUG_MODE="true"`](#debug-mode). ### Using nginx #### Allow http and https requests ``` server { listen 80; expires epoch; location / { proxy_connect_timeout 300; proxy_pass http://127.0.0.1:3000; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-for $remote_addr; } } server { listen 443 ssl http2; ssl_certificate /etc/ssl/certs/pairdrop-dev.crt; ssl_certificate_key /etc/ssl/certs/pairdrop-dev.key; expires epoch; location / { proxy_connect_timeout 300; proxy_pass http://127.0.0.1:3000; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-for $remote_addr; } } ``` #### Automatic http to https redirect: ``` server { listen 80; expires epoch; location / { return 301 https://$host:3000$request_uri; } } server { listen 443 ssl http2; ssl_certificate /etc/ssl/certs/pairdrop-dev.crt; ssl_certificate_key /etc/ssl/certs/pairdrop-dev.key; expires epoch; location / { proxy_connect_timeout 300; proxy_pass http://127.0.0.1:3000; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Forwarded-for $remote_addr; } } ```
### Using Apache install modules `proxy`, `proxy_http`, `mod_proxy_wstunnel` ```bash a2enmod proxy ``` ```bash a2enmod proxy_http ```
Create a new configuration file under `/etc/apache2/sites-available` (on Debian) **pairdrop.conf** #### Allow HTTP and HTTPS requests ```apacheconf ProxyPass / http://127.0.0.1:3000/ upgrade=websocket ProxyPass / https://127.0.0.1:3000/ upgrade=websocket ``` #### Automatic HTTP to HTTPS redirect: ```apacheconf Redirect permanent / https://127.0.0.1:3000/ ProxyPass / http://127.0.0.1:3000/ upgrade=websocket ``` Activate the new virtual host and reload Apache: ```bash a2ensite pairdrop ``` ```bash service apache2 reload ```
## Coturn and PairDrop via Docker Compose ### Setup container To run coturn and PairDrop at once by using the `docker-compose-coturn.yml` with TURN over TLS enabled you need to follow these steps: 1. Generate or retrieve certificates for your `` (e.g. letsencrypt / certbot) 2. Create `./ssl` folder: `mkdir ssl` 3. Copy your ssl-certificates and the privkey to `./ssl` 4. Restrict access to `./ssl`: `chown -R nobody:nogroup ./ssl` 5. Create a dh-params file: `openssl dhparam -out ./ssl/dhparams.pem 4096` 6. Copy `rtc_config_example.json` to `rtc_config.json` 7. Copy `turnserver_example.conf` to `turnserver.conf` 8. Change `` in both files to the domain where your PairDrop instance is running 9. Change `username` and `password` in `turnserver.conf` and `rtc-config.json` 10. To start the container including coturn run: \ `docker compose -f docker-compose-coturn.yml up -d`
#### Setup container To restart the container including coturn run: \ `docker compose -f docker-compose-coturn.yml restart`
#### Setup container To stop the container including coturn run: \ `docker compose -f docker-compose-coturn.yml stop`
### Firewall To run PairDrop including its own coturn-server you need to punch holes in the firewall. These ports must be opened additionally: - 3478 tcp/udp - 5349 tcp/udp - 10000:20000 tcp/udp
## Local Development ### Install All files needed for developing are available in the folder `./dev`. For convenience, there is also a docker compose file for developing: #### Developing with docker compose First, [Install docker with docker compose.](https://docs.docker.com/compose/install/) Then, clone the repository and run docker compose: ```bash git clone https://github.com/schlagmichdoch/PairDrop.git && cd PairDrop ``` ```bash docker compose -f docker-compose-dev.yml up --no-deps --build ``` Now point your web browser to `http://localhost:8080`. - To debug the Node.js server, run `docker logs pairdrop`. - After changes to the code you have to rerun the `docker compose` command
#### Testing PWA related features PWAs requires the app to be served under a correctly set up and trusted TLS endpoint. The NGINX container creates a CA certificate and a website certificate for you. To correctly set the common name of the certificate, you need to change the FQDN environment variable in `docker-compose-dev.yml` to the fully qualified domain name of your workstation. (Default: localhost) If you want to test PWA features, you need to trust the CA of the certificate for your local deployment. \ For your convenience, you can download the crt file from `http://:8080/ca.crt`. \ Install that certificate to the trust store of your operating system. \ ##### Windows - Make sure to install it to the `Trusted Root Certification Authorities` store. ##### macOS - Double-click the installed CA certificate in `Keychain Access`, - expand `Trust`, and select `Always Trust` for SSL. ##### Firefox Firefox uses its own trust store. To install the CA: - point Firefox at `http://:8080/ca.crt` (Default: `http://localhost:8080/ca.crt`) - When prompted, select `Trust this CA to identify websites` and click _OK_. Alternatively: 1. Download `ca.crt` from `http://:8080/ca.crt` (Default: `http://localhost:8080/ca.crt`) 2. Go to `about:preferences#privacy` scroll down to `Security` and `Certificates` and click `View Certificates` 3. Import the downloaded certificate file (step 1) ##### Chrome - When using Chrome, you need to restart Chrome so it reloads the trust store (`chrome://restart`). - Additionally, after installing a new cert, you need to clear the Storage (DevTools → Application → Clear storage → Clear site data). ##### Google Chrome - To skip the installation of the certificate, you can also open `chrome://flags/#unsafely-treat-insecure-origin-as-secure` - The feature `Insecure origins treated as secure` must be enabled and the list must include your PairDrop test instance. E.g.: `http://127.0.0.1:3000,https://127.0.0.1:8443` Please note that the certificates (CA and webserver cert) expire after a day. Also, whenever you restart the NGINX Docker container new certificates are created. The site is served on `https://:8443` (Default: `https://localhost:8443`). [< Back](/README.md) --- ### How To # How-To ## Send directly from share menu on iOS I created an iOS shortcut to send images, files, folder, URLs \ or text directly from the share-menu https://routinehub.co/shortcut/13990/ [//]: # (Todo: Add screenshots)
## Send directly from share menu on Android The [Web Share Target API](https://developer.mozilla.org/en-US/docs/Web/Manifest/share_target) is implemented. When the PWA is installed, it will register itself to the share-menu of the device automatically.
## Send directly via command-line interface Send files or text with PairDrop via command-line interface. \ This opens PairDrop in the default browser where you can choose the receiver. ### Usage ```bash pairdrop -h ``` ``` Send files or text with PairDrop via command-line interface. Current domain: https://pairdrop-dev.onrender.com/ Usage: Open PairDrop: pairdrop Send files: pairdrop file1/directory1 (file2/directory2 file3/directory3 ...) Send text: pairdrop -t "text" Specify domain: pairdrop -d "https://pairdrop.net/" Show this help text: pairdrop (-h|--help) This pairdrop-cli version was released alongside v1.10.4 ```
### Setup #### Linux / Mac 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) ```shell wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.2/pairdrop-cli.zip" ``` or ```shell curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.2/pairdrop-cli.zip" ``` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/` ```shell sudo unzip pairdrop-cli.zip -d /usr/share/pairdrop-cli/ ``` 3. Copy the file _.pairdrop-cli-config.example_ to _.pairdrop-cli-config_ ```shell sudo cp /usr/share/pairdrop-cli/.pairdrop-cli-config.example /usr/share/pairdrop-cli/.pairdrop-cli-config ``` 4. Make the bash file _pairdrop_ executable ```shell sudo chmod +x /usr/share/pairdrop-cli/pairdrop ``` 5. Add a symlink to /usr/local/bin/ to include _pairdrop_ to _PATH_ ```shell sudo ln -s /usr/share/pairdrop-cli/pairdrop /usr/local/bin/pairdrop ```
#### Windows 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) 2. Put file in a preferred folder e.g. `C:\Program Files\pairdrop-cli` 3. Inside this folder, copy the file _.pairdrop-cli-config.example_ to _.pairdrop-cli-config_ 4. Search for and open `Edit environment variables for your account` 5. Click `Environment Variables…` 6. Under _System Variables_ select `Path` and click _Edit..._ 7. Click _New_, insert the preferred folder (`C:\Program Files\pairdrop-cli`), click *OK* until all windows are closed 8. Reopen Command prompt window **Requirements** As Windows cannot execute bash scripts natively, you need to install [Git Bash](https://gitforwindows.org/). Then, you can also use pairdrop-cli from the default Windows Command Prompt by using the shell file instead of the bash file which then itself executes _pairdrop-cli_ (the bash file) via the Git Bash. ```shell pairdrop.sh -h ```
## Send multiple files and directories directly from context menu on Windows ### Registering to open files with PairDrop It is possible to send multiple files with PairDrop via the context menu by adding pairdrop-cli to Windows `Send to` menu: 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) 2. Unzip the archive to a folder of your choice e.g. `C:\Program Files\pairdrop-cli\` 3. Inside this folder, copy the file _.pairdrop-cli-config.example_ to _.pairdrop-cli-config_ 4. Copy the shortcut _send with PairDrop.lnk_ 5. Hit Windows Key+R, type: `shell:sendto` and hit Enter. 6. Paste the copied shortcut into the directory 7. Open the properties window of the shortcut and edit the link field to point to _send-with-pairdrop.ps1_ located in the folder you used in step 2: \ `"C:\Program Files\PowerShell\7\pwsh.exe" -File "C:\Program Files\pairdrop-cli\send-with-pairdrop.ps1"` 8. You are done! You can now send multiple files and directories directly via PairDrop: _context menu_ > _Send to_ > _PairDrop_ ##### Requirements As Windows cannot execute bash scripts natively, you need to install [Git Bash](https://gitforwindows.org/).
## Send multiple files and directories directly from context menu on Ubuntu using Nautilus ### Registering to open files with PairDrop It is possible to send multiple files with PairDrop via the context menu by adding pairdrop-cli to Nautilus `Scripts` menu: 1. Register _pairdrop_ as executable via [guide above](#linux). 2. Copy the shell file _send-with-pairdrop_ to `~/.local/share/nautilus/scripts/` to include it in the context menu ```shell cp /usr/share/pairdrop-cli/send-with-pairdrop ~/.local/share/nautilus/scripts/ ``` 3. Make the shell file _send-with-pairdrop_ executable ```shell chmod +x ~/.local/share/nautilus/scripts/send-with-pairdrop ``` 4. You are done! You can now send multiple files and directories directly via PairDrop: _context menu_ > _Scripts_ > _send-with-pairdrop_
## File Handling API The [File Handling API](https://learn.microsoft.com/en-us/microsoft-edge/progressive-web-apps-chromium/how-to/handle-files) was implemented, but it was removed as default file associations were overwritten ([#17](https://github.com/schlagmichdoch/PairDrop/issues/17), [#116](https://github.com/schlagmichdoch/PairDrop/issues/116) [#190](https://github.com/schlagmichdoch/PairDrop/issues/190)) and it only worked with explicitly specified file types and couldn't handle directories at all. [< Back](/README.md) --- ### Technical Documentation # Technical Documentation ## Encryption, WebRTC, STUN and TURN Encryption is mandatory for WebRTC connections and completely done by the browser itself. When the peers are first connecting, \ a channel is created by exchanging their signaling info. \ This signaling information includes some sort of public key \ and is specific to the clients IP address. \ That is what the STUN Server is used for: \ it simply returns your public IP address \ as you only know your local ip address \ if behind a NAT (router). The transfer of the signaling info is done by the \ PairDrop / Snapdrop server using secure websockets. \ After that the channel itself is completely peer-to-peer \ and all info can only be decrypted by the receiver. \ When the two peers are on the same network \ or when they are not behind any NAT system \ (which they are always for classic \ Snapdrop and for not paired users on PairDrop) \ the files are send directly peer-to-peer. When a user is behind a NAT (behind a router) \ the contents are channeled through a TURN server. \ But again, the contents send via the channel \ can only be decrypted by the receiver. \ So a rogue TURN server could only \ see that there is a connection, but not what is sent. \ Obviously, connections which are channeled through a TURN server \ are not as fast as peer-to-peer. The selection whether a TURN server is needed \ or not is also done automatically by the web browser. \ It simply iterated through the configured \ RTC iceServers and checks what works. \ Only if the STUN server is not sufficient, \ the TURN server is used. _Diagram created by wowza.com_ Good thing: if your device has an IPv6 address \ it is uniquely reachable by that address. \ As I understand it, when both devices are using \ IPv6 addresses there is no need for a TURN server in any scenario. Learn more by reading https://www.wowza.com/blog/webrtc-encryption-and-security \ which gives a good insight into STUN, TURN and WebRTC. ## Device Pairing The pairing functionality uses the [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). It works by creating long secrets that are served \ by the server to the initiating and requesting pair peer, \ when the inserted key is correct. \ These long secrets are then saved to an \ indexedDB database in the web browser. \ IndexedDB is somewhat the successor of localStorage \ as saved data is shared between all tabs. \ It goes one step further by making the data persistent \ and available offline if implemented to a PWA. All secrets a client has saved to its database \ are sent to the PairDrop server. \ Peers with a common secret are discoverable \ to each other analog to peers with the same \ IP address are discoverable by each other. What I really like about this approach (and the reason I implemented it) \ is that devices on the same network are always \ visible regardless whether any devices are paired or not. \ The main user flow is never obstructed. \ Paired devices are simply shown additionally. \ This makes it in my idea better than the idea of \ using a room system as [discussed here](https://github.com/RobinLinus/snapdrop/pull/214). [< Back](/README.md) --- ### CONTRIBUTING # Priorities - PairDrop should be extremely simple, clean, and easy to use. - The main user flow should never be obstructed! - New features must be tested thoroughly before we are able to merge them. - Stability always comes first! # Agenda PairDrop is a study in radical simplicity. The user interface is insanely simple. Features are chosen very carefully because complexity grows quadratically since every feature potentially interferes with each other feature. We focus very narrowly on a single use case: instant file transfer. We are not trying to optimize for some edge-cases. We are optimizing the user flow of the average users. Don't be sad if we decline your feature request for the sake of simplicity. If you want to learn more about simplicity you can read [Insanely Simple: The Obsession that Drives Apple's Success](https://www.amazon.com/Insanely-Simple-Ken-Segall-audiobook/dp/B007Z9686O) or [Thinking, Fast and Slow](https://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555). # Contributing guidelines Make sure to follow these guidelines before opening an [issue](https://github.com/schlagmichdoch/pairdrop/issues/new/choose) or a [pull request](https://github.com/schlagmichdoch/pairdrop/pulls): - Before opening an issue of a pull request, please check if the issue or the pull request already exists. - Pull requests for packages updates are not allowed since there is [Dependabot](https://github.com/schlagmichdoch/pairdrop/blob/master/.github/dependabot.yml) that checks them automatically. - If you don't know how to contribute, also if you don't know JavaScript or Node.js, you can still share your awesome ideas with a new issue (feature request) and check the whole project for misspellings, too. --- ### README
Logo # _Send it_, with [PairDrop](https://pairdrop.net)

Local file sharing in your web browser.
Inspired by Apple's AirDrop.
Fork of Snapdrop.

Report a bug
Request feature


## Features File sharing on your local network that works on all platforms. - A multi-platform AirDrop-like solution that works. - Send images, documents or text via peer-to-peer connection to devices on the same local network. - Internet transfers - Join temporary public rooms to transfer files easily over the Internet. - Web-app - Works on all devices with a modern web-browser. Send a file from your phone to your laptop?
Share photos in original quality with friends using Android and iOS?
Share private files peer-to-peer between Linux systems? Screenshot GIF showing PairDrop in use ## Differences to the [Snapdrop](https://github.com/RobinLinus/snapdrop) it is based on
View all differences ### Paired Devices and Public Rooms — Internet Transfer * Transfer files over the Internet between paired devices or by entering temporary public rooms. * Connect to devices in complex network environments (public Wi-Fi, company network, iCloud Private Relay, VPN, etc.). * Connect to devices on your mobile hotspot. * Devices outside of your local network that are behind a NAT are auto-connected via the PairDrop TURN server. * Devices from the local network, in the same public room, or previously paired are shown. #### Persistent Device Pairing Always connect to known devices * Pair devices via a 6-digit code or a QR-Code. * Paired devices always find each other via shared secrets independently of their local network. * Pairing is persistent. You find your devices even after reopening PairDrop. * You can edit and unpair devices easily. #### Temporary Public Rooms Connect to others in complex network situations, or over the Internet. * Enter a public room via a 5-letter code or a QR-code. * Enter a public room to temporarily connect to devices outside your local network. * All devices in the same public room see each other. * Public rooms are temporary. Closing PairDrop leaves all rooms. ### [Improved UI for Sending/Receiving Files](https://github.com/RobinLinus/snapdrop/issues/560) * Files are transferred after a request is accepted. Files are auto-downloaded upon completing a transfer, if possible. * Multiple files are downloaded as a ZIP file * Download, share or save to gallery via the "Share" menu on Android and iOS. * Multiple files are transferred at once with an overall progress indicator. ### Send Files or Text Directly From Share Menu, Context Menu or CLI * [Send files directly from context menu on Ubuntu (using Nautilus)](docs/how-to.md#send-multiple-files-and-directories-directly-from-context-menu-on-ubuntu-using-nautilus) * [Send files directly from the context menu on Windows](docs/how-to.md#send-files-directly-from-context-menu-on-windows) * [Send directly from the "Share" menu on iOS](docs/how-to.md#send-directly-from-share-menu-on-ios) * [Send directly from the "Share" menu on Android](docs/how-to.md#send-directly-from-share-menu-on-android) * [Send directly via the command-line interface](docs/how-to.md#send-directly-via-command-line-interface) ### Other Changes * Change your display name to easily differentiate your devices. * [Paste files/text and choose the recipient afterwards ](https://github.com/RobinLinus/snapdrop/pull/534) * [Prevent devices from sleeping on file transfer](https://github.com/RobinLinus/snapdrop/pull/413) * Warn user before PairDrop is closed on file transfer * Open PairDrop on multiple tabs simultaneously (Thanks [@willstott101](https://github.com/willstott101)) * [Video and audio preview](https://github.com/RobinLinus/snapdrop/pull/455) (Thanks [@victorwads](https://github.com/victorwads)) * Switch theme back to auto/system after dark or light mode is on * Node-only implementation (Thanks [@Bellisario](https://github.com/Bellisario)) * Auto-restart on error (Thanks [@KaKi87](https://github.com/KaKi87)) * Lots of stability fixes (Thanks [@MWY001](https://github.com/MWY001) [@skiby7](https://github.com/skiby7) and [@willstott101](https://github.com/willstott101)) * To host PairDrop on your local network (e.g. on Raspberry Pi): [All peers connected with private IPs are discoverable by each other](https://github.com/RobinLinus/snapdrop/pull/558) * When hosting PairDrop yourself, you can [set your own STUN/TURN servers](docs/host-your-own.md#specify-stunturn-servers) * Translations.
## Translate PairDrop on [Hosted Weblate](https://hosted.weblate.org/engage/pairdrop/) Translation status ## Built with the following awesome technologies: * Vanilla HTML5 / JS ES6 / CSS 3 frontend * [WebRTC](http://webrtc.org/) / WebSockets * [Node.js](https://nodejs.org/en/) backend * [Progressive web app (PWA)](https://en.wikipedia.org/wiki/Progressive_web_app) unified functionality * [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) storage handling * [zip.js](https://gildas-lormeau.github.io/zip.js/) library * [cyrb53](https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js) super-fast hash function * [NoSleep](https://github.com/richtr/NoSleep.js) display sleep, add wake lock ([MIT](licenses/MIT-NoSleep)) * [heic2any](https://github.com/alexcorvi/heic2any) HEIC/HEIF to PNG/GIF/JPEG ([MIT](licenses/MIT-heic2any)) * [Weblate](https://weblate.org/) web-based localization tool * [BrowserStack](https://www.browserstack.com/) This project is tested with BrowserStack [FAQ](docs/faq.md) [Host your own instance with Docker or Node.js](docs/host-your-own.md). ## Support Buy me a coffee

PairDrop is libre, and always will be. \ If you find it useful and want to support free and open-source software, please consider donating using the button above. \ I footed the bill for the domain and the server, and you can help create and maintain great software by supporting me. \ Thank you very much for your contribution! ## Contributing Feel free to [open an issue](https://github.com/schlagmichdoch/pairdrop/issues/new/choose) or a [pull request](https://github.com/schlagmichdoch/pairdrop/pulls), following the [Contributing Guidelines](CONTRIBUTING.md). ---