A minimal file upload/pastebin service.
Rustypaste is a minimal file upload/pastebin service.
$ echo "some text" > awesome.txt
$ curl -F "[email protected]" https://paste.site.com
https://paste.site.com/safe-toad.txt
$ curl https://paste.site.com/safe-toad.txt
some textTable of Contents
capital-mosquito.txt)yB84D2Dv.txt)file.MRV5as.tar.gz)?download=truePackaging status
cargo install rustypastepacman -S rustypasterustypaste is available for Alpine Edge. It can be installed via apk after enabling the community repository.
apk add rustypastepkg install rustypasteSee the available binaries on the releases page.
git clone https://github.com/orhun/rustypaste.git
cd rustypaste/
cargo build --releaseopenssl: use distro OpenSSL (binary size is reduced ~20% in release mode)rustls: use rustls (enabled as default)To enable a feature for build, pass --features flag to cargo build command.
For example, to reuse the OpenSSL present on a distro already:
cargo build --release --no-default-features --features opensslcargo test -- --test-threads 1./fixtures/test-fixtures.shThe standalone command line tool (rpaste) is available here.
function rpaste() {
curl -F "file=@$1" -H "Authorization: " ""
}* consider reading authorization headers from a file. (e.g. -H @rpaste_auth)
# upload a file
$ rpaste x.txt
# paste from stdin
$ rpaste -$ curl -F "[email protected]" -H "expire:10min" ""supported units:
nsec, nsusec, usmsec, msseconds, second, sec, sminutes, minute, min, mhours, hour, hr, hdays, day, dweeks, week, wmonths, month, Myears, year, y$ curl -F "[email protected]" ""$ curl -F "oneshot_url=https://example.com" ""Upload a file with auto-generated password:
$ curl -F "[email protected]" ""
https://paste.site.com/secret.txt
Password: aBcD1234EfGh5678IjKl9012Download with Bearer token:
$ curl -H "Authorization: Bearer aBcD1234EfGh5678IjKl9012" https://paste.site.com/secret.txtOr with Basic Auth:
$ curl -u "user:aBcD1234EfGh5678IjKl9012" https://paste.site.com/secret.txtNote: Protected files cannot be combined with other paste types (oneshot, URL). The password is permanently tied to the file and cannot be changed. If the password is lost, the file becomes inaccessible. Password files are deleted automatically when the main file is deleted or expires.
$ curl -F "url=https://example.com/some/long/url" ""$ curl -F "remote=https://example.com/file.png" ""Configure [paste].delete_expired_files to set an interval for deleting the expired files automatically.
On the other hand, following script can be used as cron for cleaning up the expired files manually:
#!/bin/env sh
now=$(date +%s)
find upload/ -maxdepth 2 -type f -iname "*.[0-9]*" |
while read -r filename; do
[ "$(( ${filename##*.} / 1000 - "${now}" ))" -lt 0 ] && rm -v "${filename}"
doneSet delete_tokens array in config.toml to activate the DELETE endpoint and secure it with one (or more) auth token(s).
$ curl -H "Authorization: " -X DELETE "/file.txt"The
DELETEendpoint will not be exposed and will return404error ifdelete_tokensare not set.
When using the random_url config option, or when pasting a file from remote URL, rustypaste automatically selects a filename.
This can be overridden by sending a header called filename:
curl -F "[email protected]" -H "filename: " ""
curl -F "remote=https://example.com/file.png" -H "filename: " ""To start the server:
$ rustypasteIf the configuration file is not found in the current directory, specify it via CONFIG environment variable:
$ CONFIG="$HOME/.rustypaste.toml" rustypasteTo enable basic HTTP auth, set the AUTH_TOKEN environment variable (via .env):
$ echo "AUTH_TOKEN=$(openssl rand -base64 16)" > .env
$ rustypasteThere are 2 options for setting multiple auth tokens:
[server].auth_tokens in your config.toml.AUTH_TOKENS_FILE and DELETE_TOKENS_FILE respectively.If neither
AUTH_TOKEN,AUTH_TOKENS_FILEnor[server].auth_tokensare set, the server will not require any authentication.Exception is the
DELETEendpoint, which requires at least one token to be set. See deleting files from server for more information.
See config.toml for configuration options.
rustypaste determines a file's MIME type from its extension (with optional overrides) and serves
text-like types as text/plain; charset=utf-8 to avoid script execution.
[paste].mime_override lets you override MIME types by filename regex.[paste].mime_blacklist blocks uploads of specific MIME types.[paste].text_mime_overrides forces additional detected/guessed MIME types to be rendered as plaintext (unlike mime_override which matches by filename regex, this matches the content's actual MIME type).Set expose_list to true in 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.
$ curl "http:///list"
[{"file_name":"accepted-cicada.txt","file_size":241,"expires_at_utc":null}]This route will require an AUTH_TOKEN if one is set.
It is possible to use an HTML form for uploading files. To do so, you need to update two fields in your config.toml:
[landing_page].content_type to text/html; charset=utf-8.[landing_page].text field with your HTML form or point [landing_page].file to your html file.For an example, see examples/html_form.toml
Following command can be used to run a container which is built from the Dockerfile in this repository:
$ docker run --rm -d \
-v "$(pwd)/upload/":/app/upload \
-v "$(pwd)/config.toml":/app/config.toml \
--env-file "$(pwd)/.env" \
-e "RUST_LOG=debug" \
-p 8000:8000 \
--name rustypaste \
orhunp/rustypaste./upload (on the host machine)AUTH_TOKEN via -e or --env-file to enable authYou can build this image using docker build -t rustypaste . command.
If you want to run the image using docker compose, simply run docker-compose up -d. (see docker-compose.yml)
Example server configuration with reverse proxy:
server {
listen 80;
location / {
proxy_pass http://localhost:8000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "sameorigin";
add_header X-Content-Type-Options "nosniff";
}
}If you get a 413 Request Entity Too Large error during upload, set the max body size in nginx.conf:
http {
# ...
client_max_body_size 100M;
}Pull requests are welcome!
Consider submitting your ideas via issues first and check out the existing issues.
All code is licensed under The MIT License.
No open issues yet, or sync has not completed.