Skip to content

Commit

Permalink
docs: adds UPGRADE.md docs (#402)
Browse files Browse the repository at this point in the history
* docs: adds UPGRADE.md docs

* fix: address review feedback

* fix: use new port

* docs: address feedback
  • Loading branch information
nathanielc authored Jul 22, 2024
1 parent cd5ed0c commit bfe2380
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 83 deletions.
88 changes: 5 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Install a the latest release using dpkg:
# get deb.tar.gz
curl -LO https://github.com/ceramicnetwork/rust-ceramic/releases/download/latest/ceramic-one_x86_64-unknown-linux-gnu.tar.gz
# untar the Debian software package file
tar zxvf ceramic-one_x86_64-unknown-linux-gnu.tar.gz
tar zxvf ceramic-one_x86_64-unknown-linux-gnu.tar.gz
# install with dpkg - package manager for Debian
dpkg -i ceramic-one.deb
```
Expand Down Expand Up @@ -95,16 +95,16 @@ Running the ceramic-one binary is simply passing the `daemon` cli option.

```sh
# if necessary, include the path/to/the/binary e.g. /usr/local/bin/ceramic-one or ./target/release/ceramic-one
$ ceramic-one daemon
$ ceramic-one daemon
# There are many flags for the daemon CLI that can be passed directly or set as environment variables.
# There are many flags for the daemon CLI that can be passed directly or set as environment variables.
# See `DaemonOpts` in one/src/lib.rs for the complete list or pass the -h flag
$ ceramic-one daemon -h

# A few common options are overriding the log level:
$ RUST_LOG=warn,ceramic_one=info,ceramic_service=debug ceramic-one daemon
# Or modifying the network
$ ceramic-one daemon --network testnet-clay
# Or modifying the network
$ ceramic-one daemon --network testnet-clay
$ ceramic-one daemon --network local --local-network-id 0
# Or changing where directory where all data is stored. This folder SHOULD be backed up in production
# and if you change the defaults, you MUST specify it every time you start the daemon.
Expand All @@ -114,84 +114,6 @@ $ ceramic-one daemon --store-dir ./custom-store-dir
The process honors RUST_LOG env variable for controlling its logging output.
For example, to enable debug logging for code from this repo but error logging for all other code use:

### Migration
This repo also contains the kubo to ceramic-one migration script.

This script will read ipfs repo files matching ~/.ipfs/blocks/**/*
and insert them into the ceramic-one database ~/.ceramic-one/db.sqlite3

The migration script will scan the input-ipfs-path for any file that has
a b32 multibase as the filename not including the extension. When a file matches its hash it will be copied into the database at output-ceramic-path.

you can run it with cargo

$ cargo run --bin migration -- -h
Usage: migration [OPTIONS]

Options:
-i, --input-ipfs-path <INPUT_IPFS_PATH>
The path to the ipfs_repo [eg: ~/.ipfs/blocks]
-c, --input-ceramic-db <INPUT_CERAMIC_DB>
The path to the input_ceramic_db [eg: ~/.ceramic-one/db.sqlite3]
-o, --output-ceramic-path <OUTPUT_CERAMIC_PATH>
The path to the output_ceramic_db [eg: ~/.ceramic-one/db.sqlite3]
-v, --verbose...
More output per occurrence
-q, --quiet...
Less output per occurrence
-h, --help
Print help
-V, --version
Print version

or build it, move migration to you ceramic box, run it there.

$ cargo build --frozen --release --bin migration
$ cp target/release/migration ./migration
$ ./migration -h
Usage: migration [OPTIONS]

Options:
-i, --input-ipfs-path <INPUT_IPFS_PATH>
The path to the ipfs_repo [eg: ~/.ipfs/blocks]
-c, --input-ceramic-db <INPUT_CERAMIC_DB>
The path to the input_ceramic_db [eg: ~/.ceramic-one/db.sqlite3]
-o, --output-ceramic-path <OUTPUT_CERAMIC_PATH>
The path to the output_ceramic_db [eg: ~/.ceramic-one/db.sqlite3]
-v, --verbose...
More output per occurrence
-q, --quiet...
Less output per occurrence
-h, --help
Print help
-V, --version
Print version

Migration

* Ingest all the SHA256 blocks from your local filesystem block store to a sqlite3 database
```zsh
./migration --input-ipfs-path '~/.ipfs/blocks' --output-ceramic-path '~/.ceramic-one/db.sqlite3'
```
* Pass in the input path to the blocks folder the script will import all blocks
in the directory that is named with its multihash.
* Pass in the where you would like the sqlite database as the output path.
* Move the sqlite3 database to the new rust-ceramic node.
* Start the new rust-ceramic server and point the compose DB node to it.
```zsh
./ceramic-one daemon --bind-address '127.0.0.1:5101'
```
* Once the traffic is cut over to the new node and we know there are not new block being crated on the old node.
Re-run the migration to pick up any new block that were crated after the first migration
```zsh
./migration --input-ipfs-path '~/.ipfs/blocks' --output-ceramic-path '~/.ceramic-one/db.sqlite3.bck'
```
* Move the second sqlite3 database to the new rust-ceramic node.
* Ingest the new block from this second sqlite3 database.
```zsh
./migration --input-ceramic-db 'db.sqlite3.bck' --output-ceramic-path '~/.ceramic-one/db.sqlite3.bck'
```

## License

Fully open source and dual-licensed under MIT and Apache 2.
Expand Down
155 changes: 155 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Upgrade to Ceramic One from Kubo

This document describes how to upgrade an existing Ceramic node (js-ceramic) using Kubo to run with `ceramic-one` while preserving existing data.

## Overview

Follow these steps for basic upgrade of a Ceramic node with some downtime.

1. Shutdown existing `js-ceramic` node.
2. Migrate data from IPFS blocks into Sqlite database file `ceramic-one` can consume.
3. Start `ceramic-one` daemon.
4. Configure `js-ceramic` to run against `ceramic-one`.
5. Start `js-ceramic` node and validate.

If you require a zero downtime upgrade see the section below that expands the basic steps for a near zero downtime upgrade.

### Shutdown Existing Node

First shutdown both the `js-ceramic` and `kubo` processes using whatever mechanism your infrastructure dictates.
If you have your `js-ceramic` daemon configured to _bundle_ `ipfs` then stopping `js-ceramic` will also stop `kubo`.
Otherwise you will need to explicitly stop `kubo`.

### Migrate IPFS Blocks to Ceramic Events

Kubo stores data as IPFS blocks on disk.
You must be using the disk backed Kubo storage.

These IPFS blocks are the raw pieces of Ceramic Events.
In order to preserve this data we need to migrate them into Ceramic Events stored in a Sqlite database file.

The `ceramic-one` command contains a subcommand for migrating data from IPFS blocks.
Install the `ceramic-one` binary following the instructions in README.md.

See the complete usage information for the migration command:

ceramic-one migrations from-ipfs --help

The command requires an input directory where the IPFS blocks are found and an output directory where the sqlite file containing the migrated events will be written.

The following command will migrate data assuming the default directories for both Kubo and `ceramic-one`.
Adjust the command arguments as needed by your infrastructure.

ceramic-one migrations from-ipfs -i ~/.ipfs/blocks -o ~/.ceramic-one --network mainnet

This command will migrate all blocks stored in the `~/.ipfs/blocks` directory into the database file `~/.ceramic-one/db.sqlite3` for the `mainnet` network.
As output from the command you should see a total number of events migrated, this will not be the same as the number of blocks as multiple blocks construct into a single event.
You will also see a number of errors. This represents the number of blocks found that are part of a Ceramic Event but for whatever reasons could not be constructed into a complete event.
Any error will be logged for investigations.
Any blocks stored in Kubo that are not Ceramic Events will be ignored.

The `js-ceramic` daemon will not start if it does not find data for its events in its block store.
Therefore in the next steps you will verify that the migration was successful.


### Start `ceramic-one` Daemon

Once the data is migrated it's time to start the node again.
The `ceramic-one` process is started in place of the `kubo` process, Kubo is no longer needed.

Read the full usage of the `ceramic-one` daemon:

ceramic-one daemon --help

Once you are familiar with configuring the daemon start it with defaults or specify any arguments specific to your infrastructure.

ceramic-one daemon

You should see logs indicating the daemon is running.
The first few logs line will look similar to this:

```
2024-07-02T15:04:55.730992Z INFO ceramic_one: service__name: "ceramic-one", version: "0.25.0", build: "git:efd1fb0-modified", instance_id: "remarkable-screw", exe_hash: "uEiDQmcM1n-lG2Qxi0jOCyFdPpqA_ijIC29RPd_7FhwqqBg"
at one/src/lib.rs:363
2024-07-02T15:04:55.731205Z INFO ceramic_p2p::node: identity loaded: 12D3KooWD2C2aWKagfowBN7LDkiXpXyMiJyN4FAuEptqZAQ2GgZp
at p2p/src/node.rs:1153
2024-07-02T15:04:55.732282Z INFO libp2p_swarm: local_peer_id: 12D3KooWD2C2aWKagfowBN7LDkiXpXyMiJyN4FAuEptqZAQ2GgZp
at /home/nathanielc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libp2p-swarm-0.44.2/src/lib.rs:367
2024-07-02T15:04:55.732300Z INFO ceramic_p2p::node: iroh-p2p peerid: 12D3KooWD2C2aWKagfowBN7LDkiXpXyMiJyN4FAuEptqZAQ2GgZp
at p2p/src/node.rs:168
2024-07-02T15:04:55.733218Z INFO ceramic_p2p::rpc: p2p rpc listening on: mem
at p2p/src/rpc.rs:434
in ceramic_p2p::rpc::new with addr=mem
2024-07-02T15:04:55.733239Z INFO ceramic_p2p::node: Listen addrs: ["/ip4/0.0.0.0/tcp/4001", "/ip4/0.0.0.0/udp/4001/quic-v1"]
at p2p/src/node.rs:249
in ceramic_p2p::node::run
2024-07-02T15:04:55.733257Z INFO ceramic_p2p::node: Local Peer ID: 12D3KooWD2C2aWKagfowBN7LDkiXpXyMiJyN4FAuEptqZAQ2GgZp
at p2p/src/node.rs:250
in ceramic_p2p::node::run
```



### Configure `js-ceramic` for `ceramic-one`

Change the `ipfs` section in the `daemon.config.json` to use `remote` mode and point it at the running `ceramic-one` daemon.
By default the `ceramic-one` daemon listens on port 5101, if you configured it differently make sure to match that configuration for `js-ceramic` as well.

```json
"ipfs": {
"mode": "remote",
"host": "http://localhost:5101"
},
```


### Start `js-ceramic` Node and Validate

Now start the `js-ceramic` node with its new configuration and environment.
Validate the process starts as before and that your application can communicate with it as needed.

To validate that everything worked you can run any tests you may have against the node or perform a random sample query to ensure all data has migrated.
This will depend on the specifics of your application.

## Recovery

At this point you should have a working upgraded `js-ceramic` node but sometimes things go wrong.
The Ceramic node does some basic checks on startup to ensure its various data stores are in sync, if these checks fail the process will exit with an error message about missing data.
In that case or any other failure mode follow these steps to return your node to its working state.

1. Stop the `ceramic-one` and `js-ceramic` processes.
2. Revert the configuration and environment changes to `js-ceramic`.
3. Start `js-ceramic` process.

These steps work because the existing data is not modified during the migration, instead it is only read and copied.

## Live Upgrade Steps

If you cannot tolerate a window of downtime of your Ceramic node you can perform a two pass migration process to minimize the amount of time your node is offline.
The basic strategy here is to run two nodes behind a proxy in an active/passive mode.
A downside to this approach is that there will be a period of time where the new node is missing data.

If your application cannot tolerate such a regression in this approach is not recommended.

These steps are very similar to the normal upgrade process so please review those steps first.
The high level sequence is:

1. Migrate the data from the active old node.
2. Start new node as the passive with the migrated data.
3. Validate new passive node is working
4. Switch active role to new node and passive role to old node.
5. Migrate data from the old node to the new node again to catch any new data since the first migration.
6. Shutdown old node as it is now behind and out of date.


The `ceramic-one migrations from-ipfs` command can be run against a running `ceramic-one` daemon process.
It will cause contention on the database, as a result traffic to the node may be impacted, but no downtime is required.

NOTE: During step 5 the new node is missing the data that occurred after the initial migration in step 1 until the second migration completes in step 5.

0 comments on commit bfe2380

Please sign in to comment.