Todos

flask soc site todos

Steps to deploy to sec.joostagterhoek.nl

Manual

Install and configure a Flask app on my server

Following the steps described in this Yunohost-forum-post, I managed to install a ‘Hello World’-app on sec.joostagterhoek.nl.

Deploy to production according to Flask-documentation

source: link to Flask-documentation on production deployment

To deploy a Flask app, the documentation recommends to:

  1. Build a wheel (.whl) file.
  2. Configure a secret key
  3. Run the app with a production server

How to build a wheel

  • Look this up and note here

Docker

Dockerize the Flask application

Enable the container registry in Gitlab

The commands/configuration code below works, but I had to rework the paths to the *.pem files. Below is what I found in this Yunohost-package issue:

/etc/gitlab/gitlab-persistent.rb
registry_external_url 'https://git.example.com:5050'
registry_nginx['ssl_certificate'] = "/etc/ssl/private/yunohost_crt.pem"
registry_nginx['ssl_certificate_key'] = "/etc/ssl/private/yunohost_key.pem"

Then
sudo gitlab-ctl reconfigure

I then had to find out where the actual current pem files are:

/etc/ssl/certs/yunohost_crt.pem
/etc/ssl/private/yunohost_key.pem

Configure the registry to receive Docker containers

Authentication:
  • With only a username and password:
    • docker login registry.example.com -u -p
    • Probably unsafe (you also get a warning that your hashed password is stored in home/$USER/.docker/config.json).
  • Use Gitlab CI/CD to authenticate
    • Upside: per-job user and password managed by Gitlab CI/CD pipeline.
  • Authenticate with a token
    • Downside: token management (tokens should have a limited lifespan)
Approach
  • Build and push the local dockerized Flask image with a temporary token
  • Create a Gitlab deployment pipeline that does the following:
    • SSH into production server as Gitlab Runner-account
    • Use the CI job token (unique to each CI/CD pipeline) which only has read_registry scope for read (pull) access.

Managing Docker secrets

Adding secrets to Docker

From https://docs.docker.com/engine/swarm/secrets/#simple-example-get-started-with-secrets:

printf "This is a secret" | docker secret create my_secret_data -

(…). The docker secret create command reads standard input because the last argument, which represents the file to read the secret from, is set to -.

Thinking it through: in no way would adding ‘reusable’ secrets like an API key or a Flask secret key in an image build be a good idea: even if someone would not be able to access those secret values directly because of Docker’s encryption or access levels, the built image would still allow the secrets to be used by others (and for example exceed API key usage limits). Instead, it would be better to add those secrets at runtime, in the case of my preferred DevOps-flow, when the Docker Compose file uses the prebuilt image from the most current code (which both have no baked in secrets) and adds the secret at/before runtime.

Like this flowchart:

flowchart TD
code --> pipeline --> container_registry --> compose -->|secrets injected| production_server
code[Code commited and pushed to remote]
pipeline[GitLab pipeline to build Docker image]
container_registry[image pushed to Docker container registry]
compose[Docker Compose runs built image on production server]
production_server[Provides Flask app]