-
Notifications
You must be signed in to change notification settings - Fork 24
docs: complete v5 to v6 migration guide (#4257) #4265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,38 +1,123 @@ | ||
| .. _nuts-node-migration: | ||
| .. _nuts-node-migrations: | ||
|
|
||
| Migrating from v5 to v6 | ||
| ************************ | ||
| *********************** | ||
|
|
||
| Nuts node v6 runs several migrations on startup for DID documents that are managed by the node, namely: | ||
| Operator runbook for upgrading a v5 deployment to v6 while keeping the existing ``did:nuts`` setup. Work through the steps in order. If you also want to adopt ``did:web`` as part of the upgrade, finish the main steps first, then see :ref:`also-enabling-did-web`. | ||
|
|
||
| 1. Remove controllers and add self-control to ``did:nuts`` documents, | ||
| 2. Import ``did:nuts`` documents into the new SQL database under a ``subject`` with the same name, and | ||
| 3. Add a ``did:web`` document to the same ``subject``. | ||
| .. contents:: | ||
| :local: | ||
| :depth: 1 | ||
|
|
||
| **Migration: convert did:nuts to self-control** | ||
| Requires ``didmethods`` to contain ``nuts``. | ||
| 1. Provision an SQL database | ||
| ============================ | ||
|
|
||
| Previously, DID documents could either by under self-control or under control of another DID as was recommended for vendor and care organisation, respectively. | ||
| In the new situation a user manages ``subjects``, and the node manages all DIDs under the ``subject``. | ||
| To reduce complexity and allow future adoption of other did methods, all documents will be under self-control from v6. | ||
| v6 requires SQL storage. Supported engines: PostgreSQL, MySQL, Microsoft SQL Server, Azure SQL, SQLite. | ||
| SQLite is acceptable for small deployments, and for ``did:nuts``-only deployments that won't adopt ``did:web`` in the near future — in that case the SQL state is rebuilt at startup from BBolt and the key backend. | ||
|
|
||
| **Migration: convert did:nuts to subject** | ||
| Requires ``didmethods`` to contain ``nuts``. | ||
| Configure the connection string in ``storage.sql.connection``. See :ref:`storage-configuration` for the full reference. | ||
|
|
||
| All owned ``did:nuts`` DID documents will be migrated to the new SQL storage. | ||
| This migration includes all historic document updates as published upto a potential deactivation of the document. | ||
| For DIDs with a document conflict this is different than the resolved version of the document, which contains a merge of all conflicting document updates. | ||
| To prevent the state of the resolver and the SQL storage to be in conflict, all DID document conflicts must be resolved before upgrading to v6. | ||
| See ``/status/diagnostics`` if you own any DIDs with a document conflict. If so, use ``/internal/vdr/v1/did/conflicted`` to find the DIDs with a conflict. | ||
| .. code-block:: yaml | ||
|
|
||
| .. note:: | ||
| # SQLite — fine for a did:nuts-only upgrade | ||
| storage: | ||
| sql: | ||
| connection: sqlite:file:/opt/nuts/data/sqlite.db?_pragma=foreign_keys(1)&journal_mode(WAL) | ||
|
|
||
| The document migration will run on every restart of the node, meaning that any updates made using the VDR V1 API will be migrated on the next restart. | ||
| However, any changes made via the V1 API wil NOT propagate to other DID documents under the same ``subject``, so you MUST set ``didmethods = ["nuts"]`` to use the V1 API. | ||
| 2. Update the host and container references | ||
| =========================================== | ||
|
|
||
| **Migration: add did:web to subjects** | ||
| Requires ``didmethods`` to contain ``web`` and ``nuts`` (default). | ||
| The v6 container runs as UID ``18081`` (was ``root``). Before the first v6 start, on the host: | ||
|
|
||
| This migration adds a new ``did:web`` DID Document to owned subjects that do not already have one. | ||
| A new verification method is created for the document and added to all verification relationships except KeyAgreement. | ||
| This means did:web cannot be used for encryption (yet). | ||
| .. code-block:: shell | ||
|
|
||
| chown -R 18081:18081 /opt/nuts/data | ||
|
|
||
| Docker image tags no longer carry a ``v`` prefix — pull ``nutsfoundation/nuts-node:6.0.0``, not ``v6.0.0``. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. better to encourage here to use only the major version so they always fetch the latest: |
||
|
|
||
| 3. HTTP interfaces | ||
| ================== | ||
|
|
||
| v5 supported flexible HTTP binding via ``http.<name>.*`` (with ``http.default.*`` as the default interface; operators could define additional named interfaces like ``http.admin.*`` bound to separate addresses). v6 replaces this with two fixed interfaces — update your reverse proxy / ingress to route accordingly: | ||
|
|
||
| - ``:8080`` (``http.public.address``) — public endpoints (``/iam``, ``/oauth2``, ``/n2n``, ``/.well-known``, …). | ||
| - ``127.0.0.1:8081`` (``http.internal.address``) — ``/internal``, ``/status``, ``/metrics``, ``/health``. Loopback only by default; if you need to access it from another host, set ``http.internal.address`` to ``0.0.0.0:8081`` and make sure it is not accessible to unauthorized callers (firewall, network segmentation, auth). | ||
|
|
||
| See :ref:`nuts-node-recommended-deployment` for a reference topology. | ||
|
|
||
| 4. Adjust the config file | ||
| ========================= | ||
|
|
||
| Set ``didmethods = ["nuts"]`` (unless you are also adopting ``did:web`` — see :ref:`also-enabling-did-web`). The v6 default is ``["web", "nuts"]``; setting it explicitly to ``["nuts"]`` keeps the deployment behaviour aligned with v5. | ||
|
|
||
| Remove or rename the following: | ||
|
|
||
| .. list-table:: | ||
| :header-rows: 1 | ||
| :widths: 45 55 | ||
|
|
||
| * - v5 key | ||
| - Action | ||
| * - ``auth.publicURL`` | ||
| - Replace with the new top-level ``url`` (introduced in v6). | ||
| * - All ``http.<name>.*`` interface bindings (``http.default.address``, ``http.default.tls``, ``http.default.cors.origin``, and any custom-named interfaces) | ||
| - Remove. v6 uses fixed ``http.public.address`` and ``http.internal.address``. | ||
| * - IRMA/Yivi CORS origin | ||
| - Move to ``auth.irma.cors.origin``. | ||
| * - ``network.certfile``, ``network.certkeyfile``, ``network.truststorefile`` | ||
| - Rename to ``tls.certfile``, ``tls.certkeyfile``, ``tls.truststorefile``. v6 refuses to start otherwise. | ||
| * - ``http.internal.auth.type = token`` | ||
| - No longer accepted. Either configure ``token_v2`` (see :ref:`nuts-node-api-authentication`) or rely on another authentication mechanism on the internal interface — reverse-proxy auth, mTLS, or network-level controls. | ||
|
|
||
| 5. Start v6 | ||
| =========== | ||
|
|
||
| Back up the v5 data directory first — see `Rolling back`_. | ||
|
|
||
| Bring up the v6 node. It runs the ``did:nuts`` migrations on every start (self-control rewrite and history import into SQL). The migrations are idempotent, so an interrupted upgrade is safe to retry. | ||
|
|
||
| 6. Check the startup logs | ||
| ========================= | ||
|
|
||
| Schema migrations abort startup on failure — if the node booted, those are fine. The DID-document migrations don't: per-DID failures (corrupted history, key resolution errors) are logged at ``error`` and the node keeps running with that DID missing from SQL. Grep the startup logs for ``level=error`` lines from the migration step. | ||
|
|
||
| Rolling back | ||
| ============ | ||
|
|
||
| v6 rewrites the v5 on-disk state on first start. There is no in-place downgrade. To roll back, restore the v5 data directory from the backup you took before Step 5, then start v5. The SQL database is new in v6 and not used by v5. If you plan to retry the upgrade, wipe the SQL database first to avoid stale state. | ||
|
|
||
| Other notes | ||
| =========== | ||
|
|
||
| TLS termination | ||
| --------------- | ||
|
|
||
| v6 can no longer terminate server-side TLS for HTTP itself. If you already run v5 behind a reverse proxy or ingress (the typical setup), no change is needed. If you relied on the node's built-in TLS, move termination to a reverse proxy or ingress before upgrading. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I expected this to be higher up, under HTTP interfaces for example. |
||
|
|
||
| Creating DIDs with ``selfControl=false`` | ||
| ---------------------------------------- | ||
|
|
||
| ``POST /internal/vdr/v1/did`` ignores the request body in v6. The v5 vendor-controls-care-organisation pattern is gone — new DIDs are always self-controlled, and existing ones are flattened to self-control by the startup migration. | ||
|
|
||
| Mixing VDR v1 and v2 APIs | ||
| ------------------------- | ||
|
|
||
| The v1 and v2 APIs read from different stores. Do not mix usage, or you risk data drift and stale reads. VDR v1 / DIDMan v1 are deprecated and slated for removal in a future major release. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is ambiguous. When I read carefully I read that it is ok to use v1 and the warning is not to use both of them. But the deprecation warning suggest to not use v1 at all.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is a footgun, shouldn't we made either one available by a config param? |
||
|
|
||
| .. _also-enabling-did-web: | ||
|
|
||
| Also enabling ``did:web`` | ||
| ------------------------- | ||
|
|
||
| If you also want to support ``did:web`` use cases, leave ``didmethods`` at its default (both methods enabled) — drop the ``didmethods = ["nuts"]`` line from Step 4. The startup migration adds a ``did:web`` document to every existing subject; this is one-way and cannot be reversed without manually rebuilding subjects. | ||
|
|
||
| Additional preconditions: | ||
|
|
||
| - **Resolve all DID document conflicts on v5 first.** A conflicted ``did:nuts`` document imports into SQL as the replayed published history, not the merged state the v1 resolver returns. The new ``did:web`` is derived from the SQL view, so for any conflicted DID it will diverge from what v1 callers see. On v5, check ``GET /status/diagnostics``; if any are owned, list them via ``GET /internal/vdr/v1/did/conflicted`` and resolve each one. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when you enable did:web, is the sqlite backend forbidden in strict mode? (should we build this?) |
||
| - **Move all DID and service management to VDR v2 before the first multi-method write.** VDR v1 / DIDMan v1 writes only touch the ``did:nuts`` document, not the ``did:web`` in the same subject. Mixed use silently desynchronises the two, and the startup migrations do not repair this on later restarts. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we disable the didman api's or error/warn when did:web is enabled? |
||
| - ``did:web`` resolution requires the public interface to be reachable at the configured ``url`` over HTTPS (handled by the reverse proxy from Step 3). | ||
|
|
||
| After the first v6 start with ``did:web`` enabled, verify each subject contains both DIDs: | ||
|
|
||
| - ``GET /internal/vdr/v2/subject/{id}`` lists both the ``did:nuts`` and the ``did:web``. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say possible but discouraged.