Send
Upload files, create a share, and send a browser link. Add a password, expiry or view limit, and send recipient email notifications.
THE FIELD GUIDE
Practical documentation for running Amfora and using it to send, collect and manage files.
01 / Start here
Amfora keeps file metadata in SQLite and stores objects through an S3 compatible storage layer. The image includes a private MinIO service for a zero configuration starting point, and can use an external S3 compatible provider when that better fits your infrastructure.
Upload files, create a share, and send a browser link. Add a password, expiry or view limit, and send recipient email notifications.
Publish a receive link so people can upload without an Amfora account. Set limits before sharing it.
Manage users and groups, folders, the trash, links, branding, two factor authentication, passkeys, and optional OAuth2/OIDC providers.
02 / Install
You need Docker with Compose v2 and a running Docker engine. Run
this command from a directory without an existing
amfora folder:
curl -fsSL https://amfora.solutionmax.net/get | sh
The installer script checks Docker and Compose,
creates an amfora directory with a compose file pinned
to the current release, pulls
ghcr.io/solutionmax/amfora (amd64 and arm64) and
starts it. Existing Amfora directories, containers or data volumes
are refused. It does not install Docker or configure HTTPS.
To inspect the script before running it:
curl -fsSL https://amfora.solutionmax.net/get -o amfora-get.sh
less amfora-get.sh
sh amfora-get.sh
To build the release yourself, add --source: the
installer clones the release tag and builds it, which also needs
Git, Bash and Buildx 0.30 or later. The build reuses layers in a
dedicated Amfora builder and keeps unused cache near a 4 GB
target; make clean only reclaims build cache.
Open http://localhost:5487. The first start creates
the SQLite database, seeds configuration, and makes the first
account created on an empty database an administrator. Later
accounts are ordinary users unless an administrator creates or
promotes them.
The sample Compose file publishes the web interface on
5487 and bundled storage on 9379. The
API listens on 3333 inside the container and is left
unpublished because the bundled web app reaches it through its
server side proxy.
For access from another computer, change
STORAGE_URL from localhost to the storage address
that computer can reach. For public use, complete the HTTPS setup
below before sharing the instance.
03 / Production
Use a trusted reverse proxy for both the web interface and the browser facing storage endpoint. A split domain deployment can look like this:
https://app.example.com → container port 5487
https://files.example.com → container port 9379
Set the values that describe that public arrangement:
environment:
SECURE_SITE: "true"
STORAGE_URL: "https://files.example.com"
STORAGE_URL is the URL used by a browser, not the
address one container uses to reach another. The storage hostname
must forward to the internal storage service and accept the
browser’s upload and download requests. Keep the API on the
private container network unless you operate another authenticated
API client.
For Caddy running on the same host, bind the application ports to localhost in Compose. Replace the domains below with your own and point their DNS records at that host.
ports:
- "127.0.0.1:5487:5487"
- "127.0.0.1:9379:9379"
app.example.com {
reverse_proxy 127.0.0.1:5487
}
files.example.com {
reverse_proxy 127.0.0.1:9379
}
The product website at amfora.solutionmax.net is
separate from your Amfora application. These example domains do
not provide a hosted Amfora service.
Forward the original host and protocol through the proxy.
SECURE_SITE=true enables secure cookies. Configure
HSTS at your HTTPS reverse proxy. Set
TRUST_PROXY=false when the API is exposed without a
trusted proxy in front of it.
04 / Storage
Leave ENABLE_S3=false (the default) to run the
included MinIO service. Set STORAGE_URL to the public
URL that browsers can reach. The Compose example uses
http://127.0.0.1:9379 for local use. The bucket is
private and the container writes its generated credentials under
the persistent application directory.
Set ENABLE_S3=true and provide the external endpoint
and credentials. The endpoint and bucket must be reachable and
permitted for the browser requests represented by generated upload
and download URLs.
ENABLE_S3=true
S3_ENDPOINT=s3.example.com
S3_PORT=443
S3_USE_SSL=true
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key
S3_REGION=us-east-1
S3_BUCKET_NAME=amfora-files
S3_FORCE_PATH_STYLE=false
Use S3_FORCE_PATH_STYLE=true for providers such as
MinIO. If a provider rejects the SDK checksum, set
S3_DISABLE_CHECKSUMS=true as documented by that
provider. Keep S3_REJECT_UNAUTHORIZED=true unless you
have a deliberate certificate exception.
A new installation seeds a 1 GiB maximum file size and 10 GiB
maximum storage per user. Administrators can adjust those values
in Settings, and set a different storage limit for one user in the user
form on the Users page. PRESIGNED_URL_EXPIRATION controls the
default generated storage URL lifetime in seconds and defaults to
3600.
05 / Daily work
The application opens at sign in, or your dashboard when you are already signed in. The dashboard gives you a starting point for files, shares and upload requests. Use folders to organize files before creating a share. Profile manages your personal details and account security; administration controls are available to administrators.
/s/<alias> link.A share can have a password, expiration date, maximum view count, and recipient email notifications. Recipient entries do not restrict access to a public share. Its owner can later edit the contents, notification recipients, password, expiry, or alias from Shares. A recipient opens the link in a browser; a protected share asks for its password before files are available.
Use the share menu to copy its link. Open the QR code action to display or download a PNG that points to the same URL. After changing an alias or application hostname, generate a new QR code and replace any older copies. Anyone with the link or code can reach the share, subject to its restrictions.
/r/<alias> link.The sender uploads from the public receive page without an Amfora account. The owner reviews the received files in Reverse shares.
/x/<id>#<key> link straight away.
It is shown once.
The text is encrypted in your browser. The key is the part of the
link behind the #, which a browser never sends to a
server, so nobody can read the secret without the link, also not
an administrator. After the last opening, or when its time runs
out, the text is destroyed. Three wrong passphrases destroy it too.
The reader presses one button to see the secret. Loading the page costs nothing, so a chat app that fetches the link for a preview cannot use it up.
An administrator can open /secret to visitors without
an account, with its own limits, under Settings,
Security. It is off by default. A full access API
key can store secrets too; the sealing recipe and test vectors are
in
SECRETS.md.
Activity lists what happened to your links and your account: a share opened or downloaded, a wrong password, files received, a secret opened, a sign in. A user sees their own links, an administrator sees everyone, and the list can be exported as CSV. It is kept for 90 days unless you change that.
Each line can say where a visitor was. The address itself is never stored. Places need a database you supply in MaxMind format, for example the free DB-IP City Lite; without it only your own network is recognised. See ACTIVITY.md for the file location and for running behind a reverse proxy.
On a share you can ask for an email when it is downloaded, and on a share or receive link for a reminder three days before it ends. Both need outgoing email. Under Settings, Security you can also give one webhook address that is called, signed, when files are received, a share is downloaded or a secret is opened.
06 / Administration
Administrators can invite users, list and deactivate accounts, change roles, set storage limits, customize the installation, configure SMTP, and manage external login providers. Invite links are one time registration links.
Open Customization to set the application name, description, logo, accent color, font and corner radius. All of it is stored on the server, so every visitor sees the same brand; the logo also replaces the mark in link previews and the favicon. Check the result in both light and dark themes, on mobile, and on a public upload and download page. Use Settings for storage limits, language, email and authentication configuration.
Free installations show "Powered by Amfora" on the public pages. A brandpack is a signed key that removes that credit and unlocks two more settings: a background image for the public pages and custom CSS. Paste the key under Customization → Brandpack and press Activate; the installation verifies the signature itself with a public key that ships in the source, so nothing has to reach SolutionMAX for it to work. Removing the key brings the credit back and keeps the stored background and CSS for the next activation.
Custom CSS is admin-only and sanitised on the server: imports,
external URLs, expressions and behaviours are removed and the size
is capped at 20 kB. The background image is converted to WebP,
resized to 2400 px wide and served from
/api/app/background. Details for operators and
vendors are in
docs/BRANDPACK.md.
Each user can enable TOTP in their profile, verify setup with an authenticator, save backup codes, and remove trusted devices. A 2FA login verifies the password first and then accepts a TOTP or unused backup code. Users can also add passkeys on their profile and sign in with them. See Sign in security for requiring a second step.
External login is optional. A new installation offers Authentik, GitHub and Google. Any other compatible OIDC or OAuth 2.0 provider can be added with Add provider. Match callback URLs and client settings at both ends. Keep password authentication enabled until an external provider has been tested; disabling it also disables password reset.
Password reset requires password authentication and a working SMTP configuration. Responses deliberately do not reveal whether an email address exists. For operator recovery, the container includes an interactive reset tool:
docker compose exec amfora sh -lc 'cd /app/amfora-app && ./reset-password.sh'
docker compose exec amfora sh -lc 'cd /app/amfora-app && ./reset-password.sh --list'
Under Customization, Download page, upload one image to use as the cover at the top of every download page. The same image is the preview in WhatsApp, Slack and similar apps; a separate default link preview image is used when no cover is set. Files from a share are never used for either.
Download pages do not play video and audio. Visitors see no play or Preview button for those files and the server refuses to stream them; they download instead. Images, PDFs and text keep their preview.
07 / Version 2.4
The settings and options an administrator meets in Amfora 2.4. Everything here is optional or has a default that changes nothing for an existing installation.
Deleting a file or folder in the workspace moves it, with everything in it, to the Trash page. Restore puts it back where it was. Delete for good and Empty trash are the only places where files leave storage. Deleted items show nowhere else and count toward the storage limit. Everybody sees only their own trash.
Under Settings, Storage:
trashRetentionDays):
days an item stays in the trash before it is deleted for good.
Once a day the server cleans up. Default 30, at least 1.
expiredLinkRetentionDays): days after which a share
or receive link that has ended is removed. Default 0, which means
never. Only the link goes: its files stay in the workspace. A
receive link that holds files stays. Each removal is written to
the activity log.
Under Settings, Security, choose whether administrators, everyone or nobody must set up two step sign in or a passkey. Turning it on signs nobody out. A user who has neither is taken to a set up page and cannot use anything else until it is done. API keys and users who sign in through an external provider are not affected.
An administrator can switch off the two step sign in of another
user on the Users page (passkeys stay). Passkeys need an https
address or localhost.
If the only administrator loses the authenticator while the
requirement is on, start the server once with
TWO_FACTOR_REQUIRED=off. It wins over the setting, so
you can sign in and repair the account. Remove the variable and
recreate the container afterwards with
docker compose up -d.
On the Users page, the Groups tab lets an administrator create, rename and delete groups and add or remove members. A share can be limited to one group under “Who can open it”. It then opens only for a signed in member, its maker and administrators. Members find such shares under Shared with me on the Shares page. Removing somebody from a group takes the access away at once. A group that shares still use cannot be deleted.
GET /api/v1/metrics answers in the Prometheus text
format: version, database and storage up, users, files and bytes,
the trash, shares, receive links, secrets, the data disk and the
virus scan. Only the API key of an administrator opens it. The
answer is cached for 30 seconds, so scrape every 30 to 60 seconds.
curl -s https://files.example.com/api/v1/metrics \
-H "Authorization: Bearer amf_..."
Examples for Prometheus and Zabbix are in MONITORING.md.
Set CLAMAV_HOST to the address of a
ClamAV scanner (clamd) and
Amfora checks every uploaded file after the upload, one at a time,
also files received on a receive link. While a file is being
checked or is infected nobody can download, preview or share it;
its owner can only delete it. An infected file is written to the
owner’s activity log, shown in the bell and mailed to the
owner and the administrators. Without CLAMAV_HOST
nothing changes. ClamAV needs about 1.2 GB of memory.
services:
amfora:
environment:
CLAMAV_HOST: "clamav"
clamav:
image: clamav/clamav:stable
environment:
CLAMD_CONF_StreamMaxLength: "100M"
volumes:
- clamav_data:/var/lib/clamav
mem_limit: 2g
volumes:
clamav_data:
The full recipe, the retry times and what each status means are in VIRUS-SCAN.md.
Amfora comes in English, Dutch, German, French, Spanish, Italian, Portuguese (Brazil) and Polish. Users pick their language in the language picker; the default is set under Settings. Italian, Portuguese and Polish were translated without review by a native speaker.
TWO_FACTOR_REQUIRED: off,
admins or all. Wins over the setting
in Settings. Use it to get back in after a lockout, then remove
it.
CLAMAV_HOST: address of clamd. Unset means no
virus scan.
CLAMAV_PORT: the TCP port of clamd, default
3310.
CLAMAV_MAX_SIZE_MB: files above this size are not
scanned and show as “Not checked”. Default
100.
08 / Operate
Back up the complete persistent
/app/server directory, including
prisma/amfora.db, minio-data, and
generated storage credentials. Stop the container or use a
filesystem snapshot consistent for the database and objects.
Back up the SQLite database and the external S3 bucket through that provider’s supported process. Keep the database and object backup points close enough to restore a consistent workspace.
Your files and settings live in the persistent volume; an update
only replaces the image. In the amfora directory, set
the new version in docker-compose.yaml and run:
docker compose pull
docker compose up -d
Startup applies the Prisma schema and seeds missing
configuration and provider records. Older database filenames are
migrated to prisma/amfora.db; an existing internal
bucket is preserved when no explicit bucket override is supplied.
Verify a test share and download afterwards, and keep the
previous image until the new one runs so you can switch back.
The first start of 2.4.0 adds the tables and columns for the trash, scan status, passkeys, groups and the storage limit per user, by itself. Going back to an older version needs the database backup from before the upgrade.
The admin area shows when a newer release is out. To let the host install signed releases for you with one click, set up over the air updates once. Every release is on the releases page.
09 / Troubleshooting
STORAGE_URL is browser reachable,
forwards to the storage service, and accepts the storage
requests. Then inspect
docker compose logs -f amfora.
.minio-credentials in the persistent directory. For
external S3, verify every S3_* value and bucket
permission.
SECURE_SITE=true for HTTPS, and set
TRUST_PROXY=false when no trusted proxy is present.
.minio-credentials.
10 / About Amfora
Amfora is a self hosted file workspace for sending files, collecting uploads, and managing access. This guide covers the installation, storage, sharing, and administration workflows that keep a handoff moving.
The application source is publicly available on GitHub. No account or access request is required. Amfora has its own visual identity and ongoing improvements. Its upstream attribution is preserved in NOTICE. It is licensed under the Apache License 2.0. Bundled MinIO and mc are separate, unmodified AGPL-3.0 programs. See LICENSE, NOTICE and the bundled program license.
Fonts: Bricolage Grotesque and Plus Jakarta Sans, distributed under the SIL Open Font License. Font license files are included with the source repository.
No matching topics. Try “storage”, “password” or “upload”.