#file-sharing #url-shortener #pastebin

app filite

A simple, light and standalone pastebin, URL shortener and file-sharing service

3 releases (breaking)

0.3.0 Jan 16, 2020
0.2.0 Oct 28, 2019
0.1.0 Oct 25, 2019

#1139 in Web programming

38 downloads per month

MIT license



A simple, light and standalone pastebin, URL shortener and file-sharing service that hosts files, redirects links and stores texts.

GitHub Actions Crates.io

Live Example

Table of Contents


What it is

  • Easy to use. Installation and set-up take less than a minute and a built-in web UI is provided.
  • Standalone. No external dependencies required, everything that is needed is packed into the binary.
  • Light and fast. The Rust web framework Actix is used under the hood, providing great speed with a minimal footprint.

What it is not

  • A tracking tool. No stats are stored to increase speed, reduce resource usage and maintain simplicity, if this is what you are looking for filite is not for you.


  1. Get the binary either from the releases page or using Cargo
  2. Run filite init to perform the initial setup (you can do this at any time to reset the config and password)
  3. Edit your config file as you see fit (check the dedicated section for details)
  4. Run filite

That's it!


When asked for a login, use whatever username you want and the password you provided during setup. Details for programmatic usage are provided in the dedicated section.

Planned features

  • Decent test suite
  • TLS support
  • Simple admin page
  • Multiple logins (?)


# Port to listen on
port = 8080
# SQLite database connection url
database_url = "database.db"
# SQLite database connection pool size
pool_size = 4
# Directory where to store static files
files_dir = "files"

# Highlight.js configuration
# Theme to use
theme = "github"
# Additional languages to include
languages = ["rust"]

Client tools


  • <AUTHORIZATION> is the result of encoding <USERNAME>:<PASSWORD> to base64
    • <USERNAME> is an arbitrary username, it doesn't matter
    • <PASSWORD> is the password entered during setup
  • <ADDRESS> is the root address where the filite is running, for instance http://localhost:8080 or https://filite.raphaeltheriault.com


  "Version": "13.0.1",
  "Name": "filite (file)",
  "DestinationType": "ImageUploader, FileUploader",
  "RequestMethod": "POST",
  "RequestURL": "<ADDRESS>/f",
  "Headers": {
    "Authorization": "Basic <AUTORIZATION>"
  "Body": "MultipartFormData",
  "FileFormName": "file",
  "URL": "<ADDRESS>/$response$"
  "Version": "13.0.1",
  "Name": "filite (link)",
  "DestinationType": "URLShortener",
  "RequestMethod": "POST",
  "RequestURL": "<ADDRESS>/l",
  "Headers": {
    "Authorization": "Basic <AUTORIZATION>"
  "Body": "JSON",
  "Data": "{\"forward\":\"$input$\"}",
  "URL": "<ADDRESS>/l/$response$"


You can remove the prompt and always enable or disable syntax highlighting by replacing $prompt:Highlight|false$ with true or false.

  "Version": "13.0.1",
  "Name": "filite (text)",
  "DestinationType": "TextUploader",
  "RequestMethod": "POST",
  "RequestURL": "<ADDRESS>/t",
  "Headers": {
    "Authorization": "Basic <AUTORIZATION>"
  "Body": "JSON",
  "Data": "{\"contents\":\"$input$\",\"highlight\":$prompt:Highlight|false$}",
  "URL": "<ADDRESS>/t/$response$"

Reverse proxy

  • <DOMAIN> is the domain the requests will be coming from, for instance filite.raphaeltheriault.com
  • <PORT> is the port on which filite is listening

Upload limits are set to 10M as an example


server {
  listen 80;
  listen [::]:80;

  server_name <DOMAIN>;

  location / {
    proxy_pass http://localhost:<PORT>;

    location /f {
      client_max_body_size 10M;


<VirtualHost *:80>
  ServerName <DOMAIN>

  ProxyPreserveHost On
  ProxyPass / http://localhost:<PORT>/
  ProxyPassReverse / http://localhost:<PORT>/

  <Location "/f">
    LimitRequestBody 10000000

Programmatic usage

All requests that require authentication use HTTP Basic Auth (without taking the username into account).

Listing existing entries

It's possible to get an array of all existing entries for each type with an authenticated request.

  • GET /f
  • GET /l
  • GET /t

Creating new entries

There are two ways to create new entries, PUT or POST requests. PUT lets you choose the ID manually and POST assigns a free one automatically, but that's the only difference. Both methods require authentication.

PUT requests will overwrite any existing entry.


  • PUT /f/{id}
  • POST /f

Files are sent as multipart/form-data. The field name isn't important but the file name needs to be included. Only one file is treated.

  • PUT /l/{id}
  • POST /l

Links are sent as application/json according to the following schema.

  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Link",
  "type": "object",
  "properties": {
    "forward": {
      "description": "URL this link forwards to",
      "type": "string"


  • PUT /t/{id}
  • POST /t

Texts are sent as application/json according to the following schema.

  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Text",
  "type": "object",
  "properties": {
    "contents": {
      "description": "Text contents",
      "type": "string"
    "highlight": {
      "description": "Whether to enable code highlighting or not for that text",
      "type": "boolean"

Deleting entries

It's possible to delete any entry with an authenticated request.

  • DELETE /f
  • DELETE /l
  • DELETE /t


The project is open to contributions! Before submitting a PR, make sure your changes work both with and without the dev feature enabled.


  • The Rust toolchain
  • diesel_cli with the sqlite feature enabled


  1. Copy .env.example to .env and set the variables to your liking
  2. Run diesel database setup
  3. Build or run with the dev feature enabled


filite is licensed under the MIT License.


~1.5M SLoC