Redis for Laravel on a private network, over TLS

How a serverless Laravel app gets a Scaleway Managed Database for Redis on a Private Network, over TLS, and what to keep in it on serverless containers.

In this post
  1. How does a serverless Laravel app use Redis on Scaleway?
  2. Add the cache
  3. The Private Network
  4. The variables Brewless sets
  5. What to keep in Redis on serverless
  6. Summary

A serverless Laravel app keeps its cache in the database by default, and for many apps that is fine. Once the cache gets busy, or you would rather let a serverless database sleep between visits, Redis is the usual next step. On Scaleway that is a Managed Database for Redis, and the safe way to reach it is over a Private Network, with TLS.

This post shows how to add one to a Laravel environment with Brewless, what Brewless sets up, and what belongs in Redis when your containers come and go.

How does a serverless Laravel app use Redis on Scaleway?

Through cache in brewless.yml. Brewless gives the environment a Scaleway Managed Database for Redis, puts the containers on the project's Private Network, and sets CACHE_STORE=redis and the REDIS_* variables. With brewless/laravel 0.8 or later, the connection speaks TLS and trusts only the certificate of that cache.

Add the cache

brewless.yml
environments:
  production:
    region: fr-par
    database: shop-main
    cache: shop-cache
  staging:
    region: fr-par
    database: shop-staging
    cache:
      name: shop-staging-cache
      size: RED1-XS

On the next deploy, Brewless looks for a cache of that name in the region. One that stands is used as it is. Otherwise it makes one with the size you gave and the newest version of Redis Scaleway offers.

Key What it does
cache: <name> Uses or makes a cache of that name, size RED1-micro
cache.name The name of the cache at Scaleway
cache.size The node type of a new cache: RED1-micro, RED1-2XS, RED1-XS, RED1-S, RED1-M, RED1-L or RED1-XL
cache: false Lets the cache go from the environment; it keeps running at Scaleway

Run brewless plan production first to see what the file asks for next to what stands.

Warning

Scaleway bills a cache by its size, for every hour it exists. A cache does not sleep. cache: false takes it out of the environment, but it keeps running, and costing, until you remove it in your Scaleway console.

A cache that stands is not swapped for another name or size from brewless.yml; a deploy that asks for that is refused. Scaleway offers Managed Database for Redis in Paris, Amsterdam and Warsaw, not in Milan.

The Private Network

A cache is reached over the project's Private Network only, so cache brings network: private along. You can also set it on its own:

brewless.yml
environments:
  production:
    network: private

What that does:

  • Each Scaleway project gets one Private Network per region, called brewless, made the first time an environment asks for it. Every environment of the project that says network: private joins it. Scaleway does not charge for a Private Network.
  • The web, release and worker containers go on it. For an environment that runs already, Scaleway deploys them again for that.
  • A Managed Database the environment uses gets a private endpoint on the network, and DB_HOST and DB_PORT move to it unless you set them yourself. Its public endpoint stays; remove it in your Scaleway console once nothing uses it.
  • A Serverless SQL Database cannot join a network. It stays as it is, reached over the internet with its key, next to a cache on the network.

An environment does not leave the network from brewless.yml: network: public for an environment on it is refused. A container or database that is on another Private Network already is not moved; setting up stops and says which. See A Private Network.

The variables Brewless sets

Variable Value
CACHE_STORE redis
REDIS_CLIENT phpredis
REDIS_HOST, REDIS_PORT The cache's endpoint on the Private Network
REDIS_USERNAME, REDIS_PASSWORD The user brewless of a cache Brewless made
BREWLESS_REDIS_CA The certificate of the cache's cluster

For a cache Brewless makes, the password of the brewless user goes into your own Secret Manager, as <application>-<environment>-cache-key, before the cache is made. Brewless never keeps it. A cache that stood there already has users of your own making, so REDIS_USERNAME and REDIS_PASSWORD are left for you to set with brewless env:push.

