v1.0.0 · released 5 November 2026

Changelog

Release notes from 1.0.0 onward. The full history lives in the repository.

All notable changes to Rivetr are documented here. The format follows Keep a Changelog and Semantic Versioning. The full history is in the repository.

[1.0.0] - 2026-11-05

First stable release. Everything below the highlights was previously listed as unreleased.

Highlights

  • New dashboard shell: grouped sidebar with submenus, a contextual sidebar inside apps, databases, services and servers, a top bar with breadcrumb switchers (team, project, environment, resource), a status pill and the primary action. Shared page components (page header, framed section cards, form grid, data table with pagination, empty states, skeletons).
  • Clear page structure and URLs: every page sits in one place and has breadcrumbs. Instance settings under /settings, personal pages under /account, team under /team, integrations under /integrations, credentials under /keys, monitoring under /monitoring. App, database and service sections use the same names (/build, /domains, /environment, /storage, /healthcheck, /resources, /advanced, /rollback, /operations, /danger). Duplicate tabs (two Network, two Security, a Settings tab with its own tab strip) are gone. Old URLs redirect. See docs/planning/ui-information-architecture.md.
  • Projects canvas: zoomable canvas of projects, environments and resources with live status, a side panel, filters and resource links; list, grid or canvas view on the dashboard and projects page.
  • Theme customisation per user: light, dark or system mode, accent colour (presets or custom hex), neutral base, corner radius, density, font and size, sidebar style, reduced motion and high contrast, with a live preview. Saved to the account (migration 129), applied before first paint; admins set the instance default under Settings > Branding.
  • Remembered UI state: sidebar collapse and open groups, view toggles, canvas viewport and filters, table page size and filters, log viewer options, terminal font size, metric time ranges, in-page tabs and command palette recents are kept per browser (rivetr:ui:*).
  • Instance settings: editable update channel and schedules, Advanced page (registration, API access with IP allowlist, MCP toggle, two-step destructive confirmation, DNS validation with custom resolvers, outbound target policy, passkeys), public IPv4/IPv6 detection, transactional email (SMTP or Resend) with a test send (migration 123).
  • Server operations: images page with reclaimable space, Docker cleanup schedule with per-category options and run history, OS patching with automatic security updates, maintenance window and reboot detection, patch status on the servers list (migration 124). Non-root SSH users with passwordless sudo, and Tailscale connectivity per server (migration 131).
  • App configuration: structured healthcheck (HTTP or command, expected code and body, timing), per-domain internal port, search indexing and DNS status, an unsaved-changes bar, a container file browser for apps, databases and services, and clone to another server, project or environment with optional volume data (migration 125).
  • Tags (migration 126), passkey sign-in (migration 127) and traffic analytics per app, server and team with optional GeoIP (migration 128).
  • AI-generated Docker Compose from a description, advanced Swarm service spec (migration 130), and 30 new service templates (365 total).

Breaking

  • Dashboard URLs changed (old ones redirect). API paths are unchanged.
  • The MCP server can now be turned off; existing installs keep it on.
  • smtp_tls = true in rivetr.toml now means STARTTLS, or implicit TLS on port 465.
  • Swarm services are created through the Docker API instead of the docker service create CLI.

Added

  • Deployments for Docker Compose services: a Deploy button pulls (or builds) the images and runs docker compose up -d, recreating only changed containers. Each run is recorded with who started it, the trigger, duration, live and stored logs, and the image digest per compose service before and after (migration 120). Optional build from source per service (migration 121): a git repo + branch or a path on the server, images built in order, tagged with the revision and latest and pushed (a local registry:2 works), with auto deploy on push for git sources. Pre- and post-deploy hooks run in a one-off container of a compose service (docker compose run --rm --no-deps); a failed pre-deploy hook leaves the running containers, the compose file and the latest tags as they were. Rollback redeploys a previous deployment's images pinned by digest. New Containers tab (state, health, usage, restart one container, logs, terminal) and Environment tab: encrypted env vars (migration 122) written to a managed .env the compose file can use, with .env import. Services without a build source keep deploying by pulling. See docs/reference/service-deployments.md.

  • Storage usage for apps and services: the Storage tile that databases already had now shows on app and Docker Compose service pages too. It counts the container's writable layer plus its mounted volumes; a service counts a volume its containers share only once. Sizes are measured at most once a minute per container, so polling stays cheap. Docker only for now; on Podman the tile stays hidden.

  • Rollback with data (pre-deploy database snapshots): new per-app snapshot_before_deploy setting (default off; Settings > Deployment > Rollback with Data, or PUT /api/apps/:id). When on, every deployment snapshots each linked PostgreSQL, MySQL, MariaDB, MongoDB, Redis and KeyDB database right before the new container starts, reusing the managed database backup code (backup type pre_deploy, linked via the new deployment_db_snapshots table, migration 115). A failed or skipped snapshot is logged in the deployment log and never blocks the deploy. POST /api/deployments/:id/rollback accepts restore_data: true to restore the snapshots taken while the target deployment was running, after the rollback container is healthy and the old container is retired; it returns 400 before doing anything if the target has no usable snapshot. Before overwriting a database a safety backup of its current data is taken (the database is skipped if that fails). Data written after the snapshot is lost on restore. Per engine: PostgreSQL replays the dump in one transaction after dropping the public schema; MySQL and MariaDB drop every table and view in the database, then replay the dump (exact rollback, but not transactional: a dump that fails midway leaves a partial database, which the safety backup covers); MongoDB takes a mongodump --archive, validates it with mongorestore --dryRun before touching anything, then drops the app database and restores the archive (exact rollback; admin, local and config are never dropped); Redis and KeyDB take an RDB with redis-cli --rdb (AUTH is used only when the server asks for it) and restore by stopping the database container, replacing dump.rdb in its data volume and starting it again, which means a few seconds of downtime for that database. Redis/KeyDB restore needs the data volume on the Rivetr host and no AOF persistence; this is checked before the rollback starts (the rollback returns 400, and a deploy logs that the snapshot was skipped). DragonflyDB and ClickHouse are not snapshotted. MongoDB, Redis and KeyDB backups (including manual and scheduled ones) are now binary safe: they are copied out of the container through base64 and length-checked, where they were previously corrupted by the text-only copy. GET /api/deployments/:id/snapshots lists the snapshots a rollback to that deployment would restore, and the rollback dialog shows an "Also restore database data" checkbox when there are any. New [data_retention] deployment_snapshots_keep (default 3; 0 disables pruning) keeps snapshots for the N most recent deployments per app; the daily cleaner removes older dump files and rows in batches.

  • CPU Steal tile on Monitoring, surfaces the host's CPU "steal" (the since-boot share of cycles the hypervisor took from this VM for other tenants), read from /proc/stat. Explains why an in-guest CPU reading can look low while a hosting provider's host-side graph reads high: persistent steal means the node is oversubscribed. The tile is muted under 5%, amber 5-25%, red above 25%. GET /api/system/stats gained cpu_steal_percent.

  • Per-app proxy access logging toggle: new access_logging app setting (Configuration > Network, or PUT /api/apps/:id). When off, the proxy skips building log metadata and writing that app's requests to proxy_logs, which saves CPU and DB writes on high-traffic apps. Existing apps stay on (migration 114, default 1); new apps default to the new [proxy] access_log_default config value (default true) unless the create request sets it. Takes effect immediately.

