Self-hosted service
psi-4ward/psitransfer avatar
psi-4ward/psitransfer

PsiTransfer for Self-Hosted File Sharing

Simple open source self-hosted file sharing solution.

1,962 stars244 forksJavaScriptBSD-2-Clause

At a glance

What is it?
PsiTransfer is a JavaScript-based, self-hosted file sharing service for sending large files through browser-based buckets. It emphasizes resumable transfers, optional download controls, and simple Docker deployment, but it does not provide end-to-end payload encryption.
Who is it for?
Adopt PsiTransfer when a small internal or self-hosted file exchange service is enough and the deployment owner accepts its security boundaries. Do not treat it as an end-to-end encrypted transfer system, and verify Node compatibility, storage permissions, HTTPS exposure, and password configuration before placing real files behind it.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 143 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What PsiTransfer Is For

PsiTransfer addresses the basic problem of moving files between people without requiring an account. A user creates an upload bucket, sends its identifier through another channel, and the recipient uses that identifier to retrieve the files. The README describes this as an alternative to paid services such as Dropbox and WeTransfer, but the actual scope is narrower than a general-purpose cloud storage system. It is aimed at operators who want to host their own transfer service and at senders who need a direct browser interface rather than an organization account.

The service supports many and very large files through streaming. It also provides resumable uploads and downloads through tus.io, configurable upload expiry, one-time downloads, and archive downloads in zip or tar.gz format. A bucket can be addressed with an explicit identifier through the `sid` query parameter. The interface is responsive for mobile use and includes a modal-style file preview.

This model suits temporary transfers, internal file exchange, or a hosted replacement for sending large attachments. It does not document collaboration, accounts, persistent user ownership, synchronization, version history, or a storage quota policy. Those absences matter when comparing it with a managed file storage product. PsiTransfer concentrates on handing a bucket to another person rather than managing files inside a long-lived account.

How PsiTransfer Handles Uploads and Buckets

The repository layout shows a Node.js application entry point in `app.js`, supporting libraries under `lib/`, frontend sources under `app/`, server-rendered templates under `public/pug/`, language files under `lang/`, and plugins under `plugins/`. The `package.json` scripts start the application with `NODE_ENV=production node app.js`. The README identifies streams as the reason PsiTransfer can handle many and very big files, while resumable transfers rely on tus.io.

Configuration controls the listening port and data directory in `config.js`. Operators can edit that file, although the README marks this approach as not recommended. The preferred choices are a `config.production.js` file whose name matches the production value of `NODE_ENV`, or environment variables such as `PSITRANSFER_UPLOAD_DIR`. A second environment variable, `PSITRANSFER_UPLOAD_PASS`, is intended to restrict unwanted or unauthorized uploads when the service is exposed to the internet.

The application also has an `/admin` page for bucket information. It is disabled until `adminPass` is set in configuration. Download lists can be password protected using AES. These are server-side access controls, not client-side end-to-end protection. The repository layout also includes Docker and plugin files, indicating that the default deployment is a self-contained Node service with persistence supplied through a data volume.

Docker Setup and First Upload

The documented Docker path is the shortest route to a running service. It maps host port 3000 to container port 3000, sets an administrator password, and mounts the current `data` directory at `/data`. The README states that the data volume needs UID 1000, so the host directory must be owned by that user before starting the container.

bash
$ docker run -p 0.0.0.0:3000:3000 -e PSITRANSFER_ADMIN_PASS=secret -v $PWD/data:/data psitrax/psitransfer
# data volume needs UID 1000
$ sudo chown -R 1000 $PWD/data

The command uses the unversioned image, which the README identifies as corresponding to the `master` branch. For a stable major version, the README lists the `2` image tag, while `1.1` and `1.0.0` identify older stable lines. The Docker image is based on `node:24-alpine`, exposes port 3000, declares `/data` as a volume, runs as the `node` user, and starts with `node app.js`.

After the container starts, the operator can open the published service, create an upload bucket, and send the bucket identifier to the recipient. The README does not document a specific URL path or API sequence for creating a bucket beyond the browser interface and the `sid=<myBucketID>` query parameter. It also does not document TLS termination, so a public deployment needs an independently confirmed HTTPS arrangement.

Running PsiTransfer from Source

The manual source path is appropriate when the frontend must be built locally or the Docker image is not part of the deployment plan. The README first asks for a frontend build in `app`, then installs the root dependencies and starts the application. Its stated Node guidance is older than the repository's package metadata: the README says Node >= 12 in the manual section, while `package.json` declares `engines.node` as `>= 24` and the Dockerfile uses `node:24-alpine`.

bash
# Compile the frontend apps
$ cd app
$ npm install
$ npm run build

# Install dependencies
$ cd ..
$ npm install
$ npm start

The root `npm start` script sets `NODE_ENV=production` and runs `app.js`. The frontend build is not needed for the precompiled release path described in the README. That path tells users to download and extract the latest release package, then run:

bash
$ NODE_ENV=production npm install
$ npm start

For a quick manual check, the package scripts also define `npm test`, `npm run test:unit`, and `npm run test:integration`. The README does not describe their expected output or provide test setup instructions, so they should not be treated as documented deployment acceptance criteria. The repository contains a `tests/` directory, but the README does not explain coverage or test prerequisites.

Configuration, Controls, and Operational Limits

PsiTransfer has useful controls for a temporary transfer service. Upload buckets can expire, download lists can be password protected, and downloads can be configured as one-time operations. The `/admin` page provides bucket information once `adminPass` is configured. These features are most relevant when an operator controls the host and needs to reduce the lifetime or discoverability of a shared transfer.

There are two important boundaries in the documentation. First, the README explicitly says that there is no end-to-end payload encryption yet. Password protecting a download list does not change that statement. The service should therefore not be described as protecting file contents from the server host, a network intermediary, or every component involved in serving the transfer. Second, `Download all as ZIP` does not support resuming the download. A large archive transfer can therefore lose its resumability even when ordinary file downloads support it.

The application is designed for streaming, but the documentation does not state maximum bucket size, maximum file count, timeout behavior, disk quota enforcement, or retention cleanup details beyond setting an expiry time. Operators should verify those limits against their storage and network requirements. The `/admin` page is also not an authentication system for ordinary users. It is an administrative view that remains disabled until `adminPass` is set.

PsiTransfer Compared With Managed File Storage

PsiTransfer and managed services such as Dropbox or WeTransfer use a different operational model. PsiTransfer gives the operator control over the host, the data directory, upload configuration, and browser interface. It does not require accounts or logins according to the README, which can simplify a temporary exchange where both parties already trust the operator.

A managed service generally supplies its own storage, user identity, account recovery, access policy, and operational infrastructure, although those exact features are not described for any particular competitor here. PsiTransfer leaves those concerns to the deployment owner. The tradeoff is direct: self-hosting can fit a controlled environment and avoid depending on a hosted account, but it also requires Node.js, persistent disk, container or process management, and decisions about network exposure.

For a small internal transfer endpoint, PsiTransfer's streaming, tus.io support, expiry controls, and one-time download option are more relevant than a large collaboration suite. For a public service with unknown users, the absence of end-to-end payload encryption and the lack of documented quotas, retention policy, and TLS instructions deserve more weight. A dedicated self-hosted storage system would be the better comparison when users need durable directories, permissions, or long-term availability rather than temporary handoff.

Licensing and Maintenance Status

The repository declares `BSD-2-Clause` in `package.json`, and the README links to the repository's `LICENSE` file. That designation identifies the project's published license, but it does not answer questions about the licenses of bundled dependencies or the obligations of a particular deployment. This review does not provide legal advice.

The repository is not archived. Its last push was on 2026-06-02, and the listed releases include `v2.4.4` on 2026-06-02, `v2.4.3` on 2026-04-14, and `v2.4.2` on 2026-04-13. Those dates indicate recent repository activity and a sequence of patch releases, but the README does not provide a maintenance policy or upgrade procedure. The version discrepancy is operationally important: `package.json` requires Node >= 24, while the README's manual instructions mention Node >= 12. The Docker image's `node:24-alpine` base is consistent with the package metadata.

The license and release history can inform an initial review, but they do not remove the need to inspect the exact Docker tag, persisted data format, and configuration before an upgrade. The repository's `package-lock.json` and `Dockerfile` provide concrete files to check when planning a reproducible deployment.

Editorial conclusion

Adopt PsiTransfer when a small internal or self-hosted file exchange service is enough and the deployment owner accepts its security boundaries. Do not treat it as an end-to-end encrypted transfer system, and verify Node compatibility, storage permissions, HTTPS exposure, and password configuration before placing real files behind it. The repository requires Node >= 24 in package.json, while the README still gives older Node guidance, so the runtime requirement must be checked first.

Frequently asked questions

How do I install PsiTransfer with Docker?

The README documents a Docker command that publishes port 3000, sets `PSITRANSFER_ADMIN_PASS`, mounts `$PWD/data` at `/data`, and runs `psitrax/psitransfer`. It also says to give the data volume UID 1000.

Does PsiTransfer provide end-to-end encryption?

No. The README explicitly states that there is no end-to-end payload encryption yet. It does document password protection for download lists using AES, but that is not the same as end-to-end payload encryption.

Can PsiTransfer handle large files and resume transfers?

The README says PsiTransfer supports many and very big files through streams and supports resumable uploads and downloads through tus.io. It separately notes that downloading all files as a ZIP does not support resuming the download.

Official sources

  1. Issues
  2. License: BSD-2-Clause
  3. psi-4ward/psitransfer on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/psi-4ward-psitransfer.svg)](https://hysenlabs.com/projects/psi-4ward-psitransfer)

Was this useful?