Laravel's default config/database.php reads these names. TLS is the one thing Laravel's default config does not set up from a variable. Require the package version that does:

composer require brewless/laravel:^0.8

With 0.8 or later, your redis connections speak TLS and trust the certificate in BREWLESS_REDIS_CA, and no other. A Private Network already keeps the traffic inside your project; TLS means the password and data are not readable on that network either.

Note

A variable change reaches the containers with the next deploy. Adding cache to an environment that runs puts the variables in the same deploy, as a new revision of the environment's variables.

What to keep in Redis on serverless

Serverless containers start and stop all day, and two of them never share memory or disk. Anything that has to be shared between requests goes to a store outside the container. Redis is a good fit for some of that, and not for all of it.

What Where Why
Cache Redis Brewless sets CACHE_STORE=redis for you
Locks (Cache::lock, withoutOverlapping, onOneServer) Redis Locks use the cache store, so they move with it
Sessions Redis, if you set SESSION_DRIVER=redis Fast, and takes a query off the database per request
Rate limiting Redis Uses the cache store
Jobs Scaleway Queues or the database Brewless's queue choices are sqs, database or none
Anything you cannot rebuild The database or a bucket A cache is for what you can work out again

Cache. Fragments, expensive queries and the answers of slow services. With the cache in Redis, a page that only reads from the cache does not touch the database.

Locks. Cache::lock(), the scheduler's withoutOverlapping() and onOneServer() all go through the cache store. On serverless, where several replicas can run the same code at once, those locks are what keep a task from running twice. In Redis they are shared by every container of the environment.

Sessions. Brewless leaves SESSION_DRIVER alone. Set it to redis when you want sessions there; on a serverless database that saves a query on every request. Keep in mind that a session in a cache lives only as long as the cache does.

Jobs. The worker of an environment is called by Scaleway Queues as soon as a job is put on it, or by a trigger every minute when jobs wait in the database. The cache is not one of those choices. See Queues and schedule.

Tip

If you moved to Redis so a Serverless SQL Database can sleep, check the rest of the app too. Jobs that wait in the database, or a schedule that runs every minute, keep it awake whatever the cache does. Read Serverless SQL or Managed PostgreSQL for Laravel.

Summary

  1. Add cache with a name, and a size if RED1-micro is too small, in Paris, Amsterdam or Warsaw.
  2. Accept that the environment joins the project's Private Network, and remove the public endpoint of a managed database yourself once nothing uses it.
  3. Require brewless/laravel 0.8 or later so the connection uses TLS.
  4. Keep the cache, locks and, if you want, sessions in Redis; keep jobs at Scaleway Queues or in the database.
  5. Remember that the cache bills every hour, and that cache: false does not remove it.

The full description is in A cache.

Frequently asked questions

How do I add Redis to a Laravel app on Brewless?

Add cache with a name under the environment in brewless.yml and deploy. Brewless uses a cache of that name in the region or makes one, puts the environment on the Private Network, and sets CACHE_STORE=redis and the REDIS_* variables.

Is the Redis cache reachable from the internet?

No. It is reached over the Private Network of your Scaleway project only, which nothing outside the project can reach, and the connection uses TLS on top of that.

Which Redis sizes can I choose?

Scaleway's node types from RED1-micro to RED1-XL, set with cache.size. Without a size a new cache gets RED1-micro. A cache that stands is not resized from brewless.yml; that is refused.

Does Brewless put Laravel sessions in Redis?

Brewless sets CACHE_STORE=redis only. Laravel can keep its sessions and locks in the same cache, but you choose that yourself, for example with SESSION_DRIVER=redis in your variables.

In which regions is Managed Database for Redis available?

Scaleway offers it in Paris, Amsterdam and Warsaw, not in Milan. An environment in Milan cannot have a cache from brewless.yml.

All posts Read this post as markdown

Try it on your own app

Brewless deploys your Laravel app to Scaleway and bunny.net, in your own accounts. We open access to Laravel teams in small batches.