[Tutorial] Run your own satellite (part 18) - Entitlements

We learn about placement in part 17, but here come the kicker:

Each customer can have their own private placements with their own private pricings (via storj deal backstage) AND storj can set different pricing for the same placement for different customer :exploding_head:.

Entitlements

First, you would need this flag: --entitlements.enabled=true on both satellite-modular console AND satellite-modular api.

(It goes without saying but just to be sure: you need to enable --console.placement.self-serve-enabled=true so customer can select their self serve placements on console frontend UI).

Transition from no entitlements

When you are setting up a new satellite, there could a situation where initially you are not using placement (actually you do, one default placement with index 0) to multiple placements and custom pricing. What need to be done?

You need to backfill database for entitlements table:

# for this task we need the old binary `cmd/satellite`
./satellite entitlements projects set-new-bucket-placements \
--config-dir=. \
--database="cockroach://my_role:123456@127.0.0.1:26257/my_metainfo_database?sslmode=verify-full&sslrootcert=ca.crt"

./satellite entitlements projects set-placement-product-mappings \
--config-dir=. \
--database="cockroach://my_role:123456@127.0.0.1:26257/my_database?sslmode=verify-full&sslrootcert=ca.crt"

These two commands will fix your database - it create if not exist and sync record of entitlements table with the latest config placement and product mapping (to pricing) in your config.yaml.

I think this supposed to be run once and never again (?), after that you suppose to use admin UI to config this?


Also, important note, we might not use storj default billing system, we can use tally and rollup stat and calculate billing ourself using external system. In that case, you don’t need to provide payments key in config.yaml or even run ./satellite entitlements projects set-placement-product-mappings.

A record of entitlements look like this:

-[ RECORD 1 ]
scope      | \x70726f6a5f69643a70edd064e5c747c78921f041211cf9e2
features   | {"new_bucket_placements": [0, 11]}
updated_at | 2026-08-03 18:39:05.523474+00
created_at | 2026-08-03 18:39:05.523477+00

Features only have new_bucket_placements and not placement_product_mappings cause I don’t input payments key for config.yaml.


There is a another tool: ./satellite entitlements projects migrate-pricing, it looks pretty powerful but I’ve no need for that at the moment, so that will have to wait, see you on part 19.