---
title: Charmhub | Deploy Enterprise Store using Charmhub - The Open Operator Collection
description: Deploy the latest version of Enterprise Store on any cloud.
url: https://charmhub.io/enterprise-store/docs/deploy-offline
---

# Enterprise Store

[Colin Christophe](https://charmhub.io/publisher/colin-c "View all packages from Colin Christophe")

* [Colin Christophe](https://charmhub.io/publisher/colin-c "View all packages from Colin Christophe")

Platform:

24.04

stable 7

```
juju deploy enterprise-store
```

[Learn to deploy on juju >](https://juju.is/docs/juju/manage-applications)

---

Share your thoughts on this charm with the community on discourse.

[Join the discussion](https://discourse.charmhub.io/)

# Deploying in airgapped mode

This page describes how to deploy the enterprise-store charm in **offline /
airgapped mode**, in which nothing reaches the internet. The snaps that make up
the enterprise-store are shipped in through the `store-bundle` resource, and
blob storage is provided by an S3 backend via the
[s3-integrator charm](https://charmhub.io/s3-integrator).

For a deployment that proxies the global Snap Store, see the Proxy mode deploy
guide instead.

Offline mode requires two things in addition to a proxy-mode deployment:

* The `store-bundle` resource, containing the snaps to install.
* The `offline` config set to `true`
* The `s3-credentials` relation to an `s3-integrator`, providing blob storage.
  The unit stays in `BlockedStatus` until this relation is established.

## [Prerequisites](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-prerequisites)

### [Controller](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-controller)

A Juju controller on a machine cloud (for example LXD) is required:

```
sudo snap install juju
sudo snap install lxd
lxd init --auto
juju bootstrap localhost <controller_name>
```

### [PostgreSQL](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-postgresql)

The charm requires a PostgreSQL database over the `postgresql_client`
interface. The enterprise-store needs the `btree_gist` extension. The charm
requests the `superuser` role and attempts to provision the extension itself,
but it is recommended to also enable it explicitly on the PostgreSQL charm so
the extension is available regardless of role handling:

```
juju config postgresql plugin_btree_gist_enable=true
```

## [The offline store bundle](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-the-offline-store-bundle)

Everything needed for the airgapped install ships in a single tarball,
`offline-snap-store.tar.gz`, produced by registering the store with the
[store-admin snap](https://snapcraft.io/store-admin) using the `--offline` flag:

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

When extracted, the tarball contains an `offline-snap-store/` directory holding:

* `snapd_*.snap`, `core22_*.snap` and `enterprise-store_*.snap`
* a matching `*.assert` file for each of those snaps
* `proxy.assert` - the store assertion, applied on first bootstrap only
* `registration_bundle.b64` - the base64 registration bundle for the
  `registration_bundle` config option

This single tarball is used in two different places, described below.

### [As the store-bundle resource](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-as-the-store-bundle-resource)

Attach the tarball to the charm as-is, as the `store-bundle` resource. All three
snaps are installed together whenever a new tarball is attached (because
`enterprise-store` depends on `core22`), but the store assertion is applied
exactly once. Updating the snaps later therefore never recreates the store, and
update tarballs may omit `proxy.assert`.

Attaching can be done at deploy time with `--resource` (see the deploy sections
below), or on an already-deployed charm with:

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

### [As the registration\_bundle config option](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-as-the-registration_bundle-config-option)

The `registration_bundle` config value is *not* the tarball itself but the
`registration_bundle.b64` file contained inside it, which must first be
extracted:

```
tar xzf offline-snap-store.tar.gz offline-snap-store/registration_bundle.b64
```

Once extracted, supply the contents of that file to the charm through the
`registration_bundle` config option, either during deployment (via the Juju
bundle or Terraform config shown below) or afterwards on the CLI:

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

## [S3 storage setup](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-s3-storage-setup)

The `s3-integrator` needs credentials and connection details for your S3
endpoint (for example MinIO). Credentials are provided through a Juju secret:

```
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 charm maps the s3-integrator connection info onto the enterprise-store snap
configuration as follows (the same bucket is used for both the scanned and
unscanned containers, and the charm sets `proxy.storage.backend` to `s3`):

| s3-integrator field | enterprise-store snap config |
| --- | --- |
| 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](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-deploy-with-the-juju-cli)

```
juju deploy postgresql --channel 14/stable
juju config postgresql plugin_btree_gist_enable=true
juju deploy enterprise-store --channel stable \
    --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)"
```

If the charm is already deployed, a new bundle can be attached (and updated
later) with:

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

Configure the `s3-integrator` credentials and connection details as shown in the
S3 storage setup section.

## [Deploy with a Juju bundle](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-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: /path/to/charm
    num_units: 3
    options:
      offline: true
      registration_bundle: include-file://path/to/registration_bundle.b64
    resources:
      store-bundle: ./offline-snap-store.tar.gz

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

With the above example it is assumed that `offline-snap-store.tar.gz` is
available in the current directory.

## [Deploy with Terraform](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-deploy-with-terraform)

The Juju Terraform provider cannot deploy a purely local `.charm` using the most current release (v2.3.0). Without this offline deployments are not possible using terraform. This functionality *may* be added at some point at which point the information would be detailed in the [provider documentation](https://canonical.com/juju/docs/terraform-provider-juju/2.2/howto/manage-charms/)

## [High availability and TLS](https://charmhub.io/enterprise-store/docs/deploy-offline#p-42305-high-availability-and-tls)

For a highly available deployment (multiple units fronted by haproxy) and for
TLS termination options, see the High availability deploy guide.

---
