# ProjectSend: a self-hosted client file portal, not general cloud storage

> ProjectSend is a GPLv2 PHP application that gives each client a private page for the files you share with them. This review covers the Docker install, the delivery model, the REST API, and where it stops being the right tool.

**projectsend/projectsend** — Share files with your clients, from your own server. Free, open source (GPLv2), self-hosted — or use ProjectSend Cloud, the official hosted version run by the same team.

- Repository: https://github.com/projectsend/projectsend
- Website: https://www.projectsend.org/
- Stars: 2,025 · Forks: 359
- Language: PHP
- License: GPL-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/projectsend-projectsend

## The problem ProjectSend solves: sending files to named people, not to a link

Most file-sharing advice assumes you want a drive. ProjectSend assumes you want a delivery. You upload a file, pick the clients or client groups who may see it, and each of them signs in to a private area that lists only their material. There is no public URL to paste into an email, and no third-party service holding the documents. The README frames the trade-off plainly: "No public link passed around by email, no third-party service holding your clients' documents, no per-seat pricing."

The audience is anyone whose work involves handing documents to outside people on a recurring basis: agencies, accountants, consultants, small practices. The client-facing side is deliberately narrow. According to the README, a client can search, filter and sort their files, download one, several as a zip, or a whole folder, and optionally leave comments on a file. Sign-in is by email address, with optional two-factor authentication, and notifications arrive in the recipient's own language.

The administrative side is where the product spends its complexity. Resumable uploads, folders, categories and client groups, share expiry dates and download limits, per-client storage quotas, custom fields, a full activity log and download history. If none of that sounds like your problem, you are not the target user. If your problem is "which client received which revision, and when," that is exactly what the log is for.

## How ProjectSend works: PHP application, queue worker, and three storage backends

The repository layout tells you most of the architecture. There is an artisan file, app/, bootstrap/, config/, database/, routes/ and storage/, which is the standard shape of a Laravel application. The frontend is Inertia with React: package.json depends on @inertiajs/react, a set of @radix-ui components, @dnd-kit for drag and drop, and Tailwind tooling via prettier-plugin-tailwindcss. Vite builds it. None of that is needed on a production server, because the release zip ships with the frontend already compiled and the README says you do not need Composer or npm there.

The runtime is PHP 8.4 or later, per the badge in the README. The compose.yaml at the repository root defines four services: app, web, worker and a database, with Redis alongside. The worker runs the queue, which is what carries email notifications and other background jobs. The web service maps port 80 in the container to ${APP_PORT:-8090} on the host. The app and web services use restart: unless-stopped, and a comment in the file explains why: a partial restart leaves "the queue runs and the site is down." The database service is gated with condition: service_healthy, so the app waits for it.

File delivery is more configurable than the README's feature list suggests, and the .env.example is where that shows. PROJECTSEND_FILE_DELIVERY accepts auto, xsendfile, nginx or php. Left unset or set to auto, ProjectSend hands files to nginx when it detects nginx and otherwise streams them through PHP, which the comment notes "works everywhere but holds a PHP worker for the whole of each download." That is a real capacity decision, not a cosmetic one: with php delivery, concurrent downloads consume PHP workers. The dashboard's System panel reports which mode is in use, which is the only place the .env.example points to for confirming it. Storage itself can be local disk, S3-compatible object storage, or Google Cloud Storage.

## Installing ProjectSend with Docker and creating the first administrator

The README calls Docker the quickest path and the one the project recommends, because the published image ships with dependencies and a compiled frontend. The documented sequence is to fetch the example compose file, edit it, then start it.

```bash
curl -O https://raw.githubusercontent.com/projectsend/projectsend/main/docker/production/compose.example.yaml
# edit the passwords and APP_URL in it, then:
docker compose -f compose.example.yaml up -d
```

After that, the README says opening APP_URL shows a setup screen that creates your administrator account. You can skip that screen by uncommenting ADMIN_EMAIL and ADMIN_PASSWORD in the compose file with a password of your own, in which case the account is created for you. The repository's .env.example lists the same trio as ADMIN_NAME, ADMIN_EMAIL and ADMIN_PASSWORD, and notes that leaving them unset uses the first-run setup screen instead. The dev compose.yaml at the repository root defaults APP_PORT to 8090, though the production example file is the one the README tells you to copy.

Before putting real files in it, the README says to read DOCKER.md, which covers where the database and uploads live, how to move them onto paths you chose, and how to back them up. That instruction is worth taking literally. On the non-Docker path, INSTALL.md covers requirements, .env, nginx, the background worker and cron, updating, and troubleshooting, and the release zip is ready to run without Composer or npm. If you are already running the application, UPDATE.md describes one command on Docker and one script on your own server. A git clone is not an installation: the README states that dependencies and the compiled frontend are deliberately absent from git, so a clone needs Composer and npm before it runs.

## File delivery, quotas and the failure modes the documentation leaves open

The most consequential limitation is the one the .env.example describes in a comment rather than the README in a feature bullet. If you do not configure PROJECTSEND_FILE_DELIVERY, you may end up on PHP streaming, where every download occupies a PHP worker for its whole duration. On a small installation that is invisible. On one where several clients pull large archives at once, it is the difference between a slow download and a site that stops answering. Setting nginx or xsendfile moves the transfer off PHP, but each requires the surrounding server to be configured for it, and the file only says the dashboard's System panel shows which mode is in use.

The CAPTCHA flag is a small but telling design decision. PROJECTSEND_CAPTCHA_DISABLED exists as an emergency off switch for an operator who has a shell but no working login. Only true or 1 disables it; anything else, including no, off, or a misspelling, leaves the CAPTCHA on. The comment states the reasoning: a flag that removes a protection should not do so because a value was typed wrong. That is defensible, and it also means a hurried operator who writes yes will not get what they expected.

