Initial commit

This commit is contained in:
Ian Keane 2025-11-30 18:20:47 -05:00
commit 9453fa56ac
3 changed files with 1445 additions and 0 deletions

710
Cargo.lock generated Normal file
View file

@ -0,0 +1,710 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr 2.4.1",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "async-stream"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625"
dependencies = [
"async-stream-impl",
"futures-core",
]
[[package]]
name = "async-stream-impl"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-trait"
version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atomic"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88d82667eca772c4aa12f0f1348b3ae643424c8876448f3f7bd5787032e234c"
dependencies = [
"autocfg",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi 0.3.9",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "base-x"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b"
[[package]]
name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bin"
version = "2.2.1"
dependencies = [
"clap",
"once_cell",
"rand",
"rocket",
"rocket_dyn_templates",
"rust-embed",
"sha256",
"syntect",
"time 0.3.7",
"tree_magic",
]
[[package]]
name = "binascii"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array 0.12.4",
]
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array 0.14.5",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"memchr 2.4.1",
]
[[package]]
name = "bumpalo"
version = "3.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"winapi 0.3.9",
]
[[package]]
name = "chrono-tz"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]]
name = "clap"
version = "3.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b63edc3f163b3c71ec8aa23f9bd6070f77edbf3d1d198b164afa90ff00e4ec62"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"indexmap",
"lazy_static",
"os_str_bytes",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a1132dc3944b31c20dd8b906b3a9f0a5d0243e092d59171414969657ac6aa85"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "const_fn"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
[[package]]
name = "cookie"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d"
dependencies = [
"percent-encoding",
"time 0.2.27",
"version_check",
]
[[package]]
name = "cpufeatures"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120"
dependencies = [
"cfg-if 1.0.0",
"lazy_static",
]
[[package]]
name = "deunicode"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690"
[[package]]
name = "devise"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595"
dependencies = [
"devise_codegen",
"devise_core",
]
[[package]]
name = "devise_codegen"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2"
dependencies = [
"devise_core",
"quote",
]
[[package]]
name = "devise_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0"
dependencies = [
"bitflags",
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
"syn",
]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array 0.12.4",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array 0.14.5",
]
[[package]]
name = "discard"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "encoding_rs"
version = "0.8.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]]
name = "figment"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790b4292c72618abbab50f787a477014fe15634f96291de45672ce46afe122df"
dependencies = [
"atomic",
"pear",
"serde",
"toml",
"uncased",
"version_check",
]
[[package]]
name = "filetime"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall 0.2.10",
"winapi 0.3.9",
]
[[package]]
name = "fixedbitset"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]]
name = "flate2"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
dependencies = [
"cfg-if 1.0.0",
"crc32fast",
"libc",
"miniz_oxide",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fsevent"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
dependencies = [
"bitflags",
"fsevent-sys",
]
[[package]]
name = "fsevent-sys"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
dependencies = [
"libc",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7"
[[package]]
name = "futures-executor"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2"
[[package]]
name = "futures-macro"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508"
[[package]]
name = "futures-task"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72"
[[package]]
name = "futures-util"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr 2.4.1",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "generator"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee"
dependencies = [
"cc",
"libc",
"log",
"rustversion",
"winapi 0.3.9",
]
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "globset"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
dependencies = [
"aho-corasick",
"bstr",
"fnv",
"log",
"regex",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags",
"ignore",
"walkdir",
]
[[package]]
name = "h2"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94

435
README.md Normal file
View file

@ -0,0 +1,435 @@
# Bin Pastebin Nix Flake
This flake provides a Nix package and NixOS module for [bin](https://github.com/wantguns/bin), a minimal pastebin service that accepts binary files like images and PDFs.
## Features
- **Minimal and fast**: Written in Rust using the Rocket framework
- **Binary file support**: Upload images, PDFs, and other binary files
- **Multiple clients**: Web UI, CLI, and Vim integration
- **Self-contained**: No external database required
- **Security hardened**: Systemd service with strict security policies
- **Nginx integration**: Built-in reverse proxy configuration with SSL support
## Quick Start
### Using the Flake in Your NixOS Configuration
Add the flake to your `flake.nix` inputs:
```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
bin-flake.url = "path:/path/to/this/flake";
# Or from GitHub (once published):
# bin-flake.url = "github:yourusername/bin-flake";
};
outputs = { self, nixpkgs, bin-flake, ... }: {
nixosConfigurations.yourhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
bin-flake.nixosModules.default
./configuration.nix
];
};
};
}
```
### Basic Configuration
In your NixOS configuration:
```nix
{
services.bin = {
enable = true;
port = 6162;
address = "127.0.0.1";
};
}
```
### Complete Configuration Example
```nix
{
services.bin = {
enable = true;
# Network settings
address = "127.0.0.1";
port = 6162;
openFirewall = false; # Set to true if not using nginx
# Storage settings
uploadDir = "/var/lib/bin/upload";
binaryUploadLimit = 100; # MiB
# UI settings
clientDescription = true; # Show CLI client info on landing page
# Custom environment variables
environmentFile = pkgs.writeText "bin-env" ''
BIN_LIMITS={form="16 MiB"}
BIN_WORKERS=8
BIN_IDENT=false
BIN_KEEP_ALIVE=5
BIN_LOG_LEVEL=normal
'';
# Nginx reverse proxy
nginx = {
enable = true;
domain = "paste.yourdomain.com";
enableSSL = true; # Uses Let's Encrypt
};
};
# Ensure nginx and ACME are configured
services.nginx.enable = true;
security.acme = {
acceptTerms = true;
defaults.email = "admin@yourdomain.com";
};
}
```
## Configuration Options
### Core Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `enable` | bool | false | Whether to enable the bin service |
| `package` | package | bin | The bin package to use |
| `user` | string | "bin" | User account under which bin runs |
| `group` | string | "bin" | Group under which bin runs |
### Network Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `address` | string | "127.0.0.1" | Address on which the webserver listens |
| `port` | int | 6162 | Port on which the webserver listens |
| `openFirewall` | bool | false | Whether to open the firewall for the service |
### Storage Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `uploadDir` | path | "/var/lib/bin/upload" | Directory where uploaded pastes are stored |
| `binaryUploadLimit` | int | 100 | Binary uploads file size limit (in MiB) |
### Feature Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `clientDescription` | bool | true | Whether to show the /client description on landing page |
| `extraArgs` | list of strings | [] | Extra command-line arguments to pass to bin |
| `environmentFile` | null or path | null | File containing environment variables for bin |
### Nginx Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `nginx.enable` | bool | false | Whether to enable nginx reverse proxy |
| `nginx.domain` | string | "paste.example.com" | Domain name for the bin service |
| `nginx.enableSSL` | bool | true | Whether to enable SSL (uses ACME/Let's Encrypt) |
## Environment Variables
The bin service supports additional configuration through environment variables. You can set these using the `environmentFile` option:
```nix
environmentFile = pkgs.writeText "bin-env" ''
# Rocket configuration
BIN_LIMITS={form="16 MiB"} # Form data size limit
BIN_WORKERS=8 # Number of worker threads
BIN_IDENT=false # Disable server identification
BIN_KEEP_ALIVE=5 # Keep-alive timeout in seconds
BIN_LOG_LEVEL=normal # Log level: off, critical, normal, debug
# Additional Rocket settings
BIN_SECRET_KEY=your-secret-key # For encrypted cookies (generate with openssl)
BIN_TLS={certs="path/to/certs",key="path/to/key"} # TLS configuration
'';
```
## Client Configuration
### Web Client
Access the web interface at `http://localhost:6162` (or your configured domain).
### CLI Client
The CLI client can be installed and configured:
```bash
# Download the client
curl -o ~/.local/bin/pst https://yourdomain.com/client
chmod +x ~/.local/bin/pst
# Or create your own client script
cat > ~/.local/bin/pst << 'EOF'
#!/bin/bash
URL="https://paste.yourdomain.com"
FILEPATH="$1"
FILENAME=$(basename -- "$FILEPATH")
EXTENSION="${FILENAME##*.}"
RESPONSE=$(curl --data-binary @${FILEPATH:-/dev/stdin} --url $URL)
PASTELINK="$URL$RESPONSE"
[ -z "$EXTENSION" ] && \
echo "$PASTELINK" || \
echo "$PASTELINK.$EXTENSION"
EOF
chmod +x ~/.local/bin/pst
```
Usage:
```bash
# Upload a file
pst somefile.txt
# Pipe content
echo "Hello, World!" | pst
# Upload an image
pst screenshot.png
```
### Vim Integration
Add to your `init.vim` or `.vimrc`:
```vim
nnoremap <leader>p :!pst %<CR>
```
## Security Considerations
The NixOS module implements several security measures:
1. **Systemd Hardening**: The service runs with strict sandboxing
2. **Separate User**: Runs under a dedicated system user
3. **Filesystem Isolation**: Only the upload directory is writable
4. **Network Restrictions**: Limited to IPv4/IPv6 address families
5. **System Call Filtering**: Restricted to necessary system calls
## Maintenance
### Viewing Logs
```bash
# View service logs
sudo journalctl -u bin -f
# View nginx logs (if using reverse proxy)
sudo journalctl -u nginx -f
```
### Managing Uploads
```bash
# View disk usage
du -sh /var/lib/bin/upload
# Clean old uploads (example: files older than 30 days)
find /var/lib/bin/upload -type f -mtime +30 -delete
# Backup uploads
tar -czf bin-uploads-$(date +%Y%m%d).tar.gz /var/lib/bin/upload
```
### Service Management
```bash
# Restart the service
sudo systemctl restart bin
# Check service status
sudo systemctl status bin
# Reload after configuration changes
sudo nixos-rebuild switch
```
## Advanced Usage
### Custom Nginx Configuration
If you need more control over the nginx configuration:
```nix
{
services.bin = {
enable = true;
nginx.enable = false; # Disable automatic nginx config
};
services.nginx.virtualHosts."paste.yourdomain.com" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:6162";
extraConfig = ''
client_max_body_size 100M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Custom headers
proxy_set_header X-Custom-Header "value";
# Rate limiting
limit_req zone=paste burst=5 nodelay;
'';
};
};
}
```
### Running Multiple Instances
You can run multiple bin instances on different ports:
```nix
{
services.bin = {
enable = true;
port = 6162;
uploadDir = "/var/lib/bin/upload";
};
# Second instance (requires manual systemd service)
systemd.services.bin-private = {
description = "Private bin instance";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${pkgs.bin}/bin/bin --port 6163 --upload /var/lib/bin-private/upload";
User = "bin-private";
Group = "bin-private";
StateDirectory = "bin-private";
};
};
users.users.bin-private = {
isSystemUser = true;
group = "bin-private";
};
users.groups.bin-private = {};
}
```
### Integration with Monitoring
Example Prometheus/Grafana integration:
```nix
{
services.prometheus = {
enable = true;
scrapeConfigs = [{
job_name = "bin";
static_configs = [{
targets = [ "localhost:6162" ];
}];
}];
};
services.grafana.provision.dashboards = [{
options.path = ./dashboards;
# Add your bin dashboard JSON here
}];
}
```
## Troubleshooting
### Service Won't Start
1. Check logs: `sudo journalctl -u bin -e`
2. Verify permissions: `ls -la /var/lib/bin`
3. Check port availability: `sudo ss -tlnp | grep 6162`
### Upload Errors
1. Check file size limits in configuration
2. Verify disk space: `df -h /var/lib/bin`
3. Check nginx client_max_body_size if using reverse proxy
### SSL Certificate Issues
1. Ensure domain points to your server
2. Check ACME logs: `sudo journalctl -u acme-paste.yourdomain.com`
3. Verify ports 80/443 are accessible
## Development
To work on the bin source code:
```bash
# Enter development shell
nix develop
# Run locally
cargo run -- --address 127.0.0.1 --port 6162
# Run tests
cargo test
# Format code
cargo fmt
# Lint
cargo clippy
```
## Building
### Build the package
```bash
# Build the bin package
nix build .#bin
# Build the Docker image
nix build .#docker
# Load Docker image
docker load < result
```
### Cross-compilation
The flake supports cross-compilation:
```bash
# Build for aarch64-linux on x86_64-linux
nix build .#packages.aarch64-linux.bin
```
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Test your changes thoroughly
4. Submit a pull request
## License
This flake is provided under the same license as the bin project (LGPL-3.0).
## Credits
- Original bin project: https://github.com/wantguns/bin
- Based on Rocket framework: https://rocket.rs/

300
flake.nix Normal file
View file

@ -0,0 +1,300 @@
{
description = "A minimal pastebin which also accepts binary files like Images, PDFs and ships multiple clients";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay = {
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, flake-utils, rust-overlay }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
rustToolchain = pkgs.rust-bin.stable.latest.default.override {
extensions = [ "rust-src" ];
targets = [ "x86_64-unknown-linux-musl" "aarch64-unknown-linux-musl" ];
};
in
{
packages = {
default = self.packages.${system}.bin;
bin = pkgs.rustPlatform.buildRustPackage rec {
pname = "bin";
version = "2.4.0";
src = pkgs.fetchFromGitHub {
owner = "wantguns";
repo = "bin";
rev = "v${version}";
hash = "sha256-gUTDe9LPJ0Y2JLnbLv2FQaUjeNj6a1LQ3V5Z9SVnxkc=";
};
cargoHash = "sha256-2SiHrc0L9YiL2vLzKPnJ4BREPyeODJlLNReJPPpKlAE=";
nativeBuildInputs = with pkgs; [
pkg-config
];
buildInputs = with pkgs; [
openssl
] ++ lib.optionals stdenv.isDarwin [
darwin.apple_sdk.frameworks.Security
];
# Enable optimizations
CARGO_BUILD_INCREMENTAL = "false";
RUST_BACKTRACE = "full";
meta = with pkgs.lib; {
description = "A minimal pastebin which also accepts binary files";
homepage = "https://github.com/wantguns/bin";
license = licenses.lgpl3Only;
maintainers = [];
platforms = platforms.all;
};
};
docker = pkgs.dockerTools.buildImage {
name = "bin";
tag = "latest";
created = "now";
contents = [ self.packages.${system}.bin pkgs.cacert ];
config = {
Cmd = [ "${self.packages.${system}.bin}/bin/bin" ];
ExposedPorts = {
"6162/tcp" = {};
};
Env = [
"BIN_ADDRESS=0.0.0.0"
"SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
];
WorkingDir = "/";
Volumes = {
"/upload" = {};
};
};
};
};
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
rustToolchain
pkg-config
openssl
cargo-watch
rust-analyzer
clippy
rustfmt
];
RUST_BACKTRACE = 1;
};
}) // {
nixosModules = {
default = self.nixosModules.bin;
bin = { config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.bin;
in
{
options.services.bin = {
enable = mkEnableOption "bin pastebin service";
package = mkOption {
type = types.package;
default = self.packages.${pkgs.system}.bin;
defaultText = literalExpression "pkgs.bin";
description = "The bin package to use";
};
user = mkOption {
type = types.str;
default = "bin";
description = "User under which bin runs";
};
group = mkOption {
type = types.str;
default = "bin";
description = "Group under which bin runs";
};
address = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Address on which the webserver runs";
};
port = mkOption {
type = types.port;
default = 6162;
description = "Port on which the webserver runs";
};
uploadDir = mkOption {
type = types.path;
default = "/var/lib/bin/upload";
description = "Path to the uploads folder";
};
binaryUploadLimit = mkOption {
type = types.int;
default = 100;
description = "Binary uploads file size limit (in MiB)";
};
clientDescription = mkOption {
type = types.bool;
default = true;
description = "Include client description on landing page";
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [];
description = "Extra command-line arguments to pass to bin";
};
environmentFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing environment variables for bin.
Useful for setting Rocket-specific configurations.
'';
example = literalExpression ''
pkgs.writeText "bin-env" '''
BIN_LIMITS={form="16 MiB"}
BIN_WORKERS=8
BIN_IDENT=false
'''
'';
};
openFirewall = mkOption {
type = types.bool;
default = false;
description = "Whether to open the firewall for the bin port";
};
nginx = {
enable = mkOption {
type = types.bool;
default = false;
description = "Whether to enable nginx reverse proxy for bin";
};
domain = mkOption {
type = types.str;
default = "paste.example.com";
description = "Domain name for the bin service";
};
enableSSL = mkOption {
type = types.bool;
default = true;
description = "Whether to enable SSL (uses ACME/Let's Encrypt)";
};
};
};
config = mkIf cfg.enable {
systemd.services.bin = {
description = "bin pastebin service";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
User = cfg.user;
Group = cfg.group;
ExecStart = ''
${cfg.package}/bin/bin \
--address ${cfg.address} \
--port ${toString cfg.port} \
--upload ${cfg.uploadDir} \
--binary-upload-limit ${toString cfg.binaryUploadLimit} \
${optionalString cfg.clientDescription "--client-desc"} \
${concatStringsSep " " cfg.extraArgs}
'';
Restart = "on-failure";
RestartSec = 5;
StateDirectory = "bin";
WorkingDirectory = "/var/lib/bin";
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
# Security hardening
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ProtectHome = true;
ReadWritePaths = [ cfg.uploadDir ];
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
LockPersonality = true;
RestrictRealtime = true;
SystemCallFilter = "@system-service";
SystemCallErrorNumber = "EPERM";
PrivateDevices = true;
RestrictNamespaces = true;
RestrictSUIDSGID = true;
RemoveIPC = true;
};
};
users.users = mkIf (cfg.user == "bin") {
bin = {
isSystemUser = true;
group = cfg.group;
home = "/var/lib/bin";
createHome = true;
};
};
users.groups = mkIf (cfg.group == "bin") {
bin = {};
};
systemd.tmpfiles.rules = [
"d ${cfg.uploadDir} 0755 ${cfg.user} ${cfg.group} -"
];
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ cfg.port ];
services.nginx = mkIf cfg.nginx.enable {
enable = true;
virtualHosts.${cfg.nginx.domain} = {
forceSSL = cfg.nginx.enableSSL;
enableACME = cfg.nginx.enableSSL;
locations."/" = {
proxyPass = "http://${cfg.address}:${toString cfg.port}";
proxyWebsockets = true;
extraConfig = ''
client_max_body_size ${toString cfg.binaryUploadLimit}M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
'';
};
};
};
};
};
};
};
}