Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
2f7a103
add vagrant to test script
davidbeig Oct 16, 2025
f0d9789
add compose files
davidbeig Oct 16, 2025
8940ca0
add initial scripts
davidbeig Oct 16, 2025
fc2ca20
generate SECRET_KEY_BASE
davidbeig Oct 16, 2025
51f9238
add memory to Vagrant
davidbeig Oct 21, 2025
38fc814
add traefik domain and fix default decidim_image
davidbeig Oct 21, 2025
32e3f9b
add pull_policy always to worker
davidbeig Oct 21, 2025
e9d262e
add storage to handle volume in app if not bucket
davidbeig Oct 21, 2025
5181c5f
change how to handle repository path
davidbeig Oct 21, 2025
fe067ac
add migration execution on app entrypoint
davidbeig Oct 21, 2025
1e9a000
fix up script to handle local database and local storage
davidbeig Oct 21, 2025
e0b7bd5
change local database to generate user, password and database name
davidbeig Oct 21, 2025
ca858ad
add script to generate gemfiles
davidbeig Oct 23, 2025
f2955bd
add alpine versions for cache and db
davidbeig Oct 23, 2025
32009ec
generate vapid keys
davidbeig Oct 29, 2025
97c3ffb
make docker script exit after installing
davidbeig Oct 29, 2025
acc8327
pull decidim image when deciding version
davidbeig Oct 29, 2025
4035540
git clone repository to repository path
davidbeig Oct 29, 2025
e550ea6
fix on decidim version script
davidbeig Oct 29, 2025
be2ca79
change docker installation process
davidbeig Oct 29, 2025
174af9e
fix on variable assignment
davidbeig Oct 29, 2025
434d6ba
fix use of variable
davidbeig Oct 29, 2025
4917f61
add volumes for Gemfile.wrapper and Gemfile.local
davidbeig Oct 30, 2025
a47284b
read from /dev/tty
davidbeig Nov 13, 2025
c0168d1
check before deleting .env file
davidbeig Nov 24, 2025
1773cf8
ask before openning ports
davidbeig Nov 24, 2025
03553cd
fix parameters passed to docker compose
davidbeig Nov 24, 2025
dc42a99
don't exit on open_ports script
davidbeig Nov 24, 2025
5c15d5d
fix volumes on app.yml
davidbeig Nov 24, 2025
fa87b32
change bash errors
davidbeig Nov 24, 2025
4cad4c7
update traefik version
davidbeig Nov 24, 2025
4c2ca22
fix use of sidekiq_entrypoint
davidbeig Nov 24, 2025
7921196
fix on entrypoints paths
davidbeig Nov 24, 2025
6cc99b8
make scripts executable
davidbeig Nov 24, 2025
add55e3
make entrypoints execute bundle install
davidbeig Nov 24, 2025
2feb6f7
remove sudo from entrypoints
davidbeig Nov 24, 2025
a30dcb5
change database env variables
davidbeig Nov 24, 2025
9ddd38f
change password generated base
davidbeig Nov 24, 2025
0adb8ed
update composes
davidbeig Nov 24, 2025
a144c41
fix commands
davidbeig Nov 24, 2025
1408e79
fix reference passed to exec
davidbeig Nov 24, 2025
87796f2
remove network mode
davidbeig Nov 24, 2025
59c7f59
move scripts and add action to build release zip
davidbeig Nov 26, 2025
74c7c9c
move scripts to install folder
davidbeig Nov 26, 2025
907f171
add log debug to traefik
davidbeig Nov 27, 2025
fb9d9fa
exit if not a correct distribution
davidbeig Nov 27, 2025
b1e12ff
add container name
davidbeig Nov 27, 2025
94a9f10
add keys for s3-compatible buckets
davidbeig Nov 27, 2025
5c206ee
script to create system admin
davidbeig Nov 27, 2025
4fdfe3e
add redis_url env
davidbeig Nov 27, 2025
661dacb
remove env for system admin
davidbeig Nov 27, 2025
783c6fd
unify composes
davidbeig Nov 27, 2025
cc10b73
some fixes
davidbeig Nov 27, 2025
c480654
add certificates and make worker wait for app first
davidbeig Nov 28, 2025
fd55517
fixes on aws variables
davidbeig Nov 28, 2025
6cd940b
remove wait for healthy
davidbeig Dec 3, 2025
df615ea
add interactivity to some missing commands
davidbeig Dec 3, 2025
5d3a4f7
update README
davidbeig Dec 9, 2025
a7d459c
clean up a bit
davidbeig Dec 9, 2025
2100eb9
add sidekiq config
davidbeig Dec 11, 2025
f828cdb
add some readme documentation
davidbeig Dec 11, 2025
9a4fc1d
shell linting
davidbeig Dec 11, 2025
553c013
remove vagrantfile
davidbeig Dec 16, 2025
a65ab0b
improve messages to choose decidim version
davidbeig Dec 16, 2025
5ec5764
add more context to vapid and export vars
davidbeig Dec 16, 2025
712467f
change check of decidim running to create system admin
davidbeig Dec 16, 2025
6750e1c
Improve messages and flow of docker installation
davidbeig Dec 16, 2025
dccb70b
change messages of up.sh
davidbeig Dec 16, 2025
26ebc1f
add new messages and bash fixes
davidbeig Dec 16, 2025
e581b92
refactor and add maps envs
davidbeig Dec 16, 2025
b23a5ad
remove env var
davidbeig Dec 16, 2025
5344a7b
shellcheck fixes
davidbeig Dec 16, 2025
d83e3c9
shellcheck 1091
davidbeig Dec 16, 2025
3931590
disable sc1091
davidbeig Dec 16, 2025
96ac72f
fixes on certs and health_check
davidbeig Dec 18, 2025
7aa5159
update release zip url
davidbeig Dec 18, 2025
5fa1536
improve and fix zip download
davidbeig Dec 18, 2025
75b462c
force overrite of extracted files
davidbeig Dec 22, 2025
94513a0
add minor improvements
davidbeig Dec 22, 2025
4a665e0
remove pull_policy
davidbeig Dec 22, 2025
9e7b7b8
open ports by default
davidbeig Dec 22, 2025
4e8a722
remove option to change decidim version, only install latest
davidbeig Dec 22, 2025
fc3ed3a
automatically create system password
davidbeig Dec 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/build_install_folder.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Build Deployment Zip

