Main CI / check-and-package (pull_request) Successful in 3m51s
Development CI / check-and-package (push) Successful in 3m52s
GitHub Git mirror / mirror (push) Successful in 4s
Main CI / image (pull_request) Successful in 15s
Development CI / image (push) Successful in 16s
Development CI / deploy-development (push) Successful in 11s
186 lines
14 KiB
Markdown
186 lines
14 KiB
Markdown
# Deployment and maintenance
|
|
|
|
**English** · [简体中文](deployment.zh-CN.md)
|
|
|
|
[Project home](../README.md) · [User guide](guide.md) · [Development guide](development.md)
|
|
|
|
RawMark embeds the frontend in its Go service and uses SQLite and the filesystem at runtime. No separate database service is needed. You can use a release image or build from source; the source-build commands below remain available.
|
|
|
|
## Docker quick start
|
|
|
|
With Git and Docker installed:
|
|
|
|
```sh
|
|
git clone https://github.com/eezd/RawMark.git
|
|
cd RawMark
|
|
docker build -t rawmark .
|
|
docker run -d --name rawmark --restart unless-stopped \
|
|
-p 127.0.0.1:21000:8080 \
|
|
-v rawmark-data:/data \
|
|
rawmark
|
|
```
|
|
|
|
Open http://localhost:21000 to set the initial password. The named volume `rawmark-data` holds application data; reuse it when recreating the container and do not delete it. For a remote server, reach its local port through an SSH tunnel to complete setup:
|
|
|
|
```sh
|
|
ssh -L 21000:127.0.0.1:21000 user@your-server
|
|
```
|
|
|
|
The container defaults to UID/GID `65532:65532`. A new Docker named volume inherits permissions from the image's data directory.
|
|
|
|
A fresh instance with an empty vault receives seven English example notes from the public template in `deploy/data/vault/`. They are embedded in the binary, so Docker and native deployments behave the same way. You still set your own password; no account credentials or personal settings are shipped. Existing accounts and nonempty vaults are left untouched. Examples are ordinary user files: deleting them, restarting, or resetting preferences does not recreate them. Initialization state is retained in the application database, outside user preferences.
|
|
|
|
## Docker Compose
|
|
|
|
The repository includes [deploy/docker-compose.yml](../deploy/docker-compose.yml), which stores runtime data in an independent Docker named volume:
|
|
|
|
```sh
|
|
docker compose -f deploy/docker-compose.yml up -d --build --wait
|
|
```
|
|
|
|
The tracked `deploy/data/` directory is a public example template, not a runtime data directory. Do not mount it as writable application storage. To use a host directory instead, create it with UID/GID `65532:65532` and set an absolute path:
|
|
|
|
```sh
|
|
sudo install -d -o 65532 -g 65532 /your/storage/rawmark/data
|
|
RAWMARK_DATA_DIR=/your/storage/rawmark/data \
|
|
docker compose -f deploy/docker-compose.yml up -d --build --wait
|
|
```
|
|
|
|
Keep the same `RAWMARK_DATA_DIR` value for every subsequent Compose command, for example in a private file passed with `--env-file`. This Compose variable selects the host mount; it is separate from the application's `RAWMARK_DATA` variable inside the container. Existing deployments that used `deploy/data/` must explicitly select that directory until it has been migrated; omitting the override starts a separate instance in a named volume.
|
|
|
|
This configuration publishes port **21000** on all network interfaces by default. Complete initialization and configure access boundaries before exposing it publicly. With a reverse proxy, you can change the Compose port binding to `127.0.0.1:${RAWMARK_PORT:-21000}:8080`. For a custom port, use `RAWMARK_PORT=21001 docker compose -f deploy/docker-compose.yml up -d --build --wait`.
|
|
|
|
Do not point the quick-start container and a Compose instance at the same database or vault concurrently. Stop the old instance, back up, and verify data locations before switching deployment methods.
|
|
|
|
## Prebuilt images and native programs
|
|
|
|
Formal releases publish `ghcr.io/eezd/rawmark:<version>` for Linux amd64 and arm64. The earlier releases were withdrawn; `VERSION` alone does not mean a version is available. Check the Releases page and package visibility before using the example version below. Replace `rawmark` in the Docker commands above with that image name to skip source builds. `latest` follows the latest stable release; use a version tag for controlled upgrades. The repository Compose file continues to support source builds.
|
|
|
|
Native archives for Linux amd64/arm64, Windows amd64/arm64 and macOS Intel/Apple Silicon, plus `SHA256SUMS`, are available on the [Releases page](https://github.com/eezd/RawMark/releases). Download the archive matching your operating system and architecture and verify its checksum before extracting it:
|
|
|
|
```sh
|
|
sha256sum --ignore-missing --check SHA256SUMS
|
|
tar -xzf RawMark_YYYYMMDD-xxxxxxxx_linux_amd64.tar.gz
|
|
./rawmark --version
|
|
RAWMARK_DATA="$HOME/rawmark-data" RAWMARK_ADDR=127.0.0.1:21000 ./rawmark
|
|
```
|
|
|
|
For macOS, use `darwin_arm64` on Apple Silicon or `darwin_amd64` on Intel. Compare `shasum -a 256 RawMark_YYYYMMDD-xxxxxxxx_darwin_arm64.tar.gz` with its entry in `SHA256SUMS`, extract it with `tar -xzf`, then use the same environment variables as above. The program is unsigned; review and approve it through macOS security settings if prompted.
|
|
|
|
On Windows, compare the output of `Get-FileHash` with the archive's entry in `SHA256SUMS`, then run in PowerShell:
|
|
|
|
```powershell
|
|
Get-FileHash .\RawMark_YYYYMMDD-xxxxxxxx_windows_amd64.zip -Algorithm SHA256
|
|
Expand-Archive .\RawMark_YYYYMMDD-xxxxxxxx_windows_amd64.zip -DestinationPath .\rawmark
|
|
Set-Location .\rawmark
|
|
.\rawmark.exe --version
|
|
$env:RAWMARK_DATA = Join-Path $env:LOCALAPPDATA 'RawMark'
|
|
$env:RAWMARK_ADDR = '127.0.0.1:21000'
|
|
.\rawmark.exe
|
|
```
|
|
|
|
Open `http://127.0.0.1:21000` and set your password. These downloads run a web server in the terminal, not a desktop window, and include no installer or code signing. Stop with Ctrl+C. Keep the data directory when replacing the executable. Moving an existing vault between operating systems requires filenames supported by the destination filesystem; Windows rejects device names, alternate data streams and trailing dots/spaces rather than silently renaming them.
|
|
|
|
Use the Linux arm64 archive on Linux ARM systems. Run as an unprivileged user with write access to the chosen data directory. The executable embeds the frontend and examples; no Node.js or separate database service is needed. Configure your service manager and HTTPS proxy for long-running remote use.
|
|
|
|
## Storage and configuration
|
|
|
|
| Environment variable | Default | Description |
|
|
| --- | --- | --- |
|
|
| `RAWMARK_DATA` | `/data` | Application database, index, resources, and default vault directory |
|
|
| `RAWMARK_VAULT` | `$RAWMARK_DATA/vault` | Markdown vault; can be a separately mounted existing directory |
|
|
| `RAWMARK_ADDR` | `:8080` | Listen address inside the container or binary |
|
|
|
|
Main data locations:
|
|
|
|
| Path | Contents |
|
|
| --- | --- |
|
|
| `vault/` | Markdown files, attachments, and vault metadata; stored at the configured location when using an external vault |
|
|
| `rawmark.db` | Password, sessions, API tokens, settings, and other application state |
|
|
| `index.db` | Rebuildable search index |
|
|
| `fonts/`, `themes/`, `plugins/` | User-imported fonts, themes, and plugins |
|
|
| `backups/` | Rollback backups created before imports or restores |
|
|
| `logs/` | Runtime logs |
|
|
|
|
To use an existing folder, mount it separately and set `RAWMARK_VAULT`:
|
|
|
|
```sh
|
|
docker run -d --name rawmark --restart unless-stopped \
|
|
--user "$(id -u):$(id -g)" \
|
|
-p 127.0.0.1:21000:8080 \
|
|
-v "$HOME/rawmark-data:/data" \
|
|
-v "$HOME/notes:/vault" \
|
|
-e RAWMARK_VAULT=/vault \
|
|
rawmark
|
|
```
|
|
|
|
Create `$HOME/rawmark-data` and `$HOME/notes` first and ensure the selected user can write to them. This example runs as the current host user, which suits an existing personal directory. Without `--user`, grant write access to the container's default user. RawMark modifies notes and links, so back up an existing directory before first use.
|
|
|
|
## HTTPS and reverse proxy
|
|
|
|
Use HTTPS for remote access. The proxy must forward Host, protocol, and client address information and support WebSocket upgrades and long-lived connections. Browser event connections use `/api/v1/resources/<ticket>/events/`. Proxy upload limits should accommodate your imports.
|
|
|
|
The [repository's Nginx configuration](../deploy/nginx/raw.134333.xyz.conf) includes examples of WebSocket support and redacted ticket logging. Its domain, certificate includes, anti-bot includes, port, and log paths belong to the original deployment environment: **adapt them to your server rather than installing the file unchanged**. Define the `$connection_upgrade` map in Nginx's `http` context as well.
|
|
|
|
Resource tickets are credentials. Proxies, CDNs, and access logs must not record plaintext tickets, query parameters, or credential-bearing Referer headers. The application's `no-store` policy does not replace proxy log redaction. Nginx error logs can also contain raw request paths; the repository example disables error logging for ticket resource paths while retaining redacted access logs and application error logs.
|
|
|
|
When using a CDN, configure its custom domain and TLS certificate separately, and ensure APIs, private resources, and WebSocket connections are not cached incorrectly. DNS configuration alone does not complete HTTPS setup.
|
|
|
|
## Backup and restore
|
|
|
|
Choose an export type under **Settings → Storage**:
|
|
|
|
| Type | Intended use | Restore behavior |
|
|
| --- | --- | --- |
|
|
| Plain Markdown vault | Move to another note-taking tool | Imports into a new folder without replacing the instance |
|
|
| Settings and resources | Migrate preferences, plugin data, fonts, themes, and plugins | Merges resources, replaces matching IDs, and retains resources absent from the archive |
|
|
| Full instance | Migrate or restore RawMark | Replaces application data, including login credentials, recycle bin, and resources; requires signing in again |
|
|
|
|
Settings imports and full restores accept only RawMark's versioned ZIP format. A rollback archive is kept in `backups/` before applying changes. Uploads use sequential 8 MiB chunks. Limits are 2 GiB compressed, 8 GiB expanded, and 100,000 entries. Operational environment configuration, derived indexes, and temporary files are excluded.
|
|
|
|
Stop other programs from directly modifying the vault before a full restore. API operations pause during maintenance; the restore closes databases and background tasks, and rolls back to the pre-operation backup if interrupted. Full exports contain sensitive account and note data. Store them securely; do not commit them or attach them to public issues.
|
|
|
|
In addition to application backups, stop the service before upgrades and back up the complete data directory, external vault, deployment configuration, and previous image. SQLite may have WAL files while running; copying only an actively written `rawmark.db` is not a consistent backup.
|
|
|
|
## Upgrade and rollback
|
|
|
|
1. Check the target version's behavior and data compatibility; retain the current image and deployment configuration.
|
|
2. Stop the old service and back up application data and any external vault.
|
|
3. Pull the selected prebuilt image digest and start with the same mounts. Source builds are optional contributor workflows, not managed production updates. Do not run old and new services concurrently.
|
|
4. Verify container health, sign-in, notes, and attachments. Roll back using the matching previous image and data backup.
|
|
|
|
The Bearer authentication upgrade requires the frontend and backend to be released together. Old Cookie-based pages require signing in again. Startup creates the resource-ticket table and indexes through the existing SQLite initialization flow; notes, passwords, settings, and existing API tokens are retained. Third-party clients must follow the [current JSON protocol](api.md).
|
|
|
|
`scripts/remove-sharing.sql` and `scripts/reset-shortcuts.sql` are one-time historical migrations. The former removes old sharing data; the latter clears old shortcut overrides. **New deployments do not need them, and instances that have already run them must not rerun them.** Execute one separately only after confirming an applicable old version, stopping the service, and backing up.
|
|
|
|
## Routine maintenance and troubleshooting
|
|
|
|
- The container includes a health check. You can also call `GET /api/v1/health`; a healthy result does not verify every business workflow.
|
|
- Index optimization/rebuilding affects only derived indexes. Temporary-file cleanup does not delete user files, active uploads, or restore backups.
|
|
- Resetting settings retains the account, resources, plugin storage, and local tabs.
|
|
- Logs live in `logs/`, with three rotated files retained, each up to 10 MiB. Settings can export logs and a version summary; this does not reconstruct historical logs.
|
|
- If the interface breaks after an update, first check that the frontend and backend come from the same build, then inspect browser network requests and application logs. See the [user guide](guide.md#plugins-and-interface-recovery) for plugin and appearance recovery entry points.
|
|
- Note reads send `Cache-Control: no-store, no-transform` so proxies preserve the strong revision ETag used by conditional saves. A proxy rewriting it to a weak ETag can cause otherwise valid edits to return HTTP 412; preserve this response policy through the public ingress.
|
|
|
|
## Managed DEV and formal artifacts
|
|
|
|
Personal use keeps only `/docker/gitea/dev/RawMark` running: container `RawMark-dev`, Compose project `rawmark-dev`, loopback port 21001 and public entry `https://raw.134333.xyz`. The raw-dev site is retired. DEV holds real private data; CI and isolated smoke tests use synthetic data.
|
|
|
|
Copy `deploy/compose.image.yml` to the instance as `compose.yml`, with a private mode-600 `.env` beside it. Preserve existing ownership and never mount repository examples as live data.
|
|
|
|
```dotenv
|
|
RAWMARK_CHANNEL=development
|
|
RAWMARK_PROJECT=rawmark-dev
|
|
RAWMARK_CONTAINER_NAME=RawMark-dev
|
|
RAWMARK_BIND=127.0.0.1
|
|
RAWMARK_PORT=21001
|
|
RAWMARK_DATA_DIR=/docker/gitea/dev/RawMark/data
|
|
RAWMARK_IMAGE=git.134333.xyz/eezd/dev/rawmark@sha256:<verified-digest>
|
|
```
|
|
|
|
Dev pushes deploy verified Gitea development digests after checks and isolated smoke tests. Main pushes and PRs only validate. Manual formal releases publish packages and Gitea/GHCR images with GitHub mirrors; they do not create MAIN or update DEV. `/docker/gitea/dev/manage.sh start|stop` manages first-level projects using instance `.deploy.lock` files and rejects starts with unresolved pending deployments.
|
|
|
|
Deployment stops the service and backs up complete data, including SQLite WAL, configuration and previous-image details before writing `deployment.pending.json`. Successful health checks write `deployment.json` and clear pending. A failed candidate is stopped while its backup and pending record remain; no automatic data restore or program downgrade occurs. Recovery and private-data migration require explicit authorization and compatibility review. Never run two instances sharing writable data.
|
|
|
|
Domain changes require public, CDN and TLS validation while preserving resource-ticket log redaction. DNS remains user-managed.
|