Files
projectsend/docker/production/compose.example.yaml
T
ignacionelson acab833b72 Put the Docker quick start first, and fill the gaps a first install falls into
The README now opens its instructions before the screenshots, and says
what the quick start assumed: Docker Engine with Compose installed, your
own user in the docker group (so nobody reaches for sudo), and which
directory the commands run from.

The quick start also saved the file as compose.example.yaml and started
it with -f. Every later command in DOCKER.md, UPDATE.md and the migration
guide is a plain `docker compose ...`, which only finds a file called
compose.yaml, so each of them failed with "no configuration file
provided". It is now saved as compose.yaml, as the Docker Hub page
already said, with one line for people who kept the old name.

The migration guide covered "Legacy on this machine, ProjectSend in
Docker" in one sentence. It now has a worked route through a bundle. The
exporter runs with the host's own PHP, where Legacy's `localhost`
database really is local, so no container networking is needed. The
guide also says why Direct is harder there: the database, and hardlinks
that cannot cross a mount. Step 2 was run against a real v1 install on
the host (60 files, 63 MB).

Reported by @lukatong (#1635), with the install and migration gaps
pointed out by @jjoelc.
2026-09-25 01:34:38 -03:00

179 lines
6.5 KiB
YAML

# A complete ProjectSend install using the official image.
#
# 1. Save this file as compose.yaml, in a directory of its own, and edit
# the passwords and APP_URL below.
# 2. docker compose up -d
# 3. Open APP_URL — the setup screen creates your administrator account.
#
# This is the file the Docker Hub description points at, so it is written
# for someone who has never seen the project before.
name: projectsend
services:
app:
image: projectsend/projectsend:2
restart: unless-stopped
ports:
# Put a TLS-terminating proxy in front of this in any real install.
# ProjectSend issues download links and password-reset emails using
# APP_URL, so that value — not this port — is what users must reach.
#
# Bound to the loopback address, not to every interface, because
# TRUSTED_PROXIES below is "*". That setting tells the application to
# believe the X-Forwarded-For header of whoever connects to it, which
# is correct behind a proxy and catastrophic when anybody can connect
# directly: a visitor who reaches this port themselves is then the
# "proxy", and can hand the application any client IP they like —
# which is enough to walk straight through the login lockout, every
# named rate limit, and the address recorded in the download log.
#
# Publishing on the loopback address keeps the proxy (on this host,
# or in this compose file) able to reach it while nothing off the
# machine can. If you move the proxy to another host, publish on the
# interface it comes from and narrow TRUSTED_PROXIES to that address
# or subnet at the same time — the two settings only make sense
# together.
- "127.0.0.1:8080:80"
environment:
APP_URL: https://files.example.com
APP_ENV: production
APP_DEBUG: "false"
# Generated on first boot and kept on the storage volume. Set it
# explicitly if you manage secrets elsewhere — but never change it on
# a running install: it decrypts existing data.
# APP_KEY: base64:...
DB_CONNECTION: mysql
DB_HOST: db
DB_PORT: "3306"
DB_DATABASE: projectsend
DB_USERNAME: projectsend
DB_PASSWORD: change-me-database
REDIS_HOST: redis
CACHE_STORE: redis
SESSION_DRIVER: redis
QUEUE_CONNECTION: redis
# Uncomment together with the clamav service at the bottom of this
# file. It is written into the settings once, on first boot, so the
# site arrives configured — and it stays yours afterwards: the
# address and the switch are both on System → Settings → Virus
# scanning, and this line is ignored on every later boot.
# PROJECTSEND_SCANNER_DEFAULT_ADDRESS: tcp://clamav:3310
# Mail is easier to configure from System → Settings → Email once you
# are logged in — it has a "send test" button. These are the fallback
# until then.
MAIL_MAILER: smtp
MAIL_HOST: smtp.example.com
MAIL_PORT: "587"
MAIL_USERNAME: ""
MAIL_PASSWORD: ""
MAIL_FROM_ADDRESS: files@example.com
# Required whenever anything sits between your visitors and this
# container — which includes the reverse proxy you should be running.
# Without it every visitor appears to come from the proxy: the login
# rate limiter treats all of your users as one attacker, and the
# download log records the proxy's address.
#
# "*" means "trust whoever connects to me", which is only safe when
# nothing but the proxy can — which is what the loopback binding
# above is for. Change one and you have to change the other.
TRUSTED_PROXIES: "*"
# Optional: uncomment these — with a password of your own — to create
# the first administrator unattended and skip the setup screen. Left
# commented, the setup screen creates it instead. Ignored once any
# user exists.
# ADMIN_NAME: Administrator
# ADMIN_EMAIL: admin@example.com
# ADMIN_PASSWORD: change-me-admin
volumes:
# Every uploaded file lives here, along with the generated APP_KEY.
# This is the volume to back up; losing it loses the data.
- storage:/var/www/html/storage
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.4
restart: unless-stopped
environment:
MYSQL_DATABASE: projectsend
MYSQL_USER: projectsend
MYSQL_PASSWORD: change-me-database
MYSQL_ROOT_PASSWORD: change-me-root
volumes:
- db-data:/var/lib/mysql
healthcheck:
# The app waits for this before migrating, so a slow first start is
# normal rather than a failure.
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
interval: 5s
timeout: 5s
retries: 20
redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis-data:/data
# Virus scanning, off unless you ask for it:
# docker compose --profile scanner up -d
# then point Settings → Virus scanning at tcp://clamav:3310.
#
# Budget about 1-1.5 GB of memory: the virus definitions are held in
# memory. The first start downloads them and does not answer until it
# has, which the Test button on that screen reports plainly.
clamav:
image: clamav/clamav:stable
restart: unless-stopped
# Deliberately no ports. clamd has no authentication and no
# encryption, so anything that can reach it can use it, and files
# cross that connection in the clear.
volumes:
- clamav-data:/var/lib/clamav
# ClamAV's own defaults are not enough: left on them, clamd answers
# "OK" for an archive it cannot open, and every password-protected zip
# would be recorded as clean. The settings it needs are at the bottom
# of this file.
configs:
- source: clamd-conf
target: /etc/clamav/clamd.conf
profiles:
- scanner
volumes:
storage:
db-data:
redis-data:
clamav-data:
configs:
clamd-conf:
content: |
LogTime yes
Foreground yes
TCPSocket 3310
# The largest stream clamd accepts. Keep it at or above "Largest file
# to scan" on the settings screen, or larger files are not scanned.
StreamMaxLength 512M
MaxFileSize 512M
MaxScanSize 1024M
MaxRecursion 16
MaxFiles 10000
# Report what could not be opened instead of calling it clean. These
# four are the reason this file exists.
AlertExceedsMax yes
AlertEncrypted yes
AlertEncryptedArchive yes
AlertEncryptedDoc yes