In short
A 40 GB warehouse has no business travelling through a browser: put it on the server, and Linkr points at it by path — nothing is copied. The administrator’s job is to bound what that picker can reach, with LINKR_FS_BROWSE_ROOTS. By default no bound is set: it is the deployment’s job to mount only what the server should see.
The problem it solves
Every “file” entry point in a web application assumes the file is on the user’s machine. For a DuckDB file or a Parquet folder an administrator has already placed on the server, that forces an absurd detour: download the file to your machine in order to upload it back. Past the maximum upload size it is not even possible.
Pointing at a server path removes the detour. Nothing moves: Linkr reads the files where they are.
Three file origins, not to be confused
Uploading remains the right answer for small authored files — an import archive, an image, a script. The server path is for large volumes of data. There is also, in browser mode, direct access to folders on your own machine with no copy: that is the client-side equivalent. Both answer the same need — not duplicating gigabytes — each on its own side.
Where it is used
| Screen | What you point at |
|---|---|
| Databases › Add | A .duckdb or .sqlite file, or a folder of Parquet files. |
| IDE › Connections | The same thing, from the project’s coding environment. |
| Concept mapping › Vocabulary | An OHDSI vocabulary folder — several gigabytes, a dozen tables. |
| Project › Folders | The project’s three locations: IDE working directory, code sub-folder, datasets folder. |
In the add-database dialogs a Choose on the server option sits next to the upload, with the hint “Click to browse the server”. A server-side file browser then opens.
/data/warehouse,/data/vocabulariesChoose a file on the server
Elsewhere, uploading stands alone
The other entry points — archive imports, attachments, IDE files — accept uploads only. That is deliberate: those files come from the user’s machine, and adding a “server” tab everywhere would have helped nowhere.
Bounding what can be reached
This is the administration decision on this page, and it deserves to be made explicitly.
By default the picker sees the whole filesystem
With no configuration, LINKR_FS_BROWSE_ROOTS is empty and no root is enforced: the picker can traverse the entire filesystem the server can see. This is the RStudio Server model — confinement is the deployment’s responsibility: mount into the container only what the server should see.
If your server sees more than that, set roots — all the more since, with no roots, anyone who can edit databases can also create a database file anywhere the server may write.
The variable takes a comma-separated list of absolute paths:
LINKR_FS_BROWSE_ROOTS="/data/warehouse,/data/vocabularies"
The picker then never leaves those folders or their sub-folders.
What is checked, and when
Three protections stack, and the last one matters most.
A permission is required
Browsing the server is not open to everyone: pointing a database at a source requires the right to edit databases, and binding a project’s folders the right to edit its settings.
Symbolic links are resolved
A path is resolved before being compared with the roots, so a symbolic link cannot be used to escape an allowed root.
The boundary is re-checked on save
The check done in the picker is only an interface convenience. It is redone when the path is persisted — which is what stops anyone bypassing the picker by sending an arbitrary path directly.
What it does not allow
- Writing to a database pointed at. A database pointed at by path is opened read-only, and cannot be the target of an ETL pipeline. Creating a database is a different act: a database Linkr creates can be placed in a folder on the server, inside the same roots.
- Leaking the path in an export. The server path is stripped from exports, like other connection details: a shared entity does not reveal your server’s directory layout.
- Binding a project’s folders without the IDE. If code execution is disabled on the instance, folder bindings are disabled too. Pointing a database, by contrast, still works: attaching read-only data is not running code.
A vocabulary on the server is read as Parquet
A vocabulary folder pointed at on the server is read in Parquet format. A CSV OHDSI export is refused with an explicit message rather than imported empty — a readable refusal beats a silently incomplete import.
A project’s folders
A project exposes three locations, each set separately and described in its settings:
- The IDE working directory — what the file explorer shows, and where terminals and R and Python sessions start.
- The code sub-folder — the part packaged on export and versioning. Set separately precisely so an export never carries datasets that live elsewhere in the IDE folder.
- The datasets folder — reachable from scripts through an environment variable.
All three are independent and machine-local: they do not travel in an export, and another installation will use its own.
Folders
Choose which server folders this project's IDE and datasets use. These paths are specific to this server and are never included in exports.
IDE folder
The IDE working directory — what the file explorer shows and where terminals and R/Python sessions start.
Code folder
The code sub-tree packaged as scripts/ when the project is exported or versioned.
Datasets folder
Where the project's datasets live. Reachable from scripts via the LINKR_DATASETS environment variable.
When a folder changes and the old one still holds files, Linkr offers to copy them into the new one, letting you choose what to do with a file that already exists: keep both, keep the existing one, or overwrite it.
What this means for your users
Because these folders can be re-pointed, a script must never derive one location from another — writing ”../datasets” works until the day someone moves a folder. The linkr libraries provide the accessors to use. See IDE.
Going further
- Configuration — an instance’s other environment variables.
- Authentication and permissions — which rights open this picker.
- Databases — the user’s view of the same screens.
- IDE — the project’s folders, seen from the code.