Skip to content

Commit f60eba6

Browse files
committed
release: v1.5.3
New: NodeCircle auto-sync from a subscription. Linking a circle to a subscription makes every refresh keep its membership current — nodes the panel still serves are kept or added (including one that returned under a new address, which arrives as a new id and previously needed re-adding by hand), dropped ones leave, and members added by hand or from another subscription are preserved. Unlinked circles keep the old prune + "check members" behaviour, so nothing changes without opting in. Reported as circle.synced in Recent Events. Adds nodecircle.subscription_id (migration 023) and forces a dataplane re-apply when an enabled circle's membership moves, which the existing reload heuristic missed because freshly imported ids are in neither changed_ids nor the running config. New: whole-box configuration backup (Settings -> Backup & Restore). One JSON bundle covering settings, subscriptions, nodes, routing sets and rules, DNS rules, balancer groups, circles, devices and UA templates. Secrets are opt-in, so a shared file carries no credentials, and restoring a secret-less bundle never blanks credentials already on the box. Restore previews per-section add/update/delete counts and warnings before writing; merge adds and updates, replace also deletes rows absent from the bundle. Settings are matched by their unique key so a restore can't duplicate one. The dataplane is regenerated and xray reloaded afterwards. Runtime tables and users are deliberately out of scope. Frontend build + 82 tests green; backend suites (backup, subscriptions, nodecircle, config_gen) 142 passing. Alembic head is a single revision, 023.
1 parent 77b3935 commit f60eba6

16 files changed

Lines changed: 1135 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,37 @@ All notable user-facing changes to PiTun. Full per-release detail lives in the
44
[GitHub Releases](https://github.com/DaveBugg/PiTun/releases); this file is the
55
committed summary.
66

7+
## v1.5.3 — 2026-08-11
8+
9+
Two ways to stop hand-maintaining state: a NodeCircle can now track a
10+
subscription automatically, and the whole configuration can be exported to (and
11+
restored from) a single file. Ships DB migration 023.
12+
13+
### Added
14+
15+
- **NodeCircle auto-sync from a subscription.** Link a circle to a subscription
16+
and every refresh keeps its membership current: nodes the panel still serves
17+
are kept or **added** — including one that came back under a new address, which
18+
arrives as a new id and previously had to be re-added by hand — while nodes the
19+
panel dropped leave. Members you picked yourself, or that came from another
20+
subscription, are always preserved. Unlinked circles behave exactly as before
21+
(dangling ids pruned, "check members" badge), so nothing changes unless you opt
22+
in. Membership changes are reported in Recent Events as `circle.synced`.
23+
- **Whole-box configuration backup.** **Settings → Backup & Restore** exports
24+
settings, subscriptions, nodes, routing sets and rules, DNS rules, balancer
25+
groups, node circles, devices and UA templates as one JSON file, and restores
26+
it onto a fresh box.
27+
- **Secrets are opt-in** (`include_secrets`, off by default), so the file you
28+
share for debugging carries no node credentials or subscription URLs — and
29+
restoring such a file never blanks the credentials already on the box.
30+
- **Restore previews before it writes**: per-section add / update / delete
31+
counts plus warnings, then an explicit confirm. `merge` adds and updates;
32+
`replace` additionally deletes rows the backup doesn't contain.
33+
- The dataplane is regenerated and xray reloaded afterwards, so restored
34+
routing and DNS take effect immediately.
35+
- Endpoints: `GET /api/system/backup`, `POST /api/system/backup/preview`,
36+
`POST /api/system/backup/restore`.
37+
738
## v1.5.2 — 2026-08-06
839

940
Adds HTTPS for the panel (per-install cert + downloadable local CA), disables
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Add nodecircle.subscription_id — auto-sync a circle from a subscription.
2+
3+
Linking a circle to a subscription makes every refresh of that subscription
4+
rebuild the circle's membership: nodes the panel still serves are kept/added,
5+
dropped ones removed, and hand-added members (or ones from a different
6+
subscription) preserved.
7+
8+
NULL default keeps every existing circle manually managed, which is exactly
9+
how they behaved before this migration.
10+
11+
The model declares `foreign_key="subscription.id"` (same convention as
12+
`node.subscription_id`), but this migration adds a plain column: SQLite can't
13+
attach a constraint via ALTER TABLE, and re-creating the table for it buys
14+
nothing here — a stale link is harmless (the sync path simply finds no
15+
subscription and leaves the circle alone) and the app layer already clears
16+
circle references when nodes disappear.
17+
18+
Revision ID: 023
19+
Revises: 022
20+
Create Date: 2026-08-11
21+
"""
22+
from typing import Sequence, Union
23+
24+
from alembic import op
25+
import sqlalchemy as sa
26+
27+
28+
revision: str = "023"
29+
down_revision: Union[str, None] = "022"
30+
branch_labels: Union[str, Sequence[str], None] = None
31+
depends_on: Union[str, Sequence[str], None] = None
32+
33+
34+
def upgrade() -> None:
35+
op.add_column("nodecircle", sa.Column("subscription_id", sa.Integer(), nullable=True))
36+
37+
38+
def downgrade() -> None:
39+
op.drop_column("nodecircle", "subscription_id")

0 commit comments

Comments
 (0)