Changed

  • New Rivetr logo and favicon: an indigo R tile now shows in the sidebar, on the login, setup, forgot and reset password and invitation pages, as the browser and touch icon, and at the top of the README. A white-label logo, app name or favicon still overrides it, and clearing a custom favicon restores the default. Source and usage notes are in docs/branding/.
  • App detail page tabs consolidated from 12 to 6: Overview, Deployments (Deployments, Previews), Jobs, Logs & Monitoring (Logs, Monitoring, Log Drains, Terminal), Configuration (Env Vars, Network, Settings) and Security. Groups with more than one page show a pill row under the tab strip. No routes changed: every /apps/:id/... URL still opens the same page and highlights its group.
  • Deploys and rollbacks drain the old container before stopping it: after the proxy swaps routes, Rivetr now waits for in-flight HTTP requests on the old container to finish (up to the new proxy.drain_timeout_secs, default 30, 0 disables) before stopping it, instead of stopping it immediately. WebSocket tunnels are not waited for. Apps without a healthcheck now wait up to 30s for their port to accept connections before routes are swapped (a timeout logs a warning and continues, as before).
  • Dashboard and Monitoring redesigned: the dashboard opens with one metric strip (running, CPU, memory, disk, uptime, each with a utilisation meter and a skeleton while loading instead of "..."), then the resource chart and a running-services list that share one height and scroll inside the card, then cost and recent events. Monitoring drops the nine-card grid, the two duplicated memory and disk sections and the radial gauges: it shows four utilisation meters (CPU, memory, disk, load average), the history chart, a compact Host card (uptime, CPU steal, free memory, swap, free disk, database and runtime state) and a Health checks list with an "N of N passing" summary. Status is always text plus a dot, never colour alone. The chart no longer re-animates on every poll and its legend shows the live values.
  • Usage panels unified across apps, databases and services: the shared resource panel is now a metric strip (CPU and memory with utilisation meters, network, and storage for databases). App Overview leads with live usage and merges Configuration and Details into one list; database and service General pages show read-only facts as a list instead of disabled inputs; per-app uptime stats use the same strip with a Healthy, Degraded or Unreliable label; the service Stats tab reuses the shared panel. The app Logs tab is a single card with a taller, neutral console. Service and project pages now show the project name in the breadcrumb.
  • Projects page redesigned: the header shows project, app and database counts; a search box matches project names, descriptions and the names of the apps, databases and services inside them; a sort menu defaults to problems first. Each card has a health pill (Healthy, Needs attention, Building or Empty), links straight to every app, database and service, lists failing resources first so they are never hidden behind "+N more", and keeps its footer pinned so cards in a row line up. Status dots carry a screen-reader label.
  • axum upgraded to 0.8: all routes use the /{param} path syntax and the two custom extractors no longer need async_trait. Prometheus /metrics path labels now read /api/apps/{id} instead of /api/apps/:id. Handlers whose JSON body is optional (delete app, deploy, rollback, reject deployment, clone app) use a new lenient OptionalJson extractor: axum 0.8 started answering 400 to an empty body that still carries Content-Type: application/json, which is what the dashboard sends. The unused axum-extra dependency was removed.
  • bollard (Docker client) upgraded to 0.21: container, network, image, exec, stats and log calls moved to the new request builders and models. Checked against a real Docker daemon: deploy from an image and from an uploaded Dockerfile, container limits, restart policy, ports, env vars and network aliases as created by Docker, stats, log stream, terminal exec with resize, scheduled-job exec with exit codes, live resource-limit updates, stop, start, restart and a rolling redeploy. One known limit: the new client library sends build memory limits as a 32-bit number, so a build memory limit above 2147483647 bytes (just under 2 GiB) is capped there and a warning appears in the build log. The 2g default is unaffected in practice.
  • sqlx upgraded to 0.9: the new release refuses any SQL string that is not a literal unless the code explicitly marks it as audited. The 23 places that build SQL at runtime (log search, proxy and audit log filters, webhook events, database settings update, retention cleanup, key-file checks and the migration runner) were each reviewed: they only assemble static fragments, fixed table and column names and ? placeholders, and every value is bound as a parameter. The retention cleanup helper now only accepts &'static str table and column names, so the compiler enforces that no runtime text can reach its SQL. Existing databases open unchanged. Checked with injection strings on every filtered endpoint (they return nothing and leave the tables intact).
  • New command rivetr db encrypt-secrets: enabling an encryption key only protected values written afterwards, so an existing install kept every earlier secret in plaintext. The command (dry run by default, --execute to apply) creates the key and salt files if needed and encrypts env vars, SSH keys and passwords, S3 keys, TOTP secrets and GitHub App secrets in one transaction. Each value is decrypted back and compared before it is written, and running it again changes nothing. The startup warning for installs without a key now points at it.
  • Typography: the dashboard now uses Geist (UI) and Geist Mono (numbers, paths, code) instead of Figtree with the system monospace font.
  • Dependencies upgraded to current stable releases: frontend React 19.3, React Router 8, Vite 8, TypeScript 7, Tailwind 4.3, lucide-react 1, TanStack Query, Radix and the rest of the in-range updates; the build no longer needs vite-tsconfig-paths (Vite resolves tsconfig paths itself) and lucide's removed GitHub icon is replaced by a local component. Backend: zip 9, rand 0.10, totp-rs 6, argon2 0.6, sha2 0.11, hmac 0.13, aes-gcm 0.11, jsonwebtoken 11 (with the aws_lc_rs backend), reqwest 0.13 (bundled root certificates kept), git2 0.21, x509-parser 0.18, rcgen 0.14, tower-http 0.7, toml 1, cron 0.17, parking_lot 0.13, base64 0.23, pem 4, ratatui 0.30, plus all semver-compatible updates. Stored data is unaffected: existing Argon2 password hashes, encrypted secrets and enrolled authenticator apps keep working (covered by new tests against a reference Argon2 vector, the RFC 6238 SHA1 vector and the existing legacy-format AES-GCM vector). The minimum supported Rust version is now 1.95. axum 0.8, bollard 0.21 and sqlx 0.9 are intentionally not included yet: each is a breaking migration of a core subsystem and needs its own end-to-end test pass.

Fixed

  • Deleting a database left its data on disk: the container was removed but the data directory under <data_dir>/databases (and the named volume of an adopted database) stayed, even though the dialog said all data would be deleted. Delete now removes both. Files written by the database's own user are removed from a short-lived alpine container when Rivetr cannot delete them itself. Data another database still points at is kept, and nothing outside <data_dir>/databases is touched. Backups are not affected.
  • A failed deploy no longer marks a working app red: the Projects page used the latest deployment's status, so one failed or cancelled deploy turned the app's dot red although the previous deployment was still serving. GET /api/apps/statuses now reports running while any deployment of the app is running; the failure is still listed under Deployments.
  • Docker Compose service domains never got HTTPS: the TLS certificate only listed app domains, so a service with a domain was routed but served the instance certificate, and browsers refused it. Service domains are now added to the certificate at startup and picked up by the renewal loop within a minute of being set. Startup and the renewal loop now share one domain collector (proxy::acme::collect_cert_domains), so they no longer disagree: startup also reads the older plain-string domains format, and the renewal loop also skips .sslip.io and .traefik.me helper hosts.
  • Images from a registry with a port were rejected: localhost:5000/app and registry.example.com:443/team/app:1.2 failed with "Invalid character in docker image tag" because the reference was split at the first :. The tag is now read after the last /, and only the registry host may carry a numeric port.
  • Managed PostgreSQL 18 databases crash-looped on start: the 18 image refuses a data volume mounted at /var/lib/postgresql/data and expects one at /var/lib/postgresql, with the cluster in a version subdirectory. Rivetr now mounts the right path for the version (18 and later, and non-numeric tags such as latest); 12 to 17 are unchanged. Installing TimescaleDB follows $PGDATA instead of a fixed path. An existing 18 database never started, so nothing needs migrating.
  • Pale status badges and the service status pill turned white on the dark theme: the database log and network badges, the team permission allow and deny badges, the GitHub connected badge and the service status pill now have dark variants.
  • A failed image pull now says why: the deployment log shows the registry's answer (for example "pull access denied" or "repository does not exist"). Before, it only said "Failed to pull image from registry". A failed Dockerfile build step keeps showing the daemon's reason (for example "returned a non-zero code: 7") with the new Docker client.
  • Docker networks are no longer duplicated on older engines: Rivetr now checks that the rivetr and per-app networks exist before creating them, instead of relying on a duplicate check that engines older than Docker 25 apply only when asked.
  • ZIP uploads over 2MB always failed: the upload routes (/api/apps/:id/deploy/upload, /api/projects/:id/apps/upload, /api/build/detect) inherited axum's 2MB default body limit, so any realistic project archive was rejected with "Error parsing multipart/form-data request". They now accept up to 100MB, matching the cap on extracted contents. Every other route keeps the 2MB limit.
  • Pages scrolled sideways on phones and tablets: the main column could grow past the screen when any child was wide, and the app header, cost toolbar and Settings sub-navigation did not wrap. Checked on 20 pages at widths from 360 to 1280px. The Settings sub-navigation now stays a dropdown until there is room beside the sidebar (1024px).
  • Dashboard metric strip left an empty cell on phones next to Disk.
  • Resource chart gridlines and ticks, and the monitoring gauges, rendered with invalid colours: they used hsl(var(--border)) on oklch theme tokens.
  • Every restart reset most app settings: the migration 066 check (sqlite_autoindex_apps%) matched the apps table's own text primary key, so the table was rebuilt on every startup and every column added after it (snapshot_before_deploy, access_logging, restart_policy, privileged, cap_add, devices, shm_size, init_process, the Docker options, ...) went back to its default. The check now looks only for a UNIQUE constraint on name.
  • Cloning an app or an environment dropped snapshot_before_deploy and access_logging: POST /api/apps/:id/clone and POST /api/projects/:project_id/environments/:env_id/clone now carry both settings over.
  • SSO/OIDC login had no browser binding on its CSRF state: GET /auth/sso/:provider_id/login now also sets an HttpOnly; SameSite=Lax cookie rivetr_sso_state (path /auth/sso, Secure over HTTPS) and the callback requires the state to match it, so an attacker-minted state cannot be replayed into a victim's browser. The state is consumed atomically (single use) and expires after 10 minutes (previously only cleaned up lazily, never checked). The cookie helpers are shared with social login (api/state_cookie.rs).
  • Cloudflare tunnels, GitHub Apps, Docker Swarm and SSH keys were not team scoped: tunnels get a nullable team_id (migration 117; existing tunnels stay global) and POST /api/tunnels accepts one the caller belongs to. GET /api/tunnels, GET /api/github-apps, GET /api/github-apps/installations and GET /api/ssh-keys only return the caller's teams' rows plus legacy team-less ones (system-wide GitHub Apps stay visible to all, SSH keys follow their app). resource_authz_middleware now covers /api/tunnels/:id/..., /api/github-apps/:id/... and /api/github-apps/installations/:id/... (previously any signed-in user could list a team's repos through its installation token or stop its tunnel) and requires the developer role for writes. App-bound SSH keys, tunnel routes and swarm services now require write access to the app they reference. Swarm init/leave/nodes and swarm services with no app are admin-only. Instance admins and team-less legacy rows behave as before.
  • Global SSH keys, the GitHub App manifest callback and system-wide GitHub Apps were open to any signed-in user: SSH keys now record their creator (migration 119); a global key (no app) can be edited or deleted only by that user or an instance admin, and keys created before this change are admin-only to modify. The GitHub App registration state moved from an unsigned, client-supplied blob to a server-side single-use table (github_manifest_states, migration 118, 30 minute expiry): the callback rejects a missing, forged or replayed state, takes the team and scope from the row written by the authorized caller, and records that user as created_by. POST /api/github-apps with is_system_wide: true is admin-only. The dashboard's "Create GitHub App" flow now passes the state to GitHub (it never did, so the team and scope were dropped) and only asks for a system-wide app when the user is an instance admin.
  • Notification channels created through POST /api/notification-channels had no team: they were visible to every signed-in user, including their webhook URLs and bot tokens. The request now takes an optional team_id (default: the caller's first team) and needs the team admin role, like POST /api/teams/:id/notification-channels. Only instance admins can still create a global channel, by leaving the team out. Existing team-less channels are unchanged.
  • Resource authorization middleware never ran, and team roles were not enforced: resource_authz_middleware matched on /api/... but the router is mounted with .nest("/api", ..), which strips the prefix, so almost every /api/apps/:id/... route (deployments, stats, status, commits, volumes, basic-auth, snapshots, ...) answered 200 to members of other teams. It now matches on the original URI. It also now requires the developer team role (or higher) for any mutating request on apps, deployments, volumes, previews, databases, services, projects and servers, so a viewer can no longer edit or deploy an app, and a team that only holds a view-only app share cannot write. Instance admins and the admin API token are unaffected, and team-less (legacy) resources stay open to every signed-in user.
  • Social login (GitHub/Google/GitLab/Azure/Bitbucket) failed with a 500: the CSRF state was stored in sessions under a fake oauth_state user id, which violates the sessions.user_id foreign key. States now live in their own oauth_login_states table (migration 116).
  • Redeploying an app with replicas dropped its extra replicas: old replica containers kept their canonical name (rivetr-<app>-<n>), so creating the new replica failed with a Docker 409 and the app ended up with one container. Old replicas are now renamed to -prev before the new ones start, like the primary container, and drained and retired after the route swap.
  • Manual rollback dropped HTTP Basic Auth from the app's proxy route: the route rebuilt after a rollback only carried the strip prefix, so an app protected by Basic Auth became publicly reachable until its next deploy (it also lost its healthcheck path and access-logging flag). The rollback route now keeps all three. The "Rollback to this" button on the deployment detail page now rolls back to that deployment instead of the most recent other one.
  • Dashboard and Monitoring stats took 30s+ to load: GET /api/system/stats queried Docker stats for each container one after another (about 1-2s each, 36s with 16 apps). It now collects container IDs first, queries them concurrently (32 at a time, 5s timeout each) and caches the aggregate for 10s.
  • Dashboard "Running Services" card fired one stats request per app and database every 15s: added GET /api/system/resources, which returns CPU and memory for every running app and database in one call (containers queried concurrently, cached 10s, team_id scoping as in /api/system/stats). The card uses it.
  • Projects page fired one /apps/:id/status request per app: added GET /api/apps/statuses (same team_id scoping and visibility as GET /api/apps) returning every app's latest deployment status in one query, and the projects page uses it.
  • Unbounded growth of proxy_logs, webhook_events, audit logs, scheduled_job_runs and expired sessions: the daily log cleaner now prunes these in bounded 10,000-row batches. New [data_retention] config (defaults: proxy_logs_days = 14, webhook_events_days = 30, audit_logs_days = 90, scheduled_job_runs_keep = 100; 0 disables an item); sessions expired for over a day (including OAuth state rows) are always removed. Behavior change: existing rows older than these windows are deleted on the first daily run (about 5 minutes after start).
  • Proxy access log write amplification: the proxy no longer spawns a task plus an INSERT per request. Entries go through a bounded queue (10,000, dropped and counted when full) to a single writer that batch-inserts every second or 200 entries, and log metadata is only built when logging is enabled. Redirect-rule regexes are compiled once and cached instead of per request.
  • Proxy logs page full-table COUNT(*): GET /api/proxy/logs now counts at most 10,000 matching rows; total is capped and a new total_capped field flags it.
  • Monitoring CPU usage was wrong (showed e.g. 129.7%), the "CPU Usage" card and the utilization chart summed each container's Docker CPU% (where 100% = one core), so the figure was noisy and could exceed 100%, never reflecting real host load. Both the live GET /api/system/stats endpoint and the history collector now read true host CPU utilization from /proc/stat (sampling the cumulative counters over a 200 ms window), reported as a 0-100% aggregate across all cores. Falls back to the old container sum on non-Linux dev machines.
  • Notification channel "Send test" reported a JSON error, the test endpoint returned an empty 200 OK, but the dashboard parses the response as JSON, so the button failed with "Unexpected end of JSON input" even though the test was actually sent. The endpoint now returns a small JSON body.
  • Subscribing to "Container Crashed" / "Container Restarted" failed, these event types exist in the backend enum and the UI, but the notification_subscriptions.event_type CHECK constraint (from migration 016) never listed them, so the insert hit a CHECK violation. Migration 110 rebuilds the table with the full event-type set.
  • Dashboard Disk Usage card overlapped its icon: long values like "76.61 GB / 95.82 GB" now wrap inside the card instead of running under the icon.
  • API failures showed fake zeros and empty states: the dashboard, Monitoring, Projects, Services, Templates, Running Services, Cost Overview, Recent Events and several settings lists (API tokens, SSH keys, destinations, teams, tunnels, audit log, webhook events, proxy logs) now show an inline error with a Retry button when the request fails, instead of 0% or "No items".
  • Accessibility: icon-only buttons (delete, edit, copy, back, refresh, row menus) and unlabelled inputs now have accessible names, and the ZIP and database dump drop zones can be activated from the keyboard.
  • Removed unused legacy route files routes/apps/$id.tsx and routes/services/$id.tsx.

Security

  • Dependency updates for Dependabot alerts: Rust quinn-proto, rustls-webpki, aws-lc-sys, lettre and the AWS SDK crates (which also moves aws-smithy-json past its recursion advisory) are on patched versions in Cargo.lock; the frontend moved react-router and the @react-router/* packages from 7.10.1 to 7.18.4 and took the non-breaking npm audit fix updates. 6 npm advisories remain, all one build-time chain (braces through the shadcn CLI) with no patched release; nothing in it ships in the dashboard.
  • SSH host keys are now pinned for servers and build servers: every SSH, scp and rsync call used StrictHostKeyChecking=no, so a man-in-the-middle could impersonate a managed server. Connections now use accept-new against <data_dir>/ssh/known_hosts: the key is trusted on first use and a later key change is refused by OpenSSH. After legitimately rebuilding a server, clear its pin with DELETE /api/servers/:id/host-key (or /api/build-servers/:id/host-key). Behavior change: the first connection to each server after upgrading pins whatever key it presents. Git clone connections are unchanged.
  • Encryption at rest no longer silently off on fresh installs (SEC-M10): when [auth] encryption_key is unset, Rivetr loads <data_dir>/.encryption_key if present; on a fresh install (no users, env vars, servers or git providers) it generates one (random 256-bit, mode 0600, created atomically, never overwritten) and logs a notice to back it up with the database. Existing installs without a key keep running unchanged but log a prominent warning with the exact line to add. Legacy plaintext values stay readable once a key is enabled. KDF hardening (per-install salt, Argon2id) remains a follow-up needing a versioned ciphertext format.
  • Client IP spoofing and brute force (SEC-H3, SEC-L4, SEC-M4): rate limiting and audit logs now use the TCP peer address and honor X-Forwarded-For / X-Real-IP only from trusted proxies (new rate_limit.trusted_proxies list of IPs/CIDRs; loopback is always trusted; X-Forwarded-For is read right to left). Behavior change: if Rivetr sits behind a proxy on another host or a Docker bridge, add that proxy to trusted_proxies, otherwise all clients share the proxy's rate-limit bucket. Added per-account lockout for /api/auth/login and /api/auth/2fa/validate (5 failures in 15 min, exponential backoff up to 15 min, 429 while locked, cleared on success). Unknown emails now run a dummy Argon2 verify so login timing no longer reveals whether an account exists. The admin token check in get_current_user is constant time.
  • Content-Security-Policy and HSTS (SEC-M6, SEC-L3): the dashboard is served with a CSP (default-src 'self', script-src 'self' plus sha256 hashes of the inline scripts in the embedded HTML computed at serve time, style-src 'self' 'unsafe-inline' for white-label CSS, same-host ws:/wss: for connect-src, img-src 'self' data: blob: https:, frame-ancestors 'none', object-src 'none', base-uri 'self'). Non-HTML responses get default-src 'none'; frame-ancestors 'none'. Strict-Transport-Security: max-age=31536000 is sent when the request arrived over HTTPS (X-Forwarded-Proto). Behavior change: a custom frontend build that adds external scripts, fonts or API origins will be blocked.
  • OAuth login hardening (SEC-M3): the callback now rejects a missing, unknown or expired state with 400 and consumes it atomically (single use). A new OAuth identity is linked to an existing local account by email only when the provider vouches for the address (GitHub /user/emails verified flag, Google verified_email, GitLab confirmed_at, Bitbucket is_confirmed, Azure single-tenant only); otherwise sign-in is refused with an explanatory error. Existing connections are unaffected.
  • Login returnUrl validation (SEC-M7): the post-login redirect read from localStorage must be a same-origin path (single leading /, no //, backslash or control characters), otherwise it falls back to /.
  • Authorization tail (SEC-C3): the per-resource authorization middleware now also covers build servers, notification channels and subscriptions, destinations, CA certificates, S3 configs and backups, volumes, previews, project environments and app-bound SSH keys. Behavior change: build servers are team scoped like servers (members of the owning team and instance admins only; build servers with no team stay visible to everyone), and the lists of build servers, notification channels, destinations, CA certificates, S3 configs/backups and previews only return rows of the caller's teams plus team-less rows. Creating a resource with a team_id the caller is not a member of now returns 403 (apps, servers, databases, services, projects, build servers, destinations, CA certificates, S3 configs), as does assigning an app to an inaccessible project. Git provider connections (get, delete, list repos) are limited to their owner or an instance admin. Bulk start/stop/restart/deploy skip apps the caller cannot access. Admin token and instance admins are unchanged.
  • OAuth state bound to the browser (SEC-M3): the OAuth login redirect sets a short-lived rivetr_oauth_state cookie (HttpOnly, SameSite=Lax, 10 min, Secure behind HTTPS) and the callback requires the state to match it in addition to the stored row, then clears it. Behavior change: start the sign-in and finish it on the same host name (the one in external_url); a login started on one address and redirected back to another now fails with a 400 asking to restart.
  • Versioned encryption with per-install salt (SEC-M10, SEC-L8): new secrets are written as ENC2: (AES-256-GCM with an HKDF-SHA256 subkey derived from the key and a random per-install salt in <data_dir>/.encryption_salt, mode 0600, created on first use whenever an encryption key is in use). Existing ENC: values and legacy plaintext keep decrypting and are upgraded lazily the next time their row is written. Behavior change: back up .encryption_salt together with the key and the database; without it ENC2: values cannot be read, and an older Rivetr binary cannot read ENC2: values (no downgrade after new secrets are saved).

0.11.0 - 2026-06-09

Added

  • Competitive-parity sweep (Coolify v4.1.0 / Dokploy v0.29.x), Closed five gaps surfaced by a fresh re-research of both competitors. See docs/research/competitive-gap-analysis.md (§ "Re-research 2026-05-27").
    • [skip ci] / [skip cd] commit markers, A push whose tip commit message contains [skip ci], [ci skip], [skip cd], [cd skip], [skip deploy], or [no deploy] (case-insensitive) no longer triggers a deployment. Honored across the GitHub, GitLab, Gitea, and Bitbucket webhook handlers via the shared commit_skips_deploy() helper.
    • Configurable stop grace period, New per-app stop_grace_period (seconds) controls how long a container gets to shut down gracefully (SIGTERM) before SIGKILL on stop/replace. NULL/empty uses the runtime default (Docker's 10s). New ContainerRuntime::stop_timeout() (Docker StopContainerOptions.t, Podman --time); editable in the app's Docker Options settings. Migration 107.
    • PostgreSQL 17 & 18, Added to the managed-Postgres version list (pgvector already supported); default bumped 16 → 17 to match the dashboard.
    • LibSQL managed database, New DatabaseType::Libsql (Turso's server-side SQLite sqld, ghcr.io/tursodatabase/libsql-server). Auth-less HTTP/HRANA API on port 8080; http:// connection string; appears in the new-database picker.
    • Expanded MCP tool surface, The /mcp endpoint grew from 4 tools to 9: added list_deployments, get_deployment_status, list_services, list_databases, list_projects, and restart_app (database credentials are masked in list_databases).
  • Move resources between projects from their settings page, Each app, database, and service settings page now has a "Project" card to reassign (or unassign) the resource to any project, complementing the existing project-centric add/remove flow. update_database now accepts project_id (empty string clears the assignment).
  • Per-service resource limits, Services now have cpu_limit / memory_limit fields (Service settings → "Resource Limits"). Rivetr injects them as the top-level cpus / mem_limit compose keys (honored by docker compose up, unlike swarm-only deploy.resources.limits) on every service at deploy time, a service that already sets a key keeps its own value, so Docker enforces the caps via cgroups, bringing services in line with apps and managed databases. Applied across the start and both restart paths. The service stats page shows the configured caps alongside live usage. Migration 108.
  • Database storage usage in stats, the database stats endpoint now reports storage_bytes, the actual on-disk size of the data directory (measured with du -sb inside the container, using the engine's volume root so it covers adopted layouts too). Surfaced as a "Storage Used" tile in the resource monitor.
  • Configurable deployment concurrency, caps how many deployments build at once via a shared semaphore in the deploy engine; additional deploys queue until a slot frees. Previously every triggered deployment spawned immediately with no bound, so a monorepo push (one repo → several apps) or a burst of webhooks could start many simultaneous Docker builds and exhaust host CPU/RAM. Configurable from Settings → "Max concurrent deployments" (saved instance setting, applied live with no restart) or runtime.max_concurrent_deployments in rivetr.toml. Default 2.
  • Host metrics on the Monitoring page, the page now shows true host RAM (used / available / total + %), swap, load average (1/5/15m + per-core), CPU core count, and host uptime alongside the existing CPU and disk views (previously it showed no memory at all). GET /api/system/stats was extended to read host memory/swap/load from /proc, no new crates.
  • Sendry email notifications, new "Sendry" notification channel (a Resend-compatible HTTP email API, https://docs.sendry.online). Configure an API key + from/to addresses in Settings → Notifications; delivered via reqwest like the other providers (no new crate). Migration 109 extends the notification_channels type constraint.
  • Dashboard polish, System Overview stat values no longer wrap to two lines; the CPU / Memory / Disk cards link to /monitoring; the Running Services list shows a per-service health dot and links to each resource; Recent Events use meaning-coded dots (success / failure / info) with tooltips and link to the relevant app or deployment; added a live "updated N ago" indicator.

Fixed

  • Long log lines widened the whole page, on the logs tab a single very long line (URL, base64, stack trace) stretched the layout horizontally instead of staying inside the log box. The log container is now width-constrained (min-w-0 / max-w-full) and long lines wrap/scroll within it.
  • Repeated sections across resource detail tabs, the same control or info was rendered in multiple tabs of an app/database/service (restart policy in both General and Docker settings; the domain editor in both the Network tab and Settings → Network; database resource-limits and metadata in both Overview and Settings; service exposed-ports in both Overview and Network). Each is now shown in a single canonical tab.
  • Queued deployments showed a running clock and inflated duration, a deployment's started_at was stamped when it was created (queued), so a deploy waiting behind the concurrent-deployment limit displayed a growing timer and, once it finally built, a total duration that included the queue wait (looking as long as the deploy ahead of it, easily mistaken for the cap not working). started_at is now reset to the real build start when a slot frees, and pending deployments render as "Queued" instead of a running timer. The concurrency cap itself was already correct.
  • App update ignored github_app_installation_id, PUT /api/apps/:id accepted the field but never wrote it, so an existing app couldn't have a GitHub App installation attached or changed (e.g. converting an app from a registry image to a private git source left it with no clone auth). It's now merged and persisted like the other fields, so switching an app to a git source works entirely via the API/UI.
  • Database CPU/memory limits couldn't be changed after creation, the DB settings "Resource Limits" card was read-only ("delete and recreate to change limits"), and update_database ignored limit changes for the running container. The card is now editable with a Save button, and a limit change is applied live to the running container via docker update (cgroups), no restart needed.
  • Database overview showed fake resource-limit placeholders, when a database had no CPU/memory limit set, the overview rendered hardcoded 512mb / 0.5 defaults, implying a cap that wasn't actually applied (e.g. a DB using 2.4 GB displaying a "512mb" limit). It now shows the configured value or "No limit".
  • Live memory-limit update failed on containers started without a cap, update_container_limits (apps' apply-limits and the new DB path) set memory without memory_swap, which Docker rejects with "Memory limit should be smaller than already set memoryswap limit" whenever the container had unlimited swap. It now sets memory_swap == memory so the update is accepted and the cap is hard.
  • Service restart didn't apply config changes, restart_service ran docker compose restart, which only restarts the existing container processes and never re-reads the compose file, so changes made since the last start (resource limits, env, domain/port, compose edits) silently didn't take effect on a restart. It now runs docker compose up -d --force-recreate, rebuilding the containers from the current compose.
  • Reverse proxy always sent X-Forwarded-Proto: http, Even on the HTTPS listener (:443) the proxy hard-coded X-Forwarded-Proto: http, so upstream apps that build absolute URLs from the forwarded scheme (Laravel, Rails, Django, …) emitted insecure http:// asset and redirect URLs that browsers block as mixed content (symptom: pages render unstyled because the CSS request is blocked). The HTTPS listener now reports https, the HTTP listener still reports http; applies to both request and WebSocket forwarding.
  • Migration 107 (stop_grace_period) was never wired into run_migrations(), The migration file and the App.stop_grace_period field shipped, but the matching execute_sql call was missing, so fresh installs never created the column and every POST /api/apps failed with no column found for name: stop_grace_period. Now wired with an idempotent pragma_table_info guard.

Removed

  • Template suggestion / submission features, removed the "My Suggestions", "Submit a template", and "Suggest a template" actions from /templates together with their pages, API-client methods, and backend endpoints/handlers/models (template_suggestions and community_template_submissions code paths). The core template catalog and one-click deploy are unchanged.

Tests

  • +5 unit tests: commit skip-marker detection (case-insensitivity + non-matches), LibSQL config / no-credential-env, and Postgres 17/18 availability. Suite now 251 passing.

0.10.23 - 2026-05-27

Added

  • Host-protection resource defaults: every container now inherits configurable safety defaults (memory limit, PID limit, OOM score bias) when it sets none, so a runaway container can no longer exhaust host RAM. Per-resource limits still override; set default_memory_limit = "" to opt out.
  • Container log rotation + critical-disk auto-reclaim: containers now get log rotation defaults, and the disk monitor automatically prunes images and build cache when usage crosses the critical threshold, closing the disk host-hang vector.
  • Database integrity check on startup: self-check runs a SQLite PRAGMA quick_check and surfaces corruption loudly in the startup report. Non-critical; the server still starts.
  • Tooling & reference docs: added rustfmt.toml, a [lints] table in Cargo.toml, and configuration/API reference docs covering every rivetr.toml field and REST endpoint.

Tests

  • Expanded unit coverage for build-type auto-detection and API input validation (+33 tests covering precedence, framework detection, and injection/path-traversal blocking). Suite now 246 passing.

0.10.22 - 2026-05-27

Fixed

  • Panic isolation: switched the release profile from panic = "abort" to panic = "unwind" so a panic in one of the ~79 Tokio tasks unwinds only that task instead of killing the whole process. A new guarded() helper wraps all 16 background loops in catch_unwind, and the 8 reverse-proxy hot-path unwrap() calls now fall back to a header-less response on untrusted-input errors.

Changed

  • Release builds now unwind on panic (slightly larger binary, negligible runtime cost) for process-level resilience.

0.10.21 - 2026-05-02

Added

  • Database-to-app linking with auto env injection: a new "Linked Databases" section lets users connect a managed database to an app with one click, auto-injecting connection env vars (DATABASE_URL, HOST, PORT, etc., or REDIS_URL / MONGODB_URL) on the next deploy. An optional prefix avoids key collisions; user-defined env vars always win.
  • Inline credentials display on the project DB list: each database card now has a "Show credentials" toggle that expands the connection string, username, and password inline with copy buttons.

Fixed

  • MySQL 8 connection broken via published connection string: managed MySQL containers now start with --skip-ssl so clients can connect without TLS errors, reverting the prior query-string workaround.
  • Audit ip_address was always null: the ClientIp extractor is now wired into all 30+ audit-emitting handlers, recording socket IP (or X-Forwarded-For for proxied requests).
  • Disk-stats path inconsistency: backend now canonicalizes data_dir so the Dashboard and Monitoring pages report the same number.

UX

  • Sidebar user menu: clearer spacing, hover/focus states, and a rotating chevron make the user pill obviously interactive.
  • Deploy menu commit/tag and ZIP-file modals: both menu items now open their dialogs (fixed a Radix dropdown-to-dialog focus race).
  • Template page category anchors: category sections have anchors and "View all N" links that smooth-scroll and expand inline.
  • Resource Limits live-apply: saving limits now applies them immediately to a running container via docker update, with helper text that adapts to running/stopped state.

Removed

  • The prior ?ssl-mode=DISABLED MySQL connection-string workaround, replaced by the --skip-ssl server-side fix.

0.10.20 - 2026-05-02

Added

  • Coolify-style deploy log side panel: a dockable panel opens automatically on Deploy/Start/Restart (apps, services, databases) and streams image-pull and container-start activity in real time, via new per-resource WebSocket/REST routes.
  • MariaDB as a managed database type: MariaDB joins the catalogue (versions 11 default, 10.11, 10.6, 10.5) with the correct mariadb:// scheme, data mount, and mariadb-dump backups.
  • scripts/deploy-vm.sh: local Parallels Ubuntu ARM64 VM deploy mirror for faster iteration on Apple Silicon.

Fixed

  • Container monitor service health check broken since v0.10.18: the health-check query omitted columns added by a later migration, silently disabling crash detection for all Compose services. Now selects the full column set.
  • /api/apps/:id/insights returned 503 when AI not configured: now returns 404, eliminating misleading console 503s and log spam.
  • Docker network "endpoint already exists" warnings on restart: the connect helper now treats the 403 + "already exists" pair as an idempotent no-op.
  • MariaDB/MySQL post-start user-provisioning warning silenced when the entrypoint already created the user.
  • Audit log now records the full set of mutating actions (token, app, service, database, deployment, env-var, and domain operations) that were previously missing.
  • /api/audit?limit=N alias accepted, matching the Coolify/Dokploy convention.
  • POST/DELETE endpoints accept empty body / no Content-Type: delete-app, rollback, and cancel no longer return 415 without a body.
  • Cancel deployment in non-cancellable state returns 409 (was 404), reflecting that the deployment exists but isn't cancellable.
  • Rollback commit_message references the correct deployment id (the path-param target).
  • Old running deployment marked replaced not failed after rollback, since no build error occurred.
  • Stable internal hostname surfaced in App model: GET /api/apps/:id now exposes a derived internal_hostname so the Network tab connection example stays correct across restarts.
  • Templates list endpoint compressed + slim: responses now gzip-compress and return a slim field set (was ~500 KB plain, now ~86 KB gzipped); full bodies live at GET /api/templates/:id.
  • Database SQL backup downloads use application/sql Content-Type so browsers can display rather than save-as.
  • Compose service auto-domain fallback: services with no domain now auto-assign <service-name>.local so they're reachable via the proxy.

Frontend bug fixes (VM sweep)

  • Setup form placeholder and validator now agree on a 12-character minimum.
  • App General tab hides the "Dockerfile path" field unless build type is dockerfile.
  • Network tab shows the actual network name "rivetr" (was "rivetr-network").
  • Templates page first paint capped to 6 cards per category with a "View all N" link (was ~1300 cards).
  • /monitoring chart wrapper now has an explicit min-height, ending the recharts width(-1) warning.
  • Setup auto-logs-in when the API returns a session token, falling back to /login otherwise.
  • Deployment detail label shows "Deployed at" instead of "Finished" while still running.
  • Project page no longer double-renders empty-state CTA buttons.
  • Added form autocomplete attributes so password managers and iOS strong-password generation work.
  • Login submit button is disabled when email or password is empty.
  • Project page hides the Healthy/Issues/Building tabs when a project has zero apps.
  • Deployment-log render strips ANSI escape sequences.

Infrastructure

  • Added scripts/deploy-vm.sh for fast Parallels-VM iteration on Apple Silicon.
  • Fixed 7 pre-existing clippy errors; cargo clippy with -D warnings now exits 0.

[v0.10.19] - 2026-03-25

Fixed

  • Zero-downtime HTTPS during instance restarts: proxy listeners are now pre-bound once in main.rs and shared, so the HTTPS server inherits its systemd socket instead of failing with "Address already in use." Connections now queue at the kernel during restarts instead of getting refused.

[v0.10.18] - 2026-03-25

Added

  • Service resource monitor: the service detail page now shows live CPU, memory, and network stats when running.
  • Service public port exposure: services can expose a container port on the host via a new Network tab, with port-conflict checks and auto-restart on change.
  • Full backup includes service data: backups now bundle Compose files and database dumps for running service containers (Postgres, MySQL/MariaDB, Redis-family, MongoDB), with non-fatal dump failures.

Fixed

  • Migrations 104 and 105 not auto-applied: both are now registered with idempotent guards so they apply on next startup.

[v0.10.17] - 2026-03-25

Changed

  • AI provider config moved to dashboard: provider, API key, model, and max-token cap are now set under Settings, stored in the database, and hot-applied with no restart. The [ai] config section remains a startup fallback; the raw key is never returned by the API.

Added

  • Settings AI Provider card: configure provider (Claude, OpenAI, Gemini, Moonshot), masked API key, model override, and max-tokens, with a "Configured" badge.

[v0.10.16] - 2026-03-25

Added

  • AI-powered features (Phase 1): multi-provider AI client across the platform, all requiring an [ai] API key in rivetr.toml.
    • Deployment error diagnosis: sends recent logs to the AI and returns a structured diagnosis with actionable suggestions.
    • Deployment insights: success rate, average build time, and 30-day trend with an optional AI summary.
    • Cost optimisation suggestions: AI-generated resource tuning recommendations on the Monitoring tab.
    • Dockerfile Optimizer: returns an optimised Dockerfile with a list of improvements.
    • Security & Compliance Advisor: five rule-based checks plus an optional AI summary, surfaced in a new Security tab; a global scan aggregates across all apps.

[v0.10.15] - 2026-03-25

Fixed

  • ACME cert saved under wrong directory on renewal: save_certificate now takes an explicit instance_domain so renewed certs land in the correct directory and survive restarts.
  • Uptime checker skipped apps with no custom domain: the poller now falls back to auto_subdomain and checks *.rivetr.site subdomains over HTTPS.
  • Monitoring page showed "100% availability" with 0 checks: now renders "-" when there are zero checks.
  • Uptime summary stats ignored period selector: the period dropdown now threads through to the backend and re-fetches.
  • Westel Dockerfiles: removed unsupported BuildKit cache mounts, upgraded PHP 8.3 to 8.4, and preserved layer-ordering optimisations.

[v0.10.13] - 2026-03-22

Fixed

  • App API boolean types: app endpoints now return AppResponse, mapping SQLite integer columns to JSON booleans and fixing frontend deserialization errors.
  • Frontend error handling for non-JSON responses: the API helper now catches SyntaxError and surfaces the raw text body instead of a confusing JSON-parse message.
  • Docker image prune filter: replaced the invalid system prune --filter dangling=true with docker image prune -f.
  • Full system backup failure: ManagedDatabase queries now use SELECT * so newer schema fields no longer cause column-not-found errors.
  • Firewall security check false positive: the check no longer marks inactive firewalls as active.

Added

  • Webhook events pagination: GET /api/webhook-events now accepts page/per_page and returns a paginated envelope; the UI persists state in URL params.
  • Disk pressure auto-cleanup: the cleanup engine checks disk usage and, above 85% full, keeps only the latest deployment per app and prunes images and build cache.
  • Docker build cache pruning: every cleanup cycle now runs docker builder prune -f to reclaim cache that previously grew unbounded.
  • Reduced default deployment retention: max_deployments_per_app default lowered from 10 to 3.

[v0.10.12] - 2026-03-18

Added

  • Proxy access logs: every proxied request is now logged to a proxy_logs table (host, method, path, status, latency, bytes, client IP, user agent), with a Settings page offering filters and auto-refresh.
  • User Preferences panel: a Settings page with localStorage preferences for theme, date/time format, default log lines, deployment notifications, and compact mode.
  • 11 new service templates (Sprint 26): MediaWiki, SuperTokens, Netbird, AFFiNE, HeyForm, OpnForm, GitHub Actions Runner, Bluesky PDS, PeerTube, Roundcube, and docker-mailserver. Rivetr now has 335+ one-click templates.

[v0.10.11] - 2026-03-18

Added

  • Custom container labels: apps support arbitrary Docker labels via a key-value editor, applied at launch alongside built-in Rivetr labels.
  • Proxy-level www redirect: www_redirect_mode now issues 301 redirects at the proxy layer before any upstream connection.
  • 5 new service templates (Sprint 25): Joomla, Drupal, Grafana standalone, Etebase, Obsidian Remote. Rivetr now has 315+ one-click templates.

Fixed

  • Missing migrations 092-099: the runner was missing these migrations, causing 500s on app/server endpoints; now registered.
  • Migration 101 column check: the guard now checks for the destination_id column, not just table existence, fixing a 500 on fresh deployments.

[v0.10.10] - 2026-03-18

Added

  • Docker Destinations: named Docker networks that apps can be assigned to, mirroring Coolify's destinations.
  • CA Certificate management: upload trusted CA certificates (PEM) for custom TLS trust chains.
  • Inline Dockerfile: deploy from a pasted Dockerfile with no git repo, skipping the clone entirely.
  • Fetch server details: SSHes into a server to collect OS, Docker version, disk, CPU, and RAM, shown via "Refresh details."
  • WWW redirect mode: per-domain dropdown (No redirect / Serve both / to www / to non-www) issuing 301s for the redirect variants.
  • Instance timezone: global IANA timezone for scheduled tasks and log timestamps.
  • 11 new service templates (Sprint 24): Vaultwarden, LiteLLM, MindsDB, Matrix Synapse, Rocket.Chat, NodeBB, Zipline, Joplin Server, Siyuan Notes, Hatchet, EasyAppointments. Rivetr now has ~113 one-click templates.

[v0.10.9] - 2026-03-18

Fixed

  • Cost analysis pricing: estimates were 300-600x too low. Fixed with a per-server hourly_rate model (default $0.036/hr matching DigitalOcean), DO-aligned fallback rates ($10/vCPU + $1/GB per month) for unassigned apps, and billing against allocated rather than used memory.

Added

  • Hourly rate field on servers: the server edit dialog now includes an "Hourly Cost (USD/hr)" input with DigitalOcean size hints.

Added

  • Git clone options: per-app toggles for submodules (--recurse-submodules), LFS (git lfs pull), and shallow clone (--depth 1, default on).
  • Build cache control: a disable_build_cache toggle passes --no-cache to Dockerfile/Nixpacks builds for a clean rebuild.
  • SOURCE_COMMIT build arg: an include_source_commit toggle injects the current git SHA as a Docker build argument.
  • Custom container name: overrides the auto-generated rivetr-<app-name> name.
  • Static site flag: marks an app as a static site, toggled in Build Settings.
  • Generate domain: auto-assigns a random subdomain from the server's base domain (falls back to sslip.io).
  • Links dropdown: app nav now lists all configured domains as quick-open external links.
  • Environment Clone: duplicate a project environment's apps, databases, and services into a fresh environment (containers stopped, domains cleared, deployment state reset).
  • 8 new service templates (Sprint 23): Flowise, Langflow, Open WebUI, AnythingLLM, Pocket ID, Activepieces, Trigger.dev, SigNoz. Rivetr now has ~102 one-click templates.
  • Server timezone setting: per-server IANA timezone (default UTC), in the Edit Server dialog.
  • Strip URL prefix: a per-app strip_prefix removes a URL prefix before proxying, in both HTTP and WebSocket forwarding.
  • Resend notification channel: fixed validation for the resend, mattermost, lark, and gotify channel types, which were previously blocked.
  • Theme toggle in top nav: the Light/Dark/System toggle is now in the header bar as well as the sidebar.
  • Version + feedback in sidebar: the footer now shows the current version (linked to GitHub releases) and a Feedback link.
  • 7 new service templates (Sprint 22): Minecraft Java, Palworld, Terraria, Satisfactory, Argilla, Mage AI, Glitchtip. Rivetr now has ~94 one-click templates.
  • 13 new service templates (Sprint 21): Beszel Agent, ClassicPress, CloudBeaver, Diun, Homebox, Karakeep, Linkding, PairDrop, Readeck, Ryot, Shlink, Slash, Wakapi. Rivetr now has ~87 one-click templates.

[v0.10.8] - 2026-03-17

Fixed

  • Server status stuck offline: the SSH health check now falls back to sshpass password auth when a stored key fails to load, instead of leaving the server permanently offline.
  • Server action buttons cluttered: replaced the flat row of buttons with Terminal and Files as primaries and the rest grouped in a ... dropdown.

[v0.10.7] - 2026-03-16

Added

  • Service resource monitoring: built-in template services now have a Stats tab with live CPU, RAM, and network, aggregated across all containers in the Compose project.
  • Deployment Cleanup Settings UI: configure max_deployments_per_app and image pruning from Settings; values persist in the database and fall back to config defaults.
  • Restart History in Deployments Tab: app restarts now create deployment records with logs and a distinct "restart" trigger badge.
  • TUI (rivetr tui): a terminal UI with tabbed Apps/Deployments/Servers/Logs views, keyboard navigation, and live log polling (enable with --features tui).
  • Fine-grained RBAC: per-resource permission overrides let admins grant or deny individual members access to specific apps, projects, databases, or services.
  • Deployment Queue Cancellation: any queued or running deployment can be cancelled via the detail view, aborting the current pipeline stage.
  • Community Template Submissions: users can submit Compose templates for admin review; approved submissions are promoted to the live registry.
  • Remote Filesystem Browser: browse, read, write, and delete files on any connected server over SSH, with a full file browser and inline editor.

Fixed

  • GitHub App webhooks silently dropped by HTTPS redirect: /webhooks/ paths are now excluded from the HTTP-to-HTTPS redirect so push events aren't dropped after TLS is issued.
  • GitHub App webhook URL used wrong scheme after HTTPS setup: the registered URL now defaults to HTTPS, and a new sync endpoint updates the GitHub App's webhook URL.
  • App settings never showed webhook setup instructions: the General tab now shows an "Auto-Deploy Setup" card with the ready-to-paste webhook URL and steps for the detected provider.
  • Duplicate webhook deployments on push: fixed four overlapping bugs (non-atomic delivery-ID guard, unfiltered branch-deletion events, missing per-app idempotency, and a too-narrow active-status check) so a single push deploys once.
  • CPU chart compared against full host CPU instead of allocated limit: the Resource Monitor now normalises against the container's CPU limit so 100% means the allocated quota.
  • API token auth in middleware: rvt_-prefixed tokens are now validated in auth_middleware, fixing 401s on endpoints that don't use the user extractor.
  • TUI ping using auth-required endpoint: switched to the public /health endpoint so connectivity and auth failures are reported separately.
  • TUI /api/deployments 404: replaced the nonexistent global query with merged per-app requests.
  • Stale container_id causing stuck 'starting' state: when a database's container is gone, Rivetr now clears the id, resets status, and provisions a fresh container.
  • Reconciliation queries failing after new migrations: recovery queries now use SELECT * to stay resilient to schema additions.
  • 5-field cron expressions rejected by scheduler: 5-field Unix cron strings are now normalized by prepending a seconds field.
  • React setState-during-render in LogRetentionSection: moved the sync state update into a useEffect.
  • MySQL/MariaDB user not created on reused data directory: Rivetr now idempotently provisions the app user via the Unix socket after every container start.
  • New app subdomains missing SSL coverage: certs can now be hot-swapped without a restart, and the renewal manager reissues immediately when new app subdomains appear.
  • Orphaned restart containers causing CPU/RAM drain: stale rivetr-*-restart-* containers are now removed on startup, and the stop/remove task logs failures.
  • No swap warning: Rivetr now warns at startup when the host has no swap, and the installer creates a 2-4 GB swapfile with swappiness=10.

Planned

  • SAML 2.0 support
  • Remote build execution (SSH-based)
  • Overlay networking and rolling updates for Docker Swarm

[0.10.6] - 2026-03-14

Added

  • Container Resource Limits UI: configure CPU and memory limits per app, with an "Apply Now (Live)" button that enforces them on the running container via docker update, no redeploy needed.
  • DragonFlyDB: new Redis-compatible managed database type (port 6379, redis://, RDB backups).
  • KeyDB: new multi-threaded Redis-compatible managed database type (port 6379, redis://).
  • ClickHouse: new columnar analytics managed database (port 8123, clickhouse://) with access management and post-start init.
  • Docker Compose Raw Mode: a per-service toggle that deploys the compose file exactly as written, skipping Rivetr network injection, name namespacing, and labels.
  • Ansible Playbook: ansible/rivetr.yml for idempotent server provisioning on Ubuntu/Debian (Docker, binary, systemd, UFW).
  • Service Templates Master Registry: a reference doc listing all unique templates by category to prevent duplicates.

Fixed

  • Duplicate Service Templates: removed 55 duplicate entries, reducing unique templates from 328 to 273.
  • Env Vars in Storage Settings: removed the duplicate Environment Variables panel; env vars are managed only from the dedicated tab.

[0.10.5] - 2026-03-13

Added

  • 27 New Service Templates: added across Dashboards, AI, Analytics, Backup, Communication, Dev Tools, Media, Storage, and Security categories. Total now ~119.
  • Port Conflict Validation: ports already in use are now rejected at template deployment (debounced live check), custom service creation, and database external-port update (409 Conflict), backed by a check-port endpoint.
  • Auto-Subdomain for Template Services: template-deployed services now get a {name}.{base_domain} subdomain with a proxy route on startup.

Fixed

  • Service Stop Status: template services now show "Stopped" instead of "Failed" after stop (fixed a compose-dir lookup that ignored the temp dir).

[0.10.4] - 2026-03-12

Added

  • API Tokens: create named tokens (prefixed rvt_, stored as SHA-256 hashes, optional expiry) for programmatic access via /api/tokens. Existing admin-token scripts are unaffected.

Fixed

  • Version Reporting: Cargo.toml version now matches the release so Auto Updates reports the correct running version.
  • Breadcrumbs: added missing entries for Cost Analysis and the Previews/Jobs/Log Drains/Monitoring app sub-tabs.
  • Notification Channels 403: the team channels endpoint now grants access to the admin API token.
  • Team Breadcrumb: the team detail page now shows the team name instead of "Page."
  • Build Server Docker Column: no longer shows "vnot installed"; the v prefix is added only for version strings.
  • SSH Password Auth for Servers & Build Servers: servers can now be registered with a password (no key required), using sshpass transparently.

[0.10.3] - 2026-03-12

Added

  • Recharts Dashboard: replaced custom SVG charts with Recharts across the dashboard and monitoring pages.
  • Service Domain Routing: Compose services now support a configurable domain with full proxy integration (registered on start, removed on stop/delete, restored on startup).
  • Service Restart Button: services now have a Restart button alongside Stop when running.

Fixed

  • Proxy Route Restore on Startup: running apps now have routes (including Basic Auth and www variants) fully restored after a restart, preventing post-update 404s.
  • Audit Log User Display: the audit log now shows the user's email instead of their UUID.
  • Audit Log Resource Type Formatting: multi-word types like ssh_key now display as "SSH Key."
  • SSH Key Delete Audit Log: deleting a key now records its name, not the UUID.
  • DB Backup Download 401: backup downloads now fall back to the stored auth token.
  • Database Data Directory Uniqueness: data directories now include the first 8 chars of the DB UUID to prevent path collisions.
  • Deployment Detail Status Badge: now shows "Running" for active deployments (plus "Replaced" and "Stopped" labels).
  • Service Logs Duplication: the log viewer no longer shows REST and SSE history entries simultaneously.
  • Service Network Tab Open Link: now uses the configured domain URL when the port matches.
  • Dashboard Stats Console Errors: the app stats endpoint now returns zeroed stats (200) for apps with no running deployment.
  • Recent Events Replaced Status: superseded deployments now show a descriptive message instead of "unknown."
  • Deployment Log Streaming: Docker and Nixpacks build output is now streamed in real time.
  • Logout Auth Header: logout now passes the Authorization header and clears the token.
  • Team-Scoped Queries Backward Compat: team-scoped queries now include OR team_id IS NULL so legacy resources stay visible.
  • Freeze Windows API Path: the frontend now calls the correct freeze-windows endpoint.
  • Migration 067/068 Registration: the container-slug and service domain/port migrations are now registered.
  • Admin API Token Permissions: the admin token now has full access to all teams and can delete apps without a password.
  • Stuck Deployments Cleanup: deployments stuck in running/pending are cleaned up on startup.
  • TypeScript Fixes: corrected a DeploymentLog.id type mismatch, a missing icon prop, and a log sort comparison.

[0.10.2] - 2026-03-11

Added

  • Deployment Detail Page: shows real-time build logs over WebSocket plus metadata and error details, navigated to automatically after a deploy.
  • GitLab Source in New App: a GitLab repo picker is now available alongside GitHub in the new-app form.

Fixed

  • Git Clone Authentication: HTTPS clones for private GitHub/GitLab/Bitbucket repos now inject the provider's token so git doesn't prompt for credentials.
  • App Name Validation: names are auto-sanitized in the frontend and validation is relaxed; the global uniqueness constraint was removed (apps are identified by UUID).
  • Bitbucket Auth: migrated from deprecated App Passwords to Atlassian API Tokens.
  • HTTP-to-HTTPS Redirect: port 80 no longer redirects to HTTPS until a TLS certificate is confirmed.
  • Sidebar URL Restructure: infrastructure and access items now live at clean top-level URLs.
  • Missing Project Routes: the project environments and env-vars routes are now registered.

Changed

  • Deployment Diff & Build Logs Modals: widened for readability.
  • "View Full Logs" Button: now navigates to the deployment detail page instead of a small modal.
  • Deploy Button: now takes the user to the deployment detail page to watch live logs.
  • Database Migration 066: removed the apps.name UNIQUE constraint (existing data preserved).

[0.10.1] - 2026-03-10

Fixed

  • PackConfig Default: trust_builder now correctly defaults to true, fixing test_empty_config.
  • Frontend TypeScript: fixed option-object args and removed a reference to a nonexistent app field.
  • servers.tsx: replaced an inline require("react") with proper top-level imports.
  • Cargo.toml: bumped version to 0.10.1 and fixed the repository URL.
  • install.sh: fixed the Railpack download URL (uses -musl, includes the version tag).
  • Database migrations: fixed a startup crash in the comment-aware SQL parser and registered missing migrations (051, 052, 054, 055, 056, 065).

[0.10.0] - 2026-03-10

Added

Container Registry Push

  • Registry Push on Deploy: apps can push built images to any Docker registry after a successful build (URL, username, encrypted password, per-app toggle), configured in a new app settings section.

Rollback Retention Policies

  • Configurable Retention: keep 1-50 previous deployments per app (default 10); older deployments and logs are trimmed after each successful deploy. Configurable in deployment settings.

Community Template Suggestions

  • Suggest a Template: users can submit template suggestions (name, image, category, description, URL); admins can list and approve them into the service templates.

Auto-scaling Foundation

  • Autoscaling Rules: define per-app CPU/memory threshold rules with min/max replica bounds and cooldowns, enforced by a 60-second background scaler, managed from an app settings card.

Enhanced Prometheus Metrics

  • New metrics for deployment count and duration by app, live app/database gauges, and webhook ingestion by provider.

Webhook Audit Log

  • Webhook Events: all incoming webhook events are logged (provider, type, repo, branch, apps triggered, status) and viewable on a Settings page with filters and auto-refresh.

MCP Server

  • Model Context Protocol: a /mcp endpoint exposes Rivetr tools (list_apps, deploy_app, get_app_status, get_deployment_logs) for AI assistant integration.

[0.9.0] - 2026-03-10

Added

Multi-Server Enhancements

  • Server App Assignment: assign apps to specific registered servers, with a RemoteContext foundation for the remote build pipeline.
  • Remote Server Terminal: an xterm.js WebSocket SSH terminal embedded in the server settings page.
  • Server App Management API: endpoints to list, assign, and remove server apps.

Docker Swarm Integration

  • Swarm Management: initialize/leave a Swarm and store join tokens.
  • Node Management: list, sync, and drain/activate nodes.
  • Service Scaling: create, scale, remove, and inspect Swarm services.
  • Swarm Dashboard: a settings page with status, nodes, and services tables.

Build Servers

  • Dedicated Build Server Registration: separate build servers with encrypted SSH keys, concurrency limits, and health checks, plus full CRUD and a dashboard.

Deployment Preview Diff

  • Diff View: a per-deployment "View Diff" button showing the commit range, count, messages, and changed files in a modal.

Instance Backup to S3

  • Upload to S3: a per-backup button to upload an instance backup to S3.

[0.8.0] - 2026-03-10

Added

DockerHub Webhook

  • DockerHub Integration: apps with a matching docker_image auto-deploy when the image is pushed to DockerHub, with callback acknowledgement.

Scheduled Backups

  • Backup Schedules: cron-based scheduling for instance and S3 backups with configurable retention and an enable/disable toggle, run by a 60s background scheduler.

2FA Enforcement Per Team

  • Team-level 2FA Requirement: owners can require all members to have 2FA, blocking non-TOTP users from team resources, via an owner-only Security tab.

Template Search & Filtering

  • Template Search: a search param filters templates by name/description, with a result count and scrollable category pills.

Service Dependency Graph

  • Dependency Visualization: projects show a graph of apps, databases, and services with labeled nodes and edges, backed by dependency endpoints and a service_dependencies table.

Zero-Downtime Indicator

  • Deployment Phase Banner: the Deployments tab shows a real-time phase indicator (Stable, Deploying, Health Checking, Switching Traffic), and app status now returns deployment_phase, active_deployment_id, and uptime_seconds.

Multi-Server Support

  • SSH Server Registration: register remote servers with encrypted credentials; health checks gather CPU/memory/disk/OS/Docker stats, shown on a management page with per-server "Check Now."

SSO/OIDC

  • OpenID Connect: a full OIDC auth flow with provider management and quick-fill presets for Auth0, Keycloak, Google, Azure AD, and Okta; the callback creates or links a user account.

Container Replicas

  • Replica Scaling: set 1-10 replicas per app; the pipeline starts N containers and the proxy round-robins across them via a lock-free RoundRobinBackend.

Refactored

  • Split all Rust files over 1000 lines into organized submodules, and split the frontend API types into 7 domain files and several large pages into components (all imports unchanged).

[0.5.0] - 2026-03-10

Added

Deployment Enhancements

  • Approval Workflow: apps can require approval before deploys; pending deployments await admin sign-off with an approve/reject UI and reason field, surfaced via a badge and timeline status.
  • Scheduled Deployments: deploy at a specific time via scheduled_at, picked up by a 60s scheduler.
  • Deployment Freeze Windows: define windows (days + UTC start/end) when deploys are blocked (returns 409).

Bulk Operations & App Management

  • Bulk Actions: multi-select apps to Start/Stop/Restart/Deploy at once.
  • App Cloning: deep-copy an app's config, env vars, and domains as {name}-copy.
  • Config Snapshots: save and restore named point-in-time snapshots of app config and env vars.
  • Project Export/Import: download a full project as JSON and re-import to recreate it.
  • Maintenance Mode: toggle per-app maintenance mode with a custom message and header badge.

Shared Environment Variables

  • Inheritance Chain: team, project, environment, and app variables resolve in that order (highest wins), with a "Resolved" tab showing effective variables and source badges, managed from team and project settings.

[0.4.0] - 2026-03-10

Added

S3 Backup Integration

  • S3 Storage Configs: support for AWS S3, MinIO, Cloudflare R2, and any S3-compatible endpoint with encrypted credentials.
  • Backup to S3 / Restore from S3: upload instance, database, and volume backups to S3 and restore any of them with one click, managed from an S3 settings UI.

Advanced Monitoring

  • Full-Text Log Search: search deployment logs by query, date range, and level.
  • Uptime Tracking: 60s health checks with availability percentage, response time, and 24h/7d/30d history.
  • Log Retention Policies: per-app retention (days + max size) with daily background cleanup.
  • Scheduled Container Restarts: cron-based per-app restarts with an enable/disable toggle.
  • Monitoring Tab: a per-app tab combining log search, uptime, retention, and scheduled restarts.

Log Draining

  • Provider Support: Axiom, New Relic, Datadog, Logtail (Better Stack), and a generic Custom HTTP target.
  • Batched Forwarding: logs buffered and flushed every 5 seconds or 100 lines, with error tracking and a per-app management tab with test button.

Changed

  • Watch path filtering added to the GitHub push handler (was missing; only Gitea/GitLab had it).

[0.3.0] - 2026-03-09

Added

Preview Deployments

  • PR Preview Environments: automatic preview deploys for pull/merge requests across GitHub, GitLab, and Gitea, with unique subdomains, auto-posted GitHub PR comments, automatic cleanup on close/merge, and lower default resource limits.

Watch Paths

  • Selective Deployment: configure per-app glob patterns so pushes only deploy when matched files change, applied across all four Git providers, with a settings card.

Bitbucket Webhooks

  • Bitbucket Support: push and PR webhook handling with HMAC-SHA256 verification, a bitbucket_secret config option, and a Git Providers tab with webhook URL, copy, and connection test.

Notification Channels (4 New)

  • Telegram, Microsoft Teams, Pushover, Ntfy: added rich-formatted integrations, bringing Rivetr to 8 notification channels.

Instance Backup & Restore

  • Full Instance Backup: bundle the database (after WAL checkpoint), config, and SSL certs to a tar.gz, with create/list/download/delete/restore endpoints, rivetr backup/restore CLI commands, and a Settings page.

OAuth Login

  • GitHub & Google OAuth: full authorization flows with user creation/linking, account linking in settings, an admin provider config page, and conditional login buttons.

Project Environments

  • Environments: dev/staging/production environments per project (auto-created) with environment-scoped variables, predefined system variables (RIVETR_ENV, RIVETR_APP_NAME, RIVETR_URL), a switcher, and a management page.

Two-Factor Authentication

  • TOTP 2FA: compatible with standard authenticator apps, with QR-code setup, 10 hashed recovery codes, AES-256-GCM-encrypted secrets, a 2FA-aware login flow, and a security settings page.

Service Templates Expansion (26 to 74)

  • Added ~48 templates across AI/ML, Analytics, Automation, CMS, Communication, Development, Documentation, File/Media, Monitoring, Security, Search, and Project Management, with new category enum variants for gallery organization.

Scheduled Jobs

  • Cron Scheduler: a 60s background evaluator runs container jobs via Docker/Podman, with CRUD endpoints, a scheduled_job_runs history table, and a per-app management tab.

Deploy by Commit/Tag

  • Commit/Tag Deploy: deploy a specific commit SHA or tag (commit_sha/git_tag); the pipeline checks out the ref, the API lists commits/tags, and a deploy modal offers a selector with timeline badges.

Changed

  • Updated the notification channel CHECK constraint to include all 8 providers.
  • Login response now includes requires_2fa.
  • Project creation auto-creates production, staging, and development environments.
  • The deployment pipeline merges environment-scoped and system variables and supports commit/tag checkout.
  • The template gallery now shows 74 templates across 12+ categories.

0.2.16 - 2026-02-13

Fixed

  • Auto-Update Download: fixed the "Downloaded update undefined" message by adding a version field to the response.
  • Auto-Update Apply: fixed the "Failed to create backup" error by falling back to a temp dir when the install dir is read-only, with symlink resolution and proper permissions.
  • Delete GitHub App: fixed a 405 by adding and registering the DELETE handler that also removes installations.
  • Git Providers FK Constraint: fixed a 500 when adding GitLab/Bitbucket providers by using the authenticated user's ID instead of a hardcoded one.

Added

  • Audit Logging: extended audit logging to Auth (login/setup), SSH Keys, GitHub App deletes, and Git Provider add/delete, with new action and resource constants.

0.2.15 - 2026-02-13

Fixed

  • Install Script: changed the default version to latest so it auto-fetches a real release instead of failing on a never-released tag, and added a frontend build step before cargo build to fix the RustEmbed compilation error.
  • GitHub App Callback: corrected the post-install redirect to the existing git-providers page.

0.2.14 - 2026-02-05

Fixed

  • Container Monitor: added the missing team_id column to database queries, ending the recurring "no column found" warning.
  • Notification Channels: migration 038 adds webhook to the channel-type CHECK constraint, handling foreign keys correctly.

0.2.13 - 2026-02-05

Fixed

  • Teams API Panic: fixed a string-slicing panic when creating a Personal team for user IDs shorter than 8 characters, using safe character iteration for slug generation.

0.2.12 - 2025-02-05

Fixed

  • Dashboard Stats Chart: fixed an auth-token key mismatch so the stats history API receives the token on the dashboard and monitoring pages.

0.2.11 - 2025-02-05

Added

  • Auto-Update System: background update checking (default 6h) with version-info, check, download, and apply endpoints, configured via [auto_update] in rivetr.toml, with an optional auto-apply mode.

Changed

  • Added comprehensive testing documentation.

0.2.10 - 2025-02-05

Fixed

  • PORT Environment Variable: Rivetr now auto-injects PORT (set to the container port) into deployments, rollbacks, and previews when not already set, so Heroku-style apps work out of the box.

0.2.9 - 2025-02-05

Changed

  • Version bump for release pipeline.

0.2.8 - 2025-02-04

Fixed

  • Container Monitor: added the missing team_id column to the services query, fixing a SQL error when restarting crashed services.

0.2.7 - 2025-02-04

Added

  • Personal Team Auto-Creation: new users get a "Personal" team on first login, and existing teamless users get one when needed.

0.2.6 - 2025-02-04

Fixed

  • Frontend API URL: uses window.location.hostname instead of hardcoded localhost, so the dashboard works via IP or custom domain.

0.2.5 - 2025-02-04

Fixed

  • Systemd Service: multiple Docker/Podman compatibility fixes (read-only home, added ReadWritePaths, created the rivetr home directory).
  • Install Script: auto-detect external_url from the server IP.
  • Cost API: fixed a SQL type mismatch in cost calculations.

0.2.4 - 2025-01-10

Added

  • Team Collaboration (Multi-tenant): full multi-tenant teams with resource scoping via team_id, a sidebar team switcher, email invitations (7-day expiry) with HTML/text templates, role hierarchy (owner > admin > developer > viewer) and member management, app sharing, team-scoped stats, audit logging with a paginated UI, a migrate-teams CLI command, and a Personal workspace fallback.
  • Resource Alerts & Cost Estimation: per-app CPU/memory/disk/network metrics, customizable alert thresholds with email notifications and event history, configurable cost rates, daily cost snapshots, and a team-cost aggregation API.
  • Embedded Frontend Assets: frontend files are embedded via rust-embed for single-binary deployment, with compressed cached assets, SPA fallback, and MIME detection.
  • CLI Tool: status, apps list/show, deploy, logs --follow, and config check, with --api-url/--token options and env-var equivalents.
  • Metrics Storage with Retention: stats_hourly (30-day) and stats_daily (365-day) aggregates from an hourly background task, configurable retention, and a stats-summary endpoint.

Fixed

  • Team Switcher: fixed switching back to the Personal workspace by persisting an explicit marker in localStorage.
  • Install Script: corrected the binary download URL and architecture detection, added CAP_NET_BIND_SERVICE for ports 80/443, added build-dependency installation, and added dynamic version fetching for latest.

0.2.3 - 2025-01-10

Fixed

  • Updated the macOS x86_64 build runner from retired macos-13 to macos-15-intel.

0.2.2 - 2025-01-10

Fixed

  • Resolved OpenSSL cross-compilation issues by adding git2's vendored-openssl feature.
  • Changed macOS builds to native runners instead of cross-compilation for reliability.

0.2.1 - 2025-01-10

Fixed

  • Switched reqwest from native-tls to rustls-tls for cross-platform builds.

0.2.0 - 2025-01-09

Added

  • Railpack Builder: Railway's Nixpacks successor with BuildKit integration.
  • Cloud Native Buildpacks: Heroku and Paketo buildpack support via the pack CLI.
  • Auto-rollback: automatic rollback on health-check failure.
  • Paginated Deployments API: GET /api/apps/:id/deployments with page/per_page.

Changed

  • Updated Claude Code agents and skills documentation.

Fixed

  • JWT generation test for malformed PEM structures.
  • Redeployment for ZIP-uploaded apps using existing images.

0.1.0 - 2025-01-08

Added

Core Deployment Engine

  • Git deployments from GitHub, GitLab, and Gitea with webhook signature verification.
  • Multiple build types: Dockerfile, Nixpacks, and static sites.
  • Docker and Podman runtime support with auto-detection.
  • Zero-downtime deployments with health checks.
  • Real-time build and runtime log streaming via WebSocket/SSE.
  • Rollback to any previous deployment.

Platform Services

  • Managed Databases: one-click PostgreSQL, MySQL, MongoDB, and Redis.
  • Docker Compose: deploy multi-container apps from a compose file.
  • 26 Service Templates: Portainer, Grafana, Uptime Kuma, Gitea, n8n, MinIO, Traefik, and more.
  • Database Backups: scheduled hourly/daily/weekly backups.

Security

  • HTTPS with automatic Let's Encrypt certificates and renewal.
  • Team management with RBAC (owner/admin/developer/viewer).
  • Rate limiting with a sliding-window algorithm.
  • Input validation and command-injection protection.
  • Security-headers middleware.
  • AES-256-GCM encryption for environment variables at rest.
  • Constant-time comparison for timing-attack prevention.

Dashboard

  • A React + TypeScript dashboard with SSR (React Router v7).
  • Real-time deployment status and resource monitoring.
  • Browser-based container terminal (xterm.js).
  • Theme switching (light/dark/system).
  • A build-logs viewer for all historical deployments.

Operations

  • ZIP-upload deployment with build-type auto-detection.
  • GitHub App integration for repository access.
  • Container crash recovery with exponential backoff.
  • Startup self-checks (database, runtime, directories, disk).
  • A Prometheus metrics endpoint (/metrics).
  • Disk-space monitoring with alerts.

Configuration

  • Per-app and build resource limits.
  • Custom Dockerfile path and build targets.
  • Pre/post deployment commands.
  • Multiple domains per app with auto-SSL.
  • HTTP Basic Auth protection.
  • Container labels for Traefik/Caddy integration.
  • Volume management with backup/export.

Infrastructure

  • GitHub Actions CI/CD with multi-platform releases.
  • SQLite with WAL mode.
  • An embedded reverse proxy with ArcSwap for lock-free route updates.

Version History Summary

VersionDateHighlights
0.10.202026-05-02Coolify-style deploy log side panel, MariaDB managed DB type, container monitor service-health regression fix, AI insights 503 to 404
0.2.162026-02-13Auto-update fixes, delete GitHub App, git provider FK fix, audit logging
0.2.152026-02-13Install script download fix, GitHub App callback fix
0.2.142026-02-05Container monitor and notification webhook fixes
0.2.132025-02-05Teams API panic fix for short user IDs
0.2.122025-02-05Dashboard stats chart auth fix
0.2.112025-02-05Auto-update system with API endpoints
0.2.102025-02-05Auto-inject PORT env var for containers
0.2.92025-02-05Release pipeline update
0.2.82025-02-04Container monitor team_id fix
0.2.72025-02-04Personal team auto-creation
0.2.62025-02-04Frontend dynamic hostname
0.2.52025-02-04Systemd and install script fixes
0.2.42025-01-10Team collaboration, resource alerts, cost estimation
0.2.32025-01-10macOS runner update
0.2.22025-01-10OpenSSL vendoring fix
0.2.12025-01-10rustls-tls migration
0.2.02025-01-09Railpack, CNB buildpacks, auto-rollback
0.1.02025-01-08Initial release with full PaaS features

Migration Notes

Upgrading to 0.2.x

No breaking changes. The 0.2.x releases focus on build system improvements and new builder support.

From Source

git pull origin main
cargo build --release
# Restart the service

Using Install Script

curl -fsSL https://raw.githubusercontent.com/KwaminaWhyte/rivetr/main/install.sh | sudo bash