From 1e0f9410077e4118c846544dc82bbc23b97125d1 Mon Sep 17 00:00:00 2001
From: Rafael Laszlo <rlacko99@gmail.com>
Date: Thu, 4 Nov 2021 22:57:08 +0100
Subject: [PATCH] Add Harbor setup

---
 README.md                                     |  23 ++
 ansible/.gitignore                            |   7 +
 ansible/ansible.cfg                           |   6 +
 ansible/bootstrap.sh                          |  11 +
 ansible/harbor/base.yaml                      |  27 ++
 ansible/harbor/tasks/docker.yaml              |  54 ++++
 ansible/harbor/tasks/harbor.yaml              |  27 ++
 ansible/harbor/tasks/nginx.yaml               |  60 +++++
 .../harbor/templates/etc/nginx/nginx.conf.j2  |  32 +++
 .../templates/etc/nginx/sites-enabled/http.j2 |  22 ++
 .../etc/nginx/sites-enabled/letsencrypt.j2    |  58 +++++
 .../system/harbor-docker-compose.service      |  21 ++
 .../templates/home/user/harbor/harbor.yml.j2  | 232 ++++++++++++++++++
 ansible/harbor/vars/harbor.yaml               |  32 +++
 ansible/harbor/vars/secret.yaml.example       |   2 +
 ansible/inventory.yaml                        |  10 +
 ansible/requirements.galaxy.yaml              |  15 ++
 ansible/vars/base.yaml                        |  15 ++
 18 files changed, 654 insertions(+)
 create mode 100644 README.md
 create mode 100644 ansible/.gitignore
 create mode 100644 ansible/ansible.cfg
 create mode 100755 ansible/bootstrap.sh
 create mode 100644 ansible/harbor/base.yaml
 create mode 100644 ansible/harbor/tasks/docker.yaml
 create mode 100644 ansible/harbor/tasks/harbor.yaml
 create mode 100644 ansible/harbor/tasks/nginx.yaml
 create mode 100644 ansible/harbor/templates/etc/nginx/nginx.conf.j2
 create mode 100644 ansible/harbor/templates/etc/nginx/sites-enabled/http.j2
 create mode 100644 ansible/harbor/templates/etc/nginx/sites-enabled/letsencrypt.j2
 create mode 100644 ansible/harbor/templates/etc/systemd/system/harbor-docker-compose.service
 create mode 100644 ansible/harbor/templates/home/user/harbor/harbor.yml.j2
 create mode 100644 ansible/harbor/vars/harbor.yaml
 create mode 100644 ansible/harbor/vars/secret.yaml.example
 create mode 100644 ansible/inventory.yaml
 create mode 100644 ansible/requirements.galaxy.yaml
 create mode 100644 ansible/vars/base.yaml

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0be12b9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# Harbor
+
+Container registry vm using Harbor.
+
+## Terraform
+
+`/terraform` folder contains a configuration
+which creates the vm with basic networking.
+
+## Ansible
+
+`/ansible`:  
+After the vm is created you can simply
+install all the necessary configurations
+with `ansible-playbook harbor/base.yaml`.
+(cd into the folder and run `./bootstrap.sh`)
+
+## Harbor configuration
+
+The playbook handles everything and auto start
+harbor. 
+If you want to change the configuration 
+refer to the `ansible/harbor/templates/home/user/harbor/harbor.yml` file
diff --git a/ansible/.gitignore b/ansible/.gitignore
new file mode 100644
index 0000000..e6fd4b2
--- /dev/null
+++ b/ansible/.gitignore
@@ -0,0 +1,7 @@
+.idea
+.venv
+
+# autogenerated
+.template
+
+secret.yaml
\ No newline at end of file
diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg
new file mode 100644
index 0000000..cdeb744
--- /dev/null
+++ b/ansible/ansible.cfg
@@ -0,0 +1,6 @@
+[defaults]
+ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
+inventory = inventory.yaml
+
+[ssh_connection]
+ssh_args = -o StrictHostKeyChecking=accept-new
diff --git a/ansible/bootstrap.sh b/ansible/bootstrap.sh
new file mode 100755
index 0000000..127e5df
--- /dev/null
+++ b/ansible/bootstrap.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+[[ ! -d .venv ]] && python3 -m venv .venv
+source .venv/bin/activate
+
+pip3 install ansible ansible-lint
+
+ansible-galaxy install --force -r requirements.galaxy.yaml
+
+# to stay in our comfy virtualenv
+exec "${SHELL:bash}"
diff --git a/ansible/harbor/base.yaml b/ansible/harbor/base.yaml
new file mode 100644
index 0000000..cfae179
--- /dev/null
+++ b/ansible/harbor/base.yaml
@@ -0,0 +1,27 @@
+---
+- hosts: harbor
+  roles:
+    - role: kszk-k8s.base
+      tags: ["base"]
+      become: true
+    # - role: kszk-k8s.iptables
+    #   tags: ["iptables"]
+    #   become: true
+  vars_files:
+    - "../vars/base.yaml"
+    - "vars/harbor.yaml"
+    - "vars/secret.yaml"
+  tasks: 
+    - name: Install docker
+      tags: ["docker"]
+      become: true
+      import_tasks: tasks/docker.yaml
+    - name: Setup nginx
+      become: true
+      tags: ["nginx"]
+      import_tasks: tasks/nginx.yaml
+    - name: Install harbor
+      tags: ["harbor"]
+      become: true
+      import_tasks: tasks/harbor.yaml
+    
diff --git a/ansible/harbor/tasks/docker.yaml b/ansible/harbor/tasks/docker.yaml
new file mode 100644
index 0000000..dd9df78
--- /dev/null
+++ b/ansible/harbor/tasks/docker.yaml
@@ -0,0 +1,54 @@
+---
+- name: Ensure tools installed for docker setup
+  package:
+    state: present
+    name:
+      - apt-transport-https
+      - ca-certificates
+      - curl
+      - gnupg-agent
+      - software-properties-common
+
+### Installation
+
+- name: add GPG key
+  apt_key:
+    url: https://download.docker.com/linux/ubuntu/gpg
+    state: present
+
+- name: add docker repository to apt
+  apt_repository:
+    repo: deb https://download.docker.com/linux/ubuntu focal stable
+    state: present
+
+# docker uses this, on at least Ubuntu, to do port publishing.
+- name: Ensure iptables is installed
+  package:
+    name: iptables
+    state: present
+
+- name: Install docker
+  package:
+    state: present
+    name:
+      - docker-ce
+      - docker-ce-cli
+      - containerd.io
+
+- name: Enable and start docker
+  service:
+    name: docker
+    state: started
+    enabled: yes
+
+- name: Download docker-compose
+  get_url:
+    url: https://github.com/docker/compose/releases/download/1.29.2/docker-compose-Linux-x86_64
+    dest: /usr/local/bin/docker-compose
+    mode: '0755'
+
+- name: Add mgmt user to docker group
+  ansible.builtin.user:
+    name: "{{ user }}"
+    groups: docker
+    append: yes
diff --git a/ansible/harbor/tasks/harbor.yaml b/ansible/harbor/tasks/harbor.yaml
new file mode 100644
index 0000000..982ce22
--- /dev/null
+++ b/ansible/harbor/tasks/harbor.yaml
@@ -0,0 +1,27 @@
+---
+
+- name: Download harbor installer
+  get_url:
+    url: https://github.com/goharbor/harbor/releases/download/v2.4.0/harbor-online-installer-v2.4.0.tgz
+    dest: /home/{{ user }}/harbor-online-installer-v2.4.0.tgz
+    force: no
+
+- name: Extract harbor installer
+  unarchive:
+    src: /home/{{ user }}/harbor-online-installer-v2.4.0.tgz
+    dest: "/home/{{ user }}"
+    remote_src: True
+
+- name: Create data folder
+  ansible.builtin.file:
+    path: "/home/{{ user }}/data"
+    state: directory
+
+- name: Update harbor installer config
+  template:
+    src: home/user/harbor/harbor.yml.j2
+    dest: /home/{{ user }}/harbor/harbor.yml
+
+- name: Setup harbor
+  become: yes
+  shell: "/home/{{ user }}/harbor/install.sh"
diff --git a/ansible/harbor/tasks/nginx.yaml b/ansible/harbor/tasks/nginx.yaml
new file mode 100644
index 0000000..d75f8bb
--- /dev/null
+++ b/ansible/harbor/tasks/nginx.yaml
@@ -0,0 +1,60 @@
+---
+- name: Install nginx
+  package:
+    state: present
+    name:
+      - nginx
+      - letsencrypt
+
+- name: Create letsencrypt directory
+  file: 
+    name: /var/www/letsencrypt 
+    state: directory
+
+- name: Remove default nginx config
+  file: 
+    name: /etc/nginx/sites-enabled/default 
+    state: absent
+
+- name: Install system nginx config
+  template:
+    src: etc/nginx/nginx.conf.j2
+    dest: /etc/nginx/nginx.conf
+
+- name: Install nginx site for letsencrypt requests
+  template:
+    src: etc/nginx/sites-enabled/http.j2
+    dest: /etc/nginx/sites-enabled/http
+
+- name: Reload nginx to activate letsencrypt site
+  service: 
+    name: nginx 
+    state: restarted
+
+- name: Create letsencrypt certificate
+  shell: letsencrypt certonly -n --webroot -w /var/www/letsencrypt -m {{ acme_email }} --agree-tos -d {{ item.name }}
+  args:
+    creates: /etc/letsencrypt/live/{{ item.name }}
+  loop: "{{ sites }}"
+
+- name: Generate dhparams
+  shell: openssl dhparam -out /etc/nginx/dhparams.pem 2048
+  args:
+    creates: /etc/nginx/dhparams.pem
+
+- name: Install nginx site for specified site
+  template:
+    src: etc/nginx/sites-enabled/letsencrypt.j2
+    dest: /etc/nginx/sites-enabled/letsencrypt
+
+- name: Reload nginx to activate specified site
+  service: 
+    name: nginx 
+    state: restarted
+
+- name: Add letsencrypt cronjob for cert renewal
+  cron:
+    name: letsencrypt_renewal of {{ item.name }}
+    special_time: daily
+    job: letsencrypt --renew certonly -n --webroot -w /var/www/letsencrypt -m {{ acme_email }} --agree-tos -d {{ item.name }} && service nginx reload
+  loop: "{{ sites }}"
diff --git a/ansible/harbor/templates/etc/nginx/nginx.conf.j2 b/ansible/harbor/templates/etc/nginx/nginx.conf.j2
new file mode 100644
index 0000000..38a8d67
--- /dev/null
+++ b/ansible/harbor/templates/etc/nginx/nginx.conf.j2
@@ -0,0 +1,32 @@
+#
+# !!!
+# {{ ansible_managed }}
+# !!!
+
+user www-data;
+worker_processes 4;
+pid /run/nginx.pid;
+
+events {
+    worker_connections 768;
+}
+
+http {
+
+    sendfile on;
+    tcp_nopush on;
+    tcp_nodelay on;
+    keepalive_timeout 65;
+    types_hash_max_size 2048;
+    include /etc/nginx/mime.types;
+    default_type application/octet-stream;
+
+    access_log /var/log/nginx/access.log;
+    error_log /var/log/nginx/error.log;
+
+    gzip on;
+    gzip_disable "msie6";
+
+    include /etc/nginx/conf.d/*.conf;
+    include /etc/nginx/sites-enabled/*;
+}
diff --git a/ansible/harbor/templates/etc/nginx/sites-enabled/http.j2 b/ansible/harbor/templates/etc/nginx/sites-enabled/http.j2
new file mode 100644
index 0000000..64f7450
--- /dev/null
+++ b/ansible/harbor/templates/etc/nginx/sites-enabled/http.j2
@@ -0,0 +1,22 @@
+#
+# !!!
+# {{ ansible_managed }}
+# !!!
+
+server_tokens off;
+
+{% for site in sites %}
+server {
+    listen 80;
+    server_name {{ site.name }};
+
+    location /.well-known/acme-challenge {
+        root /var/www/letsencrypt;
+        try_files $uri $uri/ =404;
+    }
+
+    location / {
+        rewrite ^ https://{{ site.name }}$request_uri? permanent;
+    }
+}
+{% endfor %}
\ No newline at end of file
diff --git a/ansible/harbor/templates/etc/nginx/sites-enabled/letsencrypt.j2 b/ansible/harbor/templates/etc/nginx/sites-enabled/letsencrypt.j2
new file mode 100644
index 0000000..6cff6ad
--- /dev/null
+++ b/ansible/harbor/templates/etc/nginx/sites-enabled/letsencrypt.j2
@@ -0,0 +1,58 @@
+#
+# !!!
+# {{ ansible_managed }}
+# !!!
+
+add_header X-Frame-Options SAMEORIGIN;
+add_header X-Content-Type-Options nosniff;
+add_header X-XSS-Protection "1; mode=block";
+add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com; img-src 'self' data: https://www.google-analytics.com; style-src 'self' 'unsafe-inline'; font-src 'self'; frame-src 'none'; object-src 'none'";
+
+
+# HTTPS server
+#
+{% for site in sites %}
+server {
+    listen 443 ssl;
+    server_name {{ site.name }};
+
+    ssl_certificate         /etc/letsencrypt/live/{{ site.name }}/fullchain.pem;
+    ssl_certificate_key     /etc/letsencrypt/live/{{ site.name }}/privkey.pem;
+    ssl_trusted_certificate /etc/letsencrypt/live/{{ site.name }}/fullchain.pem;
+
+    ssl_session_cache shared:SSL:50m;
+    ssl_session_timeout 5m;
+    ssl_stapling on;
+    ssl_stapling_verify on;
+
+    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+    ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
+
+    ssl_dhparam /etc/nginx/dhparams.pem;
+    ssl_prefer_server_ciphers on;
+
+    # To allow special characters in headers
+    ignore_invalid_headers off;
+    # Allow any size file to be uploaded.
+    # Set to a value such as 1000m; to restrict file size to a specific value
+    client_max_body_size 0;
+    # To disable buffering
+    proxy_buffering off;
+
+    location / {
+
+        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_set_header Host $http_host;
+
+        proxy_connect_timeout 300;
+        # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
+        proxy_http_version 1.1;
+        proxy_set_header Connection "";
+        chunked_transfer_encoding off;
+
+        proxy_pass {{ site.proxy_to }};
+    }
+}
+{% endfor %}
\ No newline at end of file
diff --git a/ansible/harbor/templates/etc/systemd/system/harbor-docker-compose.service b/ansible/harbor/templates/etc/systemd/system/harbor-docker-compose.service
new file mode 100644
index 0000000..8e138d5
--- /dev/null
+++ b/ansible/harbor/templates/etc/systemd/system/harbor-docker-compose.service
@@ -0,0 +1,21 @@
+#
+# !!!
+# {{ ansible_managed }}
+# !!!
+
+[Unit]
+Description=Harbor Docker Compose service
+Requires=docker.service
+After=docker.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+WorkingDirectory=/home/harbor
+ExecStart=/usr/local/bin/docker-compose up -d
+ExecStop=/usr/local/bin/docker-compose down
+TimeoutStartSec=0
+User=root
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ansible/harbor/templates/home/user/harbor/harbor.yml.j2 b/ansible/harbor/templates/home/user/harbor/harbor.yml.j2
new file mode 100644
index 0000000..7f395ea
--- /dev/null
+++ b/ansible/harbor/templates/home/user/harbor/harbor.yml.j2
@@ -0,0 +1,232 @@
+# Configuration file of Harbor
+# !!!
+# {{ ansible_managed }}
+# !!!
+
+# The IP address or hostname to access admin UI and registry service.
+# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.
+hostname: "{{ harbor_hostname }}"
+
+# http related config
+http:
+  # port for http, default is 80. If https enabled, this port will redirect to https port
+  port: 8080
+
+# https related config
+https: {}
+  # https port for harbor, default is 443
+  # port: 8443
+  # The path of cert and key files for nginx
+  # certificate: /etc/letsencrypt/live/{{ harbor_hostname }}/cert.pem
+  # private_key: /etc/letsencrypt/live/{{ harbor_hostname }}/privkey.pem
+
+# # Uncomment following will enable tls communication between all harbor components
+# internal_tls:
+#   # set enabled to true means internal tls is enabled
+#   enabled: true
+#   # put your cert and key files on dir
+#   dir: /etc/harbor/tls/internal
+
+# Uncomment external_url if you want to enable external proxy
+# And when it enabled the hostname will no longer used
+external_url: https://harbor.sch.bme.hu
+
+# The initial password of Harbor admin
+# It only works in first time to install harbor
+# Remember Change the admin password from UI after launching Harbor.
+harbor_admin_password: "{{ HARBOR_INIT_PASSWORD }}"
+
+# Harbor DB configuration
+database:
+  # The password for the root user of Harbor DB. Change this before any production use.
+  password: "{{ DB_PASSWORD }}"
+  # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained.
+  max_idle_conns: 100
+  # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections.
+  # Note: the default number of connections is 1024 for postgres of harbor.
+  max_open_conns: 900
+
+# The default data volume
+data_volume: /home/{{ user }}/data
+
+# Harbor Storage settings by default is using /data dir on local filesystem
+# Uncomment storage_service setting If you want to using external storage
+# storage_service:
+#   # ca_bundle is the path to the custom root ca certificate, which will be injected into the truststore
+#   # of registry's and chart repository's containers.  This is usually needed when the user hosts a internal storage with self signed certificate.
+#   ca_bundle:
+
+#   # storage backend, default is filesystem, options include filesystem, azure, gcs, s3, swift and oss
+#   # for more info about this configuration please refer https://docs.docker.com/registry/configuration/
+#   filesystem:
+#     maxthreads: 100
+#   # set disable to true when you want to disable registry redirect
+#   redirect:
+#     disabled: false
+
+# Trivy configuration
+#
+# Trivy DB contains vulnerability information from NVD, Red Hat, and many other upstream vulnerability databases.
+# It is downloaded by Trivy from the GitHub release page https://github.com/aquasecurity/trivy-db/releases and cached
+# in the local file system. In addition, the database contains the update timestamp so Trivy can detect whether it
+# should download a newer version from the Internet or use the cached one. Currently, the database is updated every
+# 12 hours and published as a new release to GitHub.
+trivy:
+  # ignoreUnfixed The flag to display only fixed vulnerabilities
+  ignore_unfixed: false
+  # skipUpdate The flag to enable or disable Trivy DB downloads from GitHub
+  #
+  # You might want to enable this flag in test or CI/CD environments to avoid GitHub rate limiting issues.
+  # If the flag is enabled you have to download the `trivy-offline.tar.gz` archive manually, extract `trivy.db` and
+  # `metadata.json` files and mount them in the `/home/scanner/.cache/trivy/db` path.
+  skip_update: false
+  #
+  # insecure The flag to skip verifying registry certificate
+  insecure: false
+  # github_token The GitHub access token to download Trivy DB
+  #
+  # Anonymous downloads from GitHub are subject to the limit of 60 requests per hour. Normally such rate limit is enough
+  # for production operations. If, for any reason, it's not enough, you could increase the rate limit to 5000
+  # requests per hour by specifying the GitHub access token. For more details on GitHub rate limiting please consult
+  # https://developer.github.com/v3/#rate-limiting
+  #
+  # You can create a GitHub token by following the instructions in
+  # https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
+  #
+  # github_token: xxx
+
+jobservice:
+  # Maximum number of job workers in job service
+  max_job_workers: 10
+
+notification:
+  # Maximum retry count for webhook job
+  webhook_job_max_retry: 10
+
+chart:
+  # Change the value of absolute_url to enabled can enable absolute url in chart
+  absolute_url: disabled
+
+# Log configurations
+log:
+  # options are debug, info, warning, error, fatal
+  level: info
+  # configs for logs in local storage
+  local:
+    # Log files are rotated log_rotate_count times before being removed. If count is 0, old versions are removed rather than rotated.
+    rotate_count: 50
+    # Log files are rotated only if they grow bigger than log_rotate_size bytes. If size is followed by k, the size is assumed to be in kilobytes.
+    # If the M is used, the size is in megabytes, and if G is used, the size is in gigabytes. So size 100, size 100k, size 100M and size 100G
+    # are all valid.
+    rotate_size: 200M
+    # The directory on your host that store log
+    location: /var/log/harbor
+
+  # Uncomment following lines to enable external syslog endpoint.
+  # external_endpoint:
+  #   # protocol used to transmit log to external endpoint, options is tcp or udp
+  #   protocol: tcp
+  #   # The host of external endpoint
+  #   host: localhost
+  #   # Port of external endpoint
+  #   port: 5140
+
+#This attribute is for migrator to detect the version of the .cfg file, DO NOT MODIFY!
+_version: 2.4.0
+
+# Uncomment external_database if using external database.
+# external_database:
+#   harbor:
+#     host: harbor_db_host
+#     port: harbor_db_port
+#     db_name: harbor_db_name
+#     username: harbor_db_username
+#     password: harbor_db_password
+#     ssl_mode: disable
+#     max_idle_conns: 2
+#     max_open_conns: 0
+#   notary_signer:
+#     host: notary_signer_db_host
+#     port: notary_signer_db_port
+#     db_name: notary_signer_db_name
+#     username: notary_signer_db_username
+#     password: notary_signer_db_password
+#     ssl_mode: disable
+#   notary_server:
+#     host: notary_server_db_host
+#     port: notary_server_db_port
+#     db_name: notary_server_db_name
+#     username: notary_server_db_username
+#     password: notary_server_db_password
+#     ssl_mode: disable
+
+# Uncomment external_redis if using external Redis server
+# external_redis:
+#   # support redis, redis+sentinel
+#   # host for redis: <host_redis>:<port_redis>
+#   # host for redis+sentinel:
+#   #  <host_sentinel1>:<port_sentinel1>,<host_sentinel2>:<port_sentinel2>,<host_sentinel3>:<port_sentinel3>
+#   host: redis:6379
+#   password:
+#   # sentinel_master_set must be set to support redis+sentinel
+#   #sentinel_master_set:
+#   # db_index 0 is for core, it's unchangeable
+#   registry_db_index: 1
+#   jobservice_db_index: 2
+#   chartmuseum_db_index: 3
+#   trivy_db_index: 5
+#   idle_timeout_seconds: 30
+
+# Uncomment uaa for trusting the certificate of uaa instance that is hosted via self-signed cert.
+# uaa:
+#   ca_file: /path/to/ca
+
+# Global proxy
+# Config http proxy for components, e.g. http://my.proxy.com:3128
+# Components doesn't need to connect to each others via http proxy.
+# Remove component from `components` array if want disable proxy
+# for it. If you want use proxy for replication, MUST enable proxy
+# for core and jobservice, and set `http_proxy` and `https_proxy`.
+# Add domain to the `no_proxy` field, when you want disable proxy
+# for some special registry.
+proxy:
+  http_proxy:
+  https_proxy:
+  no_proxy:
+  components:
+    - core
+    - jobservice
+    - trivy
+# metric:
+#   enabled: false
+#   port: 9090
+#   path: /metrics
+
+# Trace related config
+# only can enable one trace provider(jaeger or otel) at the same time,
+# and when using jaeger as provider, can only enable it with agent mode or collector mode.
+# if using jaeger collector mode, uncomment endpoint and uncomment username, password if needed
+# if using jaeger agetn mode uncomment agent_host and agent_port
+# trace:
+#   enabled: true
+#   # set sample_rate to 1 if you wanna sampling 100% of trace data; set 0.5 if you wanna sampling 50% of trace data, and so forth
+#   sample_rate: 1
+#   # # namespace used to differenciate different harbor services
+#   # namespace:
+#   # # attributes is a key value dict contains user defined attributes used to initialize trace provider
+#   # attributes:
+#   #   application: harbor
+#   # # jaeger should be 1.26 or newer.
+#   # jaeger:
+#   #   endpoint: http://hostname:14268/api/traces
+#   #   username:
+#   #   password:
+#   #   agent_host: hostname
+#   #   # export trace data by jaeger.thrift in compact mode
+#   #   agent_port: 6831
+#   # otel:
+#   #   endpoint: hostname:4318
+#   #   url_path: /v1/traces
+#   #   compression: false
+#   #   insecure: true
+#   #   timeout: 10s
diff --git a/ansible/harbor/vars/harbor.yaml b/ansible/harbor/vars/harbor.yaml
new file mode 100644
index 0000000..1cc3551
--- /dev/null
+++ b/ansible/harbor/vars/harbor.yaml
@@ -0,0 +1,32 @@
+hostname: harbor
+motd_text: "Harbor"
+
+user: harbor
+harbor_hostname: harbor.sch.bme.hu
+
+acme_email: laszlo.rafael@kszk.bme.hu
+sites: 
+  - name: harbor.sch.bme.hu
+    proxy_to: http://localhost:8080
+
+users:
+  - name: rlacko
+    sudo: yes
+    passwordless_sudo: yes
+    ssh_key: https://git.sch.bme.hu/rlacko.keys
+  - name: harbor
+    sudo: yes
+    passwordless_sudo: yes
+
+netplan:
+  network:
+    version: 2
+    renderer: networkd
+    ethernets:
+      wan:
+        optional: false
+        match:
+          macaddress: 00:50:56:a8:cf:aa
+        set-name: wan0
+        dhcp4: true
+
diff --git a/ansible/harbor/vars/secret.yaml.example b/ansible/harbor/vars/secret.yaml.example
new file mode 100644
index 0000000..deee7dc
--- /dev/null
+++ b/ansible/harbor/vars/secret.yaml.example
@@ -0,0 +1,2 @@
+HARBOR_INIT_PASSWORD: 
+DB_PASSWORD: 
diff --git a/ansible/inventory.yaml b/ansible/inventory.yaml
new file mode 100644
index 0000000..4eb8c13
--- /dev/null
+++ b/ansible/inventory.yaml
@@ -0,0 +1,10 @@
+all:
+  hosts:
+    # Use OpenSSH config to make it comfortable
+    harbor.sch.bme.hu:
+
+  children:
+    harbor:
+      hosts:
+        harbor.sch.bme.hu: {}
+  
\ No newline at end of file
diff --git a/ansible/requirements.galaxy.yaml b/ansible/requirements.galaxy.yaml
new file mode 100644
index 0000000..6998d12
--- /dev/null
+++ b/ansible/requirements.galaxy.yaml
@@ -0,0 +1,15 @@
+---
+collections:
+  - community.general
+  - community.crypto
+  - ansible.posix
+
+roles:
+  - src: git@git.sch.bme.hu:kszk/sysadmin/kubernetes/base-ansible-role.git
+    scm: git
+    version: master
+    name: kszk-k8s.base
+  - src: git@git.sch.bme.hu:kszk/sysadmin/kubernetes/iptables-role.git
+    scm: git
+    version: master
+    name: kszk-k8s.iptables
diff --git a/ansible/vars/base.yaml b/ansible/vars/base.yaml
new file mode 100644
index 0000000..54e46c5
--- /dev/null
+++ b/ansible/vars/base.yaml
@@ -0,0 +1,15 @@
+motd_playbook_url: https://git.sch.bme.hu/kszk/sysadmin/kubernetes/cluster-setup
+motd_text: Harbor
+
+users:
+  - name: rlacko
+    sudo: yes
+    passwordless_sudo: yes
+    ssh_key: https://git.sch.bme.hu/rlacko.keys
+ssh:
+  port: 10022
+  permitRootLogin: "no"
+  pubkeyAuthentication: "yes"
+  passwordAuthentication: "no"
+  allow:
+    users: "rlacko"
-- 
GitLab