On the client side, the migration documentation names the change recipients will notice: they sign in with their email address now, using the same password. That is a communication task, not a technical one, and it lands on you. There is also a platform gap: people ask about a ProjectSend Android app, and nothing in the README or the repository listing describes a mobile application. The interface is a web application, so phone access means a browser.

Finally, the README points to LICENSING.md for the boundary between the free core and the hosted ProjectSend Cloud, and says commercial licenses exist for organizations that cannot work under copyleft. If your legal position on GPLv2 matters, that file, not this article, is the one to read.

## ProjectSend compared with Nextcloud, and what the migration tool actually does

The comparison people search for is ProjectSend versus Nextcloud, and the difference is structural rather than a feature count. Nextcloud is a general collaboration platform: file sync across devices, office documents, calendars, chat, and a desktop client that keeps folders in step. ProjectSend has none of that. It has no sync client in the repository listing, and its client experience is a web page listing the files shared with that account. If your users expect a folder on their laptop that mirrors the server, ProjectSend is the wrong tool and Nextcloud is the right shape.

The reverse also holds. In Nextcloud, sharing to an outside person usually means a public link with a token, and the recipient is not an account you manage. ProjectSend's model is the opposite: recipients are accounts with quotas, custom fields, group membership and a download history, and there is no public link to leak. If your requirement is "prove that this client downloaded revision 3 on this date," that is native here and bolted on there.

The clearest evidence that ProjectSend treats itself as a delivery portal rather than a drive is the v1 migration tool. The README is explicit that this generation is "a rebuild rather than an upgrade," so moving from ProjectSend Legacy is an import, not an update. You install fresh, then bring the old site across with the migration tool: accounts, clients, groups, categories, folders, files and history. The tool never writes to your old install, and any run can be undone with a single command. MIGRATING-FROM-V1.md describes what comes across and the two routes, same machine or a portable export from a server you cannot reach. That level of care about import reversibility is unusual, and it tells you the maintainers expect real installations with years of history to move.

## Maintenance, upgrade cost and the GPLv2 question

Maintenance signals here are strong on the surface. The repository is not archived, the last push was on 2026-09-09, and three releases landed in the weeks before that: v2.4.0 on 2026-09-08, v2.3.0 on 2026-09-01, and v2.2.1 on 2026-08-28. Release notes for those versions are not in the README, so what changed in each is something you would read in CHANGELOG.md rather than infer from the tags.

The upgrade path is documented and short. UPDATE.md describes one command on Docker and one script on your own server, plus what to check afterwards. The repository also ships update.sh at the root, which is consistent with that description. The cost that does not go away is the one the README warns about: where your database and uploads live. On Docker, DOCKER.md covers moving them onto paths you chose and backing them up so an upgrade cannot take them with it. If your volumes are still on default paths you have not inspected, an upgrade is the moment you find out.

On licensing, the project is under the GNU General Public License v2, or at your option any later version. The README states that commercial licenses are available for organizations that cannot work under copyleft terms, and points to LICENSING.md for both options. Contributions require signing a CLA, with the reasons given in CONTRIBUTING.md. Whether copyleft obligations reach your deployment is a question for your own counsel; the relevant files are LICENSE, LICENSING.md and the two CLA documents at the repository root.

## Conclusion

Adopt ProjectSend if you send documents to a defined set of clients and want those files on your own server, with per-client pages, download history and quotas. Do not adopt it as a general cloud drive for your own team, or if you cannot run PHP 8.4+ and a database. Before committing, verify three things in your own environment: that the file delivery mode shown in the dashboard's System panel is the one you intended, that storage/app/files and your database sit on paths your backup covers, and that your clients accept signing in with an email address, which the migration notes flag as the one change they will notice.

## FAQ

### How do I install ProjectSend with Docker?

The README's recommended path is to download docker/production/compose.example.yaml, edit the passwords and APP_URL, then run docker compose -f compose.example.yaml up -d. Opening APP_URL shows a setup screen that creates the administrator account, unless you set ADMIN_EMAIL and ADMIN_PASSWORD in the file first.

### What is ProjectSend?

It is a self-hosted PHP application for sending files to clients. You upload files, choose who can see them, and each client signs in to a private page to download them, with no public link and no third-party service holding the documents.

### How do I use ProjectSend?

After installation, you upload files and share them with one client, a whole group, or publicly, with an optional expiry date or download limit. Clients sign in with their email address and see only the files shared with them, which they can search, filter, download individually, as a zip, or as a whole folder.

### How does ProjectSend compare with Nextcloud?

Nextcloud is a general collaboration and file-sync platform, while ProjectSend is a client portal: recipients are managed accounts with quotas and a download history rather than holders of a public link. ProjectSend has no desktop sync client in the repository listing.

### Is there an open-source way to share files with clients?

ProjectSend is one: it is released under the GNU General Public License v2 or later, runs on your own server, and gives each client a private page listing only the files shared with them.

### What is the best self-hosted file sharing platform?

That depends on the model you need. ProjectSend is built for delivery to named clients, with per-client accounts, quotas and download history, rather than for syncing folders across your own devices, which is the shape of a general collaboration platform.

## Sources

- [License: GPL-2.0](https://github.com/projectsend/projectsend/blob/main/LICENSE)
- [projectsend/projectsend on GitHub](https://github.com/projectsend/projectsend)
- [Project website](https://www.projectsend.org/)
- [README](https://github.com/projectsend/projectsend/blob/main/README.md)
- [Releases](https://github.com/projectsend/projectsend/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/projectsend-projectsend
