**ARCHIVED** Self-hosted file storage


Development on droppy has ceased because I don't have enough time or motivation to properly support it and because of its outdated technology stack, it became exceedingly boring to work.

droppy is a self-hosted file storage server with a web interface and capabilities to edit files and view media directly in the browser. It is particularly well-suited to be run on low-end hardware like the Raspberry Pi.


  • Responsive, scalable HTML5 interface
  • Realtime updates of file system changes
  • Directory and Multi-File upload
  • Drag-and-Drop support
  • Clipboard support to create image/text files
  • Side-by-Side mode
  • Simple and fast Search
  • Shareable public download links
  • Zip download of directories
  • Powerful text editor with themes and broad language support
  • Image and video gallery with touch support
  • Audio player with seeking support
  • Fullscreen support for editor and gallery
  • Supports installing to the homescreen
  • Docker images available for x86-64, ARMv6, ARMv7 and ARMv8

General Information

Two directories will be used, one for configuration and one for the actual files:

  • config: defaults to ~/.droppy/config, override with -c /some/dir
  • files: default ~/.droppy/files override with -f /some/dir

droppy maintains an in-memory representation of the files directory. If you're on slow storage and/or serving 100k or more files, the initial indexing on startup will likely take some time.


Local Installation 📦

With Node.js >= 12.10.0 installed, run:

$ npm install -g droppy
$ droppy start -c /srv/droppy/config -f /srv/droppy/files

To make droppy run in the background, you can use the --daemon option, thought it is adviced that you install it as a persistent service in your system. For Linux, see these guides:

Docker installation 🐳

The silverwind/droppy multi-arch images supports amd64, arm64, arm/v7 and arm/v6 architectures. To pull and run, use:

$ docker run --name droppy -p silverwind/droppy

This method uses automatic volumes for /config and /files which can be overridden through -v /srv/droppy/config:/config and -v /srv/droppy/files:/files. If you're using existing files, it's advisable to use -e UID=1000 -e GID=1000 to get new files written with correct ownership.

To update a docker installation, run

$ docker pull silverwind/droppy
$ docker stop droppy && docker rm droppy
$ docker run --name droppy -p silverwind/droppy


Alternatively, you can use the example docker-compose.yml:

$ curl -O https://raw.githubusercontent.com/silverwind/droppy/master/examples/docker-compose.yml
$ docker-compose up

This example docker-compose.yml uses the subdirectories config and files of the current working directory for storing data.


See the example Caddyfile.


By default, the server listens on all IPv4 and IPv6 interfaces on port 8989. On first startup, a prompt to create login data for the first account will appear. Once it's created, login credentials are enforced. Additional accounts can be created in the options interface or the command line. Configuration is done in config/config.json, which is created with these defaults:

  "listeners" : [
      "host": ["", "::"],
      "port": 8989,
      "protocol": "http"
  "public": false,
  "timestamps": true,
  "linkLength": 5,
  "linkExtensions": false,
  "logLevel": 2,
  "maxFileSize": 0,
  "updateInterval": 1000,
  "pollingInterval": 0,
  "keepAlive": 20000,
  "allowFrame": false,
  "readOnly": false,
  "ignorePatterns": [],
  "watch": true,
  "headers": {}


  • listeners Array - Defines on which network interfaces, port and protocols the server will listen. See listener options below. listeners has no effect when droppy is used as a module. The default listens on HTTP port 8989 on all interfaces and protocols.
  • public boolean - When enabled, no user authentication is performed. Default: false.
  • timestamps boolean - When enabled, adds timestamps to log output. Default: true.
  • linkLength number - The amount of characters in a shared link. Default: 5.
  • linkExtensions boolean - Whether shared links should include the file extension. This can be used to allow other software to make a guess on the content of the file without actually retrieving it. Default: false.
  • logLevel number - Logging amount. 0 is no logging, 1 is errors, 2 is info (HTTP requests), 3 is debug (Websocket communication). Default: 2.
  • maxFileSize number - The maximum file size in bytes a user can upload in a single file. 0 means no limit. Default: 0.
  • updateInterval number - Interval in milliseconds in which a single client can receive update messages through changes in the file system. Default: 1000.
  • pollingInterval number - Interval in milliseconds in which the file system is polled for changes, which may necessary for files on external or network-mapped drives. Corresponds to chokidar's usePolling option. This is CPU-intensive. 0 disables polling. Default: 0.
  • keepAlive number - Interval in milliseconds in which the server sends websocket keepalive messages, which may be necessary when proxies are involved. 0 disables keepalive messages. Default: 20000.
  • uploadTimeout number - Request timeout for upload requests in milliseconds. Default: 604800000 which is 7 days.
  • allowFrame boolean - Allow the page to be loaded into a <frame> or <iframe>. Default: false.
  • readOnly boolean - Treat all files as being read-only. Default: false.
  • dev boolean - Enable developer mode, skipping resource minification and enabling live reload. Default: false.
  • ignorePatterns Array - Array of file path glob patterns to ignore when indexing files. See here for supported patterns. Default: [].
  • watch boolean - Whether to watch the local file system for changes. Disabling this may improve performance when dealing with a large number of files, but with the downside that changes not done via droppy won't be detected. Default: true.
  • headers Object: A object with key-value pairs of custom HTTP headers to set on all responses, for example {"Access-Control-Allow-Origin": "*"}. Default: {}.

Listener Options

listeners defines on which network interfaces, ports and protocol(s) the server will listen. For example:

"listeners": [
    "host": "::",
    "port": 80,
    "socket": "/tmp/droppy",
    "protocol": "http"
    "host": "",
    "port": 443,
    "protocol": "https",
    "key": "~/certs/example.com.key",
    "cert": "~/certs/example.com.crt"

The above configuration will result in:

  • HTTP listening on all IPv4 and IPv6 interfaces, port 80 and on the unix domain socket /tmp/droppy.
  • HTTPS listening on all IPv4 interfaces, port 443 using the provided TLS files.

A listener object accepts these options:

  • host string/Array - Network interface(s) addresses to listen on. Required when port is given. Note that "::" will typically bind to both IPv4 and IPv6 on all addresses but a "" address might be required if IPv6 is disabled.
  • port number/string/Array - Network port(s) to listen on. Required when host is given.
  • socket string/Array - Unix domain socket(s) to listen on.
  • protocol string - Protocol to use, http or https. Required.

For TLS the following additional options are available. Paths can be given relative to the configuration directory and ~ is resolved as expected.

  • cert string - Path to PEM-encoded TLS certificate file, which can include additional intermediate certificates concatenated after the main certificate. Required.
  • key string - Path to PEM-encoded TLS private key file not encrypted with a passphrase. Required.

Downloading from the command line

To download shared links with curl and wget to the correct filename:

$ curl -OJ url
$ wget --content-disposition url


To start a live-reloading dev server:

$ git clone https://github.com/silverwind/droppy && cd droppy
$ npm i
$ node droppy start --dev

The Makefile has a few tasks for updating dependencies, pushing docker images, see the comment above for dependencies of those tasks.

© silverwind, distributed under BSD licence.

  • Global installation and update feature

    Global installation and update feature

    The current installation method has a pretty bad downside that npm can't update the package when they doesn't reside in a node_modules parent directory. I'll test global installation, which ideally should make the update process just be npm update -g droppy, and the installation npm install -g droppy.

    Global installation puts the module in something like /usr/local/lib/node_modules/ (Unix) or %appdata%/npm/node_modules (Windows). Maybe we should change our default files folder to something more rememberable.

    opened by silverwind 40
  • systemd service keeps failing

    systemd service keeps failing

    Everything worked fine for long time until two weeks ago when I discovered the systemd service continuously failing

    # systemctl restart droppy
    # systemctl status droppy
    * droppy.service - droppy
       Loaded: loaded (/etc/systemd/system/droppy.service; enabled; vendor preset: disabled)
       Active: active (running) since Sat 2017-08-05 13:12:16 CEST; 2s ago
     Main PID: 416 (node)
        Tasks: 6 (limit: 4915)
       CGroup: /system.slice/droppy.service
               `-416 node /usr/sbin/droppy start -c /srv/droppy/config -f /srv/droppy/files
    # systemctl status droppy
    * droppy.service - droppy
       Loaded: loaded (/etc/systemd/system/droppy.service; enabled; vendor preset: disabled)
       Active: failed (Result: exit-code) since Sat 2017-08-05 13:12:21 CEST; 783ms ago
      Process: 416 ExecStart=/usr/bin/env droppy start -c /srv/droppy/config -f /srv/droppy/files (code=exited, status=1/FAILURE)
     Main PID: 416 (code=exited, status=1/FAILURE)
    Aug 05 13:12:21 xxxx systemd[1]: droppy.service: Main process exited, code=exited, status=1/FAILURE
    Aug 05 13:12:21 xxxx systemd[1]: droppy.service: Unit entered failed state.
    Aug 05 13:12:21 xxxx systemd[1]: droppy.service: Failed with result 'exit-code'.

    But if I start it as droppy start -c /srv/droppy/config -f /srv/droppy/files everything works fine.

    System info:

    # uname -a
    Linux skydata 4.9.40-1-ARCH #1 SMP Tue Aug 1 00:59:10 UTC 2017 armv7l GNU/Linux
    # npm -v
    # node -v

    P.S. I followed the wiki to configure the service

    opened by platipo 39
  • Express binding

    Express binding

    Would it be how easy to modify this application so that it can be used also with existing expressjs app ? Usage could be something like this:

    var express = require('express');
    var Droppy = require('droppy');
    var app = express();
    app.use( new Droppy(..)  )
    Client Feature Server 
    opened by jupe 38
  • Zipping broken

    Zipping broken

    Looking into it.

    Bug Server 
    opened by silverwind 33
  • Templating


    I would really appreciate using a templating library for client-side document view generation so styling is easier to understand and the DOM construction stuff is separated from the script.

    I would also imagine that having a templating library would make view generation faster.

    I recently saw a new client-side templating library known as Nunjucks. Which will probably be implemented using precompiling. Nunjucks use of for loops in templates means that it should be even easier to create directory views.

    Otherwise, iCanHaz.js is always a favorite of mine, as it is easy to learn and should not require any extra build code.

    Client Feature Server 
    opened by colelawrence 30
  • Improve drag and drop UX

    Improve drag and drop UX

    D&D needs a few more improvements:

    • ~~Allow dropping a file/folder on another folder so it can be moved into the target folder~~
    • ~~Don't show indication arrow when dropping a file into the same folder, except for copying~~
    • Show an indicator before the drop if a file will be moved or copied
    Client Feature 
    opened by silverwind 29
  • Droppy is not working on safari

    Droppy is not working on safari

    The web UI cannot render correctly. Tested on iOS and OSX.

    opened by txchen 27
  • Direct download not working

    Direct download not working

    I have installed droppy in my Raspberry Pi 2 and connected an HHD. I noticed that when I try to download using the download button any file (even folders) the output always is a 18.23 kb file (hexdump output is the same for every downloaded file). sample: doc.zip

    Unlike the download button the share button retrive files correctly.

    node -v
    opened by platipo 27
  • Consistent coding style suggestions

    Consistent coding style suggestions

    For consistency and cleanliness, I'd like to enforce these on the whole codebase:

    • [ ] Move var declarations to the top of their function scope, wherever possible
    • [x] No increment/decrement operator
    • [x] No for .. in, use Object.keys(obj).forEach
    • [x] Double quotes for all strings (Once everything is templated)
    • [x] Remove classic for statements in favor of forEach where possible

    There may be more, but these should be a good base set. I'll also change the relevant JSHint options to warn for this stuff. Hopefully, these will save us from a few future bugs :)

    Client Server 
    opened by silverwind 25
  • Is websocket a requirement?

    Is websocket a requirement?

    I see droppy is using websocket, but is there any fallback for a browser does not support websocket?

    opened by t-k- 25
  • Cannot download file containng hashtag # in filename

    Cannot download file containng hashtag # in filename

    As per Subject, files containing an hashtag in the filename (like "Comics #10.pdf") cannot be downloaded. In docker logs I receive a 404 because the filename it looks for gets truncated at the hash (so it tries to download "Comics ") Using droppy:latest in docker on a raspberry pi4 with ubuntu srv 64bit.

    Thanks for the great software! Bye

    opened by risidoro81 0
  • nginx reverse proxy websocket

    nginx reverse proxy websocket

    I want to use droppy with my reverse proxy in nginx but I get a websocket error, but not when I use the direct IP and port

    client.js:27 WebSocket connection to 'ws://droppy.domain.com/!/socket' failed: Error during WebSocket handshake: Unexpected response code: 307

    nginx config file

    events {
    http {
      server {
          listen 80;
          server_name droppy.domain.com;
          access_log /var/log/nginx/droppy.log;
          error_log /var/log/nginx/droppy-error.log;
          location / {
              proxy_pass http://ip:8989;

    droppy conf

      "listeners": [
          "host": [
          "port": 8989,
          "socket": "/tmp/droppy",
          "protocol": "http"
      "public": true,
      "timestamps": true,
      "linkLength": 5,
      "linkExtensions": false,
      "logLevel": 2,
      "maxFileSize": 0,
      "updateInterval": 1000,
      "pollingInterval": 0,
      "keepAlive": 20000,
      "uploadTimeout": 604800000,
      "allowFrame": false,
      "readOnly": false,
      "ignorePatterns": [],
      "watch": true,
      "headers": {}


    version: '3.7'
        container_name: droppy
        image: silverwind/droppy
          - UID=1000
          - GID=1000
          - '8989:8989'
          - /mnt/sdb/droppy/config:/config
          - /mnt/sdb/droppy/data:/files
        restart: unless-stopped
    opened by antoinebou13 0
  • Proxy behind Authelia and nginx Proxy Manager

    Proxy behind Authelia and nginx Proxy Manager

    I'm trying to place droppy behind Authelia and NPM but can't get it to work.

    I followed the proxy guide and can get it to work without Authelia, but I don't know how to change it to also work with Authelia.

    This is the template code I'm using for alll the other endpoints:

    location /authelia {
        set $upstream_authelia http://SERVERIP:9091/api/verify;
        proxy_pass_request_body off;
        proxy_pass $upstream_authelia;    
        proxy_set_header Content-Length "";
        # Timeout if the real server is dead
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
        client_body_buffer_size 128k;
        proxy_set_header Host $host;
        proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr; 
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Uri $request_uri;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_redirect  http://  $scheme://;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_cache_bypass $cookie_session;
        proxy_no_cache $cookie_session;
        proxy_buffers 4 32k;
        send_timeout 5m;
        proxy_read_timeout 240;
        proxy_send_timeout 240;
        proxy_connect_timeout 240;
        location / {
            proxy_pass $upstream_CONTAINERNAME;
    		auth_request /authelia;
    		auth_request_set $target_url $scheme://$http_host$request_uri;
    		auth_request_set $user $upstream_http_remote_user;
    		auth_request_set $groups $upstream_http_remote_groups;
    		proxy_set_header Remote-User $user;
    		proxy_set_header Remote-Groups $groups;
    		error_page 401 =302 https://auth.YOURDOMAIN.com/?rd=$target_url;
    		client_body_buffer_size 128k;
    		proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
    		send_timeout 5m;
    		proxy_read_timeout 360;
    		proxy_send_timeout 360;
    		proxy_connect_timeout 360;
    		proxy_set_header Host $host;
    		proxy_set_header X-Real-IP $remote_addr;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header X-Forwarded-Proto $scheme;
    		proxy_set_header X-Forwarded-Host $http_host;
    		proxy_set_header X-Forwarded-Uri $request_uri;
    		proxy_set_header X-Forwarded-Ssl on;
    		proxy_redirect  http://  $scheme://;
    		proxy_http_version 1.1;
    		proxy_set_header Connection "";
    		proxy_cache_bypass $cookie_session;
    		proxy_no_cache $cookie_session;
    		proxy_buffers 64 256k;
    		real_ip_header X-Forwarded-For;
    		real_ip_recursive on;
    opened by nousrfound 0
  • [Feature Request] - Dark Theme

    [Feature Request] - Dark Theme

    It would be nice if there was an option to change the color scheme to something darker.

    opened by PriamX 1
  • Possible setting to change url scheme to include file name?

    Possible setting to change url scheme to include file name?

    I would like an option to have the file name in the url like this https://droppy.example.com/myfile.txt or https://droppy.example.com/$/myfile.txt instead of something like https://droppy.example.com/$/JAJSi

    opened by wolfy01 0
  • [Feature Request] - user rights

    [Feature Request] - user rights

    1. user rights
    • normal user is not allowed to delete files by other user
    • only the administrator can delete the data of others

    cool software, by the way. waiting for a new version

    opened by welon68 0
  • Fix follow symlinks

    Fix follow symlinks

    Fixes #437

    It looks like rrdir used to follow symlinks by default and now doesn't so updating it in 12.0.0 broke that. This PR adds the followSymlinks option to make it follow symlinks again.

    I don't know if it should also be added there: https://github.com/silverwind/droppy/blob/master/server/server.js#L1399.

    opened by pdonias 0
  • Change font size

    Change font size

    Hi there!

    Is possible to change the font size? Currently it is pretty huge.


    opened by monkiki 0
  • dockerfile improvements

    dockerfile improvements

    Here you have a good improvement to create the container you will not need to build cache first or copy node_modules/ folder to created the container

    opened by buster95 0
  • Request for package add

    Request for package add

    Please add curl to the baseline image. This allows for a healthcheck script to be executed and gives a 200 response from the server.

    opened by roadrage999 0
**ARCHIVED** Self-hosted file storage

Development on droppy has ceased because I don't have enough time or motivation to properly support it and because of its outdated technology stack, i

null 1.6k Jun 2, 2021
Self-hosted file/code/media sharing website. ~~~~~~~~~~~~~~~~~~~ Demo: https://demo.linx-server.net/

Development on this repository has been frozen. Feel free to send a pull request if you are maintaining an active fork of this project to add a link t

Andrei Marcu 1.1k Jun 10, 2021
Syncany is a cloud storage and filesharing application with a focus on security and abstraction of storage.

Syncany The core team of Syncany is on hiatus for an indefinite amount of time. Feel free to do with the code what the license allows and encourages,

Syncany 1.6k May 18, 2021
Zenko CloudServer, an open-source Node.js implementation of the Amazon S3 protocol on the front-end and backend storage capabilities to multiple clouds, including Azure and Google.

Zenko CloudServer Overview CloudServer (formerly S3 Server) is an open-source Amazon S3-compatible object storage server that is part of Zenko, Scalit

Scality 1.2k Jun 2, 2021
Powerful Multi-User File Manager

FileGator - Powerful Multi-User File Manager FileGator is a free, open-source, self-hosted web application for managing files and folders. You can man

FileGator 689 Jun 9, 2021
Node.js and mongoDB Google Drive Clone

MyDrive MyDrive is an Open Source cloud file storage server (Similar To Google Drive). Host myDrive on your own server or trusted platform and then ac

null 2.4k Jun 9, 2021
High Performance, Kubernetes Native Object Storage

MinIO Quickstart Guide MinIO is a High Performance Object Storage released under Apache License v2.0. It is API compatible with Amazon S3 cloud storag

High Performance, Kubernetes Native Object Storage 28k Jun 3, 2021
A lightweight file manager with full ShareX, Screencloud support and more

XBackBone is a simple, self-hosted, lightweight PHP file manager that support the instant sharing tool ShareX and *NIX systems. It supports uploading

Sergio Brighenti 399 Jun 7, 2021
Files sharing application made in PHP

Files Sharing Powered by Laravel Description This PHP application based on Laravel 5.4 allows to share files like Wetransfer. You may install it on yo

null 34 Jun 6, 2021
Gluster Filesystem : Build your distributed storage in minutes

Gluster Gluster is a software defined distributed storage that can scale to several petabytes. It provides interfaces for object, block and file stora

Gluster.org 3.1k Jun 12, 2021
Open source PHP/Ajax cloudware that puts FTP file management right in your browser, anywhere, any time.

################################### !!! THIS SCRIPT IS NOW ARCHIVED !!! ################################### THIS VERSION IS NO LONGER SUPPORTED AS VE

Monsta 120 Apr 13, 2021
Autonomous (self-hosted) BitTorrent DHT search engine suite.

magnetico Autonomous (self-hosted) BitTorrent DHT search engine suite.    magnetico is the first autonomous (self-hosted) BitTorrent DHT search engine

Bora M. Alper 2.5k Jun 9, 2021
Perkeep (née Camlistore) is your personal storage system for life: a way of storing, syncing, sharing, modelling and backing up content.

Perkeep is your personal storage system. It's a way to store, sync, share, import, model, and back up content. Keep your stuff for life. For more, see

Perkeep (née Camlistore) 5.5k Jun 9, 2021
☁️ Cloud Torrent: a self-hosted remote torrent client

Cloud torrent is a a self-hosted remote torrent client, written in Go (golang). You start torrents remotely, which are downloaded as sets of files on

Jaime Pillora 4.9k Jun 12, 2021