├── .dockerignore ├── .editorconfig ├── .eslintrc ├── .gitattributes ├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── .ignore ├── .stylelintrc ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── client ├── client.js ├── cmtheme.css ├── images │ ├── logo.svg │ ├── logo120.png │ ├── logo128.png │ ├── logo152.png │ ├── logo180.png │ ├── logo192.png │ ├── logo32.png │ ├── readme-logo.svg │ └── sprites.png ├── index.html ├── jquery-custom.min.js ├── sprites.css ├── style.css ├── svg │ ├── add-file.svg │ ├── add-folder.svg │ ├── arrow.svg │ ├── arrows-h.svg │ ├── arrows-v.svg │ ├── check.svg │ ├── code.svg │ ├── cog.svg │ ├── copy.svg │ ├── create-file.svg │ ├── create-folder.svg │ ├── cross.svg │ ├── disk.svg │ ├── download.svg │ ├── exclamation.svg │ ├── eye.svg │ ├── find.svg │ ├── fullscreen.svg │ ├── github.svg │ ├── home.svg │ ├── info.svg │ ├── link.svg │ ├── logo.svg │ ├── loop.svg │ ├── menu.svg │ ├── next.svg │ ├── open.svg │ ├── paste.svg │ ├── pause.svg │ ├── pencil.svg │ ├── play.svg │ ├── plus.svg │ ├── previous.svg │ ├── reload.svg │ ├── rename.svg │ ├── scissors.svg │ ├── shuffle.svg │ ├── signin.svg │ ├── signout.svg │ ├── skip.svg │ ├── spinner.svg │ ├── stop.svg │ ├── trash.svg │ ├── triangle.svg │ ├── unfullscreen.svg │ ├── up-arrow.svg │ ├── upload-cloud.svg │ ├── user-cog.svg │ ├── user.svg │ ├── volume-high.svg │ ├── volume-low.svg │ ├── volume-medium.svg │ ├── volume-mute.svg │ ├── window-cross.svg │ ├── window.svg │ ├── wordwrap.svg │ ├── zoomin.svg │ └── zoomout.svg ├── templates │ ├── directory.hbs │ ├── document.hbs │ ├── file-header.hbs │ ├── list-user.hbs │ ├── login.hbs │ ├── main.hbs │ ├── media.hbs │ ├── new-file.hbs │ ├── new-folder.hbs │ ├── options.hbs │ ├── pdf.hbs │ ├── upload-info.hbs │ ├── video.hbs │ └── view.hbs └── tooltips.css ├── docker-start.sh ├── droppy.js ├── examples ├── Caddyfile └── docker-compose.yml ├── package.json ├── server ├── cfg.js ├── cookies.js ├── csrf.js ├── db.js ├── filetree.js ├── log.js ├── manifest.js ├── paths.js ├── resources.js ├── server.js ├── svg.js └── utils.js └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | examples 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | tab_width = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [LICENSE] 13 | indent_size = none 14 | 15 | [*.svg] 16 | insert_final_newline = false 17 | 18 | [Makefile] 19 | indent_style = tab 20 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | root: true 2 | extends: silverwind 3 | 4 | overrides: 5 | - files: ["client/**/*.js"] 6 | rules: 7 | prefer-arrow-callback: [2, {allowNamedFunctions: true, allowUnboundThis: true}] 8 | env: 9 | browser: true 10 | es6: true 11 | jquery: true 12 | globals: 13 | CodeMirror: false 14 | fileExtension: false 15 | Handlebars: false 16 | Mousetrap: false 17 | pdfjsLib: false 18 | PhotoSwipe: false 19 | PhotoSwipeUI_Default: false 20 | Plyr: false 21 | screenfull: false 22 | Uppie: false 23 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | test: 6 | strategy: 7 | fail-fast: false 8 | matrix: 9 | os: [macOS-latest, ubuntu-latest, windows-latest] 10 | node: ['12', '14'] 11 | 12 | runs-on: ${{ matrix.os }} 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: actions/setup-node@v1 16 | with: 17 | node-version: ${{ matrix.node }} 18 | - run: yarn -s 19 | - run: yarn -s test 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/ 2 | /dist/ 3 | /node_modules 4 | /npm-debug.log* 5 | /package-lock.json 6 | /yarn-error.log 7 | -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.min.js 3 | dist 4 | client/jquery* 5 | yarn.lock 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | extends: stylelint-config-silverwind 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:alpine 2 | MAINTAINER silverwind 3 | 4 | # Copy files 5 | COPY ["node_modules", "/droppy/node_modules"] 6 | COPY ["client", "/droppy/client"] 7 | COPY ["server", "/droppy/server"] 8 | COPY ["dist", "/droppy/dist"] 9 | COPY ["droppy.js", "docker-start.sh", "README.md", "LICENSE", "package.json", "/droppy/"] 10 | 11 | # Install build dependencies and and build modules 12 | RUN cd /droppy && \ 13 | find /droppy -type d -exec chmod 0755 {} + && \ 14 | find /droppy -type f -exec chmod 0644 {} + && \ 15 | chmod 0755 /droppy/docker-start.sh && \ 16 | chmod 0755 /droppy/droppy.js && \ 17 | mkdir -p /root/.droppy && \ 18 | ln -s /config /root/.droppy/config && \ 19 | ln -s /files /root/.droppy/files && \ 20 | ln -s /droppy/droppy.js /usr/bin/droppy && \ 21 | rm -rf \ 22 | /root/.config \ 23 | /root/.node-gyp \ 24 | /root/.npm \ 25 | /tmp/* \ 26 | /usr/lib/node_modules \ 27 | /usr/local/lib/node_modules \ 28 | /usr/local/share/.cache 29 | 30 | EXPOSE 8989 31 | VOLUME ["/config", "/files"] 32 | CMD ["/droppy/docker-start.sh"] 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) silverwind 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # os deps: node yarn git jq docker 2 | 3 | JQUERY_FLAGS:=-ajax,-css,-deprecated,-effects,-event/alias,-event/focusin,-event/trigger,-wrap,-core/ready,-deferred,-exports/amd,-sizzle,-offset,-dimensions,-serialize,-queue,-callbacks,-event/support,-event/ajax,-attributes/prop,-attributes/val,-attributes/attr,-attributes/support,-manipulation/support,-manipulation/var/rcheckableType 4 | 5 | dev: 6 | node droppy.js start --dev 7 | 8 | run: 9 | node droppy.js start 10 | 11 | lint: 12 | yarn -s run eslint server client/client.js droppy.js 13 | yarn -s run stylelint client/*.css 14 | 15 | test: lint 16 | 17 | build: 18 | @touch client/client.js 19 | node droppy.js build 20 | 21 | publish: 22 | if git ls-remote --exit-code origin &>/dev/null; then git push -u -f --tags origin master; fi 23 | if git ls-remote --exit-code git &>/dev/null; then git push -u -f --tags git master; fi 24 | npm publish 25 | 26 | docker: 27 | @rm -rf node_modules 28 | yarn -s --production --pure-lockfile 29 | $(eval IMAGE := silverwind/droppy) 30 | $(eval VERSION := $(shell cat package.json | jq -r .version)) 31 | $(eval ARCHS := "linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6") 32 | @docker rm -f "$$(docker ps -a -f='ancestor=$(IMAGE)' -q)" 2>/dev/null || true 33 | @docker rmi "$$(docker images -qa $(IMAGE))" 2>/dev/null || true 34 | @docker buildx rm builder &>/dev/null || true 35 | @docker buildx create --name builder --use &>/dev/null || true 36 | docker buildx build --pull --push --platform $(ARCHS) -t $(IMAGE):$(VERSION) . 37 | docker buildx build --pull --push --platform $(ARCHS) -t $(IMAGE):latest . 38 | @docker buildx rm builder &>/dev/null || true 39 | yarn 40 | 41 | deps: 42 | rm -rf node_modules 43 | yarn 44 | 45 | update: 46 | yarn -s run updates -u 47 | @$(MAKE) --no-print-directory deps 48 | @touch client/client.js 49 | 50 | jquery: 51 | rm -rf /tmp/jquery 52 | git clone --depth 1 https://github.com/jquery/jquery /tmp/jquery 53 | cd /tmp/jquery; yarn; yarn -s run grunt; yarn -s run grunt custom:$(JQUERY_FLAGS); yarn -s run grunt remove_map_comment 54 | cat /tmp/jquery/dist/jquery.min.js | perl -pe 's|"3\..+?"|"3"|' > $(CURDIR)/client/jquery-custom.min.js 55 | rm -rf /tmp/jquery 56 | 57 | ver-patch: 58 | yarn -s run versions -C patch 59 | 60 | ver-minor: 61 | yarn -s run versions -C minor 62 | 63 | ver-major: 64 | yarn -s run versions -C major 65 | 66 | patch: test build ver-patch docker publish 67 | minor: test build ver-minor docker publish 68 | major: test build ver-major docker publish 69 | 70 | .PHONY: dev run lint test publish docker deps update jquery version-patch version-minor version-major patch minor major 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **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.** 2 | 3 |

