158 lines
7.5 KiB
Markdown
158 lines
7.5 KiB
Markdown
# 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](https://hub.docker.com/r/gitea/gitea), as well as a nice [documentation](https://docs.gitea.com/installation/install-with-docker)
|
|
|
|
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](https://docs.drone.io/server/provider/gitea/) (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](https://docs.drone.io/quickstart/docker/), 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](https://letsencrypt.org/fr/), and the very nice [certbot](https://certbot.eff.org/) that acts like its CLI.
|
|
Since we are going all docker, we shall use the official [nginx](https://hub.docker.com/_/nginx) and [certbot](https://hub.docker.com/r/certbot/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](http://nginx.org/en/docs/beginners_guide.html) 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
|
|
|