Skip to content

EPIC: install.sh improvements #131

Description

@andreslucena

I'm on the review process for #119

As we've delayed a lot of months for this review (basically, we wanted to have full focus in v0.32.0 release process), currently on the Association don't have resources for contracting PokeCode for these changes, so the idea is to try to merge the PR as-is, and do the next set of changes on our own.

Blockers

traefik-1  | 2026-07-14T11:13:05Z DBG log/log.go:244 > http: TLS handshake error from 85.85.166.206:33212: remote error: tls: bad certificate
traefik-1  | 2026-07-14T11:13:33Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "decidim-docker.test.decidim.org"
traefik-1  | 2026-07-14T11:13:33Z DBG log/log.go:244 > http: TLS handshake error from 85.85.166.206:35022: remote error: tls: bad certificate
traefik-1  | 2026-07-14T11:13:33Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "decidim-docker.test.decidim.org"
traefik-1  | 2026-07-14T11:13:33Z DBG log/log.go:244 > http: TLS handshake error from 85.85.166.206:35036: remote error: tls: bad certificate
traefik-1  | 2026-07-14T11:13:36Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: ""
Error response from daemon: No such container: decidim
Waiting for Rails server to start...

Next tasks

  • Checksum every file.
    This will generate extra-security on the download of the shell script and the files it uses, giving the final user more security.
  • Add health capabilities to the containers.
  • Migrate to .tar.gz instead of .zip for the deployment file: https://github.com/decidim/docker/blob/feat%2Fdecidim_install/.github/workflows/build_install_folder.yml. TGZ is the GNU/Linux native for compressing files. It is installed by default in most images/distributions, meanwhile zip is an extra package that we need to document/explain the documentation. As a quick example:
$ docker run -it ubuntu /bin/bash
root@d35055f0806b:/#
root@d35055f0806b:/# zip
bash: zip: command not found
root@d35055f0806b:/# tar
tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options
Try 'tar --help' or 'tar --usage' for more information.
  • On a first clean run, I got this message:
🔄 Docker installation completed!
📋 Next steps:
   1. Log out and log back in, OR run: 'newgrp docker'
   2. Re-run this installation script

I'd expect that this be automated too (the newgrp docker and running again)
Related to this, having a manual command that needs to be run also means that it can fail:

root@dev-decidimdocker:/# newgrp docker
bash: newgrp: command not found

(On a clean LXC Ubuntu 26.04 installation)

  • I see too much text and things that I don't know if I should do anything. For instance:
To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:

    dockerd-rootless-setuptool.sh install

Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.


To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/

WARNING: Access to the remote API on a privileged Docker daemon is equivalent
         to root access on the host. Refer to the 'Docker daemon attack surface'
         documentation for details: https://docs.docker.com/go/attack-surface/

This text should be behind a verbose or debug flag, so we don't give confusing technical messages to implementers

  • Clarify where the docker-compose.yml is on. It should give the absolute path
