blog/drafts/gitea_and_drone.md
simonpetit 0b9d1294fe
All checks were successful
continuous-integration/drone/push Build is passing
completing draft
2024-12-06 16:39:12 +00:00

7.5 KiB

A personal Git enhanced with CI/CD

Gitea for a self hosted git

In the continuity of the static site generator, I wanted also to store my blog in a git repo. This has several purposes :

  • I could eventually edit my blog from any machine : I just would need to clone the repository and edit my files
  • With a CI/CD pipeline, all changes to this repository would trigger the pipeline to rebuild the static blog automatically and deploy it on my server

There are not many self host git that include a nice web UI. Of course I stick to striclty open source, and chose gitea over gitlab. Its web UI is nice, similar to github, it is relatively lightweight, compared to gitlab, its installation is quite easy and has all the basic functionnalities I need :

  • A simple git backend
  • A intuitive web UI
  • A container registry

To also improve my docker skills, I went for a all in docker solution. Gitea has an official image on the docker hub, as well as a nice documentation

To persist my data, PostgreSQL is my go to : I feel it is simply the best Database so far.

Drone for continuous integration/deployment pipelines

Whereas choosing a self hosted git was relatively easy, picking a CI/CD tool was a thougher choice : there are many of them out there. I know less about CI/CD, and narrowed my short list to two of them:

  • Drone
  • Buildbot

In order to move on my project, I tried not to overthink it and went for Drone, even though I feel Buildbot would be maybe a more complete solution. One aspect of Drone that pleased me was the possibility to run all with docker images, and its documented integration with Gitea. Let me clarify that :

  • Indeed, drone interfaces easily with gitea as per its documentation (and not so much with gitlab, which conforted my initial choice)
  • The other point is that it can run its pipeline all within docker container, as seen here, that is each step of the pipeline is the execution of a container. As I wanted to improve my docker skills as well, this was a nice touch. However this means that I would have to package my static blog generator as a docker image to run it in my pipeline.

The web UI is also very nice and intuitive, and its uses the Gitea SSO for signing in.

The actual setup

The architecture

First of all, since all these services would run of the same machine (a small VPS, as the workload of this personnal blog shall remain low), I wanted to have an nginx proxy before all of them. Of course, even Nginx shall be run as a docker container.

Hence here are all the containers that must be up and running at the end :

  • Nginx
  • Gitea
  • Postgres
  • Drone
  • Drone runner (indeed, this container ACTUALLY runs the pipeline, the Drone one only acts as a scheduler)

For clarity let us create three folders in the server, all of them containing the docker-compose.yml that ups the services :

  • gitea : it holds the gitea container as well as the postgres (as it is only used by gitea here)
  • nginx : as the proxy it is separated from the others
  • drone : of course, the last piece of the puzzle, containing drone server and runner

All of them needs to be on the same docker network to comunicate with each other.

Creating the network

As said above, all these running containers need to be on the same docker netword so that they can communicate. Frist this is then to create this network, with this simple command (mine is simply called gitea, as all revolve around it)

docker network create gitea

All default parameters for this network is quite fine here.

Hence, all the docker-compose.yml shall start with :

networks:
  gitea:
    external: true

that indicates the use of the previously created network as an externally created network.

The proxy

To make this project a serious one, we need to have https enabled. For this, there is a very convenient initiative : letsencrypt, and the very nice certbot that acts like its CLI. Since we are going all docker, we shall use the official nginx and certbot. The point of doing this in a separate folder, is to organize the mounted volumes : indeed between nginx logs, configurations and certbot, we need to know for sure where to find all those files. Only the /var/www/html will be map as is to the container, that is /var/www/html:/var/www/html. I find it easier to follow the default path for nginx even on the host machine, as if nginx was not running on docker.

In the nginx folder, let us make two subfolders : certbot and nginx, self explanatory.

Configuring the nginx web server

We considerd being in the folder $HOME/nginx, in which there are two subfolders : nginx and certbot

I will not go for a nginx tutorial as the official documentation is quite exhaustive.

However here is the part of the docker-compose.yml that concerns nginx :

services:
  webserver:
    image: nginx:latest
    ports:
      - 80:80
      - 443:443
    restart: always
    volumes:
      - ./nginx/conf:/etc/nginx/conf.d
      - ./certbot/www:/var/www/certbot/
      - ./certbot/conf:/etc/nginx/ssl/:ro
      - ./nginx/logs:/var/log/nginx/
      - /var/www/html:/var/www/html/
    networks:
      - gitea

It obviously expose ports 80 (for redirection) and 443. It always restart, as we do not want off time. Concerning the volumes : the configuration is in the ./nginx/conf, this way we can update it anytime. It will also need access to the the certbot confg. As said above, we also want to access the logs, as I prepare a web analytics sofware, that insetad of using cookies and intrusive ways, only uses the nginx logs. Of course, it is in the gitea network. As containers can belong to several networks, if in the future I want to add another web server, I will add this container to the second network.

Notice also the /var/www/certbot path within the container : it is useful for the acme challenge. We will talk about it later.

Adding certbot to the loop

We will also use docker-compose.yml to configure certbot, even though it will not be a running container, whereas a short lived one.

certbot:
  image: certbot/certbot:latest
  networks:
  - gitea
  volumes:
    - ./certbot/www:/var/www/certbot/:rw
    - ./certbot/conf:/etc/letsencrypt/:rw

It also belongs to the gitea networks, to communicate to nginx. Even though this is probably not the best idea : a dedicated network should have been more relevant. Two volumes are also mounted. The certbot/conf contains the actual certificates that will generate promptly.

The initial nginx config

For certbot to generate the certificate, we need nginx to have this minimal config :

server {
    listen 80;
    listen [::]:80;

    server_name example.org www.example.org;
    server_tokens off;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://example.org$request_uri;
    }
}

Indeed, for the ACME challenge, certbot must have a positive respone to /.well-known/acme-challenge/, which points to /var/www/cerbot.

Now we can run certbot to generate the certificate. Let us start with a dry run first :

Insert dry run command

Configuring Gitea

Starting with Drone CI