How does Voca deploy a new Decidim?
Voca needs to deploy a decidim in less than 2minutes. But the deployment process takes up to 16min in the most complicated case. Voca reduces the time of installation by preparing a set of empty decidim instance, we call this parking.
So Voca uses a parking system to always have available instances. Once a user want a new decidim, he creates an instance, that will be paired to parked environment. An instance keeps user’s settings, a parked environment keeps informations about the Jelastic infrastructure.
What do we park?
A standard infrastructure, ready for scale
Even for the most basic installation, we are ready to scale, horizontally and vertically. To do this, we setup Docker containers in jelastic to have:
- A redis database
- A memcached database
- A nginx
- A decidim server, with our special sauce
- A internal decidim API server.
- A safe storage node
Decidim docker image for Voca
We leverage a docker image for voca usage. This includes:
- specific entrypoint and hooks for jelastic infrastructures, to ensure UNIX permissions are right (shared volume storage can have have some problems, depending on starting order)
- a gem
voca
with:- a new process,
gruf
that exposes an internal Decidim API throughgRPC
protocol. - a middleware that will allow to run decidim with dynamic configuration (normally currency is setted through environnement variables). So here we can change some values dynamically.
- a new process,
Voca DB models: Environment and instance
In the Strapi backend, we define two important models:
- api::decidim.environment stores information about the Jelastic environment. You will find attributes like:
envName
The uniq name of the Jelastic environment, use to know where the environment is installed.subdomain
The subdomain used for routing
- api::decidim.instance stores the links between environments, workspaces, creators, and some non-Decidim data like:
smtp_credentials
the credentials the users wants to use in their decidimcustom_domain
The URL decidim will usesubdomain
the default subdomain of the instanceisPaused
if the user wants to pause it’s instance- …. and all the others settings are directly sync with the decidim instance through RPC
Parking process
Every time a Voca user wants to create a Decidim instance, we check the number of parked instances. If the number is below a limit (defined as MAX_PARKED_ENV
environment value), we enqueue as many parking processes as needed.
When we tell jelastic to install a new parked instance, we send to jelastic a manifest containing infrastructure definition, and some scripts:
- Setup the nodes
cp
: The Decidim images with thesupervisord
process manager that will startpuma
,sidekiq
,nginx
, and agruf
process.sql
: A Postgres image, always inalpine
. The credentials are defined in environment values.nosql
: A Redis image, always inalpine
, running in AOF (Append Only Mode). The credentials are set up in theCMD
command. This is done to enqueue jobs.cache
: A Memcache image to handle Decidim cache.storage
: Ajelastic/storage
image optimized to store data. (see Volumes Mapping section).
- Populate volumes
- Transfert to the storage nodes the directories needed by decidim
- public folder
- config folder
- storage folder
- log folder
- Check that the decidim
rpc
andcp
have the same volumes than storage during the install process.
- Transfert to the storage nodes the directories needed by decidim
- Prepare instance
- Run migrations
- Install additional modules (decidim awesome, decidim term customizer).
- Compile assets once.
- Backups and Log observability
- Set up
restic
for backup management in thesql
andstorage
groups. The Voca-Decidim images already haverestic
installed. - Link log files for Jelastic to be able to display them in the log sidebar.
- Set up
- We are done.
This installation manifest will also install a hook on before stop, to be sure the instance goes in stop mode with:
- The assets are precompiled
- The migrations are done
- The UNIX permissions of shared folders are right
Volumes Mapping
We use a storage node to store all the data used by other containers of the environment, to let containers be stateless. All the environment’s volumes defines storage node as volume destination.
See parking process in action
To see and understand the parking process, you can:
- Access your strapi administration
http://<admin>/admin
- Create a new environment
- Access your jobs dashboard
http://<admin>/_jobs
. Credentials are defined as environments:BULLMQ_USERNAME
andBULLMQ_PASSWORD
- See your Jelastic dashboard in action
Jelastic Manifests
We use several Jelastic Manifest (https://docs.cloudscripting.com) to run deployment and other actions. All the jelastic manifests are present in the voca-system
mono-repo. They are located in the contrib/jelastic-manifests/scripts
directory.
park.yml
Manifest to deploy a new decidim and park it.control.yml
Start or stop an environmentrestart.yml
Restart decidim application nodes (cp
andrpc
nodeGroup).
Debug a manifest script
To debug or test your manifest script, you have two ways:
- run an import through jelastic UI. better to see actions in processes and debug a problem that happens while the manifest is applied
- call the
jelasticClient
from a strapi console. Better to understand returns values from jelastic.
With an import through Jelastic UI:



From a strapi console
cd $ROOT && PORT=1330 yarn strapi console
# Wait for console to start
await strapi.service("api::decidim.infa").call({envName: `test-${+new Date()}`}).install("https://git.octree.ch/decidim/vocacity/system/-/raw/main/contrib/jelastic-manifests/scripts
/park.yml",{IMAGE_REGISTRY: "git.octree.c
h:4567",IMAGE_PATH: "decidim/vocacity/system/decidim-0.26:latest",IMAGE_USERNAME: "tk",IMAGE_PASSWORD: "my-token-password"})
View the Logs
Your script can takes several minutes to execute a manifest. You can see the jelastic logs from the Import button, JPS tab, and “View Log” button.

References
- Jelastic Manifest for parking
- Jelastic Manifest for post parking
- Memcache configuration with Rails
- Restic Environment Variables
- Memcached Alpine image
- Redis Alpine image
- Postgres Alpine image
- Storage Alpine image
Install process (Install)
The install process is the process of binding a parked instance to a live environment. The process takes inputs from the Voca users and works on an already prepared infrastructure.
Here is the standard process to install a vanilla template:
- Pick up a parked environment. If none are available, enqueue parked processes and retry later.
- Start the selected environment.
- Connect to the Decidim private API
- Decidim environment open a rpc server in the nodeGroup=rpc, to expose a private API. The strapi backend will connect to it to be able to communicate.
- Seed an administrator with the credentials generated by the Strapi backend.
- Define settings like name, locales, currencies, timezones through the
SetSettings
API call. - Start the server and wait for it to be up.
- Configure the Traefik router to the subdomain chosen by the Voca user.
- Add a
.yml
file in the Traefik configuration with the correct local IPv4 for the Voca subdomain. The yml file is generated from a template (seecontrib/jelastic-manifests/templates/traefik-decidim.yml
)
- Add a
- We are done, an email is sent.
Templates: vanilla and non-vanilla
Templates are decidim instances that have been backuped in order to seed decidim instance. A seed will contains:
- Custom gems
- Custom configurations
A vanilla template is a raw-decidim, with a fresh install and nothing but the essentials modules installed: decidim_awesome, decidim_term_customizer and decidim.
Install non-vanilla templates
The process to install a non-vanilla templat****e:
- Pick up a parked environment. If there is none available, enqueue parked processes, and retry later.
- Start the selected environment
- Restore the backup from the template (database, files, and configurations)
- Connect to through the
rpc
channel exposed by thecp
'sgruf
process. - [… same process as vanilla-install]