on:
push:
branches:
- main
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Create deployment ZIP
run: |
zip -r deploy_bundle.zip \
scripts/ \

- name: Release
uses: softprops/action-gh-release@v2
with:
files: deploy_bundle.zip
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,69 @@ sudo chown -R $(whoami): ${APP_NAME}
```

From here on you can follow the steps on the [Getting Started](https://docs.decidim.org/en/install/) guide.

## Using a production deploy script

We've been working on a script that you can use to have a fully functional, production ready decidim instance.

```
curl -fsSL https://decidim.org/install | bash
```

It will install the necessary tools to make decidim work on your server.

- Docker
- unzip
- UFW

The application will be hosted in the `/opt/decidim` directory by default, even though you can change it with `REPOSITOIRY_PATH`

## App - Main Decidim Web Application
The app itself will be the container with the base image you decide (By default is the latest Decidim version: `decidim/decidim:latest`). You can change it with the `DECIDIM_IMAGE` environment variable.

This is the front-end web process users access in the browser.

## Worker
The worker will be the one responsible for all the background jobs that the application needs to run.

## Cache
The app needs a cache server. This will be a `redis:8-alpine` instance. This cache will be used both by the app and the worker.

## Database

The application needs a database to run. Through the installation process you will be asked if you have an already working database, if not, you will have a postgres container with all the schema and migrations run (It will be a `postgres:17-alpine`)

## Configuration

To configure the application you will have to answer some questions that will, at the end, generate a `.env` file.

### Environment Variables Reference

To see the full list of Decidim Environment Variables, and that you can add to your generated `.env` file, you can take a look at the oficial [documentation](https://docs.decidim.org/en/develop/configure/environment_variables)

| Variable | Default | Used In | Description |
|----------|---------|---------|-------------|
| **BUNDLE_GEMFILE** | `Gemfile.wrapper` | app, worker | Selects which Gemfile the container should use. |
| **DECIDIM_IMAGE** | `decidim/decidim:latest` | app, worker | Overrides the Decidim Docker image version. |
| **DECIDIM_DOMAIN** | — | app, traefik | Domain for HTTPS routing and URL generation. |
| **SECRET_KEY_BASE** | — | app, worker | Rails secret key used for sessions and cookies. |
| **DATABASE_NAME** | `decidim` | db | PostgreSQL database name. |
| **DATABASE_USER** | `decidim` | db | PostgreSQL username. |
| **DATABASE_HOST** | `db` | app, worker | Hostname of your PostgreSQL instance. |
| **DATABASE_PASSWORD** | `decidim` | db | PostgreSQL user password. |
| **DATABASE_URL** | — | app, worker | Full PostgreSQL connection URL (overrides other DB vars). |
| **SMTP_USERNAME** | — | app, worker | Username for SMTP authentication. |
| **SMTP_PASSWORD** | — | app, worker | Password for SMTP authentication. |
| **SMTP_ADDRESS** | — | app, worker | SMTP server hostname. |
| **SMTP_DOMAIN** | — | app, worker | SMTP domain. |
| **SMTP_PORT** | — | app, worker | SMTP port. |
| **SMTP_STARTTLS_AUTO** | `true` | app | Enables STARTTLS automatically. |
| **REDIS_URL** | `redis://decidim_cache:6379/0` | app | Redis URL for cache + sessions. |
| **VAPID_PUBLIC_KEY** | — | app | Web Push public key for browser notifications. |
| **VAPID_PRIVATE_KEY** | — | app | Web Push private key (keep secret). |
| **CERTIFICATE_EMAIL** | — | traefik | Email used by Let's Encrypt for certificate issues/renewals. |
| **WEB_CONCURRENCY** | `2` | app | Puma concurrency setting. |
| **LOG_LEVEL** | `info` | app | Log level for Rails. |
| **DECIDIM_FORCE_SSL** | `false` | app | Enforce HTTPS-only traffic. |
| **MAPS_API_KEY** | — | app | API key for maps provider. |
| **MAPS_PROVIDER** | `here` | app | Selects map provider (here, mapbox, google, etc). |
16 changes: 16 additions & 0 deletions install/config/sidekiq.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
:concurrency: <%= ENV.fetch("SIDEKIQ_CONCURRENCY", 5) %>
:queues:
- [mailers, 4]
- [vote_reminder, 2]
- [reminders, 2]
- [default, 2]
- [newsletter, 2]
- [newsletters_opt_in, 2]
- [conference_diplomas, 2]
- [events, 2]
- [translations, 2]
- [user_report, 2]
- [block_user, 2]
- [metrics, 1]
- [exports, 1]
- [close_meeting_reminder, 1]
273 changes: 273 additions & 0 deletions install/dependencies/build_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
#!/bin/bash
set -e
set -u
set -o pipefail