4 | 5 |

6 |

7 | 8 | 9 | 10 |

11 | 12 | **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. 13 | 14 | ## Features 15 | * Responsive, scalable HTML5 interface 16 | * Realtime updates of file system changes 17 | * Directory and Multi-File upload 18 | * Drag-and-Drop support 19 | * Clipboard support to create image/text files 20 | * Side-by-Side mode 21 | * Simple and fast Search 22 | * Shareable public download links 23 | * Zip download of directories 24 | * Powerful text editor with themes and broad language support 25 | * Image and video gallery with touch support 26 | * Audio player with seeking support 27 | * Fullscreen support for editor and gallery 28 | * Supports installing to the homescreen 29 | * Docker images available for x86-64, ARMv6, ARMv7 and ARMv8 30 | 31 | ## General Information 32 | Two directories will be used, one for configuration and one for the actual files: 33 | 34 | - `config`: defaults to `~/.droppy/config`, override with `-c /some/dir` 35 | - `files`: default `~/.droppy/files` override with `-f /some/dir` 36 | 37 | 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. 38 | 39 | ## Installation 40 | ### Local Installation :package: 41 | With [`Node.js`](https://nodejs.org) >= 12.10.0 installed, run: 42 | 43 | ```sh 44 | $ npm install -g droppy 45 | $ droppy start -c /srv/droppy/config -f /srv/droppy/files 46 | ``` 47 | 48 | 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: 49 | 50 | - [Systemd-based distributions](https://github.com/silverwind/droppy/wiki/Systemd-Installation) 51 | - [Debian (Pre-Jessie)](https://github.com/silverwind/droppy/wiki/Debian-Installation-(Pre-Jessie)) 52 | - [Nginx reverse proxy](https://github.com/silverwind/droppy/wiki/Nginx-reverse-proxy) 53 | - [Apache reverse proxy](https://github.com/silverwind/droppy/wiki/Apache-reverse-proxy) 54 | 55 | ### Docker installation :whale: 56 | 57 | The [`silverwind/droppy`](https://hub.docker.com/r/silverwind/droppy/) multi-arch images supports `amd64`, `arm64`, `arm/v7` and `arm/v6` architectures. To pull and run, use: 58 | 59 | ```sh 60 | $ docker run --name droppy -p 127.0.0.1:8989:8989 silverwind/droppy 61 | ``` 62 | 63 | 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. 64 | 65 | To update a docker installation, run 66 | 67 | ```sh 68 | $ docker pull silverwind/droppy 69 | $ docker stop droppy && docker rm droppy 70 | $ docker run --name droppy -p 127.0.0.1:8989:8989 silverwind/droppy 71 | ``` 72 | 73 | ### docker-compose 74 | Alternatively, you can use the example [`docker-compose.yml`](https://github.com/silverwind/droppy/blob/master/examples/docker-compose.yml): 75 | 76 | ```sh 77 | $ curl -O https://raw.githubusercontent.com/silverwind/droppy/master/examples/docker-compose.yml 78 | $ docker-compose up 79 | ``` 80 | This example `docker-compose.yml` uses the subdirectories `config` and `files` of the current working directory for storing data. 81 | 82 | ### Caddy 83 | 84 | See the example [Caddyfile](examples/Caddyfile). 85 | 86 | ## Configuration 87 | 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: 88 | 89 | ```javascript 90 | { 91 | "listeners" : [ 92 | { 93 | "host": ["0.0.0.0", "::"], 94 | "port": 8989, 95 | "protocol": "http" 96 | } 97 | ], 98 | "public": false, 99 | "timestamps": true, 100 | "linkLength": 5, 101 | "linkExtensions": false, 102 | "logLevel": 2, 103 | "maxFileSize": 0, 104 | "updateInterval": 1000, 105 | "pollingInterval": 0, 106 | "keepAlive": 20000, 107 | "allowFrame": false, 108 | "readOnly": false, 109 | "ignorePatterns": [], 110 | "watch": true, 111 | "headers": {} 112 | } 113 | ``` 114 | 115 | ## Options 116 | - `listeners` *Array* - Defines on which network interfaces, port and protocols the server will listen. See [listener options](#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. 117 | - `public` *boolean* - When enabled, no user authentication is performed. Default: `false`. 118 | - `timestamps` *boolean* - When enabled, adds timestamps to log output. Default: `true`. 119 | - `linkLength` *number* - The amount of characters in a shared link. Default: `5`. 120 | - `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`. 121 | - `logLevel` *number* - Logging amount. `0` is no logging, `1` is errors, `2` is info (HTTP requests), `3` is debug (Websocket communication). Default: `2`. 122 | - `maxFileSize` *number* - The maximum file size in bytes a user can upload in a single file. `0` means no limit. Default: `0`. 123 | - `updateInterval` *number* - Interval in milliseconds in which a single client can receive update messages through changes in the file system. Default: `1000`. 124 | - `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](https://github.com/paulmillr/chokidar#performance) option. This is CPU-intensive. `0` disables polling. Default: `0`. 125 | - `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`. 126 | - `uploadTimeout` *number* - Request timeout for upload requests in milliseconds. Default: `604800000` which is 7 days. 127 | - `allowFrame` *boolean* - Allow the page to be loaded into a `` or `