Skip to main content
Users create Postgres, Redis and Files stores in the panel and connect them to their projects. Stores run in the cluster of their region, in the namespace atoll-storage. This page covers what the self-hosted install adds for that and how to turn it off.

What gets installed

The stores themselves (named st-<id>, labelled atoll.app/store and atoll.app/org) are created by atoll-server.

Secrets

create-secrets.sh runs create-storage-secrets.sh, which can also be run alone on an existing install. It keeps Secrets that already exist. Postgres backups go to bucket atoll-store-backups on the Files SeaweedFS (ATOLL_DATASTORE_BACKUP_*), so they live in the same cluster as the stores. Copy that bucket off-site like the platform’s own (see backups.md), or point features.datastore.backups at an external S3 bucket and put its keys in the atoll-store-backups Secret.

Public Files endpoint

Files stores are reachable from outside at https://s3.<apps domain> (ATOLL_DATASTORE_FILES_PUBLIC_ENDPOINT): signed requests and presigned URLs work, and buckets with public read answer anonymous reads.
  • DNS: nothing to add, the wildcard record *.<apps domain> already covers s3.
  • TLS: the wildcard certificate, served as Traefik’s default certificate like app hosts. With ingress-nginx set it as --default-ssl-certificate.
  • s3 can’t clash with a project: project names are at least three characters long.
Set features.datastore.files.publicEndpoint and files.ingress.enabled: false to publish it elsewhere.

Network

  • App pods may connect to atoll-storage on 5432, 6379 and 8333 (atoll-apps policy). Postgres and Redis pods only let in the app pods of projects connected to them, through a policy per store that atoll-server keeps.
  • Files S3 (8333) accepts every app pod and the ingress controller: requests are signed per bucket, as on the public host.
  • Everything else in atoll-storage accepts only its own namespace (replicas, backups to the Files S3), atoll-server (5432, 6379, 8333: usage probes, buckets, backup sizes; the stores’ own policies admit it from ATOLL_DATASTORE_SERVER_NAMESPACE, the release namespace), the CloudNativePG operator (5432, 8000) and networkPolicy.storage.monitoringNamespaces on the metrics ports (9187, 9121, 9327). The chart restricts no egress there: Postgres pods archive WAL to the Files S3 and talk to the Kubernetes API; Redis pods get a deny-all egress policy from their engine.

Disks and resizing

Stores get PersistentVolumeClaims of features.datastore.storageClass (ATOLL_DATASTORE_STORAGE_CLASS; per kind ATOLL_DATASTORE_REDIS_STORAGE_CLASS through features.datastore.config), or the cluster default. Growing a store resizes its claims, which needs a StorageClass with allowVolumeExpansion: true and a driver that can expand volumes (Longhorn, a cloud CSI driver, OpenEBS LVM…). k3s’ local-path (also used by deploy/selfhost/local/k3d.sh) can’t: it ignores sizes and has no resizer, so resizes are refused with a clear message (the server reads the StorageClass, rbac.storageClasses). Images default to the engines’ own; ATOLL_DATASTORE_POSTGRES_IMAGE and ATOLL_DATASTORE_REDIS_IMAGE (in features.datastore.config) pin others.

Regions

Every region that should run stores needs the same pieces in its cluster: CloudNativePG with the Barman Cloud plugin, the atoll-storage namespace with the Files SeaweedFS, the Secrets atoll-store-backups (Postgres backups fail without it) and atoll-files-s3-config, and the Role above (plus the StorageClass ClusterRole) bound to the region’s service account. Test connection on the region (Admin, Regions) checks the namespace, the rights and the operators. A region without them still runs apps; the test then says why storage is off there.

Turning it off

With the chart alone set features.datastore.enabled: false. The server then answers that storage is turned off (ATOLL_DATASTORE_ENABLED=false), and the chart creates no storage namespace, Role or policies. Existing stores and the namespace are kept (the namespace has helm.sh/resource-policy: keep); delete them by hand once they are empty.