BUILD_ENV_PATH="$REPOSITORY_PATH/.env"

if [ -z "${REPOSITORY_PATH:-}" ]; then
echo "❌ Error: REPOSITORY_PATH is not set"
exit 1
fi

echo "───────────────────────────────────────────────"
echo "🔧 Environment Configuration Phase"
echo " We'll now collect all the information needed to configure your Decidim instance."
echo " All responses will be saved in a .env file that you can edit later."
echo
echo "📝 Information we'll collect:"
echo " • Instance details (name, domain)"
echo " • Database settings (local PostgreSQL or external)"
echo " • Email configuration (SMTP server)"
echo " • File storage (local filesystem or S3 bucket)"
echo " • Security keys (auto-generated)"
echo
echo "💡 Don't worry if you don't have all the details ready!"
echo " You can always modify the .env file after installation."
echo
echo "Press Enter to continue..."
read -r </dev/tty

echo "───────────────────────────────────────────────"
echo "📦 Now we need to get some information about the instance you are building."
echo
echo "💡 The application name will be displayed throughout the interface"
echo " and used in email subjects. Make it descriptive!"
echo
read -r -p "What is the name of your organization? (For example: Decidim Barcelona)" DECIDIM_APPLICATION_NAME </dev/tty
echo "✅ The name of the instance is: $DECIDIM_APPLICATION_NAME"
echo
echo "💡 This is the domain where users will access your Decidim instance."
echo " Make sure you have DNS configured for this domain."
echo " Example: decidim.example.org"
echo
read -r -p "domain: " DECIDIM_DOMAIN </dev/tty
echo "✅ Your instance will be accessible at: https://$DECIDIM_DOMAIN"

echo "───────────────────────────────────────────────"
echo "🗄️ Database Configuration"
echo " We need to set up your Decidim database."
echo " 💡 You can use our built-in PostgreSQL database (recommended for beginners)"
echo " or connect to an existing external database."
echo
read -r -p "Do you have an external database already set up? [y/N] " yn </dev/tty
yn=${yn:-N}

