Deployment

Odoo Sync supports two deployment modes:

HTTP only

No sidecar required. Install sync_http on each Odoo instance, then add a few Python libraries from requirements.txt to your Odoo environment. Odoo instances communicate directly over HTTPS. See HTTP Transport for the setup steps.

Kubo sidecar (this page)

A Python gateway process runs alongside Odoo and bridges it to a Kubo (IPFS) daemon. The full stack is orchestrated with Docker Compose and consists of:


Install

Install Docker Compose if it is not already present. A step-by-step guide for Linux Mint / Debian-based systems is available here.

Add your user to the docker group so you do not need sudo:

sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker   # activate without logout, or restart the session

Filesystem

Create the mounted volumes and set ownership before first boot:

sudo mkdir -p /var/ipfs_data/staging /var/ipfs_data/data
sudo chown -R 1000:1000 /var/ipfs_data   # UID 1000 = default host user
chmod +x deploy/ipfs/001-setup-swarm.sh

Note

Adjust the chown UID if your Docker daemon runs under a different user mapping. The Kubo container runs as UID 1000 internally.

Environment

Sensitive credentials are injected at runtime via a .env file:

cp .env.example .env   # then fill in your values

Warning

Never commit .env to version control.

The full list of environment variables is described below:

Variable

Consumed by

Purpose

POSTGRES_DB

db, odoo, gateway

Name of the default database created on boot.

POSTGRES_USER

db, odoo

Database username.

POSTGRES_PASSWORD

db, odoo

Database password used by Odoo to connect to Postgres.

GATEWAY_URL

odoo

Gateway express API URL, consumed by ip.node.gate_url (e.g. http://gateway:5000).

ODOO_URL

gateway

Base URL of the local Odoo instance (e.g. http://odoo:8069).

ODOO_KUBO_USER

gateway

Odoo login name associated with ODOO_KUBO_API_KEY.

ODOO_KUBO_API_KEY

gateway

Odoo API token used by the gateway daemon for JSON-RPC batches.

IPFS_URL

odoo, gateway

Kubo daemon RPC URL (e.g. http://ipfs:5001).

LIBP2P_FORCE_PNET

ipfs

1 = private network (requires swarm.key); 0 = public IPFS. Defaults to 1.

BOOTSTRAP_NODE

ipfs

Optional multiaddr of a known peer for initial swarm bootstrap.

GF_SECURITY_ADMIN_USER

grafana

Grafana admin username (dashboard at port 3000).

GF_SECURITY_ADMIN_PASSWORD

grafana

Grafana admin password.

Launch

docker compose up -d        # build images and start all containers
docker compose ps -a        # verify all services are healthy

Tip

First-boot takes longer because Docker pulls images and the deploy scripts run. Subsequent starts are fast.

Connect

For local-network testing, enable mDNS reflection through the Docker bridge so Kubo nodes can discover each other via Avahi:

sudo nano /etc/avahi/avahi-daemon.conf
# In the [reflector] section, set:
#   enable-reflector=yes
sudo systemctl restart avahi-daemon

Alternatively, bootstrap directly to a known peer by setting BOOTSTRAP_NODE in .env on the joining node:

# Find the IP of node A
ifconfig   # look for your wireless interface (wlan0, wlp3s0 …)

# Find the PeerID of node A
docker compose exec ipfs ipfs id   # copy the "ID" field

# In node B's .env:
BOOTSTRAP_NODE=/ip4/<NODE_A_IP>/tcp/4001/p2p/<NODE_A_PEER_ID>

Verify the swarm connection from node B:

docker compose exec ipfs ipfs swarm connect $BOOTSTRAP_NODE
docker compose exec ipfs ipfs swarm peers   # should list node A

Tip

If swarm connect fails, check that port 4001/tcp is open on node A and that both nodes share the same swarm.key (see below).

Here are a few bare IPFS commands that may come in handy:

docker compose exec ipfs ipfs p2p listen /x/odoo/p2p/v1 /ip4/127.0.0.1/tcp/5000
docker compose exec ipfs ipfs p2p ls
docker compose exec ipfs ipfs p2p close --all

Swarm Key

By default LIBP2P_FORCE_PNET=1 — the Kubo daemon refuses connections from peers that do not share the swarm.key. The 001-setup-swarm.sh script generates one automatically on first boot and writes it to /var/ipfs_data/data/swarm.key.

Note

The IPFS swarm key is injected by 001-setup-swarm.sh on first boot, not via an environment variable, because it is a binary file rather than a scalar secret.

All nodes on a private IPFS network must share a cryptographic swarm key. To join an existing private network, obtain the swarm.key from the network administrator and install it before starting the container:

# Place the key in the mapped data directory
cp swarm.key /var/ipfs_data/data/swarm.key

# If the container is already running, restart it to apply the new key
docker compose restart ipfs

Warning

Overwriting a swarm.key on a running node disconnects it from its current network immediately. Coordinate the switch with all peers.

If you’re ready to join the public swarm, you don’t need a swarm key! Set LIBP2P_FORCE_PNET=0 in .env to join the public IPFS network instead (global bootstrap nodes are re-enabled automatically on the next gateway boot).

Danger

Every single message and payload you send over the public swarm will be visible to other nodes. Here be dragons.

Identity Key

The swarm key admits you to the network; your Ed25519 identity key proves who you are to the Odoo application. Odoo generates keypairs automatically for local ip.peer records.

To register an existing external IPFS node as a remote peer, export its public key and hand it to the Odoo administrator:

ipfs key export self --format=pem-pkcs8-cleartext

The administrator creates an ip.peer record in Odoo with that public key. All subsequent events from that node are cryptographically verified before import.