A Redis sidecar whose consumer declares no services.redis.mem_limit
runs in a container that inherits the consumer's primary entity limit.
Since the lookup replaced the old filter, maxmemory followed that limit
and rose from 204 MiB to between 819 and 3276 MiB in 17 roles.
lookup('service_memory_mb', ..., provider=<role>) caps the result at
the same share of the provider's own limit when the application does
not declare one for that service. A declared limit is not capped, and a
container smaller than the provider keeps its own share. The Redis
sidecar passes provider='svc-db-redis': those 17 roles get 409 MiB, the
seven with a 256 MiB container stay at 204.
The lookup now rejects unknown options and a provider that is no role
or declares no limit for the service, so a misspelled option fails
instead of silently lifting the cap.
The memcached sidecar's literal -m 64 takes the same lookup and keeps
its value.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
6.3 KiB
Redis
Description
This Ansible role provides Redis in two interchangeable shapes, selected per consumer with the shared flag (mirroring svc-db-postgres):
- Central (
enabled: true,shared: true): a standalone, manager-pinned Redis stack that many roles share. Each consumer gets its own ACL user restricted to the key-prefix{entity}:*. - Embedded (
enabled: true,shared: false): a Redis sidecar rendered into the consumer's own compose stack viatemplates/service.yml.j2.
Overview
The central stack (templates/compose.yml.j2) runs redis:alpine with:
requirepassfor thedefault(admin) user, sourced from theREDIS_PASSWORDcredential.- AOF persistence for cached data.
- A
maxmemoryceiling derived from the servicemem_limitwith anallkeys-lrupolicy. - A bind on
127.0.0.1:6379plus the shared cross-stack overlay network for consumers.
Per-consumer provisioning (tasks/01_init.yml) runs with application_id=svc-db-redis and database_consumer_id=<consumer>; it resolves the consumer's username, password and key-prefix via lookup('engine', 'redis', <consumer>, ...) and reconciles an idempotent ACL SETUSER restricted to ~{entity}:*. The ACL users are recreated by the consumer's 01_init on every deploy, so a container restart that drops the in-memory ACL set is healed on the next run.
The embedded snippet (templates/service.yml.j2) keeps the previous single-host behaviour: an unauthenticated in-memory Redis attached to the consumer stack's default network. Its maxmemory is 80 % of the consumer's services.redis.mem_limit; a consumer that declares none gets 80 % of the limit its container inherits, at most 80 % of this role's own mem_limit.
Cosmos
The diagram places Redis in the Infinito.Nexus cosmos: the components it deploys (capabilities), the central services it consumes (dependencies), and its outward reach (federation and bridged external networks).
flowchart LR
subgraph deps [Dependencies]
dep_svc_bkp_volume_2_local["svc-bkp-volume-2-local 💻"]
dep_svc_net_tor["svc-net-tor 🐳🐝"]
end
subgraph role [svc-db-redis 🐳🐝]
svc_redis["redis"]
svc_tor["tor"]
svc_container_backup["container_backup"]
end
subgraph dependents [Dependents]
dpt_web_app_akaunting["web-app-akaunting 🐳🐝"]
dpt_web_app_baserow["web-app-baserow 🐳🐝"]
dpt_web_app_bookwyrm["web-app-bookwyrm 🐳🐝"]
dpt_web_app_decidim["web-app-decidim 🐳🐝"]
dpt_web_app_discourse["web-app-discourse 🐳🐝"]
dpt_web_app_erpnext["web-app-erpnext 🐳🐝"]
dpt_web_app_fider["web-app-fider 🐳🐝"]
dpt_web_app_flowise["web-app-flowise 🐳🐝"]
dpt_web_app_funkwhale["web-app-funkwhale 🐳🐝"]
dpt_web_app_gitea["web-app-gitea 🐳🐝"]
dpt_web_app_gitlab["web-app-gitlab 🐳🐝"]
dpt_web_app_magento["web-app-magento 🐳🐝"]
dpt_more["..."]
end
dep_svc_bkp_volume_2_local -- "1:1" --> svc_container_backup
dep_svc_net_tor -. "0..1" .-> svc_tor
svc_redis -- "1:1" --> dpt_more
svc_redis -. "0..1" .-> dpt_web_app_akaunting
svc_redis -. "0..1" .-> dpt_web_app_baserow
svc_redis -. "0..1" .-> dpt_web_app_bookwyrm
svc_redis -. "0..1" .-> dpt_web_app_decidim
svc_redis -. "0..1" .-> dpt_web_app_discourse
svc_redis -. "0..1" .-> dpt_web_app_erpnext
svc_redis -. "0..1" .-> dpt_web_app_fider
svc_redis -. "0..1" .-> dpt_web_app_flowise
svc_redis -. "0..1" .-> dpt_web_app_funkwhale
svc_redis -. "0..1" .-> dpt_web_app_gitea
svc_redis -. "0..1" .-> dpt_web_app_gitlab
svc_redis -. "0..1" .-> dpt_web_app_magento
Solid 1:1 edges are fixed relationships; dashed 0..1 edges are conditional (enabled only in matching deployments); red 0..0 edges are turned off in this role. Node markers show the role's deploy modes (💻 host, 🐳 compose, 🐝 swarm); ❌ marks a service that is explicitly turned off, and ⚙️ an Ansible role dependency declared in meta/main.yml.
Features
- Central or embedded selected per consumer via
services.redis.shared. - ACL isolation one Redis user per consumer, scoped to
{entity}:*keys. - Idempotent provisioning ACL users reconciled on every deploy via
ACL SETUSER. - Manager-pinned central on-disk state stays node-local (never on NFS) in swarm.
- Built-in healthcheck authenticated
redis-cli ping.
Quick Setup
Development
Clone, set up the workstation, and deploy Redis onto the local stack:
git clone https://github.com/infinito-nexus/core.git
cd core
make onboard
make compose-deploy mode=reinstall apps=svc-db-redis full_cycle=false
Production
Run the published image to provision the inventory and deploy Redis to a managed server (the mounted volume persists the inventory):
APP=svc-db-redis
HOST=<your-server>
DOMAIN=<your-domain>
TLS_MODE=self_signed
SSH_PUBLIC_KEY="<your-ssh-public-key>"
docker run --rm -it \
-v "$PWD/inventories:/etc/infinito.nexus/inventories" \
-e APP="$APP" -e HOST="$HOST" -e DOMAIN="$DOMAIN" -e TLS_MODE="$TLS_MODE" -e SSH_PUBLIC_KEY="$SSH_PUBLIC_KEY" \
ghcr.io/infinito-nexus/core/debian bash -c '
INVENTORY=/etc/infinito.nexus/inventories/production
infinito administration inventory provision "$INVENTORY" \
--inventory-file "$INVENTORY/devices.yml" \
--host "$HOST" \
--include "$APP" \
--vars "{\"TLS_MODE\": \"$TLS_MODE\", \"DOMAIN_PRIMARY\": \"$DOMAIN\", \"users\": {\"administrator\": {\"authorized_keys\": [\"$SSH_PUBLIC_KEY\"]}}}" &&
infinito administration deploy dedicated "$INVENTORY/devices.yml" \
--password-file "$INVENTORY/.password" \
--diff -vv'
Further Resources
Credits
Implemented by Kevin Veen-Birkenbach. Part of the Infinito.Nexus Project and maintained by Kevin Veen-Birkenbach. Licensed under the Infinito.Nexus Community License (Non-Commercial).