# Deployment Notes The easiest way to get PairDrop up and running is by using Docker. > 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-compose (Step 5). ## Deployment with 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 ``` > You must use a server proxy to set the X-Forwarded-For \ > 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. #### Options / 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` ##### Rate limiting requests ```bash -e RATE_LIMIT=true ``` > Limits clients to 1000 requests per 5 min ##### IPv6 Localization ```bash -e IPV6_LOCALIZE=4 ``` > To enable Peer 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 -e WS_FALLBACK=true ``` > 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 -e RTC_CONFIG="rtc_config.json" ``` > Specify the STUN/TURN servers PairDrop clients use by setting \ > `RTC_CONFIG` to a JSON file including the configuration. \ > You can use `pairdrop/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/ > > Default configuration: > ```json > { > "sdpSemantics": "unified-plan", > "iceServers": [ > { > "urls": "stun:stun.l.google.com:19302" > } > ] > } > ``` ##### Debug Mode ```bash -e DEBUG_MODE="true" ``` > Use this flag to enable 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 PairDrop uses is the public IP of your device, everything is set up correctly. \ >To find out your devices public IP visit https://www.whatismyip.com/. > > To preserve your clients' privacy, **never use this flag in production!**
### Docker Image from GHCR ```bash docker run -d --restart=unless-stopped --name=pairdrop -p 127.0.0.1:3000:3000 ghcr.io/schlagmichdoch/pairdrop npm run start:prod ``` > You must use a server proxy to set the X-Forwarded-For 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. > > To specify options replace `npm run start:prod` \ > according to [the documentation below.](#options--flags-1) > The Docker Image includes a healthcheck. \ > Read more about [Docker Swarm Usage](docker-swarm-usage.md#docker-swarm-usage). ### 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. > > `--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 npm run start:prod ``` > You must use a server proxy to set the X-Forwarded-For \ > 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. > > To specify options replace `npm run start:prod` \ > according to [the documentation below.](#options--flags-1) > The Docker Image includes a Healthcheck. \ Read more about [Docker Swarm Usage](docker-swarm-usage.md#docker-swarm-usage).
## Deployment with Docker Compose Here's an example docker-compose file: ```yaml version: "2" 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. - 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 \ > 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.
## Deployment with node ```bash git clone https://github.com/schlagmichdoch/PairDrop.git && cd PairDrop ``` Install all dependencies with NPM: ```bash npm install ``` Start the server with: ```bash node index.js ``` or ```bash npm start ``` > Remember to check your IP address using your OS command to see where you can access the server. > By default, the node server listens on port 3000.
### Environment variables #### Port On Unix based systems ```bash PORT=3010 npm start ``` On Windows ```bash $env:PORT=3010; npm start ``` > Specify the port PairDrop is running on. (Default: 3000) #### IPv6 Localization ```bash IPV6_LOCALIZE=4 ``` > Truncate a portion of the client IPv6 address to make peers more discoverable. \ > See [Options/Flags](#options--flags) above. #### Specify STUN/TURN Server On Unix based systems ```bash RTC_CONFIG="rtc_config.json" npm start ``` On Windows ```bash $env:RTC_CONFIG="rtc_config.json"; npm start ``` > Specify the STUN/TURN servers PairDrop clients use by setting `RTC_CONFIG` \ > to a JSON file including the configuration. \ > You can use `pairdrop/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/ > > Default configuration: > ```json > { > "sdpSemantics": "unified-plan", > "iceServers": [ > { > "urls": "stun:stun.l.google.com:19302" > } > ] > } > ``` #### Debug Mode On Unix based systems ```bash DEBUG_MODE="true" npm start ``` On Windows ```bash $env:DEBUG_MODE="true"; npm start ``` > Use this flag to enable debugging info 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 PairDrop uses is the public IP of your device everything is set up correctly. \ >Find your devices public IP by visiting https://www.whatismyip.com/. > > Preserve your clients' privacy. **Never use this flag in production!** ### Options / Flags #### Local Run ```bash npm start -- --localhost-only ``` > Only allow connections from localhost. > > You must use a server proxy to set the X-Forwarded-For \ > to prevent all clients from discovering each other (See [#HTTP-Server](#http-server)). > > Use this when deploying PairDrop with node to prevent \ > bypassing the proxy by reaching the Docker container directly. #### Automatic restart on error ```bash npm start -- --auto-restart ``` > Restarts server automatically on error
#### Rate limiting requests ```bash npm start -- --rate-limit ``` > Limits clients to 1000 requests per 5 min
#### Websocket Fallback (for VPN) ```bash npm start -- --include-ws-fallback ``` > 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, \ 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](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.
#### Production (autostart and rate-limit) ```bash npm run start:prod ``` #### Production (autostart, rate-limit, localhost-only and websocket fallback for VPN) ```bash npm run start:prod -- --localhost-only --include-ws-fallback ``` > To prevent connections to the node server from bypassing \ > the proxy server you should always use "--localhost-only" on production. ## 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 ``` ```bash a2enmod proxy_wstunnel ```
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/ RewriteEngine on RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/?(.*) "ws://127.0.0.1:3000/$1" [P,L] ProxyPass / https://127.0.0.1:3000/ RewriteEngine on RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/?(.*) "wws://127.0.0.1:3000/$1" [P,L] ``` #### Automatic HTTP to HTTPS redirect: ```apacheconf Redirect permanent / https://127.0.0.1:3000/ ProxyPass / https://127.0.0.1:3000/ RewriteEngine on RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/?(.*) "wws://127.0.0.1:3000/$1" [P,L] ``` Activate the new virtual host and reload Apache: ```bash a2ensite pairdrop ``` ```bash service apache2 reload ``` # Local Development ## Install All files needed for developing are available on the branch `dev`. 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 git checkout dev docker-compose up -d ``` Now point your web browser to `http://localhost:8080`. - To restart the containers, run `docker-compose restart`. - To stop the containers, run `docker-compose stop`. - To debug the NodeJS server, run `docker logs pairdrop_node_1`.
## 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/fqdn.env` \ to the fully qualified domain name of your workstation. 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. \ - On Windows, make sure to install it to the `Trusted Root Certification Authorities` store. \ - On macOS, double-click the installed CA certificate in `Keychain Access`, \ - expand `Trust`, and select `Always Trust` for SSL. \ - Firefox uses its own trust store. To install the CA, \ - point Firefox at `http://:8080/ca.crt`. \ - When prompted, select `Trust this CA to identify websites` and click *OK*. \ - 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). 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`. [< Back](/README.md)