I've developed "Secure File Share", an open-source, self-hostable file sharing solution that addresses a common need in our digital world: the secure sharing of sensitive files without relying on third-party services.
Inspiration
Being a developer working with a remote team, it is very common for us to share sensitive company files online, which is at risk of accidentally leaking to the outside world. Files have been scattered over email attachments, chat threads, and anywhere we communicate. For now, we adopted the password-protected files sharing feature of Google Drive but we're always looking for solutions without any 3rd party involvement and where we can have full control over our files, especially if we can self-host it. Our DevOps guy is working on a solution, but if I were to build that solution, this is how I imagine it to be.
This is also heavily inspired by Onetimesecret. This is like one time secret, but for files.
How it Works
Upload a file you want to share
Set a passphrase and expiration, then click Create Share Link
Send the share link to your intended recipient/s. It's recommended to share the passphrase separately.
The uploaded file as well as its records will all be deleted upon the specified expiration date. Upon viewing the file, the set expiration will be overwritten and will be set to 5 minutes before it's totally gone.
Key features of Secure File Transfer include:
Disposable and password protected share links
No sign-up required.
Fully self-hostable
Demo
(Update: I already took down the demo as I'm getting a lot of traffic and I don't wanna end up with a huge bill in fly.io or redis cloud😅 besides, this project is intended to be self-hosted, so that's what I encourage everyone intending to use this to do. There are hosting services out there with generous free-tier like fly.io. I highly recommend self hosting this if you're intending to use it for full security and control over your sensitive files. I'm taking down the demo but the source code will always be available. You're free to fork it, make your own modifications if you'd like, and self-host it. I left a docker-compose file there if you don't want a separate redis server, especially if you're hosting this in a VPS.
A Dev x Pinata hackathon project for secure file sharing via password-protected disposable share links.
Overview
"Secure File Transfer" is an open-source, self-hostable file sharing solution that allows users to generate secure, password-protected file share links with customizable expiration dates. This application doesn't require any logins or signups - it's designed for simple, secure file sharing.
This app mainly solves the issue of sharing sensitive information online, without the need of signing up from any 3rd party app. Since this can be self-hosted, you can have full control over your files.
How it Works
Upload a file you want to share
Set a passphrase and expiration, then click Create Share Link
Send the share link to your intended recipient/s. It's recommended to share the passphrase separately.
Database: SQLite with Prisma ORM (easily replaceable if needed)
File Storage: Pinata cloud
Background Tasks: BullMQ with Redis
I tried to be as light weight as possible when choosing the techstack and to not over engineer this. That said, I just have a simple express ts backend, ejs templates with Alpine.js (for minimal frontend interactivity) and Bulma as the CSS framework. The database is just an sqlite file since I don't see a need for a full blown database in this hackathon project, but this can be easily changed since I used Prisma ORM for it. Just modify the datasource. I use BullMQ with Redis for background tasks (handling file expiration). And of course, Pinata cloud. I hosted this in fly.io as they have a generous free tier plan but this can be hosted anywhere, like in VPS (there's a docker compose you can use).
More Details
Pinata plays a pivotal role in this project as all the shared files need to be stored somewhere, and that's where Pinata fits.
Here's the myPinata.ts file where I primarily interacted with Pinata via the Files SDK
import{FileObject,PinataSDK}from"pinata";importdotenvfrom"dotenv";dotenv.config();constpinata=newPinataSDK({pinataJwt:process.env.PINATA_JWT,pinataGateway:process.env.PINATA_GATEWAY});exportasyncfunctionuploadFile(file:FileObject){try{constupload=awaitpinata.upload.file(file);returnupload;}catch (error){console.error(error);}}exportasyncfunctiongetFileUrl(cid:string,expires=1800){try{constsignedUrl=awaitpinata.gateways.createSignedURL({cid,expires// defaults to 30 minutes (1800 seconds)});returnsignedUrl;}catch (error){console.error(error);}}exportasyncfunctiondeleteFile(fileId:string){try{constdeleted=awaitpinata.files.delete([fileId]);returndeleted;}catch (error){console.error(error);}}
I use these three functions in my endpoint handlers to handle file operations with Pinata. My background tasks also use the deleteFile function, since these background tasks are used for dispatching deletion jobs at the set expiration of the files.