Temporary and light file uploader
Find a file
2025-12-15 22:16:02 -03:00
.forgejo/workflows chore(deps): update https://code.forgejo.org/actions/checkout action to v6 (#272) 2025-12-11 13:18:59 -03:00
.vscode 0.9.9 2025-08-20 02:51:26 -04:00
config feat: Add support for Redis as cache and improve the cache module 2025-12-15 22:16:02 -03:00
docs chore: add docs 2025-08-07 02:50:37 -04:00
locales improve css and js, add drag and drop 2025-09-30 17:27:21 -03:00
public/-/assets improve css and js, add drag and drop 2025-09-30 17:27:21 -03:00
screenshots update readme screenshot images 2025-09-30 17:32:30 -03:00
spec spec: update spec 2025-08-07 02:50:38 -04:00
src chore: rescue when config fails to load (ex: when there is errors in the configuration) 2025-12-15 22:16:02 -03:00
.ameba.yml add ameba 2025-05-27 17:57:11 -04:00
.editorconfig 0.9.9 2025-08-20 02:51:26 -04:00
.gitignore chore: update gitignore 2025-08-16 17:06:47 -04:00
.prettierrc 0.9.9 2025-08-20 02:51:26 -04:00
docker-compose.yml compose: add config.yml volume for configuration 2025-08-27 19:13:40 -04:00
Dockerfile chore(deps): update alpine docker tag to v3.23 (#269) 2025-12-09 18:16:36 -03:00
LICENSE 0.2.0 2024-07-31 18:25:30 -04:00
Makefile update makefile, refactor things 2025-08-17 21:04:45 -04:00
patchy.service rename whole project to patchy 2025-05-26 01:07:37 -04:00
README-es.md update readme.md 2025-05-26 00:46:22 -04:00
README.md chore: add docs 2025-08-07 02:50:37 -04:00
renovate.json chore: Configure Renovate (#20) 2025-05-24 19:04:24 -04:00
shard.lock chore(deps): Update redis shard to 0.14.0 2025-12-15 22:16:02 -03:00
shard.yml chore(deps): Update redis shard to 0.14.0 2025-12-15 22:16:02 -03:00

Patchy

A temporary file uploader easy to host that I did to replace Uguu, which is not easy to host due to PHP.

Uses a low amount of memory, it works without JS, it can be used on other software like Chatterino2 and ShareX and it has other features that are listed bellow

There is an instance of this software running at patchy.moe

Why is called Patchy?

At first I wanted to call it "Patchouli", from Patchouli Knowledge, but there was already some projects that already used that name, probably because of the same reason as me (they like Touhou). So I went with Patchy, which is how Remi calls Patchouli.

So, why is called Patchy and how it's related to a file uploader service? Think about it, Patchy is a librarian, take the books as files, and Patchy as the software that manages them ;)

https://safebooru.org/index.php?page=post&s=view&id=905633

Screenshots

Javascript enabled

Javascript disabled

Features

  • Temporary file uploads like Uguu
  • File deletion link (not available on the noJS until I find a way)
  • Chatterino and ShareX support
  • Thumbnails for OpenGraph User-Agents (Requires ffmpeg to be installed, disabled by default)
  • File upload rate limits (based on the IP address)
  • Small Admin API that allows you to delete files, gather file information, see cached files on RAM and more (Needs to be enabled in the configuration)
  • Unix socket support if you don't want to deal with all the TCP overhead
  • Automatic protocol detection (HTTPS or HTTP)
  • Cache files on memory to reduce stress on the drive using LRU, more information on config.example.yml
  • Low memory usage: Between 6MB at idle and 40MB if a file is being uploaded or retrieved. It will depend of your traffic, if cache is enabled and if checksumming is enabled.
  • Experimental S3 bucket support (OpenGraph thumbnails are not available, tested using Minio)
  • Localization support (Only English and Spanish supported for now)
  • VPN blocking (Not really necessary, but still, it's a good addition) (In progress)

TODO

#9

Docs

./docs

How to host Patchy

Containers

Docker Compose / Podman Compose

  • Create a folder with the name you want
  • Download the docker-compose.yml file into the folder you created
  • If you are using docker, create the data folder using mkdir ./data && sudo chown -R 10000:10000 ./data
  • Run it using docker compose up if using docker or podman compose up if using Podman. If it works fine, then you can append the -d argument next to leave the container running on the background

Kubernetes

TODO

Native (Compiling it yourself)

  • Create a user for the uploader: sudo useradd -u 10000 patchy (you can replace the username with whatever you want)
  • Clone this repository on something like /opt/patchy
  • Install Crystal and compile the uploader using shards build --release
  • Change the settings file ./config/config.yml according to what you need.
  • Setup a systemd service to keep the uploader running. Copy patchy.service into /etc/systemd/system/patchy.service
  • Give permissions to the /opt/patchy folder to the user patchy using sudo chown -R 10000:10000 /opt/patchy
  • Start the uploader using sudo systemctl start patchy

Warning

This was not tested, if you have any issues with it, please open an issue!

NGINX Server block

Assuming you are already using NGINX and you know how to use it, you can use this example server block.

server {
  # You can keep the domain prefixed with `~.` if you want
  # to allow users to use any domain to upload and retrieve
  # files. Like xdxd.example.com or lolol.example.com
  # This will only work if you have a wildcard domain and certificate.
  server_name ~.example.com example.com;

  location / {
    proxy_pass http://127.0.0.1:8080;
    # This if you want to use a UNIX socket instead
    # proxy_pass http://unix:/tmp/patchy.sock;
    proxy_set_header X-Real-IP   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_pass_request_headers      on;
  }

  # This should be the size_limit value (from config.yml)
  client_max_body_size 512M;

  listen 443 ssl;
  http2 on;
}