Deploy a charmed store in offline mode

In offline mode, the charm installs the Enterprise Store from an attached store-bundle resource rather than the Snap Store. Set offline: true and integrate the charm with an S3-compatible storage provider. The unit remains blocked until the s3-credentials integration is established.

Prerequisites

You need Juju 3.x, a controller on a machine cloud, and PostgreSQL with btree_gist enabled:

juju deploy postgresql --channel 14/stable
juju config postgresql plugin_btree_gist_enable=true

Prepare the offline store bundle

On an internet-connected machine, use store-admin to register the store and produce offline-snap-store.tar.gz:

store-admin register --offline https://offline.example.com

The archive contains an offline-snap-store/ directory with the snapd, core22, and enterprise-store snaps and matching assertions. It also contains proxy.assert and registration_bundle.b64. For more information about registration and post-deployment operations such as push-snap, see Offline store (air-gapped mode).

Attach the store-bundle resource

Attach the archive at deployment time, as shown below, or attach it to an existing application:

juju attach-resource enterprise-store \
    store-bundle=./offline-snap-store.tar.gz

The charm installs all three snaps together. On first bootstrap only, it writes proxy.assert to /var/snap/enterprise-store/common/nginx/airgap/store.assert. Attaching a bundle later does not reapply the store assertion.

Configure the registration bundle

Extract the registration bundle and provide its contents as charm configuration:

tar xzf offline-snap-store.tar.gz \
    offline-snap-store/registration_bundle.b64
juju config enterprise-store \
    registration_bundle="$(cat offline-snap-store/registration_bundle.b64)"

Configure S3 storage

Deploy s3-integrator, then provide its credentials through a Juju secret. Replace each placeholder with the value for your S3 service:

juju deploy s3-integrator --channel 2/stable
juju add-secret s3-creds \
    access-key="<access-key>" secret-key="<secret-key>"
juju grant-secret s3-creds s3-integrator
juju config s3-integrator \
    credentials=secret:<secret-id> \
    endpoint=<s3-endpoint> \
    bucket=<bucket-name>

The integration maps S3 data to the snap configuration as follows and sets proxy.storage.backend to s3:

s3-integrator field

Enterprise Store snap configuration

access-key

proxy.storage.s3.access-key-id

secret-key

proxy.storage.s3.secret-access-key

bucket

proxy.storage.s3.unscanned-container-name

bucket

proxy.storage.s3.scanned-container-name

endpoint

proxy.storage.s3.server-url

region

proxy.storage.s3.region

s3-uri-style

proxy.storage.s3.use-path-style

Deploy with the Juju CLI

juju deploy enterprise-store --channel edge \
    --config offline=true \
    --resource store-bundle=./offline-snap-store.tar.gz
juju deploy s3-integrator --channel 2/stable
juju integrate postgresql:database enterprise-store:database
juju integrate s3-integrator enterprise-store:s3-credentials
juju config enterprise-store \
    registration_bundle="$(cat offline-snap-store/registration_bundle.b64)"

Configure the S3 credentials and endpoint as described above, then wait for juju status to report the Enterprise Store unit as active.

Deploy with a Juju bundle

applications:
  postgresql:
    charm: postgresql
    channel: 14/stable
    num_units: 1
    options:
      plugin_btree_gist_enable: true
  s3-integrator:
    charm: s3-integrator
    channel: 2/stable
    num_units: 1
  enterprise-store:
    charm: enterprise-store
    channel: edge
    num_units: 1
    options:
      offline: true
      registration_bundle: <registration_bundle.b64>
    resources:
      store-bundle: ./offline-snap-store.tar.gz

relations:
- - postgresql:database
  - enterprise-store:database
- - s3-integrator
  - enterprise-store:s3-credentials

After deploying the bundle, configure the s3-integrator credentials and endpoint.

For a multi-unit deployment, continue with Deploy a highly available charmed store. See the charm reference for resource and integration details.