Migration 0005 (MigrateNFSClients) only runs once when first applied,
so any fsid=0 rows present before 0005 was applied never get repaired.
Migration 0006 triggers FixZeroFSIDs() which:
- Queries all nfs_exports rows with fsid=0
- Generates a new random fsid per row
- Updates the row
Version: 0.5.2
When migrating old clients format (string array) to new format
(NFSClient objects), also fix any exports that have fsid=0 by
generating a new random fsid. This resolves exportfs errors like:
exportfs: /path fsid=0 requires fsid= for NFS export
The migration now checks if r.FSID == 0 and generates a new one
using system.GenerateRandomFSID() before updating the row.
This is a backward-compatible MINOR bump (0.4.0 → 0.5.0).
BREAKING NOTES (for users upgrading from pre-0.5.0):
- The nfs_exports.clients column schema changed from []string to
[]NFSClient (per-host options). A migration (0005) transforms existing
string arrays into object arrays, taking export-level options as
defaults for each host.
- ValidateNFSClient now only accepts IPv4 (192.168.1.1) or IPv4/CIDR
(192.168.1.0/24). Hostnames, wildcards, netgroups are rejected.
- If you use NASCTL_IMPORT_ON_BOOT, re-import your /etc/exports to pick
up per-host options.
What changed:
- NFSClient type: {host, read_only, async, root_squash, subtree_check, advanced}
- NFSExport.Clients is now []NFSClient (was []string)
- export-level flags (ro/async/root_squash/subtree_check/advanced) are
preserved as template defaults for newly added hosts in the UI.
- buildExportLine generates: path host1(ro,sync,...) host2(rw,async,...) fsid=N
- ValidateNFSClient: strict IPv4/CIDR only (0-255 octets, /0-32 prefix)
- parseExportLine now parses per-host options from /etc/exports (previously
only the first host's options were kept, others were discarded)
- UI: per-host rows with toggles (ro/async/root_squash/subtree_check) and
advanced options (all_squash, secure, wdelay, hide, crossmnt)
Migration 0002 added fsid column with DEFAULT 0 but never
populated existing rows. Now PopulateLegacyFSIDs() runs after 0002
to extract fsid from legacy options string or generate random.
Also: move generateRandomFSID to internal/system to avoid import
cycles. Migration 0004 drops the legacy options column.
Version: 0.3.1 -> 0.3.2
The previous SAVEPOINT approach failed because Go's tx.Exec() stops at
the first error and never reaches the ROLLBACK TO statements. This caused
every subsequent startup to re-run migration 0002, fail on the first
ALTER (column already exists from a prior partial run), and crash.
Fix runMigration() to:
- Execute migrations without a wrapping transaction (DDL in SQLite is
auto-commit anyway)
- Treat "duplicate column name" / "already exists" errors as success
and record the migration anyway, covering cases where a previous
failed attempt already partially modified the schema
Also simplify 0002_nfs_structured.sql back to plain ALTER TABLE
statements (no SAVEPOINT needed with the new Go-level tolerance).
Bump VERSION 0.1.9 -> 0.1.10
- Add schema_migrations table to track applied migrations
- Migrate() now checks if a migration was already applied before running
- 0002 rewritten to use SAVEPOINT+ROLLBACK per column, making it safe
to run even if some columns were partially added previously
- Each migration runs in its own transaction; INSERT into schema_migrations
only happens if the SQL executes without error
- Bump VERSION 0.1.8 -> 0.1.9