mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-04 00:47:01 +01:00
Media answers Range requests with 206 and Content-Range, so videos seek and Safari plays them. Sealed files too: the vault's opener now decrypts by record position (STREAM BE32 through StreamPrimitive, the same construction and the same files), so a range starts at the record that holds its first byte. Compression is limited to text, because a gzipped body no longer matches the byte ranges a player asks for. GET /api/health answers without a session once the database does, and the compose healthcheck asks it instead of only opening the port. Requests are logged at info with share tokens and keys left out of the path and no query strings. A request that is not answered in 30 seconds gets a 503, except uploads, imports, the export, re-sealing and backups. The backup, mail, sweep and SFTP loops run under a supervisor that logs a panic and starts the loop again. The backup loop starts without a Proton session and picks up a later proton-login without a restart. A lock file keeps backup-now and the server from mirroring at once, and an unreadable session key file turns backups off instead of failing boot. Numbers in the configuration are checked against bounds at startup, so a session length or an upload limit can no longer overflow later, and a switch that is neither on nor off is an error rather than off. Config and MailConfig print with the password, secret and SMTP URL redacted. A session epoch is signed into each cookie (migration 0014). :logout! advances it, which ends every session, and a changed WORKSPACE_PASSWORD advances it on the next start. Cookies issued before this keep working in the first epoch.
44 lines
1.6 KiB
YAML
44 lines
1.6 KiB
YAML
services:
|
|
workspace:
|
|
build: .
|
|
image: narl-workspace:latest
|
|
restart: unless-stopped
|
|
# tini as PID 1: forwards SIGTERM and reaps anything the binary leaves behind.
|
|
init: true
|
|
env_file:
|
|
- .env
|
|
environment:
|
|
# These win over anything in .env: inside the container the app must
|
|
# listen on all interfaces and keep its state on the volume.
|
|
WORKSPACE_BIND: 0.0.0.0:4242
|
|
WORKSPACE_DATA_DIR: /data
|
|
volumes:
|
|
# Named for what it held when it was made. Renaming it would mean moving
|
|
# the database into a new volume by hand, which is no kind of upgrade.
|
|
- diary-data:/data
|
|
networks:
|
|
- internal_net
|
|
ports:
|
|
# Localhost only. Drop this in the override when a reverse proxy
|
|
# reaches the container over its own network instead.
|
|
- "127.0.0.1:4242:4242"
|
|
# Only listens if WORKSPACE_SFTP_BIND is set in .env (see there);
|
|
# otherwise this maps to a port nothing is bound on. Traefik is
|
|
# HTTP-only, so a deployment behind it must publish this port itself
|
|
# rather than relying on the reverse proxy — see compose.override.yml.example.
|
|
# - "127.0.0.1:2222:2222"
|
|
healthcheck:
|
|
# The image has bash and nothing like curl: a request by hand, and a
|
|
# 200 from /api/health, which also asks the database.
|
|
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/4242 && printf 'GET /api/health HTTP/1.0\r\n\r\n' >&3 && head -1 <&3 | grep -q ' 200 '"]
|
|
interval: 30s
|
|
timeout: 3s
|
|
start_period: 5s
|
|
retries: 3
|
|
|
|
volumes:
|
|
diary-data:
|
|
|
|
networks:
|
|
internal_net:
|