# Web portal and links

The portal is a browser interface to the same files FTP and SFTP serve.
Users sign in with their password to browse, download, and upload. An
operator can also make a link that opens one folder for someone with no
account, to collect files or hand them out.

The portal runs on the admin listener, next to the console. `/` is the
portal and `/admin/` is the console.

## Turn it on

The portal needs the console origin, so set up the [admin
console](/docs/console.html#turn-it-on) first, then:

```toml
[admin]
bind = "0.0.0.0:443"
tls = true
public_url = "https://files.example.com"

[portal]
enabled = true
```

Reload or restart siftpd, then open `https://files.example.com`.
Links are built from `public_url`, so it must be the address people
will use. The portal is off by default. `[portal]` keys are in
[Configuration](/docs/configuration.html#portal).

## What users see

A user signs in with the same name and password they use for FTP and
SFTP. They see their root, limited by their own permissions
([Users and access](/docs/identity.html)):

- **Browse and download** with `r` and `l`.
- **Upload** files and whole folders with `w`; make folders with `m`.
- **Rename and delete** with `n` and `d`.
- **Share** a folder, if they have the permissions the link would need.

Quota, rules, bans, and the audit log are the same as on the other
protocols. Sessions end after 30 minutes idle or 12 hours, and
changing a user's password ends that user's sessions.

Downloads are always saved as files, never shown in the browser, so a
file someone uploaded cannot run as a page on your host.

## Links

A link opens one folder, as if it were the whole server. Whoever holds
the URL can use it until it expires or you revoke it. It looks like
`https://files.example.com/#/s/siftp_shr_...`.

### Modes

| Mode | Bits | What the holder can do |
| --- | --- | --- |
| Read | `rl` | Browse and download |
| Upload and view | `rlwm` | Also upload files and make folders. Cannot delete, rename, or overwrite |
| Upload only | `wm` | Upload files and make folders. Sees nothing in the folder and cannot download |

A link never does more than its owner can in that folder. If Erin has
only `rl` on `/clients`, nobody can make an upload link there.

A link never overwrites a file. An upload that collides with an
existing name is saved under a new one (`report (1).pdf`).

### Expiry and passwords

- Expiry: 1, 7, 30, or 90 days, or never. The default is 7.
- An optional password, 8 to 256 characters. The holder enters it
  after opening the link. Wrong guesses count toward bans like failed
  logins.
- A label, shown to the holder and in the Links list. It defaults to
  the folder's name.

### Make a link from the console

1. Open **Users**, then the user, and browse to the folder in their
   files.
2. Choose **Share** (on a folder row, or **Share this folder**).
3. Pick the mode, expiry, optional password and label, and optionally
   an address to notify when files arrive.
4. Confirm with your passkey. The dialog shows the URL to copy.

The **Links** page lists every link: folder, owner, mode, expiry, last
use. You can copy a link again later and revoke it there.

### Make a link from the portal

A user can share their own folders. Open the folder, choose **Share**,
and pick the mode, expiry, and password. siftp asks for the user's
password again first. Users cannot set a notify address. A user can
list, copy again, and revoke their own links; they never see anyone
else's.

Only passkey sessions and signed-in users make links. A personal access
token, an OAuth token, the admin token, and MCP tools cannot create,
list, or show them.

### Revoke

Revoke a link in the Links list. It stops working at once, and anyone
signed in through it is signed out. Deleting `<shares_file>.key` ends
every link at once.

### How the secret is kept

siftp stores only a link's id and settings. The secret part of the URL
is computed from the id with a key kept in `<shares_file>.key` (default
`/var/lib/siftp/shares.toml.key`, mode 0600). That is why the Links list
can show a URL again, and why a copy of `shares.toml` alone opens
nothing. Back up both files together. A new key file means every
earlier link stops working.

## Uploads

Uploads go in 8 MiB chunks, so large files work through proxies and
slow connections. If the connection drops, the browser asks the server
how much arrived and continues from there. An upload nobody touches for
24 hours is discarded.

A file may be up to `[portal].max_upload_bytes`, 50 GiB by default.
Larger files are refused before any byte is sent. The user's quota
applies as well.

Limits to know about:

- Uploads in progress do not survive a server restart. The partial
  file stays under its final name, so remove it or upload again.
- There is no per-link size limit. The cap above applies to every
  upload.
- Folders download one file at a time. There is no ZIP download.

## Upload notices

A link can email an address when files arrive. Turn it on with
[Resend](https://resend.com):

```toml
[email]
resend_api_key = "${ENV:RESEND_API_KEY}"
from = "siftp <files@example.com>"
```

`from` must be on a domain you verified in Resend. When the first file
arrives through a link, siftp waits five minutes, then sends one
message listing the files that came in, up to 100 and then "and N
more". The subject reads "3 files arrived in Acme". The message never
contains the link. Details are in
[Configuration](/docs/configuration.html#email).

## Audit

Everything through the portal is audited like the other protocols
([Operations](/docs/operations.html)):

| Action | Meaning |
| --- | --- |
| `LOGIN` | Password sign-in (path `web`), or opening a link (path is the folder, actor `link:<id>`) |
| `READ`, `WRITE` | A download, a finished upload |
| `MKDIR`, `RENAME`, `REMOVE` | Folder and file changes |
| `SHARE_CREATE`, `SHARE_URL`, `SHARE_REVOKE` | Making, showing again, and revoking a link; the actor is the admin or user |

Lines for the portal carry `actor` `web` or `link:<id>`, and `user` is
the owner of the files. The link's id is in the Links list.
