GithubHelp home page GithubHelp logo

neztore / save-server Goto Github PK

View Code? Open in Web Editor NEW
28.0 0.0 13.0 539 KB

ShareX File Server built with NodeJS

Home Page: https://i.nezto.re

License: MIT License

CSS 3.58% JavaScript 69.75% EJS 26.19% Dockerfile 0.48%
sharex sqlite3 image host expressjs nodejs hacktoberfest

save-server's Introduction

Banner

save-server

NPM version

Save-Server is a server for the ShareX tool built on NodeJS, Bulma and SQLite.

It is a little more heavy duty than other versions as it uses SQLite, allowing for "users" and for files to be filtered by owner, which is something I wanted. Another interesting feature is that it fetches files based purely on their name and ignores the file extension. This means you could upload a txt file but have it render as Javascript, for example.

Features

  • User system allows for user-specific filtering
  • Admin dashboard
  • Automatic ShareX configuration
  • Markdown and code rendering, with syntax highlighting
  • Flexible extensions (Files are identified by the name, extension is ignored)

Demo/Example (My instance): https://i.nezto.re.

Setting up

Prerequisites

Before setting up save-server, you should:

  • Install NodeJS
  • (Optional) Install NGINX

1: Installing

Clone from GitHub

Use the command line program git:

$ git clone https://github.com/neztore/save-server

or, you can click Download on this page and then unzip it. Then, you need to install depdencies:

$ cd save-server
$ npm install

Install from NPM

Alternatively, you can install it from NPM:

$ npm install save-server

2: Running and configuring the server

The only configuration value that needs to be passed is the port which the application should run on. By default, it listens on port 80 (http port). To run the server, there are two ways. Regardless of which method you use to run it, you can provide the port through the port environment variable. For servers with a lot of images or users, you may wish want to increase the length of the file name to prevent conflicts. Use the environment variable nameLength to do this - it defaults to 6.

Run npm start to do this. For when this is running in production, you should use a process manager such as pm2, which can also take care of environment variables for you.

2.1: Using "npm start"

This method is better suited if you cloned the server from GitHub. Just run npm start while in the project directory, or configure your process manager to do so. Port can be configured by the setting the port environment variable.

2.2: Requiring the package

This method is generally for if you choose to download this package from NPM. You can require the package, which exports a function. This function then takes a single value, the port to run on, which is passed to express. If this doesn't suit, you can also require and use the port environment variable.

Example code
const saveServer = require("save-server");
saveServer(3000)

2.3: Using Docker

The project contains a Dockerfile for building and running the server in a Docker container. You can set the build-time variables port and nameLength to configure these as mentioned previously. The image will inform Docker that it listens on the port specified by the build-time variable (80 by default).

A Docker bind mount is required to persist the database located at server/util/save-server-database.db. Additionally, a Docker volume mounted at /usr/src/app/uploads is required in order to persist uploaded files. You can create a volume with docker volume create save-server-uploads (following examples assume a volume named save-server-uploads).

The following will build an image with default values, and run a container in the background (-d) with port 80 (default server port) in the container mapped to port 80 on the host:

docker build -t save-server .
docker run -dp 80:80 -v "$(pwd)"/server/util/save-server-database.db:/usr/src/app/server/util/save-server-database.db -v save-server-uploads:/usr/src/app/uploads save-server

The following will build an image with port set to 3000, nameLength to 8, and publish port 3000 in the container to port 80 on the host:

docker build -t save-server --build-arg port=3000 nameLength=8 .
docker run -dp 80:3000 -v "$(pwd)"/server/util/save-server-database.db:/usr/src/app/server/util/save-server-database.db -v save-server-uploads:/usr/src/app/uploads save-server

See the Docker documentation for more information on Docker.

2.4 Changing the root password

You must change the root password, otherwise this installation will be horrifically insecure.

Once you have the server running, open the dashboard and login to the root account with the following details:

  • Username: root
  • Password: saveServerRoot You should then navigate to the settings page using the left panel and then update your password. Once you've done this, use the Create user button to create a new user.

Configuring ShareX

For easy configuration, this server comes with a config generator. Just access it on the domain you'd like to use, go to the settings of the user who's config you'd like to download, and click one of the download buttons. The file config allows you to upload files such as images and markdown files, while the URL config allows you to add a link shortener.

Additional set-up

I recommend that you install a reverse proxy such as nginx, and with letsencrypt you can set up free https support. Please note that you must ensure that your proxy passes the host and X-Forwarded-Proto headers at a minimum. Express will trust these as it is set to trust proxies by default.

Example NGINX configuration:

server {
    listen 80;
    server_name example.com www.example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

Environment variables

Name Type Default Desc
port number 80 Defines the port Save-Server will listen on.
cloudflare_limiting boolean false Set to true to require the use of Cloudflare, so connecting_ip exists. If you use Cloudflare and do not enable this, rate limiting may not function as expected.

About

Each user is allocated a token. This token is used both to authenticate ShareX uploads and web panel access, through a cookie. This server features a rest API.

The SQLite database is included here for ease, but the root user is created at run time if it is not detected. You can find the SQL statements to create the statement tables should you wish to, for whatever reason, in create.sql.

You can manually explore the SQLite data using a variety of tools, my favourite of which is the SQLite browser.

A note on passwords

We use Bcrypt to hash passwords. This is timing attack-safe, but this algorithm only makes use of the first 72 bytes of your password. The server will not accept passwords longer than 100 characters, and a warning will be displayed - but be aware of this! Encoding dependent, 72 bytes is roughly equal to 72 characters.

Getting help

To get help setting this up, or if you encounter any issues you can:

  1. Open an issue in the Issues section of the GitHub repository.
  2. Email me: [email protected]

save-server's People

Contributors

dependabot[bot] avatar eirikfa avatar neztore avatar reduxgb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

save-server's Issues

URL shortener doesn't work from ShareX

I've setup your script with an Nginx proxy, everything seems to be working fine, but when I tried out the URL shortener, it appears I receive the following response:

{
	"error" : {
		"status" : 400,
		"message" : "Failed CSRF Token validation"
	}
}

Is this a bug or am I doing something wrong? Here's my Nginx config:

server {
        server_name cdn.hostbend.com www.cdn.hostbend.com;

        location / {
                proxy_pass http://127.0.0.1:3000;
                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;
        }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/cdn.hostbend.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/cdn.hostbend.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
    if ($host = www.cdn.hostbend.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = cdn.hostbend.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80;
        server_name cdn.hostbend.com www.cdn.hostbend.com;
    return 404; # managed by Certbot




}

I first tried this in ShareX and received an error, and so I investigated further with Postman and that's where I discovered the error response.

Improve loading

This is especially obvious when navigating pages, there is a large delay before a collection of images appear.
The images from the previous page remain during this loading time.

Could be offset by loading images with a small delay in between, or one row at a time.

Issue Deleting User

When deleting a user and content then recreating a user, ghosts of the past uploads exist.

Reset root password

Sometimes (in my case today) root password need to be reset without removing other users. Is there a way to reset it to defaults (for example env variable)?

Incorrect upload time

Describe the bug
When clicking on a recently (<1 minute ago) uploaded image, the text under it says it was uploaded 2 hours ago.

To Reproduce
Steps to reproduce the behavior:

  1. Upload an image
  2. Enter the dashboard
  3. Click on the image you just uploaded
  4. Text states username and "2 hours ago"

Expected behavior
Text under image says "just now" / whatever time ago it was actually uploaded

Screenshots
thing

Additional context

  • Browser: Firefox 88.0

I think this may be caused by something timezone-y. My server's timezone is set to CEST, which I'm also in, so this should be correct.

CSRF token validation error

Hi there! This error occurs when attempting to delete an image from iOS Safari.
image

I've attempted logging in again, yielding no results. So far, I haven't had this issue on desktop.

Some helpful information;

  • saveserver 1.2.0

  • running on node 12.18.3

  • server on Ubuntu 18.04

  • iOS 14.2

  • iPhone 7

Same issue both using 4G and WiFi.

Server throws in production when running without Cloudflare

Server throws here when running with NODE_ENV set to production and not using Cloudflare, effectively making Cloudflare mandatory.

To Reproduce

  1. Start the project with NODE_ENV set to production: NODE_ENV=production npm start (on Linux)
  2. Try to access the server, will see a 500 "No Cloudflare IP available"

Expected behavior
Project works without using Cloudflare.

Can probably be fixed by changing this snippet to

const ip = req.get("CF-Connecting-IP");
if (!ip) {
  return req.ip;
}

This will support Cloudflare but fall back instead of throwing an error in production. Alternatively, to only support Cloudflare in production, one could do

const ip = req.get("CF-Connecting-IP");
if (!ip || NODE_ENV !== "production") {
  return req.ip;
}

(413) Payload Too Large.

Describe the bug
When I try uploading a file around 1MB or more it does not let me, some screenshots also give this error.

To Reproduce

  1. Get a 1MB file or bigger.
  2. Upload the file and it will give you the error.

Expected behavior
The file should upload normally.

Screenshots
image

Additional context
Latest ShareX version.

Slow Download

I'm trying this script with a large 5GB file and it uploaded really fast in ShareX. Compared to another upload script in PHP, this one is processed by the server instantly which is very nice. Although I am having some trouble with downloading speeds. On the PHP app, I get 30MB/s but here it seems locked at 1.2MB/s. Is there a bottleneck somewhere?

nameLength is broken.

Describe the bug
When I try set nameLength to 32 using an environment variable it gives me a link which does not work.

To Reproduce
Steps to reproduce the behavior:

  1. Start save-server using nameLength=32 node index.js
  2. Take a screenshot
  3. Try view the screenshot

Expected behavior
You should be able to view the screenshot you just took.

Screenshots
image
image
image

Additional context
The image shows up on the gallery with an empty image and is unable to be deleted.

Pagination

The gallery cannot display all files/images at present, and pagination would be a good addition for perf/slow internet too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.