The filesharing service everyone either hates or loves
Go to file
Volkor d8047d8b74
fix up metrics
2022-05-06 22:16:04 +10:00
QuadFile change times to unix time 2022-04-30 02:04:20 +10:00
ansible Add Metrics 2022-04-29 13:45:26 +00:00
quadfile-theme@ef4e40ec1c huh 2022-04-27 21:27:42 +10:00
theme Thanks AB49K 2021-10-20 12:01:37 +11:00
.gitignore Add Metrics 2022-04-29 13:45:26 +00:00
.gitlab-ci.yml add ssh keys to gitignore along with fixing ansible command 2020-05-28 04:07:35 +10:00
.gitmodules add git modules 2020-05-24 03:47:14 +10:00 Updated to match 2016-02-02 21:48:51 +01:00 Add Metrics 2022-04-29 13:45:26 +00:00 Initial move from Hyozan 2015-12-23 14:11:38 +01:00 fix 403 2022-04-29 23:59:04 +10:00
requirements.txt Add Metrics 2022-04-29 13:45:26 +00:00 fix up metrics 2022-05-06 22:16:04 +10:00
schema.sql Add Metrics 2022-04-29 13:45:26 +00:00
statsschema.sql Add Metrics 2022-04-29 13:45:26 +00:00 Add Gunicorn entry point 2016-02-01 11:29:47 +01:00

QuadFile Version 2

A temporary (or permanent, depending on configuration) file sharing service written in Flask.


  • Automatically remove files that aren't accessed often enough
  • Supports all filetypes, with options to filter by file extension
  • Prevents duplicate filenames
  • Works on all platforms (as long as they can use basic JavaScript)
  • Both easy to set up and use
  • Threaded for effective use of resources (Unless you're not on SSD, in which case, enjoy your I/O clogs m8)
  • Color-coded and real-time console log
  • Easy to use with most applications, such as ShareX


Ignore the submodules directory, this is for my instance.


  • Python 3
  • sqlite3 package for your OS (To create the database)
  • Install the python requirements with (pip install -r requirements.txt)
  • nginx or another reverse proxy.


  • nginx, great for proxy_pass
  • gunicorn, allows you to use QuadFile with multiple workers

Using the thing

When deletion keys are enabled, you must either use the curl-supported 'api' or use the web browser to delete files. (Notice: these have been barely tested. Use at your own risk!)
To get your deletion key, either upload through curl, or through the web browser, it's the 16 character long random string.

  • API: curl -F key=KEYINHERE https://QUADFILE.WEBSITE/delete
  • WEB: Browse to https://QUADFILE.WEBSITE/delete/KEYINHERE

Test deployment

  • Clone the repo somewhere
  • pip install -r requirements.txt
  • Do cp
  • Edit so that the information is correct
  • sqlite3 files.db < schema.sql
  • chmod +x and then ./
  • ???
  • PROFIT (Hopefully)

Production deployment

  • Clone the repo somewhere
  • Set up a virtual environment for QuadFile
  • pip install -r requirements.txt
  • Do cp
  • Edit so that the information is correct
  • sqlite3 files.db < schema.sql
  • gunicorn wsgi:app -w 4 --bind --log-file $HOME/quadfile.log (Use systemd service to run it on boot if needed)
  • Configure nginx and proxy_pass it to gunicorn
  • ???
  • PROFIT (Hopefully)
  • Edit the pages in templates/*.html to personalize

Ansible Production Deployment (debian derivatives only)

This deploys quadfile automatically, listening on 8282, localhost only so you can manually setup nginx youself.

This creates the systemd service, along with a new user quadfile. It is installed by default to /opt/quadfile

Ensure the correct key is listed in known_hosts (ssh in with fowarding yourself, using -A and ssh into your git)

  1. Duplicate this repo, or fork it.
  2. In gitlab, add a new private key to the SSH_PRIVATE_KEY environment variable
    1. Also add the other ansible variables
  3. locally, ssh-copy-id -i <new/id_rsa> <host> copy the public key to the server
  4. [OPTIONAL] Create a submodule for your theme (make it public for the love of god, if you still want private, read here and add the pubkey to the deploy key on gitlab)
  5. setup ci
  6. run pipeline

systemd service file

Make sure to replace user with whatever user you want to run quadfile with (I reccomend a seperate user)

Description=QuadFile + Gunicorn Server

PermissionsStartOnly = true
User = user
Group = user
WorkingDirectory = /home/user/prod/QuadFile/

ExecStart = /usr/bin/gunicorn3 wsgi:app -w 8 --bind --log-file /home/user/logs/quadfile/quadfile.log --capture-output --error-log /home/user/logs/quadfile.log
ExecReload = /bin/kill -s HUP $MAINPID
ExecStop = /bin/kill -s TERM $MAINPID

WantedBy =

nginx config files

To have dynamic domain support, you must pass through a few things ontop of 'just proxy_pass it to gunicorn'.
This example includes a permenant redirect to https.

# Global redirect for http --> https
server {
        listen 80;
        listen [::]:80;
        # for certbot autorenew webroot
        location '/.well-known/acme-challenge/' {
                root /var/www/acme/;
        # redirect
        location / {
                return 301 https://$host$request_uri;

server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name domain1 domain2;
        root /path/to/QuadFile;

        ## SSL/TLS
        include snippets/https.conf;
        ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;

        ## Reverse Proxy
        location / {
                proxy_set_header Host host;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Accept-Encoding "";
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $http_host;

        location /static {
                autoindex on;