build_local_database() {
echo "🏗️ Creating local database configuration..."

POSTGRES_USER="user_$(openssl rand -hex 3)"
POSTGRES_PASSWORD="$(openssl rand -hex 18)"
POSTGRES_DB="db_$(openssl rand -hex 3)"

DATABASE_USER=$POSTGRES_USER
DATABASE_PASSWORD=$POSTGRES_PASSWORD
DATABASE_NAME=$POSTGRES_DB
DATABASE_HOST="db"

COMPOSE_PROFILES="db"

echo "✅ Local database will be created with these credentials:"
echo " Database: $DATABASE_NAME"
echo " User: $DATABASE_USER"
echo " Host: $DATABASE_HOST"
echo " 💡 Password will be securely stored in .env file"
}

build_external_database() {
echo "📋 External Database Configuration"
echo " Please provide your external database details:"
echo " 💡 Make sure your database server allows connections from this machine"
echo

while [ -z "${DATABASE_NAME:-}" ]; do
read -r -p "Name of the database: " DATABASE_NAME </dev/tty
if [ -z "$DATABASE_NAME" ]; then
echo "❌ Database name cannot be empty"
fi
done

while [ -z "${DATABASE_USER:-}" ]; do
read -r -p "Database user: " DATABASE_USER </dev/tty
if [ -z "$DATABASE_USER" ]; then
echo "❌ Database user cannot be empty"
fi
done

while [ -z "${DATABASE_HOST:-}" ]; do
read -r -p "Database host (ip or domain): " DATABASE_HOST </dev/tty
if [ -z "$DATABASE_HOST" ]; then
echo "❌ Database host cannot be empty"
fi
done

while [ -z "${DATABASE_PASSWORD:-}" ]; do
read -r -p "Database password: " DATABASE_PASSWORD </dev/tty
if [ -z "$DATABASE_PASSWORD" ]; then
echo "❌ Database password cannot be empty"
fi
done

echo "✅ External database configured: postgres://$DATABASE_USER:***@$DATABASE_HOST/$DATABASE_NAME"
}

case $yn in
[Yy]*)
EXTERNAL_DATABASE=true
build_external_database
;;
[Nn]*)
EXTERNAL_DATABASE=false
build_local_database
;;
esac

export EXTERNAL_DATABASE

DATABASE_URL="postgres://$DATABASE_USER:$DATABASE_PASSWORD@$DATABASE_HOST/$DATABASE_NAME"

echo "───────────────────────────────────────────────"
echo "📧 Email Configuration (SMTP)"
echo " Decidim needs to send emails for notifications, user registration, etc."
echo " 💡 You'll need an SMTP server. "
echo " 🔗 Documentation: https://docs.decidim.org/en/develop/services/smtp.html"
echo
read -r -p "SMTP_USERNAME: " SMTP_USERNAME </dev/tty
read -r -p "SMTP_PASSWORD: " SMTP_PASSWORD </dev/tty
read -r -p "SMTP_ADDRESS (e.g., smtp.gmail.com): " SMTP_ADDRESS </dev/tty
read -r -p "SMTP_DOMAIN (usually same as your domain): " SMTP_DOMAIN </dev/tty
read -r -p "SMTP_PORT (587 for TLS - default, 465 for SSL): " SMTP_PORT </dev/tty
SMTP_PORT=${SMTP_PORT:-587}

echo "───────────────────────────────────────────────"
echo "📁 File Storage Configuration"
echo " Decidim stores user uploads, images, and documents."
echo " 💡 For production, we recommend S3-compatible storage."
echo " But we also support local storage."
echo
read -r -p "Do you have an external S3-compatible bucket already set up? [y/N] " yn </dev/tty
yn=${yn:-N}

get_storage_keys() {
echo "🗂️ S3-compatible Storage Configuration"
echo " Please provide your S3 storage details:"
echo " 💡 Supported providers: AWS S3, Cloudflare R2, etc."
echo " 🔗 Documentation: https://docs.decidim.org/en/develop/services/activestorage"
echo
read -r -p "Access Key ID: " AWS_ACCESS_KEY_ID </dev/tty
read -r -p "Secret Access Key: " AWS_SECRET_ACCESS_KEY </dev/tty
read -r -p "Name of the bucket: " AWS_BUCKET </dev/tty
read -r -p "Region of the bucket (Defaults to auto): " AWS_REGION </dev/tty
read -r -p "Endpoint (required for non-AWS S3): " AWS_ENDPOINT </dev/tty

AWS_REGION=${AWS_REGION:-auto}

echo "✅ S3 storage configured for bucket: $AWS_BUCKET"
}

