{"id":13456707,"url":"https://github.com/orhun/rustypaste","last_synced_at":"2025-05-14T05:02:21.001Z","repository":{"id":39745657,"uuid":"389941102","full_name":"orhun/rustypaste","owner":"orhun","description":"A minimal file upload/pastebin service.","archived":false,"fork":false,"pushed_at":"2025-05-06T20:32:56.000Z","size":1413,"stargazers_count":913,"open_issues_count":11,"forks_count":57,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-06T21:34:25.795Z","etag":null,"topics":["file-sharing","file-upload","file-upload-server","file-upload-service","file-uploading","hacktoberfest","multipart-uploads","paste-service","pastebin","pastebin-service","rust","rustypaste","upload","upload-file","upload-images"],"latest_commit_sha":null,"homepage":"https://blog.orhun.dev/blazingly-fast-file-sharing","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/orhun.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"orhun","patreon":"orhunp","buy_me_a_coffee":"orhun"}},"created_at":"2021-07-27T10:29:28.000Z","updated_at":"2025-05-06T20:32:54.000Z","dependencies_parsed_at":"2023-02-16T22:01:14.697Z","dependency_job_id":"5358b6b4-a6fd-4dee-aa8c-6f49f0234045","html_url":"https://github.com/orhun/rustypaste","commit_stats":{"total_commits":470,"total_committers":27,"mean_commits":17.40740740740741,"dds":0.5468085106382978,"last_synced_commit":"8a319ff4bc5a49b66071721d653c27d8e010bed6"},"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orhun%2Frustypaste","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orhun%2Frustypaste/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orhun%2Frustypaste/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orhun%2Frustypaste/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/orhun","download_url":"https://codeload.github.com/orhun/rustypaste/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254076330,"owners_count":22010597,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["file-sharing","file-upload","file-upload-server","file-upload-service","file-uploading","hacktoberfest","multipart-uploads","paste-service","pastebin","pastebin-service","rust","rustypaste","upload","upload-file","upload-images"],"created_at":"2024-07-31T08:01:26.411Z","updated_at":"2025-05-14T05:02:20.924Z","avatar_url":"https://github.com/orhun.png","language":"Rust","readme":"\u003ca href=\"https://github.com/orhun/rustypaste\"\u003e\u003cimg src=\"img/rustypaste_logo.png\" width=\"500\"\u003e\u003c/a\u003e\n\n[![GitHub Release](https://img.shields.io/github/v/release/orhun/rustypaste?style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026logo=GitHub\u0026logoColor=white)](https://github.com/orhun/rustypaste/releases)\n[![Crate Release](https://img.shields.io/crates/v/rustypaste?style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026logo=Rust\u0026logoColor=white)](https://crates.io/crates/rustypaste/)\n[![Coverage](https://img.shields.io/codecov/c/gh/orhun/rustypaste?style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026logo=Codecov\u0026logoColor=white)](https://codecov.io/gh/orhun/rustypaste)\n[![Continuous Integration](https://img.shields.io/github/actions/workflow/status/orhun/rustypaste/ci.yml?branch=master\u0026style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026logo=GitHub%20Actions\u0026logoColor=white)](https://github.com/orhun/rustypaste/actions?query=workflow%3A%22Continuous+Integration%22)\n[![Continuous Deployment](https://img.shields.io/github/actions/workflow/status/orhun/rustypaste/cd.yml?style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026logo=GitHub%20Actions\u0026logoColor=white\u0026label=deploy)](https://github.com/orhun/rustypaste/actions?query=workflow%3A%22Continuous+Deployment%22)\n[![Docker Builds](https://img.shields.io/github/actions/workflow/status/orhun/rustypaste/docker.yml?style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026label=docker\u0026logo=Docker\u0026logoColor=white)](https://hub.docker.com/r/orhunp/rustypaste)\n[![Documentation](https://img.shields.io/docsrs/rustypaste?style=flat\u0026labelColor=823213\u0026color=2c2c2c\u0026logo=Rust\u0026logoColor=white)](https://docs.rs/rustypaste/)\n\n**Rustypaste** is a minimal file upload/pastebin service.\n\n```sh\n$ echo \"some text\" \u003e awesome.txt\n\n$ curl -F \"file=@awesome.txt\" https://paste.site.com\nhttps://paste.site.com/safe-toad.txt\n\n$ curl https://paste.site.com/safe-toad.txt\nsome text\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eTable of Contents\u003c/summary\u003e\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n- [Features](#features)\n- [Installation](#installation)\n  - [From crates.io](#from-cratesio)\n  - [Arch Linux](#arch-linux)\n  - [Alpine Linux](#alpine-linux)\n  - [FreeBSD](#freebsd)\n  - [Binary releases](#binary-releases)\n  - [Build from source](#build-from-source)\n    - [Feature flags](#feature-flags)\n    - [Testing](#testing)\n      - [Unit tests](#unit-tests)\n      - [Test Fixtures](#test-fixtures)\n- [Usage](#usage)\n  - [CLI](#cli)\n    - [Expiration](#expiration)\n    - [One shot files](#one-shot-files)\n    - [One shot URLs](#one-shot-urls)\n    - [URL shortening](#url-shortening)\n    - [Paste file from remote URL](#paste-file-from-remote-url)\n    - [Cleaning up expired files](#cleaning-up-expired-files)\n    - [Delete file from server](#delete-file-from-server)\n    - [Override the filename when using `random_url`](#override-the-filename-when-using-random_url)\n  - [Server](#server)\n    - [Authentication](#authentication)\n    - [List endpoint](#list-endpoint)\n    - [HTML Form](#html-form)\n    - [Docker](#docker)\n    - [Nginx](#nginx)\n  - [Third Party Clients](#third-party-clients)\n  - [Contributing](#contributing)\n    - [License](#license)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n\u003c/details\u003e\n\n## Features\n\n- File upload \u0026 URL shortening \u0026 upload from URL\n  - supports basic HTTP authentication\n  - random file names (optional)\n    - pet name (e.g. `capital-mosquito.txt`)\n    - alphanumeric string (e.g. `yB84D2Dv.txt`)\n    - random suffix (e.g. `file.MRV5as.tar.gz`)\n  - supports expiring links\n    - auto-expiration of files (optional)\n    - auto-deletion of expired files (optional)\n  - supports one shot links/URLs (can only be viewed once)\n  - guesses MIME types\n    - supports overriding and blacklisting\n    - supports forcing to download via `?download=true`\n  - no duplicate uploads (optional)\n  - listing/deleting files\n  - custom landing page\n- Single binary\n  - [binary releases](https://github.com/orhun/rustypaste/releases)\n- Simple configuration\n  - supports hot reloading\n- Easy to deploy\n  - [docker images](https://hub.docker.com/r/orhunp/rustypaste)\n  - [appjail images](https://github.com/AppJail-makejails/rustypaste)\n- No database\n  - filesystem is used\n- Self-hosted\n  - _centralization is bad!_\n- Written in Rust\n  - _blazingly fast!_\n\n## Installation\n\n\u003cdetails\u003e\n  \u003csummary\u003ePackaging status\u003c/summary\u003e\n\n[![Packaging status](https://repology.org/badge/vertical-allrepos/rustypaste.svg)](https://repology.org/project/rustypaste/versions)\n\n\u003c/details\u003e\n\n### From crates.io\n\n```sh\ncargo install rustypaste\n```\n\n### Arch Linux\n\n```sh\npacman -S rustypaste\n```\n\n### Alpine Linux\n\n`rustypaste` is available for [Alpine Edge](https://pkgs.alpinelinux.org/packages?name=rustypaste\u0026branch=edge). It can be installed via [apk](https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper) after enabling the [community repository](https://wiki.alpinelinux.org/wiki/Repositories).\n\n```sh\napk add rustypaste\n```\n\n### FreeBSD\n\n```sh\npkg install rustypaste\n```\n\n### Binary releases\n\nSee the available binaries on the [releases](https://github.com/orhun/rustypaste/releases/) page.\n\n### Build from source\n\n```sh\ngit clone https://github.com/orhun/rustypaste.git\ncd rustypaste/\ncargo build --release\n```\n\n#### Feature flags\n\n- `shuttle`: enable an entry point for deploying on Shuttle\n- `openssl`: use distro OpenSSL (binary size is reduced ~20% in release mode)\n- `rustls`: use [rustls](https://github.com/rustls/rustls) (enabled as default)\n\nTo enable a feature for build, pass `--features` flag to `cargo build` command.\n\nFor example, to reuse the OpenSSL present on a distro already:\n\n```sh\ncargo build --release --no-default-features --features openssl\n```\n\n#### Testing\n\n##### Unit tests\n\n```sh\ncargo test -- --test-threads 1\n```\n\n##### Test Fixtures\n\n```sh\n./fixtures/test-fixtures.sh\n```\n\n## Usage\n\nThe standalone command line tool (`rpaste`) is available [here](https://github.com/orhun/rustypaste-cli).\n\n### CLI\n\n```sh\nfunction rpaste() {\n  curl -F \"file=@$1\" -H \"Authorization: \u003cauth_token\u003e\" \"\u003cserver_address\u003e\"\n}\n```\n\n**\\*** consider reading authorization headers from a file. (e.g. `-H @rpaste_auth`)\n\n```sh\n# upload a file\n$ rpaste x.txt\n\n# paste from stdin\n$ rpaste -\n```\n\n#### Expiration\n\n```sh\n$ curl -F \"file=@x.txt\" -H \"expire:10min\" \"\u003cserver_address\u003e\"\n```\n\nsupported units:\n\n- `nsec`, `ns`\n- `usec`, `us`\n- `msec`, `ms`\n- `seconds`, `second`, `sec`, `s`\n- `minutes`, `minute`, `min`, `m`\n- `hours`, `hour`, `hr`, `h`\n- `days`, `day`, `d`\n- `weeks`, `week`, `w`\n- `months`, `month`, `M`\n- `years`, `year`, `y`\n\n#### One shot files\n\n```sh\n$ curl -F \"oneshot=@x.txt\" \"\u003cserver_address\u003e\"\n```\n\n#### One shot URLs\n\n```sh\n$ curl -F \"oneshot_url=https://example.com\" \"\u003cserver_address\u003e\"\n```\n\n#### URL shortening\n\n```sh\n$ curl -F \"url=https://example.com/some/long/url\" \"\u003cserver_address\u003e\"\n```\n\n#### Paste file from remote URL\n\n```sh\n$ curl -F \"remote=https://example.com/file.png\" \"\u003cserver_address\u003e\"\n```\n\n#### Cleaning up expired files\n\nConfigure `[paste].delete_expired_files` to set an interval for deleting the expired files automatically.\n\nOn the other hand, following script can be used as [cron](https://en.wikipedia.org/wiki/Cron) for cleaning up the expired files manually:\n\n```sh\n#!/bin/env sh\nnow=$(date +%s)\nfind upload/ -maxdepth 2 -type f -iname \"*.[0-9]*\" |\nwhile read -r filename; do\n\t[ \"$(( ${filename##*.} / 1000 - \"${now}\" ))\" -lt 0 ] \u0026\u0026 rm -v \"${filename}\"\ndone\n```\n\n#### Delete file from server\n\nSet `delete_tokens` array in [config.toml](./config.toml) to activate the [`DELETE`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) endpoint and secure it with one (or more) auth token(s).\n\n```sh\n$ curl -H \"Authorization: \u003cauth_token\u003e\" -X DELETE \"\u003cserver_address\u003e/file.txt\"\n```\n\n\u003e The `DELETE` endpoint will not be exposed and will return `404` error if `delete_tokens` are not set.\n\n#### Override the filename when using `random_url`\n\nThe generation of a random filename can be overridden by sending a header called `filename`:\n\n```sh\ncurl -F \"file=@x.txt\" -H \"filename: \u003cfile_name\u003e\" \"\u003cserver_address\u003e\"\n```\n\n### Server\n\nTo start the server:\n\n```sh\n$ rustypaste\n```\n\nIf the configuration file is not found in the current directory, specify it via `CONFIG` environment variable:\n\n```sh\n$ CONFIG=\"$HOME/.rustypaste.toml\" rustypaste\n```\n\n#### Authentication\n\nTo enable basic HTTP auth, set the `AUTH_TOKEN` environment variable (via `.env`):\n\n```sh\n$ echo \"AUTH_TOKEN=$(openssl rand -base64 16)\" \u003e .env\n$ rustypaste\n```\n\nThere are 2 options for setting multiple auth tokens:\n\n- Via the array field `[server].auth_tokens` in your `config.toml`.\n- Or by writing a newline separated list to a file and passing its path to rustypaste via `AUTH_TOKENS_FILE` and `DELETE_TOKENS_FILE` respectively.\n\n\u003e If neither `AUTH_TOKEN`, `AUTH_TOKENS_FILE` nor `[server].auth_tokens` are set, the server will not require any authentication.\n\u003e\n\u003e Exception is the `DELETE` endpoint, which requires at least one token to be set. See [deleting files from server](#delete-file-from-server) for more information.\n\nSee [config.toml](./config.toml) for configuration options.\n\n#### List endpoint\n\nSet `expose_list` to true in [config.toml](./config.toml) to be able to retrieve a JSON formatted list of files in your uploads directory. This will not include oneshot files, oneshot URLs, or URLs.\n\n```sh\n$ curl \"http://\u003cserver_address\u003e/list\"\n\n[{\"file_name\":\"accepted-cicada.txt\",\"file_size\":241,\"expires_at_utc\":null}]\n```\n\nThis route will require an `AUTH_TOKEN` if one is set.\n\n#### HTML Form\n\nIt is possible to use an HTML form for uploading files. To do so, you need to update two fields in your `config.toml`:\n\n- Set the `[landing_page].content_type` to `text/html; charset=utf-8`.\n- Update the `[landing_page].text` field with your HTML form or point `[landing_page].file` to your html file.\n\nFor an example, see [examples/html_form.toml](./examples/html_form.toml)\n\n#### Docker\n\nFollowing command can be used to run a container which is built from the [Dockerfile](./Dockerfile) in this repository:\n\n```sh\n$ docker run --rm -d \\\n  -v \"$(pwd)/upload/\":/app/upload \\\n  -v \"$(pwd)/config.toml\":/app/config.toml \\\n  --env-file \"$(pwd)/.env\" \\\n  -e \"RUST_LOG=debug\" \\\n  -p 8000:8000 \\\n  --name rustypaste \\\n  orhunp/rustypaste\n```\n\n- uploaded files go into `./upload` (on the host machine)\n- set the `AUTH_TOKEN` via `-e` or `--env-file` to enable auth\n\nYou can build this image using `docker build -t rustypaste .` command.\n\nIf you want to run the image using [docker compose](https://docs.docker.com/compose/), simply run `docker-compose up -d`. (see [docker-compose.yml](./docker-compose.yml))\n\n#### Nginx\n\nExample server configuration with reverse proxy:\n\n```nginx\nserver {\n    listen 80;\n    location / {\n        proxy_pass                         http://localhost:8000/;\n        proxy_set_header Host              $host;\n        proxy_set_header X-Forwarded-For   $remote_addr;\n        proxy_set_header X-Forwarded-Proto $scheme;\n        add_header X-XSS-Protection        \"1; mode=block\";\n        add_header X-Frame-Options         \"sameorigin\";\n        add_header X-Content-Type-Options  \"nosniff\";\n    }\n}\n```\n\nIf you get a `413 Request Entity Too Large` error during upload, set the max body size in `nginx.conf`:\n\n```nginx\nhttp {\n    # ...\n    client_max_body_size 100M;\n}\n```\n\n### Third Party Clients\n\n- [dbohdan/ferripaste](https://github.com/dbohdan/ferripaste) - Alternative rustypaste CLI client\n- [rukh-debug/droidypaste](https://github.com/rukh-debug/droidypaste) - Android client built with React Native and Expo\n- [rukh-debug/rustypaste-gui.sh](https://gist.github.com/rukh-debug/cc42900f86e39cacef6f7a6ba77ebf58) - Linux's Minimal GUI client powered by zenity\n\n### Contributing\n\nPull requests are welcome!\n\nConsider submitting your ideas via [issues](https://github.com/orhun/rustypaste/issues/new) first and check out the [existing issues](https://github.com/orhun/rustypaste/issues).\n\n#### License\n\n\u003csup\u003e\nAll code is licensed under \u003ca href=\"LICENSE\"\u003eThe MIT License\u003c/a\u003e.\n\u003c/sup\u003e\n","funding_links":["https://github.com/sponsors/orhun","https://patreon.com/orhunp","https://buymeacoffee.com/orhun"],"categories":["Rust","Install from Source","Applications","应用程序 Applications","Software","Built on Shuttle","hacktoberfest"],"sub_categories":["Pastebins","Web Servers","Web服务器 Web Servers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forhun%2Frustypaste","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forhun%2Frustypaste","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forhun%2Frustypaste/lists"}