# TP1 - Burgoni Alexandre ## Part 1 There is two compose file in the project. First, we must up the dev compose file, and then up the main docker file. ```shell docker-compose -f docker-compose-dev.yml up -d docker-compose up -d ``` By this, our app is up. BUT, in the PDF it is specified 4200 as listen port but configured as `80`. I updated the exposed port to `4200` and did the same for the environnement variables in the `api`, so we're not annoyed by the CORS :D ## Part 2 - The installation of the gitlab server is done on a VM, the traffic to the VM is done through a `proxy_pass` from the nginx of the main server. The configuration is based on the recipe provided by [GitLab](https://gitlab.com/gitlab-org/gitlab-recipes/-/tree/master/web-server/nginx). Here is the final nginx config file: ``` # cat /etc/nginx/conf.d/gitlab-omnibus-nginx.conf ## GitLab 8.3+ ## ## Lines starting with two hashes (##) are comments with information. ## Lines starting with one hash (#) are configuration parameters that can be uncommented. ## ################################## ## CONTRIBUTING ## ################################## ## ## If you change this file in a Merge Request, please also create ## a Merge Request on https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests ## ################################### ## configuration ## ################################### ## ## See installation.md#using-https for additional HTTPS configuration details. upstream gitlab-workhorse { # On GitLab versions before 13.5, the location is # `/var/opt/gitlab/gitlab-workhorse/socket`. Change the following line # accordingly. server unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket; } ## Normal HTTP host server { ## Either remove "default_server" from the listen line below, ## or delete the /etc/nginx/sites-enabled/default file. This will cause gitlab ## to be served if you visit any address that your server responds to, eg. ## the ip address of the server (http://x.x.x.x/)n 0.0.0.0:80 default_server; server_name gitlab.alexandreburgoni.io; ## Replace this with something like gitlab.example.com server_tokens off; ## Don't show the nginx version number, a security best practice root /opt/gitlab/embedded/service/gitlab-rails/public; ## See app/controllers/application_controller.rb for headers set ## Individual nginx logs for this GitLab vhost access_log /var/log/nginx/gitlab_access.log; error_log /var/log/nginx/gitlab_error.log; location / { client_max_body_size 0; gzip off; ## https://github.com/gitlabhq/gitlabhq/issues/694 ## Some requests take more than 30 seconds. proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://gitlab-workhorse; } listen [::]:443 ssl ipv6only=on; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/ssl/certs/gitlab.alexandreburgoni.io.crt; ssl_certificate_key /etc/ssl/private/gitlab.alexandreburgoni.io.key; #ssl_dhparam /etc/nginx/dhparam.pem; #ssl_ecdh_curve secp384r1 } server { if ($host = gitlab.alexandreburgoni.io) { return 301 https://$host$request_uri; } listen 0.0.0.0:80 default_server; listen [::]:80 default_server; server_name gitlab.alexandreburgoni.io; return 404; } ``` - The gitlab instance is available at https://gitlab.alexandreburgoni.io/, the user created is Ivana. - I imported the whole git repository through the wizard to import repo from URL :) - The runner is installed with `gitlab-runner` command, so it is pretty straight forward. **Well, we can't use a VM, so I installed again the gitlab instance on my server...** ... The user created can be used through: ``` username: ivana password: ivanaivana ``` ### Bind9 Config In order to config `bind9`, I started to follow this guide (done by Luca Cimini 😍) available [here](https://docs.google.com/document/d/1UVO0Vg9W_McMacJjw3OJy2QsC-nTPHnQynLQIN7kFFc/). But I edited to do my own configuration, here is the zone configuration: ``` # named.conf.local zone "alexandreburgoni.io" IN { type master; file "/etc/bind/zone.alexandreburgoni.io"; allow-update { none; }; }; # zone.alexandreburgoni.io $TTL 604800 @ IN SOA ns.alexandreburgoni.io. root.alexandreburgoni.io. ( 2020091606 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; nameservers - NS records @ IN NS ns.alexandreburgoni.local. ; sub-domain - A records ns.alexandreburgoni.io. IN A 162.38.112.112 alexandreburgoni.io. IN A 162.38.112.112 gitlab.alexandreburgoni.loiocal. IN A 162.38.112.112 ``` ### Self signed certificate Self signed certificate is created by following a [tutorial](https://www.cloudsavvyit.com/1306/how-to-create-and-use-self-signed-ssl-on-nginx/). Next, I just added this certificate to my browser as a trusted certificate. I did not use Gitlab certificates as it would have make me install again Gitlab, and lose all the work already done. :( ### DNS Resolution The DNS resolution of my local computer is done through the command: `resolvectl dns eno1 162.38.112.112` ### Build job The need is to create a build & testing job so we ensure the project is properly running. Here is the `.gitlab-ci.yml` file: ``` stages: - build - package variables: POSTGRES_USER: "ivana_chess_api" POSTGRES_PASSWORD: "ivana_chess_api" # POSTGRES_DB: "ivana_chess_api" IVANA_CHESS_BROKER_HOST: broker IVANA_CHESS_SERVER_ALLOWED_ORIGINS: "http://api" IVANA_CHESS_DB_URL: "jdbc:postgresql://db/ivana_chess_api" IVANA_CHESS_STOMP_HOST: broker IVANA_CHESS_BROKER_HOST: broker API_BASE_URL: "http://api" .cache: cache: key: gradlew-cache-${CI_COMMIT_SLUG_REF} paths: - .gradle policy: pull gradlew_assemble: stage: .pre image: gradle:7.0.2-jdk11 script: - ./gradlew assemble extends: .cache cache: policy: pull-push build_test: services: - name: postgres:11 alias: db - name: gleroy/rabbitmq-stomp:3.7-1 alias: broker image: gradle:7.0.2-jdk11 stage: build extends: .cache script: - apt update && apt install -y postgresql-client - gradle assemble -x ivana-chess-webapp:assemble - gradle check -x ivana-chess-webapp:check -Pdb.host=db -Pdb.test-schema=public -Pci=true ``` ### Container registry To activate the container registry, I just made active this property: `registry_external_url`, this information comes from [here](https://docs.gitlab.com/ee/administration/packages/container_registry.html#configure-container-registry-under-an-existing-gitlab-domain). *As I made my own certificates, there isn't any issue with them.* ### Publish to my container registry First, I created a new runner which has the executor `shell`, it is scoped to **only** the ivanna project. **Shifting direction, I won't do the CI, I wll continue with creating a gitlab instance fully.** ### Nginx configuration As gitlab is working on my existing nginx, the registry isn't working by "itself". So I have to add a complete configuration to my nginx server, which is the following: ``` server { listen 80; listen [::]:80; server_name registry.gitlab.alexandreburgoni.io; server_tokens off; return 301 https://$http_host$request_uri; access_log /var/log/nginx/gitlab_registry_access.log; error_log /var/log/nginx/gitlab_registry_error.log; } server { listen 443 http2; listen [::]:443 ssl http2; server_name registry.gitlab.alexandreburgoni.io; access_log /var/log/nginx/reverse-access.log; error_log /var/log/nginx/reverse-error.log; ssl on; ssl_certificate /etc/ssl/certs/alexandreburgoni-io.crt; ssl_certificate_key /etc/ssl/private/alexandreburgoni-io.key; ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4'; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_session_timeout 5m; access_log /var/log/gitlab/nginx/gitlab_registry_access.log; error_log /var/log/gitlab/nginx/gitlab_registry_error.log; location / { proxy_set_header Host $http_host; # required for docker client's sake proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 900; proxy_pass http://localhost:5000; } } ``` Locally, the registry is working properly. However, there are certificate problems: ``` Error response from daemon: Get https://registry.gitlab.alexandreburgoni.io/v2/: x509: certificate is valid for alexandreburgoni.io, not registry.gitlab.alexandreburgoni.io ``` Another error I got, is saying that my certificate authority wasn't valid. I added my CRT to my trusted certificates, however docker did not trust it. So I made my registry as an `insecure` registry. And now the registry is working properly. ### Proof of work At this stage, the registry is working properly, and images can be pushed into the registry: ![](image-kq6ramp0.png) ### New problem Today I discovered there is again, a new problem on my gitlab instance. I cannot push to my repository anymore, there is an internal API unreachable error on the whole instance :D After deactivating Puma, registry and some others modules of gitlab. I ended up with this property I defined days ago: ``` # gitlab_rails['internal_api_url'] = 'https://gitlab.alexandreburgoni.io' ``` This property should not be used along `puma` which made the whole gitlab API crash & have conflicts. ## Let's get back to CI/CD For the CI/CD, I'm sorry, I don't have a working deployment with Ansible! However, I have a fully working pipeline where it builds & pushes to the GitLab Container Registry of my GitLab instance. ```yaml stages: - test - build - release variables: POSTGRES_USER: "ivana_chess_api" POSTGRES_PASSWORD: "ivana_chess_api" IVANA_CHESS_BROKER_HOST: broker IVANA_CHESS_SERVER_ALLOWED_ORIGINS: "http://api" IVANA_CHESS_DB_URL: "jdbc:postgresql://db/ivana_chess_api" IVANA_CHESS_STOMP_HOST: broker API_BASE_URL: "http://api" # We cache what gradle creates in order to have a faster pipeline .cache: cache: key: gradlew-cache-${CI_COMMIT_SLUG_REF} paths: - .gradle - api/.gradle - webapp/.gradle - matchmaker/.gradle policy: pull-push # This job will build the project and export the property version so we can tag the docker image gradlew_assemble: stage: build image: gradle:7.0.2-jdk11 script: - gradle assemble - gradle properties -q | grep "version:" | awk '{print $2}' | head -n1 > VERSION extends: .cache cache: policy: pull-push artifacts: paths: - webapp/build/dist - api/build/libs - matchmaker/build/libs - VERSION expire_in: 1 week # Running test, nothign extraordinary test: services: - name: postgres:11 alias: db - name: gleroy/rabbitmq-stomp:3.7-1 alias: broker image: gradle:7.0.2-jdk11 stage: test extends: .cache script: - apt update && apt install -y postgresql-client - gradle assemble -x ivana-chess-webapp:assemble - gradle check -x ivana-chess-webapp:check -Pdb.host=db -Pdb.test-schema=public -Pci=true # I could have been using kaniko or any tool that doesn't require docker to build a container # but I add issues with my CERTIFICATES, like Kaniko couldn't verify the certificate and I didn't # want to use the --insecure argument as an easy fix release_image: stage: release image: docker:20.10.6 extends: .cache tags: - docker - privileged services: - name: docker:20.10.6-dind alias: docker script: a - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - IVANA_VERSION=$(cat VERSION) # IVANA-CHESS-API - cd ${CI_PROJECT_DIR}/api/docker - cp ../build/libs/ivana-chess-api-${IVANA_VERSION}.jar ivana-chess-api.jar - docker build -t $CI_REGISTRY/ivana/ivana-chess/api:latest -t $CI_REGISTRY/ivana/ivana-chess/api:${IVANA_VERSION} . - docker push $CI_REGISTRY/ivana/ivana-chess/api:latest - docker push $CI_REGISTRY/ivana/ivana-chess/api:${IVANA_VERSION} # IVANA-CHESS-MATCHMAKER - cd ${CI_PROJECT_DIR}/matchmaker/docker - cp ../build/libs/ivana-chess-matchmaker-${IVANA_VERSION}.jar ivana-chess-matchmaker.jar - docker build -t $CI_REGISTRY/ivana/ivana-chess/matchmaker:latest -t $CI_REGISTRY/ivana/ivana-chess/matchmaker:${IVANA_VERSION} . - docker push $CI_REGISTRY/ivana/ivana-chess/matchmaker:latest - docker push $CI_REGISTRY/ivana/ivana-chess/matchmaker:${IVANA_VERSION} # IVANA-CHESS-WEBAPP - cd ${CI_PROJECT_DIR}/webapp/docker - cp -r ../build/dist/ ./dist - docker build -t $CI_REGISTRY/ivana/ivana-chess/webapp:latest -t $CI_REGISTRY/ivana/ivana-chess/webapp:${IVANA_VERSION} . - docker push $CI_REGISTRY/ivana/ivana-chess/webapp:latest - docker push $CI_REGISTRY/ivana/ivana-chess/webapp:${IVANA_VERSION} rules: - if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH" when: always - if: "$CI_COMMIT_BRANCH == 'develop'" when: always - if: "$CI_COMMIT_TAG" when: always - when: never ``` ### Container Registry The above pipeline will create an image for each project. Below screenshot, shows the image tags: ![](https://i.imgur.com/ChQrJ0o.png) To finish, for each application, we have these tags available: ![](https://i.imgur.com/ErK3Zhs.png)