448 lines
26 KiB
Markdown
448 lines
26 KiB
Markdown
# RustPad
|
|
|
|
RustPad is a collaborative Markdown editor with standalone notes and workspaces.
|
|
|
|
## Release 0.2.97 — proportional image resize and stable PDF pagination
|
|
|
|
- Image resize controls keep the source image proportions by default. Editing width automatically updates height and editing height updates width.
|
|
- The image toolbar adds a **Keep proportions** checkbox; disabling it allows independent width/height edits and free two-axis drag resizing.
|
|
- Drag resizing now uses the image's natural aspect ratio when available instead of preserving an accidentally distorted stored size.
|
|
- PDF pagination renders movable text blocks as atomic print fragments, eliminating Chromium's thin "ghost" text artifact when headings, paragraphs, blockquotes, or definition entries move to the next page.
|
|
- Oversized text blocks still fall back to normal page splitting so long content is never clipped or forced off-page.
|
|
|
|
## Release 0.2.96 — PDF layout, inline rename and PDF tags
|
|
|
|
- Pressing Enter while renaming a note title no longer bubbles to the header copy-link shortcut.
|
|
- The More menu exposes PDF page break, header, footer, align-top, and align-center directives.
|
|
- `[PDF_PAGEBREAK]` is the canonical explicit PDF page-break tag. Legacy `[PAGEBREAK]` remains supported for existing notes.
|
|
- PDF controls are listed near the top of **More** and the menu scrolls on short viewports.
|
|
- Static assets use a build-content cache key while the application version remains `0.2.96`, so rebuilt patch packages do not reuse stale JS/CSS under the same semantic version.
|
|
- Added inline note renaming from the note editor and workspace list/table; URLs and slugs remain unchanged.
|
|
- Double-clicking the title no longer triggers the surrounding copy-link action. Successful renames show a confirmation toast; failures retain the existing error notification.
|
|
- PDF export adds header/footer directives and vertical top/center alignment, with more stable page-break handling for headings and footers.
|
|
- Mermaid export no longer leaves stale load-error messages next to successfully rendered diagrams, and failed library loads can be retried.
|
|
- Translation files are revalidated instead of being cached for 24 hours, so newly added UI strings become available after deployment.
|
|
|
|
## Release 0.2.95 — dark PDF export
|
|
|
|
- PDF export now includes a dark-mode checkbox enabled by default.
|
|
- Exported PDFs use the selected light/dark mode consistently for content, syntax highlighting, and Mermaid diagrams; colors and backgrounds are preserved automatically.
|
|
- PDF margins are selectable again (0 / 8 / 12 / 20 mm) and are applied to every page format, including 16:9 and 4:3 presentation pages.
|
|
- PDF pagination keeps short lists, short code blocks, and heading lead-ins together when possible to avoid awkward splits between pages.
|
|
|
|
## Release 0.2.94 — authentication session handling
|
|
|
|
- `GET /api/auth/session` checks the visitor's login state: `200 {"authenticated":false,"session":null}` for guests, missing/expired cookies, or logged-out users; `200 {"authenticated":true,"session":{...}}` for a valid account session. The response is never cached. Expired cookies are cleared; valid session cookies are refreshed as before.
|
|
- `GET /api/auth/me` remains a protected endpoint and returns `401` when unauthenticated. Other authenticated endpoints continue to use `401` for missing sessions.
|
|
- Frontend pages now distinguish a logged-out visitor from a server/network failure while checking the session. Session expiry clears client state once and raises the existing expiry notification; unexpected errors no longer force logout.
|
|
|
|
Run the frontend session regression tests from the project root with Node.js 22+:
|
|
|
|
```bash
|
|
node --experimental-vm-modules scripts/test_auth_session.mjs
|
|
```
|
|
|
|
## Development setup
|
|
|
|
```bash
|
|
./dev.sh
|
|
```
|
|
|
|
The script creates `data/db` and `data/files`, refreshes the generated browser libraries, builds the project, and starts it with Cargo. If Cargo is unavailable, it runs `docker compose up --build` instead; the Docker build downloads the libraries in a separate stage.
|
|
|
|
|
|
## Interface languages
|
|
|
|
Frontend translations live in the top-level `lang/` directory and are embedded into the Rust binary during the build. There is no separate language manifest: every `*.json` file is discovered automatically and its `meta` block is used to populate the language selector in the profile.
|
|
|
|
```json
|
|
{
|
|
"meta": {
|
|
"code": "pl",
|
|
"name": "Polish",
|
|
"native_name": "Polski",
|
|
"locale": "pl-PL"
|
|
},
|
|
"translations": {
|
|
"common.save": "Zapisz"
|
|
}
|
|
}
|
|
```
|
|
|
|
`lang/en.json` is the required fallback and source language. Every language file must have the same translation keys as `en.json`; invalid metadata, non-string values, duplicate codes, or mismatched keys are rejected when the embedded language catalog is initialized. To add a language, copy `lang/en.json`, translate the values, and set `meta.code`, `meta.name`, `meta.native_name`, and `meta.locale`. The filename must match `meta.code` (for example `de.json` and `"code": "de"`).
|
|
|
|
The selected interface language is stored in the browser and can be changed from the profile without reloading the page. API responses remain in their original English form; the browser client translates known messages only when presenting them in the UI.
|
|
|
|
## Workspace features
|
|
|
|
- Real-time collaborative editing over WebSocket.
|
|
- Nicknames stored in `localStorage`.
|
|
- Change authors shown in history.
|
|
- Line numbering enabled by default, with per-account preferences stored separately for each note or pad.
|
|
- The formatting toolbar can be collapsed; the state is saved per account and per note or pad.
|
|
- Signed-in users with read/write access can save personal compact view, line, font, size, authorship, and color preferences; resource-linked rows are removed with the note, pad, or account.
|
|
- Signed-in users can favorite standalone notes and workspace notes; favorites are shown only while current account, share-link, or password access still permits the resource.
|
|
- Owner color displayed next to each line.
|
|
- Image and file uploads to `data/files/pads/<id>_<token>/` or `data/files/notes/<id>_<token>/`.
|
|
- Compact attachment aliases are inserted after upload: `[file=name.ext,label]`, `[image=name.ext,alt]`, and `[video=name.ext,label]`. Video uploads can be inserted as an embedded player or a forced-download link.
|
|
- Standalone YouTube links are rendered as responsive privacy-enhanced players.
|
|
- Markdown and Mermaid diagram rendering.
|
|
- History with snippets, previews, and version restore.
|
|
- Alert blocks: `success`, `info`, `warning`, and `danger`.
|
|
- Table of contents generated with `[TOC]`, using headings after the marker and nesting them by level.
|
|
- Permalinks to Markdown headings, including custom heading IDs and duplicate heading names.
|
|
- Inline `@nickname` colored mentions for active account owners and users directly granted access to a note/pad.
|
|
- Mentioned users are listed below the participant/author badges with a count of matching mentions; repeated clicks jump to the next occurrence and cycle through them in editor, split, or preview views.
|
|
- Indented fenced code blocks shift their whole preview block rather than just the code text.
|
|
- Optional line numbers in fenced code blocks.
|
|
- PDF export with selectable A5/A4/A3, Letter, 16:9, and 4:3 page formats; optional color/background preservation keeps syntax highlighting, alerts, quotes, highlights, and table styling; `[PDF_PAGEBREAK]` creates an explicit hard PDF page break while `---` remains a normal Markdown horizontal rule.
|
|
|
|
## PDF export and page breaks
|
|
|
|
Use the **PDF** button in the editor header to choose the page format and margins, then generate a browser-native PDF print view. The export supports A5/A4/A3, Letter, 16:9, and 4:3 layouts. Syntax highlighting, alerts, quotes, highlighted text, table headers, inline code, links, and other styled Markdown elements keep their colors and backgrounds automatically. The exporter re-applies Highlight.js to the print copy and uses print-safe light/dark palettes so code colors do not depend on the editor theme. The end of the exported document includes one subtle localized RustPad footer.
|
|
|
|
A Markdown line containing only `[PDF_PAGEBREAK]` creates an explicit page break during PDF export. Existing `[PAGEBREAK]` markers remain supported for backwards compatibility. Insert it from **More → Page break (PDF)** or with `Ctrl/Cmd+Enter`. A normal `---` remains a Markdown horizontal rule and no longer forces a new PDF page.
|
|
|
|
PDF layout directives can reserve document-level slots and change vertical alignment:
|
|
|
|
- `[PDF_HEADER]` moves the next Markdown block into a header pinned to the top of the first PDF page.
|
|
- `[PDF_FOOTER]` moves the next Markdown block into the footer aligned to the bottom of the last PDF page.
|
|
- `[PDF_ALIGN_TOP]` keeps normal top-aligned content.
|
|
- `[PDF_ALIGN_CENTER]` vertically centers content when the document fits on one page; multi-page documents stay top-aligned.
|
|
|
|
Trailing empty source lines are ignored for footer placement. Mermaid export reuses an already rendered SVG when available and removes stale preview error messages before printing.
|
|
|
|
## Fenced code blocks and language aliases
|
|
|
|
RustPad recognizes common language names and aliases, including:
|
|
|
|
- JavaScript: `js`, `javascript`, `jsx`
|
|
- TypeScript: `ts`, `typescript`, `tsx`
|
|
- Python: `py`, `python`
|
|
- PHP: `php`
|
|
- Rust: `rs`, `rust`
|
|
- Shell: `sh`, `shell`, `bash`, `zsh`
|
|
- C and C++: `c`, `h`, `cpp`, `c++`, `cxx`, `hpp`
|
|
- C#: `cs`, `c#`, `csharp`
|
|
- Java, Kotlin, Go, Swift, Dart, Scala
|
|
- HTML, XML, SVG, CSS, SCSS, Sass, Less
|
|
- JSON, YAML, TOML, INI, SQL, GraphQL
|
|
- Markdown, Dockerfile, Makefile, PowerShell
|
|
- Lua, Perl, R, MATLAB, Nginx, Apache, Diff, and plain text
|
|
|
|
Standard code block:
|
|
|
|
````markdown
|
|
```python
|
|
print("Hello")
|
|
```
|
|
````
|
|
|
|
Code block with line numbers starting from line 1:
|
|
|
|
````markdown
|
|
```python=
|
|
print("Hello")
|
|
```
|
|
````
|
|
|
|
Code block with line numbers starting from a custom value:
|
|
|
|
````markdown
|
|
```python=101
|
|
print("Hello")
|
|
```
|
|
````
|
|
|
|
The `=number` suffix is a RustPad extension and may not be supported by other Markdown renderers.
|
|
|
|
Indent the opening and closing backtick fences and their content to move the entire displayed code block right by the same number of columns; RustPad strips the common indentation from the code itself.
|
|
|
|
## Heading links and member mentions
|
|
|
|
In Markdown preview, each heading includes a `#` link. Use regular Markdown links to jump to the section, for example:
|
|
|
|
```markdown
|
|
- [Run the upgrade](#run-the-upgrade)
|
|
|
|
## Run the upgrade
|
|
Step-by-step instructions here.
|
|
```
|
|
|
|
Heading IDs are created from the heading text (for example, `## Run the upgrade` becomes `#run-the-upgrade`). Repeated headings receive `-2`, `-3`, etc. You can also specify a stable ID with `## Instructions {#upgrade-steps}` and link to it using `[Instructions](#upgrade-steps)`. Opening a heading link scrolls the preview to that heading or the editor to its source line when in edit view. The existing `[TOC]` also links to these anchors.
|
|
|
|
A typed `@nickname` is shown with a colored badge only when the nickname belongs to an active registered owner or user with an accepted direct share of this pad or workspace. The list is retrieved only for logged-in owners and directly shared accounts; guests and users without a direct grant do not receive a member directory. In the Markdown source editor, typing `@` or a partial nickname such as `@do` opens an autocomplete menu of these authorized members. Use Up/Down to choose, Enter or Tab to insert the complete `@nickname`, Esc to dismiss, or click/tap a name. The list is refreshed after login or a resource reload and is never shown to guests. Mentions are visual only and do not send notifications.
|
|
|
|
The **Mentioned** row below the author/participant badges lists the recognized users currently mentioned in the note, with counts. Click `@nickname` to jump to the first mention, then click it again to cycle through the next occurrences (returning to the start). The editor selects the mention, the preview highlights it, and collapsed Markdown details sections open for a matching mention. Mentions in fenced/inline code, Markdown links, URLs, and emails are ignored. Only members returned by the resource access API are shown; the row disappears when none are mentioned or access is lost.
|
|
|
|
## Data
|
|
|
|
- SQLite database: `data/db/rustpad.db`
|
|
- Attachments: `data/files/pads/<id>_<token>/` and `data/files/notes/<id>_<token>/`
|
|
- Public attachment URL: `/f/<token>/<filename>`
|
|
|
|
In Docker, both directories are located under `/data`.
|
|
|
|
## Publishing a note as a page
|
|
|
|
Use the **Page** button in the editor. RustPad creates a permanent public `/s/<token>` URL, copies it to the clipboard, and opens it in a new tab. The page displays the current note and renders Markdown, images, video players, YouTube embeds, links, and Mermaid diagrams. Its header can toggle source line numbers and expand the document to the full browser width.
|
|
|
|
Publishing a protected note requires its password, but the generated public page itself is accessible without that password.
|
|
|
|
## Upload limit
|
|
|
|
Configure the maximum size of a single uploaded file for signed-in users with `UPLOAD_MAX_SIZE_MB` in `.env`, for example:
|
|
|
|
```env
|
|
UPLOAD_MAX_SIZE_MB=50
|
|
```
|
|
|
|
The default limit is 20 MB. Uploads by guests are disabled by default. Enable them deliberately and set their separate per-file limit with:
|
|
|
|
```env
|
|
GUEST_UPLOAD_ENABLED=true
|
|
GUEST_UPLOAD_MAX_SIZE_MB=5
|
|
```
|
|
|
|
Guest uploads still require read-write access to the note or workspace. Restart the project with `./dev.sh` after changing these values.
|
|
|
|
## Database selection
|
|
|
|
RustPad selects the database engine through `DATABASE_URL`:
|
|
|
|
- SQLite: `sqlite:///data/db/rustpad.db?mode=rwc&journal_mode=WAL&busy_timeout=5000`
|
|
- PostgreSQL: `postgres://rustpad:rustpad@postgres:5432/rustpad`
|
|
- MySQL: `mysql://rustpad:rustpad@mysql:3306/rustpad`
|
|
|
|
SQLite remains the default for development and small installations. WAL mode allows reads during writes, but SQLite still performs only one write at a time. `busy_timeout=5000` waits briefly instead of immediately returning a `database is locked` error. PostgreSQL or MySQL is recommended for many concurrent editors or multiple application instances.
|
|
|
|
Optional databases in Docker Compose:
|
|
|
|
```bash
|
|
# PostgreSQL
|
|
docker compose --profile postgres up -d pgsql
|
|
DATABASE_URL=postgres://rustpad:rustpad@postgres:5432/rustpad docker compose up -d rustpad
|
|
|
|
# MySQL
|
|
docker compose --profile mysql up -d mysql
|
|
DATABASE_URL=mysql://rustpad:rustpad@mysql:3306/rustpad docker compose up -d rustpad
|
|
```
|
|
|
|
Migrations are stored in `migrations/sqlite`, `migrations/postgres`, and `migrations/mysql`. Runtime SQL statements are centralized in `src/queries.rs`, while `src/database.rs` selects the driver and configures the connection.
|
|
|
|
## Optional user accounts and password reset
|
|
|
|
Nicknames can be used anonymously while they remain unregistered. Registering a nickname reserves it and requires a valid login session before it can be used in editor WebSocket connections.
|
|
|
|
Configure `PUBLIC_URL`, `SMTP_HOST`, `SMTP_PORT`, `SMTP_SECURITY`, `SMTP_USERNAME`, `SMTP_PASSWORD`, and `SMTP_FROM` to enable password-reset emails. `SMTP_FROM` accepts both `RustPad <no-reply@example.com>` and a value wrapped in one matching pair of single or double quotes, as may be passed literally by container env-file implementations. `SMTP_SECURITY` accepts `none` (plain SMTP, typically an internal relay on port 25), `starttls`, or `tls` (implicit TLS, commonly port 465). When omitted, it defaults to `tls` for port 465, `starttls` for port 587, and `none` for port 25 or any other port. SMTP authentication is enabled only when both `SMTP_USERNAME` and `SMTP_PASSWORD` are non-empty. Reset links expire after 30 minutes and can be used only once.
|
|
|
|
## Browser libraries
|
|
|
|
`static/libs/rustpad-player` is project-owned and stays in the repository. Mermaid and Highlight.js are generated locally and ignored by Git. Refresh or restore them with:
|
|
|
|
```bash
|
|
python3 scripts/update_browser_libs.py
|
|
```
|
|
|
|
The standard-library-only updater checks the current stable npm releases, verifies tarball integrity, and stores each license beside the generated files. `./dev.sh` runs it before local Cargo development. Docker performs the same download in the `browser-libs` stage; `dev.sh` sets `BROWSER_LIBS_REFRESH` so Docker does not reuse a stale dependency layer.
|
|
|
|
The editor serves all browser libraries through `/assets` and never loads Mermaid or Highlight.js directly from a public CDN.
|
|
|
|
## Diagnostics and logging
|
|
|
|
Server logs use `tracing`. Configure verbosity with `RUST_LOG`, for example:
|
|
|
|
```env
|
|
RUST_LOG=rustpad=debug,tower_http=info
|
|
```
|
|
|
|
Important lifecycle, database, authentication, password-reset, and WebSocket events are logged. Passwords, session tokens, reset tokens, SMTP credentials, and authorization headers are never logged.
|
|
|
|
Browser diagnostics are configured separately with `FRONTEND_LOG_LEVEL`. Supported values are `off`, `error`, `warn`, `info`, and `debug`; the default is `warn`. URL parameters cannot enable diagnostics. Use `debug` only in trusted development environments. Production should normally use `warn` or `error`.
|
|
|
|
## Registration and SMTP
|
|
|
|
Set `REGISTRATION_ENABLED=true` to enable registration. After an account is created, the application sends an SMTP message containing the nickname and `PUBLIC_URL`.
|
|
|
|
Set `ACCOUNT_CONFIRMATION_REQUIRED=true` to require users to click a confirmation link before signing in. This option is disabled by default and requires SMTP configuration.
|
|
|
|
## Attachment storage
|
|
|
|
RustPad supports two interchangeable attachment backends selected in `.env`:
|
|
|
|
- `STORAGE_DRIVER=local` stores files under `FILES_DIR` and is the default.
|
|
- `STORAGE_DRIVER=s3` uses an S3-compatible service such as AWS S3, Garage, Ceph RGW, OpenStack, or MinIO.
|
|
|
|
Stored attachment paths remain `/f/{token}/{filename}` for both backends. RustPad validates access and streams objects through the API, so the bucket does not need to be public and existing database records do not require migration.
|
|
|
|
RustPad automatically selects one of two file-serving modes:
|
|
|
|
- **Single domain** (default): leave `FILES_PUBLIC_URL` unset. `/f/{token}/{filename}` is served on `APP_PORT` (default 3000), with application-relative attachment links. `FILES_PORT` is ignored and no second listener starts.
|
|
- **Dedicated file domain**: set `FILES_PUBLIC_URL=files.note.example.com`. RustPad generates attachment links on that origin and starts a separate attachment-only router on `FILES_PORT` (default 3001, same `APP_HOST`). The application router on `APP_PORT` no longer serves `/f/...`. The file router serves `GET`/`HEAD /f/{token}/{filename}` and the health checks `GET`/`HEAD /health` (both return HTTP 200 and `ok` for GET); all other paths return an empty 404 response. The original link-based file access, local/S3 storage, and stored database paths remain unchanged.
|
|
|
|
Bare domains are normalized to HTTPS; `http://` is allowed for local testing. For a dedicated origin, point its reverse proxy directly at `APP_HOST:FILES_PORT` (e.g. `rustpad:3001` from another container in the same network). There is no need for proxy path deny-lists. For monitoring, request `http://rustpad:3001/health` from inside the network. The application origin continues to point at `APP_HOST:APP_PORT`.
|
|
|
|
**Upgrading an existing file-subdomain deployment:** change the subdomain's proxy upstream from port 3000 to port 3001 before/when installing this release. Existing attachment URLs and database records do not change. Without the proxy change, old attachment requests will return 404 at the application port. `FILES_PORT` must be between 1 and 65535 and differ from `APP_PORT` when the separate domain is enabled. Both listeners must be reachable from their respective proxies.
|
|
|
|
With Docker Compose, containers on the same network can proxy directly to `app:3001` without additional published ports. If your reverse proxy runs on the host/outside the Compose network, publish the file listener explicitly:
|
|
|
|
```sh
|
|
docker compose -f docker-compose.yml -f docker-compose.files.yml up -d --build
|
|
```
|
|
|
|
This optional override maps `${RUSTPAD_FILES_PORT:-3001}` on the Docker host to `${FILES_PORT:-3001}` in the container. Do not use it if you do not need a host-published attachment port. Example reverse-proxy configurations are in `docker/example_files_vhost.conf` and `docker/example_hahproxy_files.conf`.
|
|
|
|
Set `ASSET_CACHE_MAX_AGE_SECONDS=0` or `FILE_CACHE_MAX_AGE_SECONDS=0` to disable browser caching. RustPad then sends `Cache-Control: no-cache, no-store, must-revalidate`; positive values use `public, max-age=<seconds>`.
|
|
|
|
For the optional Docker Garage service, configure the S3 variables shown in `.env.example`, use strong unique credentials, and run:
|
|
|
|
```sh
|
|
docker compose --profile s3 up -d --build
|
|
```
|
|
|
|
Garage runs as a separate Compose service. Existing PostgreSQL and MySQL profiles remain unchanged. The included single-node setup is intended for local or self-hosted development without redundancy. Production Garage deployments should use a properly designed multi-node configuration.
|
|
|
|
## Authentication: local, LDAP, LDAPS, or Active Directory
|
|
|
|
Choose exactly one authentication backend:
|
|
|
|
```env
|
|
AUTHORIZATION_TYPE=local
|
|
```
|
|
|
|
Supported values:
|
|
|
|
- `local` - built-in registration and password login
|
|
- `ldap` - OpenLDAP-compatible directory
|
|
- `ad` - Microsoft Active Directory defaults
|
|
|
|
For `ldap` and `ad`, RustPad searches the directory with the service account, validates the password by binding as the user, and automatically provisions a local account. Existing sessions, ownership, sharing, and other account functions continue to use the existing `users` table. Local registration and guest nickname access are disabled.
|
|
|
|
The nickname is generated as `LDAP_ORGANIZATION/displayName`, for example `example/Mateusz Testowy`. Directory accounts are stored using a stable `entryUUID` (LDAP) or `objectGUID` (AD), while e-mail, nickname, and DN are synchronized after every successful login.
|
|
|
|
### OpenLDAP
|
|
|
|
```env
|
|
AUTHORIZATION_TYPE=ldap
|
|
LDAP_URL=ldap://10.87.2.6:389
|
|
LDAP_STARTTLS=false
|
|
LDAP_BIND_DN=cn=admin,dc=example,dc=org
|
|
LDAP_BIND_PASSWORD=admin
|
|
LDAP_BASE_DN=ou=people,dc=example,dc=org
|
|
LDAP_ORGANIZATION=example
|
|
```
|
|
|
|
In `ldap` mode the defaults are:
|
|
|
|
```env
|
|
LDAP_USER_FILTER=(uid={username})
|
|
LDAP_USERNAME_ATTRIBUTE=uid
|
|
LDAP_EMAIL_ATTRIBUTE=mail
|
|
LDAP_DISPLAY_NAME_ATTRIBUTE=displayName
|
|
```
|
|
|
|
### Active Directory
|
|
|
|
```env
|
|
AUTHORIZATION_TYPE=ad
|
|
LDAP_URL=ldaps://ad.example.org:636
|
|
LDAP_STARTTLS=false
|
|
LDAP_BASE_DN=DC=example,DC=org
|
|
LDAP_BIND_DN=CN=rustpad-bind,OU=Service Accounts,DC=example,DC=org
|
|
LDAP_BIND_PASSWORD=secret
|
|
LDAP_ORGANIZATION=example
|
|
```
|
|
|
|
In `ad` mode the defaults are:
|
|
|
|
```env
|
|
LDAP_USER_FILTER=(|(sAMAccountName={username})(userPrincipalName={username}))
|
|
LDAP_USERNAME_ATTRIBUTE=sAMAccountName
|
|
LDAP_EMAIL_ATTRIBUTE=mail
|
|
LDAP_DISPLAY_NAME_ATTRIBUTE=displayName
|
|
```
|
|
|
|
All LDAP attributes and filters can still be overridden explicitly. By default TLS certificates are verified. For a trusted internal or test server using a self-signed certificate, `LDAP_TLS_VERIFY=false` keeps LDAPS/StartTLS encryption enabled without requiring a custom CA file. Do not disable verification on untrusted networks.
|
|
|
|
Additional directory options:
|
|
|
|
```env
|
|
LDAP_EXTERNAL_ID_ATTRIBUTE=entryUUID
|
|
LDAP_EMAIL_REQUIRED=true
|
|
LDAP_LINK_EXISTING_BY_EMAIL=false
|
|
LDAP_TLS_VERIFY=true
|
|
LDAP_CONNECT_TIMEOUT_SECONDS=5
|
|
LDAP_OPERATION_TIMEOUT_SECONDS=10
|
|
```
|
|
|
|
For Active Directory, the default external identifier is `objectGUID`. Set `LDAP_LINK_EXISTING_BY_EMAIL=true` only during an intentional migration of existing local or legacy LDAP accounts; otherwise an e-mail collision is rejected.
|
|
|
|
### Test LDAP on 10.0.0.1 (example)
|
|
|
|
```bash
|
|
cd docker/ldap
|
|
docker compose up -d
|
|
```
|
|
|
|
Test users:
|
|
|
|
- `admin` / `test1234`
|
|
- `user` / `test1234`
|
|
|
|
phpLDAPadmin: `http://10.0.0.1:8088`
|
|
|
|
Administrator: `cn=admin,dc=example,dc=org` / `admin`
|
|
|
|
|
|
## CLI and YAML configuration
|
|
|
|
RustPad reads `.env` as before and can additionally load a YAML file. Environment variables have higher priority than YAML values.
|
|
|
|
```bash
|
|
rustpad --version
|
|
rustpad --help
|
|
rustpad --config /etc/rustpad/rustpad.yaml check-config
|
|
rustpad --config /etc/rustpad/rustpad.yaml migrate
|
|
rustpad --config /etc/rustpad/rustpad.yaml
|
|
```
|
|
|
|
`check-config` validates YAML syntax, supported keys, value types, required LDAP/S3/SMTP fields, database URL scheme, paths and dependent settings. It does not connect to the database or LDAP server. Example deployment files are in `systemd/`.
|
|
|
|
### Database query layout
|
|
|
|
SQL is selected explicitly by database engine. Application code uses logical query identifiers from `src/queries/mod.rs`; complete engine-specific statements live in:
|
|
|
|
- `src/queries/sqlite.rs`
|
|
- `src/queries/postgres.rs`
|
|
- `src/queries/mysql.rs`
|
|
|
|
PostgreSQL statements use native `$1`, `$2`, ... placeholders. Query text is not rewritten at runtime, and result-shape casts are defined independently for each engine.
|
|
|
|
## Random API test data
|
|
|
|
`tests/random_data.py` creates data only through RustPad's HTTP API. It logs in, obtains a CSRF token, creates workspaces and notes, and can seed the initial Markdown content from generated text or cached snapshots of random Wikipedia pages with Wikimedia images.
|
|
|
|
```bash
|
|
export RUSTPAD_TEST_PASSWORD='test1234'
|
|
python3 tests/random_data.py \
|
|
--ip localhost \
|
|
--port 3000 \
|
|
--source wikipedia \
|
|
--notes 10000 \
|
|
--workspaces 10 \
|
|
--notes-in-workspaces 1000 \
|
|
--user test
|
|
```
|
|
|
|
`--notes-in-workspaces` is applied to every workspace. The example creates 10,000 standalone notes and another 10,000 notes inside 10 workspaces. Wikipedia mode never falls back to generated content. Use `--wikipedia-images`, `--wikipedia-attempts`, `--workers`, `--source-pool-size`, `--scheme https`, `--base-url`, or `--dry-run` as needed. The login value may be a local account e-mail or an LDAP/AD username.
|
|
|
|
### HTTP response compression
|
|
|
|
Rustpad optionally supports Brotli and gzip for HTTP responses. Add to `.env` (or the YAML config):
|
|
|
|
```dotenv
|
|
HTTP_COMPRESSION=true
|
|
```
|
|
|
|
Defaults to `false`. When enabled, the server selects Brotli or gzip supported by the browser via `Accept-Encoding`, and sends ordinary responses otherwise. This does **not** compress live WebSocket messages. When a reverse proxy already applies HTTP compression, avoid double configuration where possible.
|