Portrait of Patrice GADEGBEPatrice GADEGBE

Deployment console

The deployment console is a web page that shows one button per project and runs, on the server, the delivery script that this project already has, so that a release requires neither an account on the server nor tooling on the machine of whoever triggers it.

Role
Sole author
Period
August 2026
Status
In service. In service; twenty actions, a single account declared to date
Technologies
OliveTin, Docker Compose, Apache, shell scripts
Repositories
One
Path of a delivery through the consoleThe operator's browser reaches the OliveTin console through Apache, which terminates the encrypted connection. The console runs the deployment script of the chosen project, which updates the repository and rebuilds the containers through the host's Docker.Browsersigned-in operatorApacheencrypted connectionOliveTinone containertwenty actionsScriptsone per project,already in its repositoryDockerhost daemon
Figure 1. Path of a delivery, from the button to the rebuilt container. The console runs nothing of its own: it calls the project's script.

Context

Each of my projects is delivered by a script placed in its repository, which updates the code on the server then rebuilds its containers. This works as long as I am the only one delivering, since it requires an account on the server, the keys that allow the repositories to be read from there and, for some projects, the token that announces the delivery.

Problem

Entrusting a delivery to a collaborator amounted to opening the whole server to them, when all they need is to trigger a known operation. Writing a separate deployment tool would moreover have created a second way of delivering, with nothing to guarantee that it would stay identical to the first.

Answer

Calling the existing script

The console is built on OliveTin, whose image already ships docker, git and ssh. Each button comes down to one line, which moves into the project’s directory and runs its script there. Nothing is rewritten: the repository’s script remains the single source of truth, and a delivery launched from the console cannot differ from a delivery launched from a terminal. The environment, production or staging, is an argument of the button, limited to a closed list.

- title: Sanu - API Django
  shell: cd "$PROJECTS_ROOT/sanu-api-django" && bash ci/{{ environnement }}.sh
  timeout: 1800
  maxConcurrent: 1
  acls: [devs]
  arguments:
    - name: environnement
      title: Environnement
      type: ascii_identifier
      default: production
      choices:
        - value: production
          title: Production
        - value: staging
          title: Recette
Listing 1. An action of the console: an existing script, a constrained argument, an access list.

Denying by default

All permissions are denied by default. The administrators group sees every action, while the developers group sees only those that name it in their access list. Adding an action therefore makes it visible to no one until a list allows it, and an oversight results in a missing button rather than in one access too many. Each delivery action is moreover limited to one execution at a time and bounded by a timeout.

The same path on both sides

The scripts call Docker from the console’s container, but it is the host’s daemon that resolves the build contexts. The projects directory is therefore mounted in the container at the exact path it occupies on the host, otherwise a build would look for files where they are not. Finally, the version of the image is pinned, so that a restart of the server does not change the console without anyone having decided it, and the redeployment of the console waits for its health check to respond before declaring itself successful.

Limits and outlook

A console able to drive Docker and to read the repositories amounts to full access to the machine, and it seemed preferable to me to write it in its documentation rather than to leave it to be guessed. Three precautions follow from it, which are not optional: the console listens only locally, behind an encrypted connection, guest mode is closed, and the image is kept up to date. A second barrier in front of the console, by filtering or by an authentication service, remains to be put in place.

Delegation, which justified the project, has not yet been exercised: a single account is declared, and the developers group has no member. The console moreover keeps no trace of a delivery other than its logs. Finally, the most recent Sanu repositories are delivered by their pipelines, so that part of the console’s scope has shifted since it was written and some of its actions need to be reviewed.

Back to the other projects