Releases: kavaliersdelikt/fledge
Release list
v0.9.1.2 preview
Fledge v0.9.1.2
This patch makes the Mews administration flows easier to complete in the panel and fixes overview access for delegated operators.
Fixed and improved
- VM setup in the panel. Ready Linux nodes now have an audited Allow new VMs on this node switch under Virtual machines → Nodes. New placement and migration require that switch; it defaults off. The switch is available only after the connected agent reports KVM, libvirt, x86-64 and native network isolation. Disabling it does not stop existing guests.
- No VM enablement environment flag. The agent discovers host capabilities automatically. Host packages, firmware and libvirt networks still need to be prepared on the Linux node, and placement remains blocked until checks pass. The panel links directly to the VM host guide, now also listed in the operator docs navigation.
- Usage reporting setup. The prepared GitHub intake, public App Client ID and encryption key are available as defaults. Super administrators can review or change these public coordinates in Settings → Panel → Usage reporting; deployments no longer need usage-specific
.envvalues. Reporting remains off until explicit consent and GitHub device authorization. OAuth tokens remain encrypted in the database; private keys are never entered in Fledge. - Inbound support email setup. Generate, enable, disable and rotate the signed inbox-bridge secret in Help desk → Settings → Inbound. The key is encrypted in the database and shown only once. Existing
SUPPORT_INBOUND_SECRETvalues remain a legacy fallback until the panel setting is saved. - Operator overview access. The overview uses a limited activity summary protected by
servers.view; the full audit feed still requiresaudit.view. The summary excludes actor identities and event details. - Workspace navigation. Customer and administrator destinations are grouped and ordered around their common tasks.
Upgrade
Update the panel and Linux agent to 0.9.1.2. The database change adds nodes.vm_enabled with a default of false; it is additive and existing nodes do not begin receiving new VM placements. Run the normal update procedure. Remove the obsolete VM_ENABLED agent setting if present; it is no longer used. Existing optional USAGE_* environment values are harmless, but no longer required.
Verification
- API and web type checks and production builds.
- VM HTTP/PostgreSQL tests for default-off placement, readiness-gated panel enablement, allowed placement and compatible migration targets.
- Usage reporting tests for built-in intake defaults, configuration validation, explicit opt-in, GitHub authorization and withdrawal behavior; support tests verify the inbox secret stays encrypted, starts off, and can be enabled and disabled in the panel.
- Delegated Operator browser/API authorization checks; full audit access remains restricted.
- Linux agent vet/tests/build, a disposable browser pass with refreshed Mews screenshots, and documentation link/build checks.
Full Changelog: v0.9.1.1...v0.9.1.2
v0.9.1.1 "Mews"
Fledge v0.9.1.1 "Mews"
Opt-in Linux KVM/libvirt virtual machines join explained account suspensions, delegated administrator access and an optional built-in help desk. A mews is where falcons are kept while they moult: looked after while they are not flying.
Added
- Account suspension. Six reasons, a customer-visible host message, an internal note, a random reference, history and scheduled or payment-based lifting. Suspended customers can sign in to billing, security, data export and permitted deletion, with an urgent ticket-backed appeal. Dark, light and mobile layouts use the existing theme and branding.
- Safe server holds. Stopping uses ordinary node jobs. Account, billing and administrator holds remain independent; only previously running account-held servers restart on lift. Paid provisioning waits until the account is released. SFTP, console streams, API tokens, schedules, placement and failover respect the hold.
- Team. Exactly one super administrator, invitations, live permission switches and presets, revocation, a password-and-fresh-factor email transfer, and an audited shell recovery command. Unknown administrative routes fail closed; token scopes intersect live grants.
- Optional help desk. Customer tickets and articles; an agent queue with search, filters, unread markers, pagination, keyboard navigation and bulk actions; public replies, private notes, attachments, drafts, macros, presence warnings, linked tickets and panel context. Suspension appeals work independently of the general desk.
- Service goals. Standard, Priority and Urgent tiers; timezone-aware business windows and holidays; deadlines pause while waiting for the customer. Plans can grant Priority. Ordered automation rules support conditions and multiple actions, with a visible run history.
- Operations. Thirty-day reports, CSV and Prometheus series; editable mail templates and normal notification channels; a bot-protected public abuse form; configurable ticket retention, export and anonymisation. Signed inbound email is an opt-in bridge endpoint, disabled without a configured secret.
- Documentation, permission reference, API reference and a repeatable screenshot/browser workflow covering the shipped screens.
Upgrade
Follow the upgrade guide. The additive schema is rerunnable. The oldest active, unblocked administrator becomes the super administrator, and other existing administrators keep full grants. Block sign-in keeps the existing hard-lock behavior.
The help desk, public articles, abuse reporting, whole-account billing suspension and automatic retention deletion are off by default. Review Team and support setup before enabling them. Suspension appeals have a separate switch. Retention normally reminds administrators; destructive retention must be explicitly enabled and uses the existing deletion cooling period.
For Stripe, suspended customers need a separately configured restricted portal configuration. If the provider cannot supply a restricted portal, Fledge refuses that portal and preserves invoice payment links. Upgrade the panel and node agent together.
Verified
- API, web and plugin-host TypeScript checks; web production build.
- Mews unit and integration suites against disposable PostgreSQL: default-deny route matrix, tokens, console and SFTP, job guards, upgrade from the previous schema, private-note isolation, diagnostics, attachment rules, business clocks, ordered rules, retention and signed inbound reply replay protection.
- Account/billing/administrator hold interactions, invoice-gated automatic lifting and deferred paid provisioning; real SMTP transfer delivery, receiver identity, both fresh factors and single-use confirmation.
- Chrome browser flows on the shipped production panel: suspension edit/lift, customer and agent replies, private-note isolation, solving, rating, reopening and rule editing; dark, light, phone and reduced-motion screenshots.
- Public abuse submission through Cloudflare's official test widget and verification endpoint, plus rejection without a bot response.
- Documentation code-block and screenshot-reference checks, example plugin validation and production site build; landing links, new hosting tabs and mobile width.
- Linux node agent:
go vet,go testand a release binary build in an isolated Go 1.25 container. - Existing API unit, account, billing, fit, template, autopilot, Rookery, branding, plugin, Discord and updater suites; plugin-host sandbox tests.
Operational limits
Attachments are content-sniffed, size-limited and authorised on every download; there is no antivirus scanner. Diagnostics include only the console lines still retained by the panel and filter known secrets. Inbound email requires a trusted mailbox bridge; Fledge does not poll a mailbox.
Virtual machine runtime and notification completion
- Explicit immutable
container | vmruntime throughout templates, servers, jobs and hosting plan presets. Existing data defaults to containers. - Opt-in x86-64 KVM/libvirt nodes, approved hardware profiles and checksum-verified cloud/ISO/driver media; Linux cloud-init and manual Windows installation with UEFI/TPM profiles.
- Dedicated VM workspace with authenticated noVNC and serial relay, disk growth, allocated NAT ports, routed pools, stopped snapshots and backup-based offline recovery.
- Granular VM grants, holds on guest operations, bounded console traffic and live authorization checks. Optional shared Redis supports API replicas.
- Notification dialogs constrain event lists and keep actions within the viewport. Added suspension, appeal, retention, help-desk and VM events with explicit customer recipients and durable external delivery retries.
VM verification status
HTTP/PostgreSQL VM smoke checks cover placement rejection, runtime compatibility, address exhaustion, console ticket issuance, container-only API refusal, snapshot outcomes and held-account access. Linux agent unit and real guest checks are recorded during the final audit. This workspace has no /dev/kvm; software-emulated guest checks cannot establish hardware KVM behavior. Windows installation, guest Secure Boot trust/PCR behavior and provider-routed public IPs require compatible hardware verification before offering those profiles. Real QEMU/libvirt tests did verify UEFI variable and swtpm-state snapshot recovery and guest restart; they do not establish Windows or hardware KVM behavior.
Full Changelog: v0.8.1.1...v0.9.1.1
v0.8.1.1 "Aerie"
Fledge v0.8.1.1 "Aerie"
A guided way to a first server, permissions you can give to one customer at a time, and Discord notifications that look the part: a complete guide and a new bundled plugin, Better Discord Notifications.
An aerie is a nest high up where a young bird is raised before its first flight. This release is about that first flight: the moment a new customer gets their first server.
Highlights
- A guided first server. Customers who may create servers and have none see a welcome on the Servers page. New server opens a three-step guide: choose a kind of server (cards with description and size), set it up (name, location, and sliders for memory, CPU and disk bounded by what is left of their allowance) and review before creating. With a single released kind the first step is skipped.
- "May create servers" now works per customer. Set it to Yes under Customers → Edit limits and that customer gets the button, in every self-service mode except Off. No always wins over a plan's Yes. Before, the switch had no effect in some modes, so customers it was set for saw no button.
- Customers are told why they cannot create. The drawer explains whether it is the panel mode, a missing plan, an unconfirmed email address or a denial, and links to the store where it helps.
- Better Discord Notifications, a fourth bundled plugin. Discord channels (administrators' and customers') can use a Rich embed (colour by severity, emoji, the server, the cause of a crash, a link to the right page in the panel, the last console lines, a footer) or a Compact embed. If the plugin is off or fails, the plain message is sent, so nothing is lost.
- Discord, Slack and webhook notifications, documented end to end, with a new set-up guide, event suggestions, customer rules and troubleshooting.
- Version 0.8.1.1.
Added
Better Discord Notifications (plugin discord-embeds 1.0.0)
-
A new plugin capability, notification styles: a manifest field
notificationsand a permissionnotifications. A style plugin is a formatter: it returns the body of the message and Fledge sends it, so it never sees the webhook address and needs no network permission. Contract: Notification styles. -
Discord channels get a Message style (plain text by default) in the channel editor, with a small preview of each style, for administrators and customers alike.
GET /api/notification-styleslists what is available;POSTandPATCH /api/notification-channelsacceptstyle. -
The plugin: severity colours you can change, an emoji per kind of event, the server, exit code and cause of a crash, simple facts from the event's data, console output in a code block (can be turned off), a title that links to the server or page in the panel, sender name and picture, time and event code, and an optional role ping on the administrators' channels only. See Better Discord Notifications.
-
Defence in depth. Whatever a formatter returns is rebuilt from an allow-list before it is sent: Discord's size limits, http(s) links only, no files or components, mention parsing always off, and role mentions only on the administrator's channel, only numeric ids, at most three. A formatter has three seconds; any failure means the plain message.
-
Tests: 9 unit tests that run the real plugin code (including hostile input), a 55-assertion integration test (
npm run test:discord), and the bundled-plugin list test now expects four plugins. -
Create-server guide and first-server welcome (web). Uses the active theme, standard radio groups and labelled sliders, and respects reduced motion.
-
Docs: Customer permissions (who may do what, mode by mode, with troubleshooting) and Discord and webhook notifications.
-
A Billing & customers menu in the documentation's top navigation and a link on the landing page, for quick access to sign-up, customers, permissions, limits, plans, the store, billing, the Stripe plugin and email templates.
-
Unit test for the self-service access rule and integration checks for customer-level grants (server-plan mode and account-plan mode).
Changed
- Self-service access is decided by one function used by the feature list, the options endpoint and the create request, so the three can no longer disagree. A customer-level Yes works in Server plans and Account plans mode; the server options endpoint now offers the released templates to such customers (0.7.2.1 offered none in Server plans mode). Off still means off for everyone.
- The options and feature responses now include a reason (
why) when creation is not possible. The existing fields are unchanged. - The panel looks at what it should offer (store, billing, creating servers) again whenever the browser tab is shown and every five minutes, so a settings change reaches customers without signing in again.
- The "templates customers may use" list in Settings is now shown in Server plans mode too, because a per-customer grant needs released templates.
- The hint on May create servers explains the modes.
Security
- Discord and generic webhook messages carry
allowed_mentions: { parse: [] }. A server, customer or plan named@everyoneor<@&role>could previously ping a whole Discord channel. Now it shows as plain text.
Fixed
- Customers with May create servers set on their account could not create servers unless an account plan also granted it.
- The Servers page could show a create action that then failed because the account was not yet allowed to create (for example an unconfirmed email address). The feature list now accounts for it.
Upgrade
- Back up PostgreSQL and follow the regular upgrade guide. There is no database migration and no node-agent change.
- Nothing changes for panels that do not use self-service. If you use Server plans mode and had set May create servers on single customers, those customers can now create fixed-size servers: check that the right templates are released and that their limits are what you want.
- If you use Discord notifications, mentions are simply no longer parsed. For colour-coded embeds, install Better Discord Notifications under Plugins and choose a message style on the Discord channel.
Verified
- API and web TypeScript checks; web production build.
- API unit tests (35, including the access rule and the Discord payload) and Rookery settings tests.
- Billing integration suite against disposable PostgreSQL, including customer-level grants, plan grants, denials and the full purchase-to-creation path.
- Rookery integration suite (sign-up, self-service, email) against disposable PostgreSQL.
- The guide was exercised in Chrome against the seeded demo: no button before the grant, button and welcome after it, all three steps, creation and landing on the new server's page.
- Better Discord Notifications: unit tests of the plugin and of the allow-list (9), and an integration test through the real plugin sandbox against a local receiver (55 assertions): styles list, install and consent, rich and compact messages, settings, customers, switching styles, fallback to plain when the plugin is off.
- Documentation generation, link and screenshot checks, and the VitePress production build.
Not verified: Safari and Firefox, screen readers, and a real Discord server. The embeds are checked as data against Discord's documented limits and delivered to a local receiver, not rendered by Discord, so how they look in Discord (colours, spacing on mobile) is unconfirmed.
Known limits
- The guide's colour per kind of server is derived from its id; there is no per-template icon yet.
- Plain-text Discord messages are a single line. Rich styles exist only for Discord; Slack and generic webhooks stay as they were.
- Discord webhooks cannot carry buttons, so links are in the title.
- Notifications are best effort and not retried; see the notification guide.
Full Changelog: 0.7.1.2...v0.8.1.1
v0.7.2.1 "Perch"
Fledge v0.7.2.1 "Perch"
Make account-plan allowances actionable: a subscription can explicitly unlock fixed-size server creation, with authorization, choices and limits enforced by the API.
A perch is a place for a bird to settle. In this release, an account plan can give a customer permission and a carefully bounded place to create a server of their own.
Highlights
- Account-plan server creation. A new self-service mode lets customers create fixed-size servers only when a qualifying account plan explicitly grants
May create servers. - Plan-scoped choices. The existing template, location, resource and effective-limit rules still apply. Customers cannot change the fixed memory, CPU or disk size in this mode.
- Server-plan behavior stays distinct. The existing server-plan-only mode is for buying or claiming preset servers; it does not advertise or permit self-created servers.
- Entitlements follow subscriptions. Trialing, active and payment-grace (
past_due) account plans grant access. Suspended, canceled and terminated subscriptions do not. Ending a plan does not delete customer-owned servers.
Added and changed
- Added Account plans to Settings → Customers & billing → Server access. It is separate from Server plans and Free choice.
- Account-plan creation requires both an explicit plan-level
selfCreategrant and no effective customer-level denial while limits are enforced. The global limits switch and warn-only mode retain their existing behavior. - The feature API now reports whether the signed-in customer can create servers; the Servers page uses that result for its create action.
- The server options API now reports the mode, whether a plan is required, and whether customers may rename their servers. It does not offer create templates in Off or Server plans mode.
- In account-plan mode, server resources come from the released template defaults. Plan allowances continue to constrain templates and locations; the normal placement, account, rate and limits checks still run on the server.
- Existing customers' created servers remain customer-owned when an account-plan subscription ends; they are not removed as if they were subscription-provisioned server-plan servers.
- Administrator Settings is grouped into top-level sections, with customer/billing and panel settings split into tabs. Switching tabs preserves unsaved form state, and existing billing and store links select their section.
- No database migration or node-agent feature change is required. The version stamp is updated across the application and release artifacts.
Upgrade
- Back up PostgreSQL and follow the regular upgrade guide.
- Existing Off, Server plans and Free choice settings remain unchanged. To enable account-plan creation, publish the templates and locations you want, define fixed resource defaults, enable May create servers on an account plan, and select Account plans in self-service settings.
- Review the account plan's limits and customer overrides. Ending the qualifying subscription revokes the grant but does not delete servers already created.
Verified
- API TypeScript check.
- Web TypeScript check and production build.
- API unit tests (35) and Rookery settings tests (8).
- Billing integration test against disposable PostgreSQL, including purchase-to-creation, no grant, fixed resources, location restrictions, customer-level denial, payment grace, suspension, cancellation and termination.
- Rookery integration suite against disposable PostgreSQL (282 assertions).
- Documentation generation and VitePress production build.
Known limits
- Account-plan self-creation uses published template defaults; per-customer custom resource sizing is available only in Free choice mode.
- The plan grants access to create, not ownership under the subscription. Existing self-created servers are not automatically deleted or resized if the plan ends.
Full Changelog: v0.6.2.1...v0.7.2.1
v0.7.1.1 "Rookery"
Fledge v0.7.1.1 "Rookery"
The Hosting Update. Fledge becomes a panel a hosting business can run: people sign up, create or buy servers, pay by the month or year, and manage them, while you stay in control of limits, abuse, money and email.
Everything is off by default: after upgrading, a panel behaves exactly as before until you switch something on.
A rookery is where many birds nest: a place that hosts others.
Highlights
- Sign-up. Open, with approval, or invite-only, with email confirmation, bot protection (Cloudflare Turnstile or hCaptcha), disposable-address and common-password checks, rate limits that pause sign-up during a flood, terms
acceptance, email change, data download and account deletion. - Customers create servers themselves from templates you release, within their limits, with a cooling-off period when they delete one.
- Limits v2. Layered (panel defaults, plans, per-customer overrides), explained (every number says where it comes from), with a master switch, a warn-only mode and many more things to limit.
- Plans, subscriptions and a store. Sell preset servers or allowances monthly, quarterly, half-yearly or yearly, with trials, setup fees, stock and free tiers. Late payments stop servers instead of deleting them.
- Stripe, included. A bundled payment plugin using hosted Checkout and the Customer Portal. Card details never reach Fledge. Verified against Stripe's real test mode.
- Email you can edit. Every email is a template with a live preview, sent through a retrying outbox with a delivery log, plus receipts, reminders and security notices.
Added
Sign-up (Settings, Sign-up)
- Modes: off (default), open, with approval, invite-only. Everyone becomes a customer; the role cannot be chosen by the request.
- A confirmation link (24 hours, single use) before anything can be created. Answers never reveal whether an address has an account; an existing address gets an email saying so.
- Rate limits per network address (5 an hour), per email (3 a day) and overall (200 an hour, then sign-up pauses itself and you are notified). Only attempts that pass every check count, so a typo never locks anyone out.
- Passwords of 12 to 128 characters (your minimum), refusing common passwords, repeating patterns, sequences and the email address; a built-in list of throw-away mailbox providers; allowed and blocked domains; a hidden form field and form timing as quiet bot traps.
- Optional Cloudflare Turnstile or hCaptcha (the content security policy allows those two providers' scripts and frames, and nothing else, on the sign-up form).
- Terms: required or not, with a version, a time and a hashed network address recorded; invitation codes (single or multiple use, optionally for one address, optionally carrying a starting plan); a free starting plan for every new account.
- Customers: change their email (new address confirmed, old address told), download their data (JSON), delete their account (password, no servers or active subscriptions, a waiting time, then anonymised; invoices stay without personal data).
- Administrators: a Waiting for you card in Customers (resend, mark confirmed, approve, decline); unconfirmed accounts are deleted after 7 days.
Customers creating servers (Settings, Customers creating servers)
- Off, plans only, or free choice within limits. Templates are invisible to customers until released (with a description). Locations can be restricted. Ten creations an hour per customer.
- One shared placement path for administrators, customers and the store, with the limit check in the same transaction. Customers get a plain "no capacity" message, never node details.
- Owners can delete their own servers (if allowed): stopped and kept for 24 hours (changeable) with one-click restore; a backup is taken first when backups are on. Servers that belong to a subscription are removed by ending the subscription.
Limits v2 (Settings, Limits)
- New limits: servers running at once, per-server memory, CPU and disk, backups per server, backup storage, people a server is shared with, scheduled tasks per server, allowed templates and locations, and yes/no permissions (create and delete servers, SFTP, add-ons, schedules, sharing, extra ports).
- Three layers with defined rules (totals add up, maxima take the most generous layer, a yes wins, a hand-set value always wins). A pure, table-tested resolver; the customer's page and the usage view show the source of every number.
- Master switch (on after an upgrade, so existing quotas keep working), enforce or warn mode, administrator override choice, warning threshold, customer notifications, hiding usage from customers. Lowering a limit never deletes anything.
- Checked when creating (administrator, customer, store), resizing, cloning, starting, backing up, adding ports, sharing, scheduling, using SFTP and installing add-ons.
- The names
maxServers,maxMemoryMb,maxCpuPercent,maxDiskMb,maxBackupsandmaxExtraPortsare unchanged in the API.
Plans, the store and billing
- Plans (Billing, Plans): server plans (one server per subscription, from a preset) and account plans (an allowance added to limits). Prices for four intervals, trials (once per customer), one-time setup fees, stock, per-customer maximum, visibility
(everyone, link only, nobody), badges, highlights, retention, duplicate, archive. Prices are whole cents and are never edited in place: a change creates a new price and existing subscribers keep theirs. - The store, closed by default and refusing to open until a provider answers, email works, a plan exists, terms are set and test and live records are not mixed. Checkout reads the amount, currency and trial from the database and freezes them on an order; the browser only names a plan and an interval.
Stock is counted under a lock, so two buyers cannot take the last one. A plan whose server fits on no node is shown as sold out and cannot be bought. - Subscriptions with a fixed table of allowed status changes, locked and recorded in a timeline: starting, trial, active, payment overdue, suspended, ended, removed. A late payment is emailed, then (after your days) the server is stopped and held, not deleted;
paying lifts only a hold billing placed. Cancel at period end, resume, change plan (provider-prorated, server resized; upgrades at once), complimentary plans with an end date, holds, refunds, disputes (stop the server until resolved), retention, optional automatic termination (off by default, with a last backup first). - Paid but no room? The subscription stays active, the customer is told, administrators are notified, Fledge retries for 24 hours and you can retry or refund and cancel.
- Reliability. Webhooks are stored once (unique per provider event), acknowledged, and processed in the background with retries; every event is turned into "ask the provider what is true now", so duplicates, delays and reordering are harmless. Events that arrive before their checkout is processed wait and retry.
A scheduled comparison with the provider (every 15 minutes) repairs anything a missed event left behind. Fulfilment is guarded by a lock and a unique constraint, so one subscription can never get two servers. - Billing pages: Overview (recurring revenue, paid this month, trials, overdue, cancellations, readiness checklist), Plans, Subscriptions (detail, timeline, actions), Invoices (CSV), Health (provider, mode, webhook address, events). Customers get Store and Billing pages.
- Billing settings: provider, currencies, reminder days, suspension and termination days, retention, final backup, what customers may do, renewal and trial reminders, stock holding, retry window, comparison interval, and what to do when a paid server can never be created.
Payments
- A payments contract for plugins (
paymentsin the manifest and permission, nine methods; see the payments contract) and the bundled Stripe Payments plugin: Checkout in subscription mode with inline prices (nothing to sync), trials, setup fees,
automatic tax, promotion codes, the Customer Portal, plan changes with proration, refunds, signed webhooks with a five-minute window, the pinned API version2024-06-20, a product tax code setting. It can reach onlyapi.stripe.com. - Plugin host:
host.crypto(hmacSha256,sha256,equals,randomHex),host.now()andDELETErequests.
- Editable templates for every email (35 of them, in Account, Billing, Limits, Administrators and System), with variable lists,
{{#if}}blocks, buttons, escaping, a linter (unknown variables, unclosed blocks, missing links), live preview and test send. - An outbox: immediate delivery, retries with growing pauses (a minute to six hours, 8 attempts), a per-minute send rate, a delivery log (30 days, message text removed after 7), manual retry. Reply-To, a copy address for receipts and billing alerts.
- HTML emails in a clean layout that follows Appearance (name or wide logo, light-theme button colour, company footer).
- Security notices when a password or an email address changes.
Documentation, tests, tools
- New guides: Sign-up, Customers creating servers, Limits, Plans,
The store, Billing, Email templates, The Stripe plugin,
[The payments contract](https://kavaliersdelikt.github.io/f...
v0.6.2.1
Fledge v0.6.2.1 "Plumage"
The Customizing Update: administrators can make the panel their own. Rename it, give it a logo, choose colours and a font, offer light and dark, restyle the sign-in page, add sidebar links and an announcement, all from Settings, Appearance, with readable colours enforced, a preview that rolls itself back, version history and a way out of a bad theme.
Highlights
- Appearance. A new editor with a live preview: identity, colours, type and shape, the sign-in page, navigation, an announcement and advanced tools. Until someone changes something, the panel looks exactly as before.
- Your name everywhere. The panel name, short name and logo appear in the sidebar, sign-in page, browser tab and icon, home-screen icon, emails, notifications, authenticator apps and the passkey prompt.
- A light theme, and your own palette. Eight presets (Fledge, Midnight, Ember, Terminal, Paper, Snow, Violet, High contrast), each in dark and light, or an accent colour and a tint from which Fledge calculates the rest. Every person can pick light, dark or "match this device" for themselves.
- Readable by construction. Every text and colour pair is checked (WCAG ratios, a stricter AAA mode, colour-blind-safe status colours). A theme that fails cannot be saved, and a dim accent is moved until it passes.
- Safe to experiment. Try on this browser shows the draft on the real panel for 60 seconds and then goes back by itself; the last 20 versions are kept with their images;
?safe=1shows the built-in look when a theme is unusable;BRANDING_DISABLED=trueis the last resort. - Sign-in page, sidebar and banner. Welcome text, centred or split layout, soft glow or picture background, links; renamed pages ("Servers" to "Worlds"); extra sidebar links; a scheduled announcement for everyone, customers or administrators.
- Share it. Export a theme (images included) and import it into another panel.
Added
Appearance
- Settings, Appearance (administrators). Tabs: Identity, Colours, Type and shape, Sign-in page, Navigation, Announcement, Advanced. A preview drawn from the draft (panel or sign-in, dark or light), a save bar, a warning before leaving with unsaved changes, and unsaved drafts that survive leaving the page.
- Identity. Panel name (1 to 40 characters), short name, tagline, logo, optional wide logo, optional tab icon, email sender name, email footer, source-code address, and a switch for the "Powered by Fledge" link.
- Images are stored in PostgreSQL and served by the panel itself (
/branding/<kind>), so the content security policy stays strict and no extra volume is needed. PNG, WebP, JPEG, plain SVG (logo, wide logo), ICO (tab icon); size and dimension limits per slot; files are identified by their bytes, not by what they claim to be; SVGs with scripts, styles, external references or a DOCTYPE are refused; images are served withnosniffand a sandboxing policy. - Colours and themes.
shared/theme.ts, one file used by the panel (preview, server-side rendering) and the API (validation), derives about 30 colour tokens in OKLCH from an accent and a tint, adjusts text to pass the contrast floors, and generates the stylesheet. Light and dark palettes are separate; High contrast raises text and borders to 7:1; individual colours can be pinned and are checked like everything else. See Theme tokens and presets. - Type and shape. Fonts: Geist (default), Inter, Atkinson Hyperlegible, the system font, monospace (all bundled; nothing is loaded from other sites). Text size 90 to 120 percent, corner radius square to 18 px, density (compact, comfortable, spacious), motion.
- Modes. Default mode dark, light or match the device; people may choose for themselves from the account menu (stored in a cookie so the server renders the right mode on the first byte, and on the account so it follows them).
PUT /api/auth/preferences;GET /api/auth/menow returnspreferences. - Sign-in page. Welcome text, centred or split layout, plain, soft glow or picture background (with a darkening gradient), up to five links, and the announcement when it is for everyone.
- Navigation. Rename any of the eleven sidebar pages (used in the sidebar, page titles, the browser tab and search); up to eight extra links with icons.
- Announcement. A banner with tone, audience, start and end, dismissible per message (a new id on every edit).
- Custom CSS (off by default). Checked on save and on every read: no
@import,@font-face, remoteurl(),image-set(),expression()or markup; embedded images up to 20 KB; at most 32 KB; balanced braces. It cannot contact other servers. - History and recovery. The last 20 versions with who and what, restore (as a new version), reset to the Fledge look, optimistic concurrency (a stale save answers 409), export and import of
fledge-themefiles with a review step. - Try on this browser. Applies the draft to the real panel in this browser only, with a 60-second countdown drawn in system colours so it stays readable; leaving the page ends it.
- About. The account menu has an About Fledge dialog (product, version, licence, source link) that cannot be switched off.
- Web app manifest and address-bar colour from the panel name, icon and colours.
- API.
GET /api/brandingandGET /api/branding/assets/:kindare public; the rest are administrator endpoints, browser session only (API tokens are refused): validate, save, upload, preview, history, restore, reset, export, import, plusGET /api/branding/announcementfor the signed-in person. All appear in the API reference. - Configuration.
BRANDING_DISABLED,BRAND_NAME(seed) andAPI_INTERNAL_URL(how the panel's server reaches the API; Compose sets it). - Audit events
branding.update,branding.asset.upload,branding.restore,branding.reset. - Documentation. New pages Appearance, Recovering from a bad theme and the generated theme reference; a "Make it yours" section on the landing page; screenshots of themed panels.
Infrastructure
shared/holds code used by both the API and the panel. Both images copy it; the panel enablesexternalDir.- The stylesheets were converted to tokens (colours, text size, corner radius, density). A test (
css-tokens.test.ts) fails if a fixed font size, radius or colour appears again. docs-site/screenshots/regress.mjsrecords and compares the computed style of every element on every screen, to prove a CSS refactor changes nothing.
Changed
- The root layout is rendered on the server with the saved appearance (cached for 3 seconds, 0.9 s timeout, built-in look as the fallback), so a reload never flashes the wrong name or mode. The pages are no longer statically prerendered.
- Server-written text uses the panel name: invitation, reset and test emails (subject and body), notification emails (
[Short name] ...), Discord, Slack and webhook messages, failover webhook text, the authenticator entry (existing entries keep working) and the passkey relying-party name. The Updates page, release notes and plugin messages keep saying "Fledge". - The default Fledge mark has a dark-ink version for light themes (
/fledge-symbol-light.png). - The content security policy allows
blob:images (for upload previews). The API lets a route set its own policy (used for images). - Pattern checks for template and plugin settings compile their scripts once and run them with a 100 ms limit (was 50 ms including compilation), so a busy machine cannot make a good pattern fail.
- Version 0.6.2.1 for the API, panel, plugin host and tools. The agent has no functional change; release builds stamp it with the tag, so nodes will offer an update to 0.6.2.1.
Fixed
- A good pattern could be rejected as "invalid format" when the machine was busy (see Changed).
Verified
- Theme engine (18 tests): colour maths, WCAG ratios, every preset in both modes passes the floors with no adjusted accent, any tint and accent keeps body text readable, pinned failures are reported, validation messages, stylesheet generation.
- Appearance API (10 unit tests, 260 integration assertions against real PostgreSQL and API processes): public document and caching, who may change what (customers and API tokens cannot), saving, history (20 kept), conflicts, restore, reset; colours and contrast; images (valid PNG, SVG, WebP, ICO, JPEG; hostile SVGs, fake files, oversize, wrong slot); caching headers; announcements by audience and time; custom CSS rules with a corpus of hostile inputs; panel name in emails, notifications and the authenticator URI; export and import; preferences;
BRANDING_DISABLED; orphaned-image sweep. - Regression: API unit 34, plugins 208 and 128, templates v2 101, quotas and clone 142, autopilot 242, accounts 171, the original smoke test 234, CORS 3, Pterodactyl 4, pack tool 2; plugin host 24; panel helpers 29 (including the stylesheet token test); type checks and production build of the panel.
- Stylesheet refactor: the computed style of 4,671 elements on 17 screens before and after: 141 differ, all from the new logo images, the Appearance card and random demo data.
- In a real browser (Chrome, GPU): the editor on every tab, a full edit and save, try-on with the automatic rollback after 60 seconds, draft restore, safe mode, the split sign-in page on desktop and phone width, the account menu and About dialog, light, dark and four themes across every main screen, no console errors, no hydration warnings.
- Container images: the API and panel images build with ...
v0.6.1.1 - Roost
Fledge v0.6.1.1 "Roost"
Fledge becomes extensible and self-serve. A sandboxed plugin system with a one-click store ships with two bundled plugins, the Modrinth Mod Browser and the Modrinth Plugin Browser, and the release adds automation, notifications, richer templates, quotas, passkeys and a long list of smaller things a panel needs once real people use it.
Highlights
- Plugin system. Install, configure and turn on plugins from the panel in one flow. Plugin code runs in a WebAssembly sandbox inside a new
pluginscontainer that has no database credentials, no Docker socket and no published port. Permissions are shown in plain language and approved by you; signatures, checksums and a hard validation of everything a plugin returns protect the rest. - Mods and plugins for Minecraft servers. Servers on Fabric, Quilt, Forge or NeoForge get a Mods tab; Paper, Purpur, Folia and Spigot servers get a Plugins tab. Search Modrinth, review versions and dependencies, install, disable, pin, update and remove. The node downloads files itself and verifies Modrinth's SHA-512 before writing.
- Autopilot. Schedules with cron, time zones and task chains (command, wait, backup, power), automatic restart after crashes with crash-loop protection, and a notification center with Discord, Slack, webhook and email delivery.
- Template v2. Typed variables, edit and version templates, update servers to a new version with a preview, import and export, a Startup panel, extra ports and clone server.
- Accounts and security. Passkeys, signed-in devices, invitations and password reset by email, per-customer quotas, an optional administrator network allow-list, audit filters and export, defensive headers.
- History and API. CPU and memory history up to 30 days, more Prometheus series, a generated OpenAPI description and an in-panel API reference.
Added
Plugins and add-ons
- A Plugins page (administrators): Store, Installed, per-plugin Settings with a Test connection button, Permissions, About and Logs. Install wizard with permission review, generated settings form and turn-on step. Update with consent for new permissions, rollback to the previous version, uninstall (installed add-ons stay on the servers and keep being listed).
- Trust tiers: Bundled, Verified (Ed25519 signature from a trusted key) and Community (unsigned, off by default; installable from a registry or an uploaded
.fledgeplugin). A registry is a signed JSON index (defaultplugins/registry/index.jsonin this repository). A dry-run inspect shows a package's manifest and permissions before anything is installed. - Plugin manifest and contracts (API version 1): permissions (
network:<host>,servers:read,servers:files.write,storage,hooks), typed settings (secrets encrypted), catalog providers (search,categories,project,versions,resolve,updates,healthCheck) and event hooks. Seedocs/plugins. - Sandbox limits per call: 25 s, 64 MB, 40 requests, 24 MB of responses, 2 MB result. Outbound requests: HTTPS only, declared hosts only, public addresses only, pinned to the checked address, redirects re-checked. A plugin that fails five times in a row (script errors, oversized results, host errors or timeouts of its own code) is switched off and an administrator is notified; a call that only timed out because the catalog was slow (
upstream-timeout) is reported but never counts towards that. Usinghost.storagewithout thestoragepermission throws instead of silently discarding the data. Updates keep the settings the new version still declares, and a rollback restores the settings and secrets the update dropped. - Add-on tab on servers (permission: files): browse with search, sort, categories and client-only toggle; project drawer with versions and changelogs; install plan with required and optional dependencies, warnings and an optional backup first; Installed, Updates (stable channel by default), disable/enable, pin, remove, and a list of files Fledge did not install. Updates download the new file first and replace the old one only after success.
file.fetch,file.deleteandfile.renamenode jobs (agent 0.6.1.1): HTTPS only, allow-listed hosts, no private addresses, checksum required, size and disk allowance enforced, atomic placement, path-safe deletes, rename restricted to the.disabledsuffix.- Bundled plugins: Modrinth Mod Browser and Modrinth Plugin Browser (release channel, client-only toggle, page size, optional contact for Modrinth's User-Agent).
- Tooling:
plugins/tools/pack.mjs(keygen, pack, index, verify) builds reproducible, signed packages. Documentation: plugin guide, reference and security model.
Automation and notifications
- Schedules v2: cron (5 fields) with time zone or every N minutes (minimum 5); steps
power,command,backup,wait; up to 20 steps; missed-run policy; run history; Run now; live preview of the next runs. Older single-action schedules keep working. - Crash protection per server: off, restart after failures, or always; restarts allowed per window, growing pauses, crash-loop detection, recovery after two stable minutes. Exit code, out-of-memory flag and log tail come from the node. Stopping from the panel is never a crash.
- Notification center: inbox with unread badge; events for crashes, crash loops, recoveries, disk almost full, failed backups and verifications, failed schedules, failed add-on installs, failover, node offline/online, failed agent updates, new versions and disabled plugins. Channels: Discord, Slack, webhook (Slack-compatible payload) and email, per event and optionally per server. Customers get their own inbox and channels with safer limits (HTTPS public webhooks, own email address only). The failover webhook keeps working and its events also appear in the inbox.
- Email (SMTP) settings with a test button; used for invitations, password reset and email channels.
Templates, servers and customers
- Typed template variables (text with pattern and length, number with range, on/off, choices, secrets) with labels and help; validated on the server. Preinstalled templates ship typed variables and quick console commands.
- Template editor, versions and history, Update servers (preview of changes, skips servers whose port layout changed), export/import as JSON, delete for unused custom templates, add-on rules per template, quick commands. Console: command history and quick-command buttons.
- Startup panel, extra ports (offsets from the base port, moved with the server), clone server (settings and optionally data from a backup).
- Quotas per customer for servers, memory, CPU, disk, backups and extra ports, enforced on create, resize, backup, extra port and clone, with an administrator override. Customers see their own usage.
- Resource history: heartbeats feed 1-minute (24 h), 5-minute (7 d) and hourly (30 d) buckets; range selector on the server page.
Accounts and security
- Passkeys (WebAuthn) as a second factor; signed-in devices with sign-out; invitations and reset links by email (single use, hashed at rest, rate limited, answers do not reveal whether an address exists); collaborator invitations that create an account; sign a customer out everywhere.
- Administrator network allow-list for accounts and API tokens (refuses a list that would lock out the saver;
ADMIN_IP_ALLOW_DISABLE=trueis the break-glass switch). - Audit log filters, CSV (formula-safe) and JSON export, retention setting.
- Security headers on the API (nosniff, frame deny, no referrer, CSP, no-store) and on the panel (CSP, frame, permissions policy).
- API: generated OpenAPI 3.1 at
/api/openapi.jsonand an API page in the panel; new Prometheus series for plugins, add-ons, schedule runs, crash loops, failing channels, sessions and passkeys.
Infrastructure
- New Compose service
plugins: read-only root file system, non-root user, all capabilities dropped, PID and memory limits, health check, own network shared only with the API. Installer and update scripts (shell and PowerShell) build and check it. CI gained plugin host, plugin, template, autopilot, account and update-flow tests and a Compose job. The release workflow packages the bundled plugins (signed when a key is configured), writes SBOMs and signs checksums on a best-effort basis.
Changed
- Template routes moved into their own module;
GET /api/templatesreturns typed variables, version, add-on rules and quick commands. Customers still never receive start commands or template-level environment values; the Startup panel shows owners the image and the variables they may edit, administrators see everything. - Schedules are now processed by a persistent run engine: runs are claimed with a lease, a schedule never has two runs at once (the database enforces it) and a due run that finds the previous one still running is recorded as skipped. The crash, alert and metrics-trim sweeps take advisory locks and every sweep step is isolated, so one failing step no longer stops the others; running several API replicas has been designed for but not tested with two live API processes. Steps that queue node work rely on per-server job order.
- Minecraft containers are created with
CREATE_CONSOLE_IN_PIPE=TRUEso the game console can be reached while the server is still starting. Existing containers pick this up the next time they are recreated. GET /api/activityaccepts filters and returns the actor's email.- The in-panel updater and
update.sh/update.ps1rebuildapi web plugins. Older update scripts that name onlyapiandwebstill start the plugin host because the API depends on it (the dependency is optional). - Agent version 0.6.1.1.
Fixed
- Hardening found in the final review.
TRUST_PROXYnow takes a hop coun...
v0.5.5.1
Fledge v0.5.2.3
Minecraft servers now stop cleanly, there are 14 new preinstalled templates (Node.js, Python, Bun, Go, Java, .NET, PHP, Ruby and more Minecraft flavors), and the Pterodactyl egg importer reads the current export formats.
Highlights
- Clean Minecraft stops. No more
Failed to stop using rcon-cliandwrite /dev/stdin: bad file descriptorfollowed by a forced kill. - 14 new preinstalled templates, from app runtimes to more Minecraft server types.
- Pterodactyl egg import understands PTDL_v2 and the older PTDL_v1.
Added
- Runtime templates for hosting bots, APIs and websites. Upload your code with the file manager or SFTP and start the server; dependencies are installed on start where it applies.
- Node.js (22), Python (3.13), Bun (1), Go (1.24), Java (JAR) (21), .NET (9), PHP (8.4) and Ruby (3.4).
- Each one has editable variables for the entry file (for example
MAIN_FILE,APP_DLL,SERVER_JARFILE), stops gracefully with Ctrl+C (SIGINT), and starts with sensible memory and disk defaults. - Node.js, Bun, Python and Ruby install dependencies from
package.json,requirements.txtorGemfileon each start.
- Minecraft templates: Purpur, Folia, Spigot, Forge, NeoForge and Bedrock (UDP 19132), alongside the existing Java, Paper, Fabric and Quilt.
- Allowed images: the default allowlist now includes
itzg/minecraft-bedrock-server:,node:,python:,oven/bun:,golang:,eclipse-temurin:,php:,ruby:andmcr.microsoft.com/dotnet/. - Agent tests for the Minecraft RCON stop and for the fallback to
docker stop, and a test for the egg importer's PTDL_v1 handling.
Changed
- Egg importer: reads PTDL_v2 (
docker_imageslabel map) and PTDL_v1 (image/images), treats^^Cas Ctrl+C, and warns when an egg uses an export format it doesn't know. - Agent version 0.5.2.3.
- Non-Minecraft containers still stop with
docker stop(30 second timeout), or the template's own stop command when one is set.
Fixed
- Minecraft stop errors. When a Minecraft container was stopped, the image's own runner tried
rcon-cli stopand, when that failed, wrotestopto its stdin. Docker gives that process a read-only stdin pipe, so the fallback always failed withbad file descriptorand Docker ended the server with a kill after the timeout. The agent now sends the RCONstopitself, over127.0.0.1, waits up to 30 seconds for the server to exit, and only then falls back todocker stop. - The same graceful stop is used for Restart (now stop, wait, start) and for the stop that backups and restores perform on running servers.
Known limits
- The graceful stop needs RCON enabled on the server (
ENABLE_RCON=TRUE, the default in the official Minecraft Java templates). If RCON isn't reachable, the stop falls back todocker stop, and the image's runner may still log the two errors above. Bedrock and non-Minecraft images are not affected by this change. - Existing installs keep their saved image allowlist. The new defaults apply to fresh installs and to installs that never changed the list. Otherwise add the new prefixes under Settings → Nodes, and set the same
ALLOWED_IMAGE_PREFIXESon each agent that has its own value, before creating servers from the new templates. - New templates are added once; templates that already exist, including ones you edited, are never overwritten.
- Runtime templates have no install script step. Pterodactyl install scripts are still not run, and the importer still turns
{{VARIABLES}}into shell variables for you to check. - The runtime templates use the official Docker Hub images, which run as root inside the container. Node.js, Python, Bun, Go and Ruby fetch packages from the internet on start.
- Verified: unit tests,
go vet, the egg importer tests, the new SQL applied in a rolled-back transaction against PostgreSQL, and a syntax check of every startup command. The images were checked to exist, but the templates were not started with real applications, and the Minecraft stop was not run against a live server.
Upgrading
Update the panel from Updates, then update agents from Nodes to 0.5.2.3. The Minecraft stop fix lives in the agent, so nodes on an older agent keep the old behavior. The new templates are added to the database automatically when the API starts; no servers need to be recreated. If you changed the allowed images before, see the note above.
Full Changelog: v0.5.2.1...v0.5.2.3
v0.5.2.2
Fledge v0.5.2.2
Windows/WSL2 node setup now works end to end without manual systemd steps, and the Updates page has a proper "you're up to date" state.
Highlights
- Automatic systemd setup on Windows. The PowerShell WSL connector detects when systemd isn't running in the selected distro, enables it in
/etc/wsl.conf, restarts the distro and waits for it to come up, then continues with the install. No more editingwsl.confby hand. - Fixed enrollment failing with exit code 24 after pasting the one-time token in a Windows terminal.
- Updates page banner when you're on the latest version, instead of an empty page.
Added
- Up-to-date banner on Updates showing the installed version, the release date, the time of the last check and a link to the release notes.
-LocalConnectScriptoption forconnect-wsl.ps1, which sends a localconnect.shinto WSL instead of downloading it from GitHub. Useful for testing connector changes before they are pushed.
Changed
- The agent's systemd unit only depends on
docker.servicewhen that unit exists inside the distro. With Docker Desktop's WSL integration there is no such unit, and the hardRequires=could stop the agent from starting.
Fixed
- The one-time enrollment token is stripped of whitespace before validation. A trailing carriage return or space from a Windows terminal paste was rejected as "invalid characters" (exit code 24).
- The WSL connector no longer fails with exit code 19 ("systemd is not running") on a fresh distro; it enables systemd itself unless
-Foregroundis used.
Known limits
- Enabling systemd restarts the selected WSL distro, which stops anything else running inside it. Docker Desktop's own distro is not touched.
- If systemd doesn't come up within about a minute after the restart, the connector stops with a message. Run
wsl --shutdownand retry, or use-Foreground. - The connector downloads
connect.shfrom the repository'smainbranch, so connector fixes reach users once they are pushed there.
Upgrading
Update from Updates in the panel or with update.sh / update.ps1. No database changes. To fix an existing node that failed to enroll, generate a fresh token in the panel and run the connector command again.
Full Changelog: v0.5.2.1...v0.5.2.2
v0.5.2.1
Fledge v0.5.2.1
Automatic failover. When a node dies, its servers come back on another node from their newest backup, and you can watch, test and tune it from a new Resilience page.
Highlights
- Automatic failover. A node that has been silent for the waiting time (5 minutes by default) has its servers rebuilt on other nodes and restored from their newest backups. In testing, a server was running again about 45 seconds after the decision, and two servers recovered side by side.
- No double running. A node that comes back removes the copies of servers that now live elsewhere. Optionally, nodes stop their protected servers when they lose the panel for too long, so a node that is cut off but alive can't keep a game running that has been started elsewhere.
- Planned moves. Move one server, or empty a whole node, with a final backup taken while the server is stopped. Nothing is lost, and the old copy is removed only after the new one works.
- Resilience page. Which servers are ready to recover and why not, a failover countdown per node, recovery history with timings and the age of the data used, node up/down history, and Simulate failure to see where every server of a node would go without changing anything.
- Settings for all of it, under Settings → Panel → Automatic failover. No
.envchanges.
Added
- Failover settings: on/off; wait before failing over; recoveries at once; oldest usable backup; pause between failovers of one server; same location only; recover servers without a backup (with empty data); keep backups fresh on an interval; stop servers if a node loses the panel; remove the old copy when a node returns; how long removed data is kept; notification webhook with a test button. Failover is off by default and refuses to be turned on without object storage unless you allow recovery with empty data.
- Keep backups fresh: takes backups of protected running servers on an interval, only on nodes with disk volumes because those backups don't stop the game.
- Per-server switch to exclude a server from failover.
- Webhook notifications (Slack, Discord and Mattermost compatible) when a node goes offline or returns, and when a server is recovered, can't be recovered, or fails. The URL is stored encrypted.
- Monitoring:
GET /api/failover/status,/api/failover/events, a dry-runPOST /api/failover/plan, and metricsfledge_failover_events{state}andfledge_servers_without_backupon/api/metrics. - Nodes record when they go offline and return, shown as history on the Resilience page.
- API:
POST /api/servers/:id/failover(run now; for a node that is still online it needsforce),POST /api/servers/:id/migrate,POST /api/nodes/:id/evacuate. - Agents report which servers' data they hold, and handle a new
evictjob. Removed data is moved to.evicted/on the node and deleted after the retention you set.
Changed
- Nodes are marked offline by the failover engine, which runs on one API replica at a time (a PostgreSQL advisory lock).
- Jobs queued in one step for the same server now run in the order they were queued. Jobs inserted together previously shared a timestamp and could run in either order.
- Agent version 0.5.2.1.
Fixed
- Planned moves no longer leave a server stopped if the final backup fails; it is started again where it was.
- A recovery is only reported done when every step (create, restore, stop or start) succeeded.
Verified
Run against real components, no mocked data: PostgreSQL, the API, the panel, two Go agents, each with its own Docker daemon, real containers, and an S3-protocol test server.
- Killed a node (agent, containers and volumes gone): detected after 35 s, failed over after the configured 2 minutes, restored from the newest backup and running on the other node; the webhook received each step.
- Two servers recovered concurrently within the limit; a server with no backup stayed down with a clear reason, and recovered with empty data once that was allowed.
- The returning node removed its stale copies and left the other node's containers alone.
- A planned move carried a file written seconds earlier, ended with the server running on the new node, and removed the old copy afterwards.
- Automatic backups appeared on schedule for a running server; the dry run named the right target and backup age.
- With stop-on-panel-loss on, a panel outage stopped the protected servers on the node and they restarted when the panel returned.
- Type checks, Go tests (including rollback), API tests and the production build.
Known limits
- Failover restores from backups. Everything written since the newest backup is lost, and recovery takes as long as a restore. It is not replication.
- It reacts to a node going silent. It does not detect a frozen game on a healthy node, a node that is reachable but broken, or the panel being down.
- Without Stop servers if a node loses the panel, a node cut off from the panel keeps its game running until it reconnects, so a server can run on two nodes in that window. Turning it on has a cost: if the panel itself goes down, protected servers stop on every node after the fencing time.
- A recovery that fails part-way leaves the server on the new node in a failed state with the old data kept aside; retry it by hand.
- Moves have downtime (a few minutes); live migration is not implemented.
- Verified with two agents on one machine, not on separate hosts or with a real game. Real AWS S3 retention, a Valheim boot, third-party SFTP clients, load testing, and rootless operation remain unvalidated.
Upgrading
Update from Updates in the panel or with update.sh / update.ps1. The database gains failover tables and a per-server switch automatically; failover stays off until you turn it on. Then:
- Make sure object storage is on and servers have recent backups (turn on Keep backups fresh if you want it automatic).
- Update agents from Nodes to 0.5.2.1. Older agents don't report what they hold, so stale copies on them are not removed.
- Use Simulate failure on each node before relying on it.
Full Changelog: v0.3.1.2...v0.5.2.1