case "$yn" in
[Yy]*)
get_storage_keys
;;
*)
STORAGE="local"
;;
esac

echo "───────────────────────────────────────────────"
echo "🔐 Security Configuration"
echo " Generating VAPID keys for secure push notifications..."
# shellcheck disable=SC1091
source "./dependencies/generate_vapid_keys.sh"

echo "───────────────────────────────────────────────"
echo "Maps and Geocoding Configuration"
echo " In order for the maps inside the application to work, we have to configure the service"
echo " 🔗 Documentation: https://docs.decidim.org/en/develop/services/maps"
echo
echo " Currently, this installation process only handles HERE Maps."
echo " You will need to provide the API KEY provided by HERE."
echo " This will be saved in the .env file, but you'll be always able to change it."
read -r -p "HERE API KEY: " MAPS_API_KEY </dev/tty
MAPS_API_PROVIDER=${MAPS_API_PROIVDER=-here}

echo "───────────────────────────────────────────────"
echo "Now we are going to create the .env file."

if [ -f "$BUILD_ENV_PATH" ]; then
echo "❌ Failing: .env file already exists."
read -r -p "Do you want to delete the .env file and create a new one? You can make a back-up of it before answering. [Y/n]" yn </dev/tty
yn=${yn:-Y}

case $yn in
[Yy]*)
echo "Deleting .env file."
rm "$BUILD_ENV_PATH"
;;
[Nn]*)
echo "Can't continue without a new .env file"
exit 1
;;
esac
fi

# Variable to handle the let's encrypt email.
CERTIFICATE_EMAIL="${CERTIFICATE_EMAIL:-postmaster@${DECIDIM_DOMAIN}}"

echo "───────────────────────────────────────────────"
echo "🎯 Final Configuration Summary:"
echo " Instance Name: $DECIDIM_APPLICATION_NAME"
echo " Domain: https://$DECIDIM_DOMAIN"
echo " Database: $DATABASE_NAME (host: $DATABASE_HOST)"
echo " Storage: $([ "$STORAGE" = 'local' ] && echo 'Local filesystem' || echo 'S3-compatible bucket')"
echo " Certificate Email: $CERTIFICATE_EMAIL"
echo
echo "💡 All configuration will be saved to .env file"
echo " You can modify these values later if needed."
echo
echo "✅ Writing the environment variables to .env file..."
cat >"$BUILD_ENV_PATH" <<EOF
BUNDLE_GEMFILE="Gemfile.wrapper"
DECIDIM_IMAGE=$DECIDIM_IMAGE
DECIDIM_APPLICATION_NAME="$DECIDIM_APPLICATION_NAME"
DECIDIM_DOMAIN="$DECIDIM_DOMAIN"

SECRET_KEY_BASE=$(openssl rand -hex 64)

DATABASE_NAME="$DATABASE_NAME"
DATABASE_USER="$DATABASE_USER"
DATABASE_HOST="$DATABASE_HOST"
DATABASE_PASSWORD="$DATABASE_PASSWORD"
DATABASE_URL="$DATABASE_URL"

SMTP_USERNAME="$SMTP_USERNAME"
SMTP_PASSWORD="$SMTP_PASSWORD"
SMTP_ADDRESS="$SMTP_ADDRESS"
SMTP_DOMAIN="$SMTP_DOMAIN"
SMTP_PORT="$SMTP_PORT"

MAPS_API_PROVIDER="$MAPS_API_PROVIDER"
MAPS_API_KEY="$MAPS_API_KEY"

REDIS_URL="redis://decidim_cache:6379"

VAPID_PUBLIC_KEY="$VAPID_PUBLIC_KEY"
VAPID_PRIVATE_KEY="$VAPID_PRIVATE_KEY"

CERTIFICATE_EMAIL="$CERTIFICATE_EMAIL"

COMPOSE_PROFILES=$COMPOSE_PROFILES

EOF

if [ "$STORAGE" != 'local' ]; then
cat >>"$BUILD_ENV_PATH" <<EOF
AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID"
AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY"
AWS_BUCKET="$AWS_BUCKET"
AWS_REGION="$AWS_REGION"
AWS_ENDPOINT="$AWS_ENDPOINT"
EOF
fi

echo "✅ All environment variables saved to $BUILD_ENV_PATH successfully!"
Loading