If you want, later on you can modify the 'docker-compose.yml' to change the Decidim version.
  • Be consistent in the formula used for asking feedback:
    for the image, it accepts with enter key
    for the ports, it asks for Y/n

  • Fix typo at UFW nos intalled. We are going to install it to allow openning ports 80 and 443 on this machine.

  • Integrate a linter for bash in the CI pipeline for this repository (like https://www.shellcheck.net/)

  • Clean-up the file tree in /opt/decidim

Current:

/opt/decidim/
├── .env
├── config/
│   ├── schedule.yml
│   └── sidekiq.yml
├── dependencies/
│   ├── build_env.sh
│   ├── check_docker.sh
│   ├── create_system_admin.sh
│   ├── decidim_version.sh
│   ├── generate_gemfile.sh
│   ├── generate_vapid_keys.sh
│   ├── open_ports.sh
│   └── os_version.sh
├── docker-compose.yml
├── Gemfile.local
├── Gemfile.wrapper
├── install.sh
├── jobs/
│   └── invoke_rake_task_job.rb
├── README.md
├── scripts/
│   ├── entrypoint.sh
│   └── sidekiq_entrypoint.sh
└── up.sh

It is difficult to have a good understanding of where do things should belong

Proposed (linuxserver.io style):

/opt/decidim/
├── .env
├── docker-compose.yml
├── Gemfile.local
├── Gemfile.wrapper
├── install.sh
├── up.sh
├── README.md
├── root/
│   ├── defaults/
│   │   ├── schedule.yml
│   │   └── sidekiq.yml
│   └── jobs/
│       └── invoke_rake_task_job.rb
└── scripts/
    ├── entrypoint.sh
    ├── sidekiq_entrypoint.sh
    └── install/
        ├── build_env.sh
        ├── check_docker.sh
        ├── create_system_admin.sh
        ├── decidim_version.sh
        ├── generate_gemfile.sh
        ├── generate_vapid_keys.sh
        ├── open_ports.sh
        └── os_version.sh

Alternative

/opt/decidim/
├── docker-compose.yml
├── .env                          # ← only secrets file
├── install.sh
├── README.md
│
├── container/                    # Mounted into the container
│   ├── Gemfile.local
│   ├── Gemfile.wrapper
│   ├── entrypoint.sh
│   ├── sidekiq_entrypoint.sh
│   ├── config/
│   │   ├── sidekiq.yml
│   │   └── schedule.yml
│   └── app/jobs/
│       └── invoke_rake_task_job.rb
│
└── setup/                        # Host-only scripts
    ├── up.sh
    ├── build_env.sh
    ├── check_docker.sh
    ├── create_system_admin.sh
    ├── decidim_version.sh
    ├── generate_gemfile.sh
    ├── generate_vapid_keys.sh
    ├── open_ports.sh
    └── os_version.sh

Question:

The dependencies/ directory is actually necessary post-installation? Or it can/should be in /tmp/decidim-docker-files/dependencies/?

  • Remove license header from install/install.sh. We have a pending task of migrating to standard SPDX headers
  • Clean-up old images and README:
  1. "Image naming has changed recently." and " Biggest naming change" are from 6 years ago
  2. Leave only decidim hello world example + production one-liner with a link to the official documentation
  3. Deprecate (with a big warning) the images decidim-generator, decidim-test, and decidim-dev
  4. Schedule for full removal at January 2028
A. Recommended: installation script

B. Manual installation
  • Add binstubs support

/opt/decidim/bin/rails would be a wrapper for docker compose run -it app bin/rails or similar

  • Consistency between the questiosn:
What is the name of your organization? (For example: Decidim Barcelona) Decidim Docker Dev
✅ The name of the instance is: Decidim Docker Dev

💡 This is the domain where users will access your Decidim instance.
   Make sure you have DNS configured for this domain.
   Example: decidim.example.org

domain: decidim-docker.test.decidim.org
✅ Your instance will be accessible at: https://decidim-docker.test.decidim.org
───────────────────────────────────────────────
🗄  Database Configuration
   We need to set up your Decidim database.
   💡 You can use our built-in PostgreSQL database (recommended for beginners).
      or connect to an existing external database.

Do you have an external database already set up? [y/N]

Instead of just domain:, it should be

What is the domain name? (For example: decidim.example.org)

It should also have a ❓ emoji to make it clear every-time we're waiting for a user response

❓ What is the name of your organization? (For example: Decidim Barcelona) Decidim Docker Dev
❓ What is the domain name? (For example: decidim.example.org)
❓ Do you have an external database already set up? [y/N]
  • Integrate a GH Action with expect for checking the correct behavior
  • Ask all the questions at the beginning

Right now:

  1. Run the curl script
  2. Ask me to do something manually after 1 minute
  3. Make me to run the curl script again (that I need to search for the URL as I don't have it in my history, being a new session)
  4. Stops and ask me to press enter (??) - wait 2 minutes for downloading things
  5. Ask me some questions
  6. Download more docker images - wait 2 minutes for downloading things

The flow should be

  1. Run the curl script
  2. Ask me all the questions
  3. Confirm the answers or cancel to start over
  4. Download everything needed
  • Other images that aren't decidim/decidim:latest should be through an ENV VAR (DECIDIM_DOCKER_IMAGE) - as it is a "power users" kind of feature

  • Install some minimal security practices: unattended-upgrades and fail2ban (opening a 22 port to the whole Internet should have a bit of security).

  • When opening a shell inside of the container the user that runs the app is root. This is against the The Principle of Least Privilege

  • Add a message after

✅ Containers started successfully!
🔍 You can monitor logs with: docker compose logs -f

It can take up to 5 minutes

  • Add a launcher script with rebuild/start/stop/etc as wrappers for docker compose API. Also with an update to download and execute the update process

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions