├── ansible ├── k8s │ ├── tasks │ │ └── main.yml │ ├── roles │ │ ├── k8s_master │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── docker │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_base │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ └── k8s_node │ │ │ └── tasks │ │ │ └── main.yml │ ├── ansible.cfg │ ├── k8s.yml │ ├── vars │ │ └── main.yml │ └── group_vars │ │ └── all ├── k8s-config │ ├── group_vars │ │ └── all │ ├── tasks │ │ └── main.yml │ ├── vars │ │ └── main.yml │ ├── roles │ │ ├── k8s_vault │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ ├── files │ │ │ │ └── vault-values.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_gateway │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ ├── files │ │ │ │ └── apisix-values.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_keycloak │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ ├── templates │ │ │ │ ├── apisix-iam-route.j2 │ │ │ │ ├── kc-config.j2 │ │ │ │ └── apisix-secure-route.j2 │ │ │ ├── files │ │ │ │ └── kc-db-config.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_postgres │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_service_mesh │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_test_service │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ ├── files │ │ │ │ ├── test_config.yml │ │ │ │ ├── test-service.yml │ │ │ │ ├── apisix_hw_route.yml │ │ │ │ └── test_application.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_storage │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── k8s_monitoring │ │ │ ├── vars │ │ │ │ └── main.yml │ │ │ ├── files │ │ │ │ └── grafana-values.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ └── k8s_your_domain │ │ │ ├── vars │ │ │ └── main.yml │ │ │ ├── files │ │ │ └── coredns-cm.yml │ │ │ └── tasks │ │ │ └── main.yml │ ├── ansible.cfg │ └── k8s-config.yml ├── bootstrap │ ├── files │ │ └── sudoer_server-admin │ ├── ansible.cfg │ ├── bootstrap.yml │ └── templates │ │ └── sshd_config.j2 ├── nfs │ ├── files │ │ └── exports │ ├── ansible.cfg │ ├── templates │ │ └── minio-config.j2 │ └── nfs.yml ├── gateway │ ├── ansible.cfg │ ├── files │ │ ├── proxy_params │ │ └── network.conf │ ├── templates │ │ └── nginx-apisix-config.j2 │ └── gateway.yml ├── openvpn-client │ ├── ansible.cfg │ ├── files │ │ ├── make_config.sh │ │ └── base.conf │ ├── templates │ │ └── sshd_config.j2 │ └── openvpn-client.yml └── openvpn-server │ ├── ansible.cfg │ ├── openvpn-server.yml │ └── files │ └── server.conf ├── terraform ├── modules │ ├── vpc │ │ ├── vpc_outputs.tf │ │ ├── vpc_variables.tf │ │ └── vpc_main.tf │ ├── private_vps │ │ ├── private_vps_outputs.tf │ │ ├── private_vps_variables.tf │ │ └── private_vps_main.tf │ └── public_vps │ │ ├── public_vps_outputs.tf │ │ ├── public_vps_main.tf │ │ └── public_vps_variables.tf ├── ansible_inventory.tftpl ├── hosts.tftpl ├── rest_api_provider.tf ├── variables.tf ├── .terraform.lock.hcl └── main.tf ├── test-pvc.yml ├── .gitignore ├── LICENSE └── README.MD /ansible/k8s/tasks/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/group_vars/all: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/tasks/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_vault/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_gateway/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_keycloak/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_postgres/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_service_mesh/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_test_service/vars/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_storage/vars/main.yml: -------------------------------------------------------------------------------- 1 | share_point: /pv-share/auto -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_monitoring/vars/main.yml: -------------------------------------------------------------------------------- 1 | share_point: /pv-share/auto -------------------------------------------------------------------------------- /ansible/bootstrap/files/sudoer_server-admin: -------------------------------------------------------------------------------- 1 | server-admin ALL=(ALL) NOPASSWD: ALL 2 | -------------------------------------------------------------------------------- /ansible/k8s/roles/k8s_master/vars/main.yml: -------------------------------------------------------------------------------- 1 | k8s_packages: 2 | - kubectl 3 | - python3-pip 4 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_your_domain/vars/main.yml: -------------------------------------------------------------------------------- 1 | key_location: /etc/ssl/live/ 2 | dot: "." 3 | escape: "\\" -------------------------------------------------------------------------------- /ansible/nfs/files/exports: -------------------------------------------------------------------------------- 1 | /pv-share *(rw,async,no_subtree_check) 2 | /pv-share/auto *(rw,async,no_subtree_check) 3 | -------------------------------------------------------------------------------- /ansible/bootstrap/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = root 5 | 6 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_monitoring/files/grafana-values.yml: -------------------------------------------------------------------------------- 1 | grafana: 2 | enabled: true 3 | 4 | prometheus: 5 | enabled: false -------------------------------------------------------------------------------- /ansible/k8s/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = server-admin 5 | 6 | -------------------------------------------------------------------------------- /ansible/k8s/roles/docker/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: start_docker 2 | service: 3 | name: docker 4 | state: started 5 | enabled: yes -------------------------------------------------------------------------------- /ansible/nfs/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = server-admin 5 | 6 | -------------------------------------------------------------------------------- /ansible/gateway/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = server-admin 5 | 6 | -------------------------------------------------------------------------------- /ansible/k8s-config/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = server-admin 5 | 6 | -------------------------------------------------------------------------------- /terraform/modules/vpc/vpc_outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc_desc" { 2 | description = "The created VPC" 3 | value = restapi_object.bl_vpc 4 | } 5 | -------------------------------------------------------------------------------- /ansible/openvpn-client/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = server-admin 5 | 6 | -------------------------------------------------------------------------------- /ansible/openvpn-server/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ../inventory 3 | private_key_file = ~/.ssh/bl_rsa 4 | remote_user = server-admin 5 | 6 | -------------------------------------------------------------------------------- /test-pvc.yml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: test 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 1Gi 11 | storageClassName: nfs-client 12 | 13 | -------------------------------------------------------------------------------- /terraform/ansible_inventory.tftpl: -------------------------------------------------------------------------------- 1 | [k8s_master] 2 | ${master_ip} 3 | 4 | [k8s_node] 5 | %{ for addr in node_ips ~} 6 | ${addr} 7 | %{ endfor ~} 8 | 9 | [gw] 10 | ${gw_ip} 11 | 12 | [open_vpn] 13 | ${openvpn_ip} 14 | 15 | [nfs_server] 16 | ${nfs_ip} -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_test_service/files/test_config.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-config-1 5 | namespace: test-env 6 | data: 7 | index.html: | 8 | 9 |

Hello world 1!!

10 | -------------------------------------------------------------------------------- /ansible/k8s/k8s.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: k8s_master 4 | become: true 5 | roles: 6 | - docker 7 | - k8s_base 8 | - k8s_master 9 | 10 | - hosts: k8s_node 11 | become: true 12 | roles: 13 | - docker 14 | - k8s_base 15 | - k8s_node 16 | -------------------------------------------------------------------------------- /ansible/gateway/files/proxy_params: -------------------------------------------------------------------------------- 1 | proxy_set_header Host $http_host; 2 | proxy_set_header X-Real-IP $remote_addr; 3 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 4 | proxy_set_header X-Forwarded-Proto $scheme; 5 | proxy_busy_buffers_size 32k; 6 | proxy_buffers 4 32k; 7 | proxy_buffer_size 16k; -------------------------------------------------------------------------------- /ansible/k8s-config/k8s-config.yml: -------------------------------------------------------------------------------- 1 | - hosts: k8s_master 2 | become: true 3 | roles: 4 | - k8s_service_mesh 5 | - k8s_your_domain 6 | - k8s_storage 7 | - k8s_gateway 8 | - k8s_test_service 9 | - k8s_monitoring 10 | - k8s_vault 11 | - k8s_postgres 12 | - k8s_keycloak 13 | -------------------------------------------------------------------------------- /terraform/modules/vpc/vpc_variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_name" { 2 | description = "Name of the VPC to be created" 3 | type = string 4 | default = "my_vpc" 5 | } 6 | 7 | variable "vpc_ip_range" { 8 | description = "Subnet definition for the VPC" 9 | type = string 10 | default = "10.240.0.0/16" 11 | } 12 | -------------------------------------------------------------------------------- /ansible/k8s/roles/k8s_base/vars/main.yml: -------------------------------------------------------------------------------- 1 | k8s_dependencies: 2 | - kubernetes-cni 3 | - kubelet 4 | k8s_packages: 5 | - kubeadm 6 | 7 | k8s_url_apt_key: "https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key" 8 | k8s_gpgpath: /usr/share/keyrings/kubernetes-apt-keyring.gpg 9 | k8s_repository: "https://pkgs.k8s.io/core:/stable:/v1.29/deb/" -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_test_service/files/test-service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: hello-world-1-svc 5 | namespace: test-env 6 | spec: 7 | selector: 8 | app: nginx 9 | testService: service-1 10 | type: NodePort 11 | ports: 12 | - name: http 13 | port: 80 14 | targetPort: 80 15 | nodePort: 30081 -------------------------------------------------------------------------------- /terraform/hosts.tftpl: -------------------------------------------------------------------------------- 1 | ${gw_ip} iam.${custom_domain} 2 | ${gw_ip} apisix.${custom_domain} 3 | ${gw_ip} secure.${custom_domain} 4 | ${master_ip} k8s.${custom_domain} 5 | ${master_ip} vault.${custom_domain} 6 | ${nfs_ip} nfs.${custom_domain} 7 | ${gw_ip} iam 8 | ${gw_ip} apisix 9 | ${gw_ip} secure 10 | ${master_ip} k8s 11 | ${nfs_ip} nfs 12 | ${openvpn_ip} vpn 13 | 14 | -------------------------------------------------------------------------------- /ansible/k8s/vars/main.yml: -------------------------------------------------------------------------------- 1 | docker_dependencies: 2 | - ca-certificates 3 | - gnupg 4 | - gnupg2 5 | - gnupg-agent 6 | - software-properties-common 7 | - apt-transport-https 8 | - curl 9 | docker_packages: 10 | - docker-ce 11 | docker_url_apt_key: "https://download.docker.com/linux/debian/gpg" 12 | docker_repository: "deb [arch=amd64] https://download.docker.com/linux/debian bullseye stable" 13 | -------------------------------------------------------------------------------- /terraform/modules/vpc/vpc_main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | restapi = { source = "Mastercard/restapi" } 4 | } 5 | } 6 | 7 | resource "restapi_object" "bl_vpc" { 8 | path = "/vpcs" 9 | id_attribute = "vpc/id" 10 | data = <') \ 8 | ${KEY_DIR}/ca.crt \ 9 | <(echo -e '\n') \ 10 | ${KEY_DIR}/${1}.crt \ 11 | <(echo -e '\n') \ 12 | ${KEY_DIR}/${1}.key \ 13 | <(echo -e '\n') \ 14 | ${KEY_DIR}/ta.key \ 15 | <(echo -e '') \ 16 | > ${OUTPUT_DIR}/${1}.ovpn 17 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_test_service/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes test service 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | - name: create test namespace 7 | kubernetes.core.k8s: 8 | state: present 9 | kind: Namespace 10 | name: test-env 11 | definition: 12 | metadata: 13 | labels: 14 | istio-injection: enabled 15 | 16 | - name: Deploy manifest files 17 | kubernetes.core.k8s: 18 | definition: "{{ lookup('template', '{{ item }}') | from_yaml }}" 19 | with_fileglob: 20 | - "*.yml" 21 | 22 | -------------------------------------------------------------------------------- /terraform/modules/private_vps/private_vps_variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_id" { 2 | description = "ID of the VPC this server is to be created in" 3 | type = number 4 | default = 0 5 | } 6 | 7 | variable "vps_name" { 8 | description = "Name of the VPS server to be created" 9 | type = string 10 | default = "my_web_svr" 11 | } 12 | 13 | variable "vps_flavour" { 14 | description = "Flavour of the VPS server defining its dimensions" 15 | type = string 16 | default = "small" 17 | } 18 | 19 | variable "ssh_key" { 20 | description = "The SSH key to allow access to the VPS" 21 | type = string 22 | default = "" 23 | } 24 | -------------------------------------------------------------------------------- /terraform/modules/public_vps/public_vps_outputs.tf: -------------------------------------------------------------------------------- 1 | output "instance_id" { 2 | description = "ID of the created server" 3 | value = restapi_object.bl_vps 4 | } 5 | 6 | locals { 7 | v4networks = jsondecode(restapi_object.bl_vps.api_response).server.networks.v4 8 | v4_private_ip = local.v4networks[index(local.v4networks.*.type, "private")].ip_address 9 | v4_public_ip = local.v4networks[index(local.v4networks.*.type, "public")].ip_address 10 | } 11 | 12 | output "v4_ips" { 13 | description = "IP V4 addresses of VPS" 14 | value = { 15 | public = local.v4_public_ip, 16 | private = local.v4_private_ip 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_keycloak/templates/kc-config.j2: -------------------------------------------------------------------------------- 1 | apiVersion: k8s.keycloak.org/v2alpha1 2 | kind: Keycloak 3 | metadata: 4 | name: my-kc 5 | namespace: kc 6 | spec: 7 | instances: 1 8 | db: 9 | vendor: postgres 10 | host: kc-db-cluster-rw 11 | port: 5432 12 | database: keycloak 13 | schema: keycloak 14 | usernameSecret: 15 | name: pg-keycloak-user 16 | key: username 17 | passwordSecret: 18 | name: pg-keycloak-user 19 | key: password 20 | http: 21 | httpEnabled: true 22 | hostname: 23 | adminUrl: https://iam.{{ custom_domain }} 24 | hostname: iam.{{ custom_domain }} 25 | strict: true -------------------------------------------------------------------------------- /ansible/gateway/templates/nginx-apisix-config.j2: -------------------------------------------------------------------------------- 1 | upstream k8s_apisix_cluster { 2 | server {{ k8s_master }}:32006; 3 | server {{ k8s_node_2 }}:32006; 4 | server {{ k8s_node_1 }}:32006; 5 | } 6 | 7 | server { 8 | listen 443 ssl; 9 | listen [::]:443 ssl; 10 | 11 | server_name {{ domain }}; 12 | 13 | location / { 14 | proxy_pass http://k8s_apisix_cluster; 15 | include proxy_params; 16 | } 17 | 18 | ssl_certificate /etc/ssl/{{ domain }}.crt; 19 | ssl_certificate_key /etc/ssl/{{ domain }}.key; 20 | } 21 | 22 | server { 23 | listen 80; 24 | 25 | server_name {{ domain }}; 26 | 27 | return 302 https://$host$request_uri; 28 | } -------------------------------------------------------------------------------- /terraform/modules/private_vps/private_vps_main.tf: -------------------------------------------------------------------------------- 1 | 2 | terraform { 3 | required_providers { 4 | restapi = { source = "Mastercard/restapi" } 5 | } 6 | } 7 | 8 | resource "restapi_object" "bl_vps" { 9 | path = "/servers" 10 | id_attribute = "server/id" 11 | force_new = ["vps_flavour"] 12 | data = < 0 11 | 12 | - name: Remove SWAP from fstab K8S will not work with swap enabled (2/2) 13 | mount: 14 | name: "{{ item }}" 15 | fstype: swap 16 | state: absent 17 | with_items: 18 | - swap 19 | - none 20 | 21 | - name: Get Kubernetes package key 22 | shell: curl -fsSL {{ k8s_url_apt_key }} | gpg --dearmor -o {{ k8s_gpgpath }} 23 | args: 24 | creates: "{{ k8s_gpgpath }}" 25 | 26 | - name: Install Kubernetes repository 27 | apt_repository: 28 | filename: kubernetes 29 | repo: "deb [signed-by={{ k8s_gpgpath }}] {{ k8s_repository }} /" 30 | 31 | - name: Install Dependencies 32 | package: name={{ item }} state=present force=yes install_recommends=no 33 | loop: "{{ k8s_dependencies }}" 34 | 35 | - name: Install Kubernetes Packages 36 | package: name={{ item }} state=present force=yes install_recommends=no 37 | loop: "{{ k8s_packages }}" 38 | 39 | - name: Install nfs 40 | package: name=nfs-common state=present force=yes install_recommends=no 41 | 42 | -------------------------------------------------------------------------------- /ansible/bootstrap/bootstrap.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: all 4 | become: yes 5 | pre_tasks: 6 | 7 | - name: install updates (Ubuntu) 8 | tags: always 9 | apt: 10 | upgrade: dist 11 | update_cache: yes 12 | when: ansible_distribution == "Ubuntu" 13 | 14 | - name: install sudoers for Ubuntu servers 15 | tags: debian 16 | apt: 17 | name: 18 | - sudo 19 | state: latest 20 | when: ansible_distribution == "Ubuntu" 21 | 22 | - hosts: all 23 | become: true 24 | tasks: 25 | 26 | - name: create server-admin user 27 | tags: always 28 | user: 29 | name: server-admin 30 | groups: root 31 | shell: "/bin/bash" 32 | 33 | - name: Set authorized key taken from file 34 | authorized_key: 35 | user: server-admin 36 | state: present 37 | key: "{{ lookup('file', '~/.ssh/bl_rsa.pub') }}" 38 | 39 | - name: add sudoers file for server-admin 40 | tags: always 41 | copy: 42 | src: sudoer_server-admin 43 | dest: /etc/sudoers.d/server-admin 44 | owner: root 45 | group: root 46 | mode: 0440 47 | 48 | - name: generate sshd_config file from template 49 | tags: ssh 50 | vars: 51 | ssh_users: server-admin 52 | template: 53 | src: "sshd_config.j2" 54 | dest: /etc/ssh/sshd_config 55 | owner: root 56 | group: root 57 | mode: 0644 58 | notify: restart_sshd 59 | 60 | handlers: 61 | - name: restart_sshd 62 | service: 63 | name: sshd 64 | state: restarted 65 | -------------------------------------------------------------------------------- /ansible/k8s/roles/docker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install Docker 2 | tags: 3 | - docker 4 | - k8s_base 5 | - k8s_master 6 | block: 7 | - name: Configure Sysctl 8 | sysctl: 9 | name: "net.ipv4.ip_forward" 10 | value: "1" 11 | state: present 12 | 13 | - name: Install Prerequisites Packages 14 | package: name={{ item }} state=present force=yes 15 | loop: "{{ docker_dependencies }}" 16 | 17 | - name: Add GPG Keys 18 | apt_key: 19 | url: "{{ docker_url_apt_key }}" 20 | 21 | - name: Add Repo Source 22 | apt_repository: 23 | repo: "{{ docker_repository }}" 24 | update_cache: yes 25 | 26 | - name: Install Specific Version of Docker Packages 27 | package: name={{ item }} state=present force=yes install_recommends=no 28 | loop: "{{ docker_packages }}" 29 | notify: 30 | - start_docker 31 | 32 | - name: Enable CRI API 33 | lineinfile: 34 | path: /etc/containerd/config.toml 35 | regexp: "disabled_plugins.*" 36 | line: "disabled_plugins = []" 37 | state: present 38 | 39 | - name: Configure containerd - get default config 40 | shell: containerd config default | tee /etc/containerd/config.toml 41 | 42 | - name: Enable SystemdCgroup 43 | shell: sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml 44 | register: containerd 45 | 46 | - name: Restart containerd after config change 47 | service: 48 | name: containerd 49 | state: restarted 50 | when: containerd.changed 51 | 52 | 53 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_monitoring/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes monitoring 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | - name: create monitoring namespace 7 | kubernetes.core.k8s: 8 | state: present 9 | kind: Namespace 10 | name: monitoring 11 | definition: 12 | metadata: 13 | labels: 14 | istio-injection: enabled 15 | 16 | - name: Install grafana helm repo 17 | kubernetes.core.helm_repository: 18 | name: grafana 19 | repo_url: https://grafana.github.io/helm-charts 20 | 21 | - name: Copy grafana-values file 22 | tags: always 23 | become: no 24 | copy: 25 | src: grafana-values.yml 26 | dest: /home/server-admin/grafana-values.yml 27 | 28 | - name: Install chart 29 | kubernetes.core.helm: 30 | namespace: monitoring 31 | create_namespace: false 32 | release_name: loki 33 | chart_ref: grafana/loki-stack 34 | values_files: 35 | - /home/server-admin/grafana-values.yml 36 | 37 | - name: Add service to make it accessible within the VPC 38 | kubernetes.core.k8s: 39 | definition: 40 | apiVersion: v1 41 | kind: Service 42 | metadata: 43 | name: grafana-ui 44 | namespace: monitoring 45 | labels: 46 | name: grafana-ui 47 | spec: 48 | ports: 49 | - name: http 50 | port: 3000 51 | targetPort: 3000 52 | nodePort: 31300 53 | selector: 54 | app.kubernetes.io/name: grafana 55 | type: NodePort -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_service_mesh/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes istio 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | - name: Install isto provisioner helm repo 7 | kubernetes.core.helm_repository: 8 | name: istio 9 | repo_url: https://istio-release.storage.googleapis.com/charts 10 | 11 | - name: Install istio base operator helm chart 12 | kubernetes.core.helm: 13 | namespace: istio-system 14 | create_namespace: true 15 | release_name: isto-base 16 | chart_ref: istio/base 17 | wait: true 18 | 19 | - name: Install istiod operator helm chart 20 | kubernetes.core.helm: 21 | namespace: istio-system 22 | release_name: istod 23 | chart_ref: istio/istiod 24 | wait: true 25 | 26 | - name: Add mtls for Istio 27 | kubernetes.core.k8s: 28 | definition: 29 | apiVersion: security.istio.io/v1beta1 30 | kind: PeerAuthentication 31 | metadata: 32 | name: default 33 | namespace: istio-system 34 | spec: 35 | mtls: 36 | mode: STRICT 37 | 38 | - name: Download istioctl command line tool 39 | get_url: 40 | url: https://istio.io/downloadIstioctl 41 | dest: ./istioctl 42 | owner: server-admin 43 | group: server-admin 44 | mode: "700" 45 | 46 | - name: Install istioctl 47 | shell: ./istioctl 48 | 49 | - name: Add istoctl to path 50 | become: true 51 | copy: 52 | dest: /etc/profile.d/custom-path.sh 53 | content: 'PATH=/home/server-admin/.istioctl/bin:$PATH' 54 | mode: "0644" 55 | 56 | 57 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_keycloak/files/kc-db-config.yml: -------------------------------------------------------------------------------- 1 | apiVersion: postgresql.cnpg.io/v1 2 | kind: Cluster 3 | metadata: 4 | name: kc-db-cluster 5 | namespace: kc 6 | labels: 7 | cnpg.io/reload: "" 8 | spec: 9 | description: "Keycloak database cluster" 10 | imageName: ghcr.io/cloudnative-pg/postgresql:15.1 11 | instances: 1 12 | 13 | superuserSecret: 14 | name: pg-superuser 15 | 16 | managed: 17 | roles: 18 | - name: keycloak 19 | ensure: present 20 | comment: user for Keycloak application 21 | login: true 22 | superuser: false 23 | passwordSecret: 24 | name: pg-keycloak-user 25 | 26 | enableSuperuserAccess: true 27 | 28 | startDelay: 30 29 | stopDelay: 100 30 | primaryUpdateStrategy: unsupervised 31 | 32 | postgresql: 33 | parameters: 34 | max_connections: '200' 35 | shared_buffers: '256MB' 36 | effective_cache_size: '768MB' 37 | maintenance_work_mem: '64MB' 38 | checkpoint_completion_target: '0.9' 39 | wal_buffers: '7864kB' 40 | default_statistics_target: '100' 41 | random_page_cost: '1.1' 42 | effective_io_concurrency: '200' 43 | work_mem: '655kB' 44 | huge_pages: 'off' 45 | min_wal_size: '1GB' 46 | max_wal_size: '4GB' 47 | 48 | pg_hba: 49 | - host all all 10.0.0.0/8 scram-sha-256 50 | - hostssl all all 192.0.0.0/8 scram-sha-256 51 | - host all all 192.0.0.0/8 scram-sha-256 52 | - host all all 127.0.0.0/24 scram-sha-256 53 | - host all all all reject 54 | 55 | bootstrap: 56 | initdb: 57 | database: keycloak 58 | owner: keycloak 59 | secret: 60 | name: pg-keycloak-user 61 | postInitApplicationSQL: 62 | - create schema keycloak authorization keycloak 63 | - grant all on schema keycloak to keycloak 64 | - grant all on all tables in schema keycloak to keycloak 65 | 66 | storage: 67 | size: 10Gi 68 | storageClass: nfs-client -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_your_domain/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes to use your domain 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | - name: Setup TLS Lets Encrypt CA certificate 7 | tags: always 8 | become: yes 9 | copy: 10 | src: ~/{{ custom_domain }}.ca 11 | dest: "{{ key_location }}" 12 | 13 | - name: Setup TLS Lets Encrypt cert 14 | tags: always 15 | become: yes 16 | copy: 17 | src: ~/{{ custom_domain }}.crt 18 | dest: "{{ key_location }}" 19 | 20 | - name: Setup TLS Lets Encrypt key 21 | tags: always 22 | become: yes 23 | copy: 24 | src: ~/{{ custom_domain }}.key 25 | dest: "{{ key_location }}" 26 | 27 | - name: Check secret 28 | shell: kubectl get secrets -n default -o json | grep vault-ha-tls 29 | register: secret 30 | ignore_errors: true 31 | 32 | - name: Create TLS secret from files 33 | command: 34 | cmd: | 35 | kubectl create secret generic vault-ha-tls 36 | -n default 37 | --from-file=vault.key={{ key_location }}{{ custom_domain }}.key 38 | --from-file=vault.crt={{ key_location }}{{ custom_domain }}.crt 39 | --from-file=vault.ca={{ key_location }}{{ custom_domain }}.ca 40 | when: secret.stdout == '' 41 | 42 | - name: Escape domain name 43 | shell: echo {{ custom_domain }} | awk 'BEGIN {OFS=FS="\t"} {gsub(/\./,"\\.",$1)}1' 44 | register: escaped_custom_domain 45 | 46 | - name: Take coreDNS config file 47 | copy: 48 | src: coredns-cm.yml 49 | dest: ~/ 50 | 51 | - name: Add escaped custom domain 52 | replace: 53 | path: ~/coredns-cm.yml 54 | regexp: '(\s+.*)input(\s+.*)?$' 55 | replace: '\1(.*)-ns-(.*)\.{{ escaped_custom_domain.stdout }}\.$\2' 56 | 57 | - name: Add custom domain 58 | replace: 59 | path: ~/coredns-cm.yml 60 | regexp: '(\s+.*)output$' 61 | replace: '\1{{ custom_domain }}.' 62 | 63 | - name: Add custom domain to coreDNS 64 | kubernetes.core.k8s: 65 | state: present 66 | src: coredns-cm.yml -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_gateway/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes gateway application 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | - name: create test namespace 7 | kubernetes.core.k8s: 8 | state: present 9 | kind: Namespace 10 | name: apisix 11 | definition: 12 | metadata: 13 | labels: 14 | istio-injection: enabled 15 | 16 | - name: Install apisix repo 17 | kubernetes.core.helm_repository: 18 | name: apisix 19 | repo_url: https://charts.apiseven.com 20 | 21 | - name: Copy apisix-values file 22 | tags: always 23 | become: no 24 | copy: 25 | src: apisix-values.yml 26 | dest: /home/server-admin/apisix-values.yml 27 | 28 | - name: Install chart 29 | kubernetes.core.helm: 30 | namespace: apisix 31 | release_name: apisix 32 | chart_ref: apisix/apisix 33 | values_files: 34 | - /home/server-admin/apisix-values.yml 35 | 36 | - name: Add fixed gateway service 37 | kubernetes.core.k8s: 38 | definition: 39 | apiVersion: v1 40 | kind: Service 41 | metadata: 42 | name: apisix-gateway-fixed-svc 43 | namespace: apisix 44 | labels: 45 | name: apisix-gateway-fixed-svc 46 | spec: 47 | ports: 48 | - name: http 49 | port: 80 50 | targetPort: 9080 51 | nodePort: 32006 52 | selector: 53 | app.kubernetes.io/name: apisix 54 | type: NodePort 55 | 56 | - name: Add fixed gateway service 57 | kubernetes.core.k8s: 58 | definition: 59 | apiVersion: v1 60 | kind: Service 61 | metadata: 62 | name: apisix-dashboard-fixed-svc 63 | namespace: apisix 64 | labels: 65 | name: apisix-ui-svc 66 | spec: 67 | ports: 68 | - name: http 69 | port: 80 70 | targetPort: 9000 71 | nodePort: 30190 72 | externalIPs: 73 | - "{{ groups['k8s_master'][0] }}" 74 | selector: 75 | app.kubernetes.io/instance: apisix 76 | app.kubernetes.io/name: dashboard 77 | type: NodePort 78 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_vault/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes vault 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | - name: Create the vault k8s namespace 7 | kubernetes.core.k8s: 8 | state: present 9 | kind: Namespace 10 | name: vault 11 | definition: 12 | metadata: 13 | labels: 14 | istio-injection: enabled 15 | 16 | - name: Setup TLS Lets Encrypt CA certificate 17 | tags: always 18 | become: yes 19 | copy: 20 | src: ~/{{ custom_domain }}.ca 21 | dest: "{{ key_location }}" 22 | 23 | - name: Setup TLS Lets Encrypt cert 24 | tags: always 25 | become: yes 26 | copy: 27 | src: ~/{{ custom_domain }}.crt 28 | dest: "{{ key_location }}" 29 | 30 | - name: Setup TLS Lets Encrypt key 31 | tags: always 32 | become: yes 33 | copy: 34 | src: ~/{{ custom_domain }}.key 35 | dest: "{{ key_location }}" 36 | 37 | - name: Check secret 38 | shell: kubectl get secrets -n vault -o json | grep vault-ha-tls 39 | register: secret 40 | ignore_errors: true 41 | 42 | - name: Create TLS secret from files 43 | command: 44 | cmd: | 45 | kubectl create secret generic vault-ha-tls 46 | -n vault 47 | --from-file=vault.key={{ key_location }}{{ custom_domain }}.key 48 | --from-file=vault.crt={{ key_location }}{{ custom_domain }}.crt 49 | --from-file=vault.ca={{ key_location }}{{ custom_domain }}.ca 50 | when: secret.stdout == '' 51 | 52 | - name: Install Vault repo 53 | kubernetes.core.helm_repository: 54 | name: hashicorp 55 | repo_url: https://helm.releases.hashicorp.com 56 | 57 | - name: Copy vault-values file 58 | tags: always 59 | become: no 60 | copy: 61 | src: vault-values.yml 62 | dest: /home/server-admin/vault-values.yml 63 | 64 | - name: Add custom domain 65 | replace: 66 | path: /home/server-admin/vault-values.yml 67 | regexp: custom_domain 68 | replace: "{{ custom_domain }}" 69 | 70 | - name: Install chart 71 | kubernetes.core.helm: 72 | namespace: vault 73 | create_namespace: true 74 | release_name: vault 75 | chart_ref: hashicorp/vault 76 | values_files: 77 | - /home/server-admin/vault-values.yml 78 | register: chartStatus 79 | -------------------------------------------------------------------------------- /terraform/.terraform.lock.hcl: -------------------------------------------------------------------------------- 1 | # This file is maintained automatically by "terraform init". 2 | # Manual edits may be lost in future updates. 3 | 4 | provider "registry.terraform.io/hashicorp/local" { 5 | version = "2.4.1" 6 | hashes = [ 7 | "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", 8 | "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", 9 | "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", 10 | "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", 11 | "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", 12 | "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", 13 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", 14 | "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", 15 | "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", 16 | "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", 17 | "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", 18 | "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", 19 | "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", 20 | ] 21 | } 22 | 23 | provider "registry.terraform.io/mastercard/restapi" { 24 | version = "1.18.2" 25 | hashes = [ 26 | "h1:oO72/tRRydsYTvSqx/+CeXXxkXTK7LAQ2uZIQ/nH6U8=", 27 | "zh:0544dc6cf5fd8d6270a8afcc2a14b64e3d89f6b9933e89d97a187746a12e0c89", 28 | "zh:0bbc011635e9b140c8112abe17e410bd19c9973526facaf4925afa20d576e693", 29 | "zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7", 30 | "zh:1d320b0781571787993af29ef869eaed675c41269c4c02eaf56a367c4080af09", 31 | "zh:26dc021321c990dc641da98a271ee702cc69fc155b9014b13721062f9790ff72", 32 | "zh:27e149a7775581557cfa8d1a7a0acac8d8b1c09b67b12006b57f3e0187961211", 33 | "zh:2e1c1f16f04bd4cc5c1e8f729f5cc82e56bf03142379e9fd327e40e4499f30fe", 34 | "zh:3854befbd1a159fa971a5ecb01ef3e18cbabeccd79270efea2368f9539d98d73", 35 | "zh:76f008fb8c68d1bb2d4ca1113ae7ddfb29621ea2bca1c289caa54dae4436794c", 36 | "zh:772d6f9b5ad18a9b7082602dbfe85e94d26e6de72e4a6d86e104b95d91350b0a", 37 | "zh:81b5d8e3f92371d50e5f5ad39677fded7ab2f714fb433a4dde80f718d5988928", 38 | "zh:9412a5ce60bb2a6bc05fea9993e1ed33ba930e9f4e99e81d23b9f6461229d52d", 39 | "zh:b7ee5f59f1f88a6dea9cf853b6b9e84bc283954d800f624c0cedf70d072e4d5a", 40 | "zh:cbfd1af32850f7732693a1ef19bce5a36ecec9f06fbe28be403aa9c4ada5ec15", 41 | "zh:f7e5575e89e63eb3c3e318a37020b32f42017f45e180281f48f9def536bc5722", 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.5.5" 3 | required_providers { 4 | restapi = { 5 | source = "Mastercard/restapi" 6 | } 7 | } 8 | } 9 | 10 | module "vpc" { 11 | source = "./modules/vpc" 12 | vpc_name = "${var.project_prefix}-vpc" 13 | } 14 | 15 | output "vpc" { 16 | description = "vpc" 17 | value = module.vpc.vpc_desc 18 | } 19 | 20 | module "gw" { 21 | source = "./modules/public_vps" 22 | vps_name = "${var.project_prefix}-gw" 23 | vps_flavour = "std-min" 24 | vpc_id = module.vpc.vpc_desc.id 25 | ssh_key = var.ssh_key 26 | } 27 | 28 | output "gw" { 29 | description = "gw" 30 | value = module.gw.v4_ips 31 | } 32 | 33 | module "openvpn" { 34 | source = "./modules/public_vps" 35 | vps_name = "${var.project_prefix}-openvpn" 36 | vps_flavour = "std-min" 37 | vpc_id = module.vpc.vpc_desc.id 38 | ssh_key = var.ssh_key 39 | port_blocking = false 40 | } 41 | 42 | output "openvpn" { 43 | description = "openvpn" 44 | value = module.k8s_master.v4_ips 45 | } 46 | 47 | module "k8s_master" { 48 | source = "./modules/private_vps" 49 | vps_name = "${var.project_prefix}-k8s-master" 50 | vps_flavour = "std-2vcpu" 51 | vpc_id = module.vpc.vpc_desc.id 52 | ssh_key = var.ssh_key 53 | } 54 | 55 | output "k8s_master" { 56 | description = "k8s_master" 57 | value = module.k8s_master.v4_ips 58 | } 59 | 60 | module "k8s_node_1" { 61 | source = "./modules/private_vps" 62 | vps_name = "${var.project_prefix}-k8s-node-1" 63 | vps_flavour = "std-2vcpu" 64 | vpc_id = module.vpc.vpc_desc.id 65 | ssh_key = var.ssh_key 66 | } 67 | 68 | output "k8s_node_1" { 69 | description = "k8s_node_1" 70 | value = module.k8s_node_1.v4_ips 71 | } 72 | 73 | module "k8s_node_2" { 74 | source = "./modules/private_vps" 75 | vps_name = "${var.project_prefix}-k8s-node-2" 76 | vps_flavour = "std-2vcpu" 77 | vpc_id = module.vpc.vpc_desc.id 78 | ssh_key = var.ssh_key 79 | } 80 | 81 | output "k8s_node_2" { 82 | description = "k8s_node_2" 83 | value = module.k8s_node_2.v4_ips 84 | } 85 | 86 | module "nfs_server" { 87 | source = "./modules/private_vps" 88 | vps_name = "${var.project_prefix}-nfs-server" 89 | vps_flavour = "std-min" 90 | vpc_id = module.vpc.vpc_desc.id 91 | ssh_key = var.ssh_key 92 | } 93 | 94 | output "nfs_server" { 95 | description = "nfs_server" 96 | value = module.nfs_server.v4_ips 97 | } 98 | 99 | resource "local_file" "inventory" { 100 | filename = "../ansible/inventory" 101 | content = templatefile("ansible_inventory.tftpl", { 102 | openvpn_ip = module.openvpn.v4_ips.public 103 | gw_ip = module.gw.v4_ips.public 104 | nfs_ip = module.nfs_server.v4_ips.private 105 | master_ip = module.k8s_master.v4_ips.private 106 | node_ips = [ 107 | module.k8s_node_1.v4_ips.private, 108 | module.k8s_node_2.v4_ips.private 109 | ] 110 | }) 111 | } 112 | 113 | resource "local_file" "etc-hosts" { 114 | filename = "etc-hosts" 115 | content = templatefile("hosts.tftpl", { 116 | gw_ip = module.gw.v4_ips.public 117 | nfs_ip = module.nfs_server.v4_ips.private 118 | openvpn_ip = module.openvpn.v4_ips.public 119 | master_ip = module.k8s_master.v4_ips.private 120 | custom_domain = var.custom_domain 121 | }) 122 | } 123 | 124 | -------------------------------------------------------------------------------- /ansible/k8s/roles/k8s_master/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up base config for k8s master and node 2 | tags: 3 | - k8s_master 4 | block: 5 | - name: Install Kubernetes Packages 6 | package: name={{ item }} state=present force=yes install_recommends=no 7 | loop: "{{ k8s_packages }}" 8 | 9 | - name: Initialise the Kubernetes cluster using kubeadm 10 | become: true 11 | command: kubeadm init --pod-network-cidr={{ k8s_pod_network }} 12 | args: 13 | creates: "{{ k8s_admin_config }}" 14 | 15 | - name: Setup kubeconfig for {{ k8s_user }} user 16 | file: 17 | path: "{{ k8s_user_home }}/.kube" 18 | state: directory 19 | owner: "{{ k8s_user }}" 20 | group: "{{ k8s_user }}" 21 | mode: "0750" 22 | 23 | - name: Copy {{ k8s_admin_config }} 24 | become: true 25 | copy: 26 | src: "{{ k8s_admin_config }}" 27 | dest: "{{ k8s_user_home }}/.kube/config" 28 | owner: "{{ k8s_user }}" 29 | group: "{{ k8s_user }}" 30 | mode: "0600" 31 | remote_src: yes 32 | 33 | - name: has calico been set up? 34 | stat: 35 | path: /home/server-admin/calico.yaml 36 | register: calico 37 | 38 | - block: 39 | 40 | - name: Download {{ calico_operator_url }} 41 | get_url: 42 | url: "{{ calico_operator_url }}" 43 | dest: "{{ k8s_user_home }}/{{ calico_operator_config }}" 44 | owner: "{{ k8s_user }}" 45 | group: "{{ k8s_user }}" 46 | mode: "0640" 47 | 48 | - name: Download {{ calico_net_url }} 49 | get_url: 50 | url: "{{ calico_net_url }}" 51 | dest: "{{ k8s_user_home }}/{{ calico_net_config }}" 52 | owner: "{{ k8s_user }}" 53 | group: "{{ k8s_user }}" 54 | mode: "0640" 55 | 56 | - name: Install calico operator {{ calico_operator_config }} 57 | become: false 58 | command: kubectl create -f "{{ k8s_user_home }}/{{ calico_operator_config }}" 59 | 60 | - name: Set CALICO_IPV4POOL_CIDR to {{ k8s_pod_network }} 61 | replace: 62 | path: "{{ k8s_user_home }}/{{ calico_net_config }}" 63 | regexp: "192.168.0.0/16" 64 | replace: "{{ k8s_pod_network }}" 65 | 66 | - name: Install calico pod network {{ calico_net_config }} 67 | become: false 68 | command: kubectl apply -f "{{ k8s_user_home }}/{{ calico_net_config }}" 69 | 70 | when: not calico.stat.exists 71 | 72 | - name: wait for k8s API port to open 73 | wait_for: 74 | port: 6443 75 | 76 | - name: Generate join command 77 | command: kubeadm token create --print-join-command 78 | register: join_command 79 | 80 | - name: Copy join command to local file 81 | become: false 82 | local_action: copy content="{{ join_command.stdout_lines[0] }}" dest="{{ k8s_join_file }}" 83 | 84 | - name: Install helm if not exists 85 | unarchive: 86 | src: https://get.helm.sh/helm-{{ helm_version }}-linux-amd64.tar.gz 87 | dest: /usr/local/bin 88 | extra_opts: "--strip-components=1" 89 | owner: root 90 | group: root 91 | mode: 0755 92 | remote_src: true 93 | args: 94 | creates: /usr/local/bin/helm 95 | 96 | - name: Install kubernetes python client dependency for ansible 97 | pip: 98 | name: 99 | - kubernetes 100 | -------------------------------------------------------------------------------- /ansible/nfs/nfs.yml: -------------------------------------------------------------------------------- 1 | - hosts: nfs_server 2 | become: yes 3 | tasks: 4 | 5 | - name: install updates (Ubuntu) 6 | tags: always 7 | apt: 8 | upgrade: dist 9 | update_cache: yes 10 | when: ansible_distribution == "Ubuntu" 11 | 12 | - name: Install nfs server 13 | apt: 14 | name: nfs-kernel-server 15 | state: present 16 | force: yes 17 | install_recommends: no 18 | 19 | - name: Set up nfs shares 20 | tags: always 21 | copy: 22 | src: exports 23 | dest: /etc/exports 24 | owner: root 25 | group: root 26 | mode: 0440 27 | notify: restart_nfs 28 | 29 | - name: Ensure (needs to be linked to exports file) 30 | tags: always 31 | file: 32 | path: '/pv-share' 33 | state: directory 34 | owner: root 35 | group: root 36 | mode: 0777 37 | notify: restart_nfs 38 | 39 | - name: Ensure (needs to be linked to exports file) 40 | tags: always 41 | file: 42 | path: '/pv-share/auto' 43 | state: directory 44 | owner: root 45 | group: root 46 | mode: 0777 47 | notify: restart_nfs 48 | 49 | - name: create minio group 50 | tags: always 51 | group: 52 | name: minio-user 53 | system: true 54 | 55 | - name: create minio user 56 | tags: always 57 | user: 58 | name: minio-user 59 | groups: minio-user 60 | shell: "/sbin/nologin" 61 | append: true 62 | create_home: no 63 | 64 | - name: Create minIO folder 65 | file: 66 | path: /mnt/minio 67 | state: directory 68 | owner: minio-user 69 | 70 | - name: Dowload minIO package 71 | get_url: 72 | url: https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20240310025348.0.0_amd64.deb 73 | dest: ./minio.deb 74 | 75 | - name: Install minIO 76 | apt: 77 | deb: minio.deb 78 | 79 | - name: has config already been uploaded? 80 | stat: 81 | path: /etc/default/minio 82 | register: minio_config 83 | 84 | - block: 85 | - name: Create minIO password 86 | set_fact: 87 | minio_pw: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii', 'digits'], length=20) }}" 88 | 89 | - name: Save config 90 | template: 91 | src: minio-config.j2 92 | dest: /etc/default/minio 93 | owner: minio-user 94 | group: minio-user 95 | mode: 0600 96 | notify: restart_minio 97 | 98 | - name: Create path for TLS certificates 99 | file: 100 | path: /etc/minio/certs 101 | state: directory 102 | owner: minio-user 103 | group: minio-user 104 | recurse: yes 105 | notify: restart_minio 106 | 107 | - name: Copy in certificate 108 | copy: 109 | src: ~/{{ custom_domain }}.crt 110 | dest: /etc/minio/certs/public.crt 111 | owner: minio-user 112 | group: minio-user 113 | notify: restart_minio 114 | 115 | - name: Copy in key 116 | copy: 117 | src: ~/{{ custom_domain }}.key 118 | dest: /etc/minio/certs/private.key 119 | owner: minio-user 120 | group: minio-user 121 | notify: restart_minio 122 | when: minio_config.stat.exists == false 123 | 124 | handlers: 125 | - name: restart_nfs 126 | service: 127 | name: nfs-server 128 | state: restarted 129 | enabled: true 130 | 131 | - name: restart_minio 132 | service: 133 | name: minio 134 | state: restarted 135 | enabled: true 136 | -------------------------------------------------------------------------------- /ansible/bootstrap/templates/sshd_config.j2: -------------------------------------------------------------------------------- 1 | # $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ 2 | 3 | # This file was generated automatically using a j2 template and Ansible 4 | 5 | # This is the sshd server system-wide configuration file. See 6 | # sshd_config(5) for more information. 7 | 8 | # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin 9 | 10 | # The strategy used for options in the default sshd_config shipped with 11 | # OpenSSH is to specify options with their default value where 12 | # possible, but leave them commented. Uncommented options override the 13 | # default value. 14 | 15 | Include /etc/ssh/sshd_config.d/*.conf 16 | AllowUsers {{ ssh_users }} 17 | 18 | #Port 22 19 | #AddressFamily any 20 | #ListenAddress 0.0.0.0 21 | #ListenAddress :: 22 | 23 | #HostKey /etc/ssh/ssh_host_rsa_key 24 | #HostKey /etc/ssh/ssh_host_ecdsa_key 25 | #HostKey /etc/ssh/ssh_host_ed25519_key 26 | 27 | # Ciphers and keying 28 | #RekeyLimit default none 29 | 30 | # Logging 31 | #SyslogFacility AUTH 32 | #LogLevel INFO 33 | 34 | # Authentication: 35 | 36 | #LoginGraceTime 2m 37 | #PermitRootLogin prohibit-password 38 | PermitRootLogin yes 39 | #StrictModes yes 40 | #MaxAuthTries 6 41 | #MaxSessions 10 42 | 43 | #PubkeyAuthentication yes 44 | 45 | # Expect .ssh/authorized_keys2 to be disregarded by default in future. 46 | #AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 47 | 48 | #AuthorizedPrincipalsFile none 49 | 50 | #AuthorizedKeysCommand none 51 | #AuthorizedKeysCommandUser nobody 52 | 53 | # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts 54 | #HostbasedAuthentication no 55 | # Change to yes if you don't trust ~/.ssh/known_hosts for 56 | # HostbasedAuthentication 57 | #IgnoreUserKnownHosts no 58 | # Don't read the user's ~/.rhosts and ~/.shosts files 59 | #IgnoreRhosts yes 60 | 61 | # To disable tunneled clear text passwords, change to no here! 62 | #PasswordAuthentication yes 63 | #PermitEmptyPasswords no 64 | 65 | # Change to yes to enable challenge-response passwords (beware issues with 66 | # some PAM modules and threads) 67 | ChallengeResponseAuthentication no 68 | 69 | # Kerberos options 70 | #KerberosAuthentication no 71 | #KerberosOrLocalPasswd yes 72 | #KerberosTicketCleanup yes 73 | #KerberosGetAFSToken no 74 | 75 | # GSSAPI options 76 | #GSSAPIAuthentication no 77 | #GSSAPICleanupCredentials yes 78 | #GSSAPIStrictAcceptorCheck yes 79 | #GSSAPIKeyExchange no 80 | 81 | # Set this to 'yes' to enable PAM authentication, account processing, 82 | # and session processing. If this is enabled, PAM authentication will 83 | # be allowed through the ChallengeResponseAuthentication and 84 | # PasswordAuthentication. Depending on your PAM configuration, 85 | # PAM authentication via ChallengeResponseAuthentication may bypass 86 | # the setting of "PermitRootLogin without-password". 87 | # If you just want the PAM account and session checks to run without 88 | # PAM authentication, then enable this but set PasswordAuthentication 89 | # and ChallengeResponseAuthentication to 'no'. 90 | UsePAM yes 91 | 92 | #AllowAgentForwarding yes 93 | #AllowTcpForwarding yes 94 | #GatewayPorts no 95 | X11Forwarding yes 96 | #X11DisplayOffset 10 97 | #X11UseLocalhost yes 98 | #PermitTTY yes 99 | PrintMotd no 100 | #PrintLastLog yes 101 | #TCPKeepAlive yes 102 | #PermitUserEnvironment no 103 | #Compression delayed 104 | #ClientAliveInterval 0 105 | #ClientAliveCountMax 3 106 | #UseDNS no 107 | #PidFile /var/run/sshd.pid 108 | #MaxStartups 10:30:100 109 | #PermitTunnel no 110 | #ChrootDirectory none 111 | #VersionAddendum none 112 | 113 | # no default banner path 114 | #Banner none 115 | 116 | # Allow client to pass locale environment variables 117 | AcceptEnv LANG LC_* 118 | 119 | # override default of no subsystems 120 | Subsystem sftp /usr/lib/openssh/sftp-server 121 | 122 | # Example of overriding settings on a per-user basis 123 | #Match User anoncvs 124 | # X11Forwarding no 125 | # AllowTcpForwarding no 126 | # PermitTTY no 127 | # ForceCommand cvs server 128 | -------------------------------------------------------------------------------- /ansible/k8s-config/roles/k8s_keycloak/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Set up Kubernetes gateway application 2 | become: false 3 | tags: 4 | - k8s_master 5 | block: 6 | # Note that this requires the k8s_postgres role to be configured 7 | - name: Create keycloak (kc) namespace 8 | kubernetes.core.k8s: 9 | state: present 10 | kind: Namespace 11 | name: kc 12 | definition: 13 | metadata: 14 | labels: 15 | istio-injection: enabled 16 | 17 | - name: Create postgres user secret 18 | kubernetes.core.k8s: 19 | state: present 20 | definition: 21 | apiVersion: v1 22 | kind: Secret 23 | type: kubernetes.io/basic-auth 24 | metadata: 25 | name: pg-superuser 26 | namespace: kc 27 | data: 28 | password: "{{ postgres_pw | b64encode }}" 29 | username: cG9zdGdyZXM= #keycloak 30 | 31 | - name: Create keycloak user secret 32 | kubernetes.core.k8s: 33 | state: present 34 | definition: 35 | apiVersion: v1 36 | kind: Secret 37 | type: kubernetes.io/basic-auth 38 | metadata: 39 | name: pg-keycloak-user 40 | namespace: kc 41 | data: 42 | password: "{{ keycloak_pw | b64encode }}" 43 | username: a2V5Y2xvYWs= #keycloak 44 | 45 | - name: Grab the database config file 46 | copy: 47 | src: kc-db-config.yml 48 | dest: ~/ 49 | 50 | - name: Install Keycloak database 51 | kubernetes.core.k8s: 52 | state: present 53 | src: kc-db-config.yml 54 | 55 | - name: Download Keycloak CRDs 56 | ansible.builtin.get_url: 57 | url: https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/23.0.6/kubernetes/keycloaks.k8s.keycloak.org-v1.yml 58 | dest: ~/keycloaks.k8s.keycloak.org-v1.yml 59 | mode: '0664' 60 | 61 | - name: Download Keycloak Realm Import CRDs 62 | ansible.builtin.get_url: 63 | url: https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/23.0.6/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml 64 | dest: ~/keycloakrealmimports.k8s.keycloak.org-v1.yml 65 | mode: '0664' 66 | 67 | - name: Apply Keycloak CRD 68 | kubernetes.core.k8s: 69 | state: present 70 | src: ~/keycloaks.k8s.keycloak.org-v1.yml 71 | 72 | - name: Apply Keycloak Realm Import CRD 73 | kubernetes.core.k8s: 74 | state: present 75 | src: ~/keycloakrealmimports.k8s.keycloak.org-v1.yml 76 | 77 | - name: Download Keycloak operator 78 | ansible.builtin.get_url: 79 | url: https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/23.0.6/kubernetes/kubernetes.yml 80 | dest: ~/keycloak-operator.yml 81 | mode: '0664' 82 | 83 | - name: Install Keycloak operator 84 | kubernetes.core.k8s: 85 | state: present 86 | namespace: kc 87 | src: ~/keycloak-operator.yml 88 | 89 | - name: Grab the base Keycloak config file 90 | template: 91 | src: kc-config.j2 92 | dest: ~/kc-config.yml 93 | 94 | - name: Install Keycloak 95 | kubernetes.core.k8s: 96 | state: present 97 | src: kc-config.yml 98 | 99 | - name: Grab the APISIX route config file 100 | template: 101 | src: apisix-iam-route.j2 102 | dest: ~/apisix-iam-route.yml 103 | 104 | - name: Install APISIX route 105 | kubernetes.core.k8s: 106 | state: present 107 | src: apisix-iam-route.yml 108 | 109 | - name: Grab the APISIX secure route config file 110 | template: 111 | src: apisix-secure-route.j2 112 | dest: ~/apisix-secure-route.yml 113 | 114 | - name: Install APISIX secure route 115 | kubernetes.core.k8s: 116 | state: present 117 | src: apisix-secure-route.yml 118 | when: client_secret != "" 119 | 120 | -------------------------------------------------------------------------------- /ansible/openvpn-client/templates/sshd_config.j2: -------------------------------------------------------------------------------- 1 | # $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $ 2 | 3 | # This file was generated automatically using a j2 template and Ansible 4 | 5 | # This is the sshd server system-wide configuration file. See 6 | # sshd_config(5) for more information. 7 | 8 | # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin 9 | 10 | # The strategy used for options in the default sshd_config shipped with 11 | # OpenSSH is to specify options with their default value where 12 | # possible, but leave them commented. Uncommented options override the 13 | # default value. 14 | 15 | Include /etc/ssh/sshd_config.d/*.conf 16 | AllowUsers {{ ssh_users }} 17 | 18 | #Port 22 19 | #AddressFamily any 20 | #ListenAddress 0.0.0.0 21 | #ListenAddress :: 22 | 23 | #HostKey /etc/ssh/ssh_host_rsa_key 24 | #HostKey /etc/ssh/ssh_host_ecdsa_key 25 | #HostKey /etc/ssh/ssh_host_ed25519_key 26 | 27 | # Ciphers and keying 28 | #RekeyLimit default none 29 | 30 | # Logging 31 | #SyslogFacility AUTH 32 | #LogLevel INFO 33 | 34 | # Authentication: 35 | 36 | #LoginGraceTime 2m 37 | #PermitRootLogin prohibit-password 38 | PermitRootLogin yes 39 | #StrictModes yes 40 | #MaxAuthTries 6 41 | #MaxSessions 10 42 | 43 | #PubkeyAuthentication yes 44 | 45 | # Expect .ssh/authorized_keys2 to be disregarded by default in future. 46 | #AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 47 | 48 | #AuthorizedPrincipalsFile none 49 | 50 | #AuthorizedKeysCommand none 51 | #AuthorizedKeysCommandUser nobody 52 | 53 | # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts 54 | #HostbasedAuthentication no 55 | # Change to yes if you don't trust ~/.ssh/known_hosts for 56 | # HostbasedAuthentication 57 | #IgnoreUserKnownHosts no 58 | # Don't read the user's ~/.rhosts and ~/.shosts files 59 | #IgnoreRhosts yes 60 | 61 | # To disable tunneled clear text passwords, change to no here! 62 | #PasswordAuthentication yes 63 | #PermitEmptyPasswords no 64 | 65 | # Change to yes to enable challenge-response passwords (beware issues with 66 | # some PAM modules and threads) 67 | ChallengeResponseAuthentication no 68 | 69 | # Kerberos options 70 | #KerberosAuthentication no 71 | #KerberosOrLocalPasswd yes 72 | #KerberosTicketCleanup yes 73 | #KerberosGetAFSToken no 74 | 75 | # GSSAPI options 76 | #GSSAPIAuthentication no 77 | #GSSAPICleanupCredentials yes 78 | #GSSAPIStrictAcceptorCheck yes 79 | #GSSAPIKeyExchange no 80 | 81 | # Set this to 'yes' to enable PAM authentication, account processing, 82 | # and session processing. If this is enabled, PAM authentication will 83 | # be allowed through the ChallengeResponseAuthentication and 84 | # PasswordAuthentication. Depending on your PAM configuration, 85 | # PAM authentication via ChallengeResponseAuthentication may bypass 86 | # the setting of "PermitRootLogin without-password". 87 | # If you just want the PAM account and session checks to run without 88 | # PAM authentication, then enable this but set PasswordAuthentication 89 | # and ChallengeResponseAuthentication to 'no'. 90 | UsePAM yes 91 | 92 | #AllowAgentForwarding yes 93 | #AllowTcpForwarding yes 94 | #GatewayPorts no 95 | X11Forwarding yes 96 | #X11DisplayOffset 10 97 | #X11UseLocalhost yes 98 | #PermitTTY yes 99 | PrintMotd no 100 | #PrintLastLog yes 101 | #TCPKeepAlive yes 102 | #PermitUserEnvironment no 103 | #Compression delayed 104 | #ClientAliveInterval 0 105 | #ClientAliveCountMax 3 106 | #UseDNS no 107 | #PidFile /var/run/sshd.pid 108 | #MaxStartups 10:30:100 109 | #PermitTunnel no 110 | #ChrootDirectory none 111 | #VersionAddendum none 112 | 113 | # no default banner path 114 | #Banner none 115 | 116 | # Allow client to pass locale environment variables 117 | AcceptEnv LANG LC_* 118 | 119 | # override default of no subsystems 120 | Subsystem sftp /usr/lib/openssh/sftp-server 121 | 122 | # Example of overriding settings on a per-user basis 123 | #Match User anoncvs 124 | # X11Forwarding no 125 | # AllowTcpForwarding no 126 | # PermitTTY no 127 | # ForceCommand cvs server 128 | -------------------------------------------------------------------------------- /ansible/openvpn-client/files/base.conf: -------------------------------------------------------------------------------- 1 | ############################################## 2 | # Sample client-side OpenVPN 2.0 config file # 3 | # for connecting to multi-client server. # 4 | # # 5 | # This configuration can be used by multiple # 6 | # clients, however each client should have # 7 | # its own cert and key files. # 8 | # # 9 | # On Windows, you might want to rename this # 10 | # file so it has a .ovpn extension # 11 | ############################################## 12 | 13 | route 10.240.0.0 255.255.0.0 14 | 15 | # Specify that we are a client and that we 16 | # will be pulling certain config file directives 17 | # from the server. 18 | client 19 | 20 | # Use the same setting as you are using on 21 | # the server. 22 | # On most systems, the VPN will not function 23 | # unless you partially or fully disable 24 | # the firewall for the TUN/TAP interface. 25 | ;dev tap 26 | dev tun 27 | 28 | # Windows needs the TAP-Win32 adapter name 29 | # from the Network Connections panel 30 | # if you have more than one. On XP SP2, 31 | # you may need to disable the firewall 32 | # for the TAP adapter. 33 | ;dev-node MyTap 34 | 35 | # Are we connecting to a TCP or 36 | # UDP server? Use the same setting as 37 | # on the server. 38 | ;proto tcp 39 | proto udp 40 | 41 | # The hostname/IP and port of the server. 42 | # You can have multiple remote entries 43 | # to load balance between the servers. 44 | remote IP 1194 45 | ;remote my-server-2 1194 46 | 47 | # Choose a random host from the remote 48 | # list for load-balancing. Otherwise 49 | # try hosts in the order specified. 50 | ;remote-random 51 | 52 | # Keep trying indefinitely to resolve the 53 | # host name of the OpenVPN server. Very useful 54 | # on machines which are not permanently connected 55 | # to the internet such as laptops. 56 | resolv-retry infinite 57 | 58 | # Most clients don't need to bind to 59 | # a specific local port number. 60 | nobind 61 | 62 | # Downgrade privileges after initialization (non-Windows only) 63 | user nobody 64 | group nogroup 65 | 66 | # Try to preserve some state across restarts. 67 | persist-key 68 | persist-tun 69 | 70 | # If you are connecting through an 71 | # HTTP proxy to reach the actual OpenVPN 72 | # server, put the proxy server/IP and 73 | # port number here. See the man page 74 | # if your proxy server requires 75 | # authentication. 76 | ;http-proxy-retry # retry on connection failures 77 | ;http-proxy [proxy server] [proxy port #] 78 | 79 | # Wireless networks often produce a lot 80 | # of duplicate packets. Set this flag 81 | # to silence duplicate packet warnings. 82 | ;mute-replay-warnings 83 | 84 | # SSL/TLS parms. 85 | # See the server config file for more 86 | # description. It's best to use 87 | # a separate .crt/.key file pair 88 | # for each client. A single ca 89 | # file can be used for all clients. 90 | #ca ca.crt 91 | #cert client.crt 92 | #key client.key 93 | 94 | # Verify server certificate by checking that the 95 | # certificate has the correct key usage set. 96 | # This is an important precaution to protect against 97 | # a potential attack discussed here: 98 | # http://openvpn.net/howto.html#mitm 99 | # 100 | # To use this feature, you will need to generate 101 | # your server certificates with the keyUsage set to 102 | # digitalSignature, keyEncipherment 103 | # and the extendedKeyUsage to 104 | # serverAuth 105 | # EasyRSA can do this for you. 106 | remote-cert-tls server 107 | 108 | # If a tls-auth key is used on the server 109 | # then every client must also have the key. 110 | ;tls-auth ta.key 1 111 | 112 | # Select a cryptographic cipher. 113 | # If the cipher option is used on the server 114 | # then you must also specify it here. 115 | # Note that v2.4 client/server will automatically 116 | # negotiate AES-256-GCM in TLS mode. 117 | # See also the data-ciphers option in the manpage 118 | cipher AES-256-CBC 119 | auth SHA256 120 | 121 | # Enable compression on the VPN link. 122 | # Don't enable this unless it is also 123 | # enabled in the server config file. 124 | #comp-lzo 125 | 126 | # Set log file verbosity. 127 | verb 3 128 | 129 | # Silence repeating messages 130 | ;mute 20 131 | 132 | 133 | key-direction 1 134 | -------------------------------------------------------------------------------- /ansible/openvpn-client/openvpn-client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: open_vpn 4 | become: no 5 | tasks: 6 | - name: has pki been set up? 7 | stat: 8 | path: /home/server-admin/my-server/pki 9 | register: pki 10 | - block: 11 | - name: create client folders 12 | tags: always 13 | file: 14 | path: /home/server-admin/my-clients 15 | owner: server-admin 16 | group: server-admin 17 | mode: '700' 18 | state: directory 19 | 20 | - name: create client keys folders 21 | tags: always 22 | file: 23 | path: /home/server-admin/my-clients/keys 24 | owner: server-admin 25 | group: server-admin 26 | mode: '700' 27 | state: directory 28 | 29 | - name: create client files folders 30 | tags: always 31 | file: 32 | path: /home/server-admin/my-clients/files 33 | owner: server-admin 34 | group: server-admin 35 | mode: '700' 36 | state: directory 37 | 38 | - name: generate client CSR 39 | tags: always 40 | shell: 41 | chdir: /home/server-admin/my-server 42 | cmd: ./easyrsa gen-req openvpn-client nopass batch 43 | creates: /home/server-admin/my-server/pki/reqs/openvpn-client.req 44 | 45 | # - name: save client key 46 | # tags: always 47 | # shell: 48 | # cmd: sudo cp /home/server-admin/my-server/pki/private/openvpn-client.key /etc/openvpn/openvpn-client.key 49 | # creates: /etc/openvpn/openvpn-client.key 50 | 51 | - name: Save CSR to local 52 | tags: always 53 | fetch: 54 | src: /home/server-admin/my-server/pki/reqs/openvpn-client.req 55 | dest: ~/ 56 | flat: true 57 | 58 | - name: has crt already been uploaded? 59 | stat: 60 | path: /home/server-admin/my-clients/keys/openvpn-client.crt 61 | register: crt 62 | 63 | - name: Wait for signed cert 64 | tags: always 65 | pause: 66 | prompt: 'Create openvpn-client.crt on your local home directory and press enter' 67 | when: crt.stat.exists == false 68 | 69 | - name: Save CRT to remote 70 | tags: always 71 | copy: 72 | src: ~/openvpn-client.crt 73 | dest: /home/server-admin/my-clients/keys/openvpn-client.crt 74 | 75 | - name: save ta key 76 | tags: always 77 | shell: 78 | cmd: sudo cp /home/server-admin/my-server/ta.key /home/server-admin/my-clients/keys/ta.key 79 | creates: /home/server-admin/my-clients/keys/ta.key 80 | 81 | - name: change ownership of ta key 82 | tags: always 83 | shell: 84 | cmd: sudo chown server-admin:server-admin /home/server-admin/my-clients/keys/ta.key 85 | 86 | - name: save ca key 87 | tags: always 88 | shell: 89 | cmd: cp /etc/openvpn/ca.crt /home/server-admin/my-clients/keys/ca.crt 90 | creates: /home/server-admin/my-clients/keys/ca.crt 91 | 92 | - name: change ownership of ca CRT 93 | tags: always 94 | shell: 95 | cmd: sudo chown server-admin:server-admin /home/server-admin/my-clients/keys/ca.crt 96 | 97 | - name: save client key 98 | tags: always 99 | shell: 100 | cmd: cp /home/server-admin/my-server/pki/private/openvpn-client.key /home/server-admin/my-clients/keys 101 | creates: /home/server-admin/my-clients/keysopenvpn-client.key 102 | 103 | - name: create base for client ovpn file 104 | tags: always 105 | copy: 106 | src: base.conf 107 | dest: /home/server-admin/my-clients 108 | owner: server-admin 109 | group: server-admin 110 | 111 | - name: update base client ovpn file with IP address 112 | tags: always 113 | lineinfile: 114 | dest: /home/server-admin/my-clients/base.conf 115 | regexp: 'remote IP 1194' 116 | line: "remote {{inventory_hostname}} 1194" 117 | 118 | - name: create script for creating ovpn config file 119 | tags: always 120 | copy: 121 | src: make_config.sh 122 | dest: /home/server-admin/my-clients 123 | owner: server-admin 124 | group: server-admin 125 | mode: '700' 126 | 127 | - name: create opnvpn config file 128 | tags: always 129 | shell: 130 | chdir: /home/server-admin/my-clients 131 | cmd: ./make_config.sh openvpn-client 132 | creates: /home/my-clients/files/openvpn-client.ovpn 133 | 134 | - name: Save ovpn config to local 135 | tags: always 136 | fetch: 137 | src: /home/server-admin/my-clients/files/openvpn-client.ovpn 138 | dest: ~/ 139 | flat: true 140 | 141 | when: pki.stat.exists 142 | -------------------------------------------------------------------------------- /ansible/gateway/gateway.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: gw 4 | become: yes 5 | pre_tasks: 6 | 7 | - name: install updates (Ubuntu) 8 | tags: always 9 | apt: 10 | upgrade: dist 11 | update_cache: yes 12 | when: ansible_distribution == "Ubuntu" 13 | 14 | - name: Install nginx 15 | package: name=nginx state=present force=yes install_recommends=no 16 | 17 | - name: Update the proxy_params file 18 | tags: always 19 | become: yes 20 | copy: 21 | src: proxy_params 22 | dest: /etc/nginx/proxy_params 23 | owner: root 24 | group: root 25 | mode: 0440 26 | 27 | - name: has CUSTOM DOMAIN.crt already been uploaded? 28 | stat: 29 | path: /etc/ssl/{{ custom_domain }}.crt 30 | register: custom_crt 31 | 32 | - name: Wait for signed cert 33 | tags: always 34 | pause: 35 | prompt: 'Create {{ custom_domain }}.crt on your local home directory and press enter' 36 | when: custom_crt.stat.exists == false 37 | 38 | - name: Save CRT to remote 39 | tags: always 40 | copy: 41 | src: ~/{{ custom_domain }}.crt 42 | dest: /etc/ssl/{{ custom_domain }}.crt 43 | when: custom_crt.stat.exists == false 44 | 45 | 46 | - name: has CUSTOM DOMAIN.key already been uploaded? 47 | stat: 48 | path: /etc/ssl/{{ custom_domain }}.key 49 | register: custom_key 50 | 51 | - name: Wait for key 52 | tags: always 53 | pause: 54 | prompt: 'Create {{ custom_domain }}.key on your local home directory and press enter' 55 | when: custom_key.stat.exists == false 56 | 57 | - name: Save KEY to remote 58 | tags: always 59 | copy: 60 | src: ~/{{ custom_domain }}.key 61 | dest: /etc/ssl/{{ custom_domain }}.key 62 | when: custom_key.stat.exists == false 63 | 64 | - name: generate CUSTOM_DOMAIN nginx sites-available file from template 65 | tags: always 66 | vars: 67 | k8s_master: "{{ groups['k8s_master'][0] }}" 68 | k8s_node_1: "{{ groups['k8s_node'][0] }}" 69 | k8s_node_2: "{{ groups['k8s_node'][1] }}" 70 | domain: "{{ custom_domain }}" 71 | template: 72 | src: "nginx-apisix-config.j2" 73 | dest: /etc/nginx/sites-available/{{ custom_domain }} 74 | owner: root 75 | group: root 76 | mode: 0644 77 | notify: restart_nginx 78 | 79 | - name: link to sites-enabled 80 | tags: always 81 | file: 82 | src: /etc/nginx/sites-available/{{ custom_domain }} 83 | dest: /etc/nginx/sites-enabled/{{ custom_domain }} 84 | state: link 85 | notify: restart_nginx 86 | 87 | - name: Install ufw firewall 88 | package: name=ufw state=present force=yes install_recommends=no 89 | 90 | - name: update sysctl 91 | tags: always 92 | sysctl: 93 | name: net.ipv4.ip_forward 94 | value: '1' 95 | sysctl_set: true 96 | state: present 97 | reload: true 98 | 99 | - name: change forward policy 100 | lineinfile: 101 | path: /etc/default/ufw 102 | regexp: '^DEFAULT_FORWARD_POLICY="DROP"' 103 | line: 'DEFAULT_FORWARD_POLICY="ACCEPT"' 104 | backrefs: yes 105 | notify: 106 | - restart_ufw 107 | 108 | - name: allow SSH through the firewall 109 | tags: always 110 | ufw: 111 | rule: allow 112 | name: OpenSSH 113 | notify: 114 | - restart_ufw 115 | 116 | - name: allow HTTP through the firewall 117 | tags: always 118 | ufw: 119 | rule: allow 120 | port: '80' 121 | from: '0.0.0.0/0' 122 | to: 'any' 123 | protocol: tcp 124 | notify: 125 | - restart_ufw 126 | 127 | - name: allow HTTPS outgoing through the firewall 128 | tags: always 129 | ufw: 130 | rule: allow 131 | port: '443' 132 | from: '0.0.0.0/0' 133 | to: 'any' 134 | protocol: tcp 135 | notify: 136 | - restart_ufw 137 | 138 | - name: add NAT to ufw 139 | blockinfile: 140 | path: /etc/ufw/before.rules 141 | block: | 142 | # NAT table rules 143 | *nat 144 | :POSTROUTING ACCEPT [0:0] 145 | 146 | # Forward traffic through eth0 147 | # Change to match your out-interface and local network 148 | -A POSTROUTING -s 10.240.0.0/16 -o eth0 -j MASQUERADE 149 | # don't delete the 'COMMIT' line or these nat table rules won't be processed 150 | COMMIT 151 | 152 | insertbefore: "^# Don't delete these required lines" 153 | notify: 154 | - restart_ufw 155 | 156 | - name: configure openVPN 157 | tags: always 158 | become: yes 159 | copy: 160 | src: network.conf 161 | dest: /etc/netplan/55-local.yaml 162 | owner: root 163 | group: root 164 | mode: 0440 165 | 166 | - name: Apply netplan 167 | tags: always 168 | become: yes 169 | command: netplan apply 170 | 171 | handlers: 172 | - name: restart_ufw 173 | ufw: 174 | state: enabled 175 | - name: restart_nginx 176 | service: 177 | name: nginx 178 | state: restarted 179 | -------------------------------------------------------------------------------- /ansible/openvpn-server/openvpn-server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - hosts: open_vpn 4 | become: yes 5 | pre_tasks: 6 | 7 | - name: install updates (Ubuntu) 8 | tags: always 9 | apt: 10 | upgrade: dist 11 | update_cache: yes 12 | when: ansible_distribution == "Ubuntu" 13 | 14 | - name: Install easy-rsa 15 | package: name=easy-rsa state=present force=yes install_recommends=no 16 | 17 | - name: Install openVPN 18 | package: name=openvpn state=present force=yes install_recommends=no 19 | 20 | - name: Install ufw firewall 21 | package: name=ufw state=present force=yes install_recommends=no 22 | 23 | - name: update sysctl 24 | tags: always 25 | sysctl: 26 | name: net.ipv4.ip_forward 27 | value: '1' 28 | sysctl_set: true 29 | state: present 30 | reload: true 31 | 32 | - name: change forward policy 33 | lineinfile: 34 | path: /etc/default/ufw 35 | regexp: '^DEFAULT_FORWARD_POLICY="DROP"' 36 | line: 'DEFAULT_FORWARD_POLICY="ACCEPT"' 37 | backrefs: yes 38 | notify: 39 | - restart_ufw 40 | 41 | - name: allow SSH through the firewall 42 | tags: always 43 | ufw: 44 | rule: allow 45 | name: OpenSSH 46 | notify: 47 | - restart_ufw 48 | 49 | - name: allow openVPN through the firewall 50 | tags: always 51 | ufw: 52 | rule: allow 53 | port: '1194' 54 | protocol: udp 55 | notify: 56 | - restart_ufw 57 | 58 | - name: add NAT to ufw 59 | blockinfile: 60 | path: /etc/ufw/before.rules 61 | block: | 62 | # NAT table rules 63 | *nat 64 | :POSTROUTING ACCEPT [0:0] 65 | 66 | # Forward traffic through eth0 67 | # Change to match your out-interface and local network 68 | -A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE 69 | # don't delete the 'COMMIT' line or these nat table rules won't be processed 70 | COMMIT 71 | 72 | insertbefore: "^# Don't delete these required lines" 73 | notify: 74 | - restart_ufw 75 | 76 | handlers: 77 | - name: restart_ufw 78 | ufw: 79 | state: enabled 80 | 81 | - hosts: open_vpn 82 | become: no 83 | tasks: 84 | 85 | - name: create server-admin folders 86 | tags: always 87 | file: 88 | path: /home/server-admin/my-server 89 | owner: server-admin 90 | group: server-admin 91 | mode: '700' 92 | state: directory 93 | 94 | - name: find easy-rsa files 95 | tags: always 96 | find: 97 | path: /usr/share/easy-rsa 98 | recurse: no 99 | pattern: "*" 100 | register: easyrsa_files 101 | 102 | - name: link to easy-rsa 103 | tags: always 104 | file: 105 | src: "{{ item.path }}" 106 | dest: "/home/server-admin/my-server/{{ item.path | basename }}" 107 | state: link 108 | with_items: "{{ easyrsa_files.files }}" 109 | 110 | - name: initialise PKI 111 | tags: always 112 | shell: 113 | chdir: /home/server-admin/my-server 114 | cmd: ./easyrsa init-pki 115 | creates: /home/server-admin/my-server/pki 116 | 117 | - name: generate CSR 118 | tags: always 119 | shell: 120 | chdir: /home/server-admin/my-server 121 | cmd: ./easyrsa gen-req openvpn-server nopass batch 122 | creates: /home/server-admin/my-server/pki/reqs/openvpn-server.req 123 | 124 | - name: Save CSR to local 125 | tags: always 126 | fetch: 127 | src: /home/server-admin/my-server/pki/reqs/openvpn-server.req 128 | dest: ~/ 129 | flat: true 130 | 131 | - name: has crt already been uploaded? 132 | stat: 133 | path: /etc/openvpn/server.crt 134 | register: crt 135 | 136 | - name: Wait for signed cert 137 | tags: always 138 | pause: 139 | prompt: 'Create openvpn-server.crt on your local home directory and press enter' 140 | when: crt.stat.exists == false 141 | 142 | - name: Save server CRT to remote 143 | tags: always 144 | copy: 145 | src: ~/openvpn-server.crt 146 | dest: /home/server-admin/openvpn-server.crt 147 | 148 | - name: install signed crt 149 | tags: always 150 | shell: 151 | cmd: sudo mv /home/server-admin/openvpn-server.crt /etc/openvpn/server.crt 152 | creates: /etc/openvpn/server.crt 153 | 154 | - name: has ca.crt already been uploaded? 155 | stat: 156 | path: /etc/openvpn/ca.crt 157 | register: cacrt 158 | 159 | - name: Wait for ca certificate 160 | tags: always 161 | pause: 162 | prompt: 'Copy your ca.crt to your local home directory and press enter' 163 | when: cacrt.stat.exists == false 164 | 165 | - name: Save CA CRT to remote 166 | tags: always 167 | copy: 168 | src: ~/ca.crt 169 | dest: /home/server-admin/ca.crt 170 | 171 | - name: install ca crt 172 | tags: always 173 | shell: 174 | cmd: sudo cp /home/server-admin/ca.crt /etc/openvpn/ca.crt 175 | creates: /etc/openvpn/ca.crt 176 | 177 | - name: install server key 178 | tags: always 179 | shell: 180 | cmd: sudo cp /home/server-admin/my-server/pki/private/openvpn-server.key /etc/openvpn/server.key 181 | creates: /etc/openvpn/server.key 182 | 183 | - name: generate DH key 184 | tags: always 185 | shell: 186 | chdir: /home/server-admin/my-server 187 | cmd: ./easyrsa gen-dh 188 | creates: /home/server-admin/my-server/pki/dh.pem 189 | 190 | - name: install DH key 191 | tags: always 192 | shell: 193 | cmd: sudo cp /home/server-admin/my-server/pki/dh.pem /etc/openvpn/dh.pem 194 | creates: /etc/openvpn/dh.pem 195 | 196 | - name: generate HMAC key 197 | tags: always 198 | shell: 199 | chdir: /home/server-admin/my-server 200 | cmd: sudo openvpn --genkey --secret ta.key 201 | creates: /home/server-admin/my-server/ta.key 202 | 203 | - name: install HMAC key 204 | tags: always 205 | shell: 206 | cmd: sudo cp /home/server-admin/my-server/ta.key /etc/openvpn/ta.key 207 | creates: /etc/openvpn/ta.key 208 | 209 | - name: configure openVPN 210 | tags: always 211 | become: yes 212 | copy: 213 | src: server.conf 214 | dest: /etc/openvpn/server.conf 215 | owner: root 216 | group: root 217 | mode: 0440 218 | 219 | - name: Start openvpn systemd service 220 | become: true 221 | systemd: 222 | name: openvpn 223 | state: started 224 | daemon_reload: yes 225 | enabled: yes 226 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # Creating Kubernetes cluster on Binary Lane 2 | 3 | This repo is designed for use with my [Medium article](https://medium.com/@martin.hodges/creating-a-kubernetes-cluster-from-scratch-in-1-hour-using-automation-a25e387be547) on how to build a Kubernetes (k8s) cluster on the Australian [Binary Lane](binarylane.com.au) cloud services. 4 | 5 | It is designed as a way to explore Infrastructure as Code as well as Kubernetes clusters using tools such as Terraform, Ansible and OpenVPN. 6 | 7 | It creates: 8 | - A Virtual Private Cloud (VPC) 9 | - An openVPN server to access the VPC 10 | - A gateway server as an ingress point 11 | - 1 k8s master node 12 | - 2 k8s worker nodes 13 | - 1 nfs server 14 | 15 | Note that the worker nodes must be a min of 4GB and 2 CPUs to allow Istio to be installed. 16 | The master node must have 2 cpus and has been made 4GB to match the workers. 17 | 18 | It creates the client configuration for the openVPN service. It also installs the gateway service as an egress point to the Internet for all private servers to allow them to access the repositories they need to update. 19 | 20 | ## Secret Dependencies 21 | 22 | If you are creating the k8s_keycloak role, you need to supply the postgres and keycloak user passwords 23 | for the database. These must be suppplied as an Ansible vault file. Create the file (the file extension should be .enc as this will prevent it being stored in the git repository): 24 | 25 | postgres_pw: {your postgres user database password} 26 | keycloak_pw: {your keycloak user database password} 27 | client_secret: {"" or the Keycloak client secret for the apisix API Gateway} 28 | custom_domain: {the domain you are going to use with your cluster} 29 | 30 | Then encrypt this file with: 31 | 32 | ansible-vault encrypt {filename} 33 | 34 | Supply a secure password and rememebr it for later use. 35 | 36 | ## Create the VPC and VPSs 37 | 38 | To create the infrastructure, execute these from the project's root folder. 39 | 40 | cd terraform 41 | terraform init 42 | terraform plan 43 | terraform apply 44 | 45 | This will create an etc-hosts file that you can cut and paste into your /etc/hosts file for convenience. 46 | 47 | ## Configure the VPC 48 | 49 | As Terraform does not allow any resource to be touched multiple times and as the VPC depends on the gw VPS, which depends on the VPC, this step has to be done manually. 50 | 51 | Add a static route to the VPC to allow private VPSs to acess the Internet. The route should be defined as: 52 | 0.0.0.0/0 -> {eg-gw private ip address} Private VPS Egress 53 | 54 | ## Configure egress through the gw server 55 | 56 | Another manual step involves setting up the interfaces on the gw server. By default these will use a 57 | single network connection. In the Binary Lane console, go to the gw server and find the VPC advanced 58 | setting. This should allow you to set dedicated interfaces for public network traffic. Select this 59 | option. 60 | 61 | Also, as we are using this as an egress point, untick the option to perform Source/Destination checks. 62 | 63 | Save and apply these. You will need to save and apply each of the two options separately. 64 | 65 | ## Setting up known hosts 66 | 67 | To allow Ansible to access your servers, you need to add your new servers to the known_hosts file. The 68 | easiest way to do this is to log in using SSH. This also ensures your personal SSH keys were added 69 | correctly. Now use the following with the public IP addresses of the servers (do not your hosts entries 70 | as Ansible uses IP addresses): 71 | 72 | ssh root@{GW PUBLIC IP ADDRESS} 73 | ssh root@{OPENVPN PUBLIC IP ADDRESS} 74 | 75 | Currently you only have public access to these two and so the others will have to wait until you have 76 | the OpenVPN up and running. 77 | 78 | ## Configure access to the VPC 79 | 80 | Once you have created the set of virtual servers, you can now configure them with ansible. This is done in a number of interdependent steps. First is to set up the openVPN and gateway servers, which first need bootstrapping. 81 | 82 | cd ../ansible/bootstrap 83 | ansible-playbook bootstrap.yml --limit open_vpn,gw 84 | 85 | Once bootstrapped, the servers can be setup. First do the openvpn. Part way through this step you will be asked to sign a server request (~/openvpn-server.req on your local computer) with a CA. You will need to provide the signed certificate (openvpn-server.crt) and the CA certificate (ca.crt) in your home folder before continuing. 86 | 87 | cd ../openvpn-server 88 | ansible-playbook openvpn-server.yml 89 | 90 | After starting the openVPN sever, you will need to create a client configuration. Part way through this step you will be asked to sign a client request (~/openvpn-client.req) with a CA. You will need to provide the signed certificate (openvpn-client.crt) in your home folder before continuing. 91 | 92 | cd ../openvpn-client 93 | ansible-playbook openvpn-client.yml 94 | 95 | This produces a client configuration in your home folder on your local machine (openvpn-client.ovpn). You will need to install this into your local VPN client software and connect to the open VPN server. You cannot continue until you do this as you cannot access your private k8s servers. 96 | 97 | Each private VPS needs to be able to access the Internet in order to access upgrades and packages. The gateway provides a Network Address Translation (NAT) gateway and nginx proxy. We bootstrapped it earlier so now it just needs to be set up. Note the need to replace { } field with your own custom domain for which you shoud have a wildcard certificate and CA certificate. Note that this config assumes you will install the APISIX API gateway and that apisix.{DOMAIN NAME} and iam.{DOMAIN NAME} are proxied through to the gateway: 98 | 99 | cd ../gateway 100 | ansible-playbook gateway.yml --extra-vars "custom_domain={DOMAIN NAME}" 101 | 102 | Once you have this up and running and and can SSH into each of the k8s nodes, you can then bootstrap them: 103 | 104 | cd ../bootstrap 105 | ansible-playbook bootstrap.yml --limit k8s_master,k8s_node,nfs_server 106 | 107 | You can now create your nfs and minIO servers. This playbook expects to find a signed certificate and 108 | an associated key file in your ansible host machine to secure the TLS connections. These are expected 109 | to be called ~/{DOMAIN NAME}.crt and ~/{DOMAIN NAME}.key. 110 | 111 | cd ../nfs 112 | ansible-playbook nfs.yml --extra-vars "custom_domain={DOMAIN NAME}" 113 | 114 | Note that this playbook creates a random, initial admin password for minIO which can be found in 115 | /etc/default/minio. You should change this password through the user interface after it is successfully 116 | installed. 117 | 118 | Now everything is set up, Kubernetes can now be installed: 119 | 120 | cd ../k8s 121 | ansible-playbook k8s.yml --limit k8s_master --extra-vars "custom_domain={DOMAIN NAME}" 122 | ansible-playbook k8s.yml --limit k8s_node 123 | 124 | With Kubernetes installed, the basic Kubernetes infrastructure can be installed. 125 | The following will install: 126 | - k8s_service_mesh (istio) 127 | - k8s_your_domain - certificates and coreDNS update for custom domain 128 | - k8s_storage - setups a auto-provisioner for your NFS service (nfs-subdir-external-provisioner) 129 | - k8s_gateway - installs and configures an API Gateway (APISIX) 130 | - k8s_test_service - deploys an instance of a simple test service (nginx) 131 | - k8s_vault - deploys Hashicorp Vault instance - 2 nodes 132 | - k8s_postgres - installs a postgres operator 133 | - k8s_keycloak - deploys the Keycloak IAM backed by postgres 134 | 135 | These commands will run the playbook. It will prompt you for the unlock password you defined at the start: 136 | 137 | cd ../k8s-config 138 | ansible-playbook k8s-config.yml -e @{your encoded password file} --ask-vault-pass 139 | 140 | Note that vault will need to be initialised and unsealed. This requires a set of manual commands. 141 | The commands you require are shown below. They need to be executed on teh k8s-master node: 142 | 143 | kubectl exec -it vault-0 -n vault -- sh 144 | vault status 145 | vault operator init -n 1 -t 1 146 | vault operator unseal {unseal key from previous command} 147 | exit 148 | kubectl exec -it vault-1 -n vault -- sh 149 | vault status 150 | vault operator raft join http://vault-active:8200 151 | vault operator unseal {unseal key from earlier command} 152 | exit 153 | 154 | Note that the -n 1 -t 1 creates a shamir key with 1 key and only needing 1 key to unseal. 155 | You may wish to use larger numbers, eg: -n 5 -t 3. 156 | 157 | After running the playbook, you should have access to Keycloak. After setting up a realm 158 | called apisix and adding a client, you should have a secret for the client. Add this into your 159 | ansible secret file and then run the playbook again. 160 | 161 | With everything set up, you should be able to access the following user interfaces: 162 | 163 | APISIX ... http://k8s.{CUSTOM_DOMAIN}:30190 164 | Grafana ... http://k8s.{CUSTOM_DOMAIN}:31300 165 | Keycloak ... http://iam.{CUSTOM_DOMAIN} 166 | Hello World ... https://apisix.{CUSTOM_DOMAIN}/worlds (unsecured) 167 | Hello World ... https://secure.{CUSTOM_DOMAIN}/worlds (secured) 168 | MinIO ... https://nfs.{CUSTOM_DOMAIN}:9001/browser 169 | Vault ... http://k8s.{CUSTOM_DOMAIN}:30802 170 | -------------------------------------------------------------------------------- /ansible/openvpn-server/files/server.conf: -------------------------------------------------------------------------------- 1 | ################################################ 2 | # Sample OpenVPN 2.0 config file for # 3 | # multi-client server. # 4 | # # 5 | # This file is for the server side # 6 | # of a many-clients <-> one-server # 7 | # OpenVPN configuration. # 8 | # # 9 | # OpenVPN also supports # 10 | # single-machine <-> single-machine # 11 | # configurations (See the Examples page # 12 | # on the web site for more info). # 13 | # # 14 | # This config should work on Windows # 15 | # or Linux/BSD systems. Remember on # 16 | # Windows to quote pathnames and use # 17 | # double backslashes, e.g.: # 18 | # "C:\\Program Files\\OpenVPN\\config\\foo.key" # 19 | # # 20 | # Comments are preceded with '#' or ';' # 21 | ################################################# 22 | 23 | # Which local IP address should OpenVPN 24 | # listen on? (optional) 25 | ;local a.b.c.d 26 | 27 | # Which TCP/UDP port should OpenVPN listen on? 28 | # If you want to run multiple OpenVPN instances 29 | # on the same machine, use a different port 30 | # number for each one. You will need to 31 | # open up this port on your firewall. 32 | port 1194 33 | 34 | # TCP or UDP server? 35 | ;proto tcp 36 | proto udp 37 | 38 | # "dev tun" will create a routed IP tunnel, 39 | # "dev tap" will create an ethernet tunnel. 40 | # Use "dev tap0" if you are ethernet bridging 41 | # and have precreated a tap0 virtual interface 42 | # and bridged it with your ethernet interface. 43 | # If you want to control access policies 44 | # over the VPN, you must create firewall 45 | # rules for the the TUN/TAP interface. 46 | # On non-Windows systems, you can give 47 | # an explicit unit number, such as tun0. 48 | # On Windows, use "dev-node" for this. 49 | # On most systems, the VPN will not function 50 | # unless you partially or fully disable 51 | # the firewall for the TUN/TAP interface. 52 | ;dev tap 53 | dev tun 54 | 55 | # Windows needs the TAP-Win32 adapter name 56 | # from the Network Connections panel if you 57 | # have more than one. On XP SP2 or higher, 58 | # you may need to selectively disable the 59 | # Windows firewall for the TAP adapter. 60 | # Non-Windows systems usually don't need this. 61 | ;dev-node MyTap 62 | 63 | # SSL/TLS root certificate (ca), certificate 64 | # (cert), and private key (key). Each client 65 | # and the server must have their own cert and 66 | # key file. The server and all clients will 67 | # use the same ca file. 68 | # 69 | # See the "easy-rsa" directory for a series 70 | # of scripts for generating RSA certificates 71 | # and private keys. Remember to use 72 | # a unique Common Name for the server 73 | # and each of the client certificates. 74 | # 75 | # Any X509 key management system can be used. 76 | # OpenVPN can also use a PKCS #12 formatted key file 77 | # (see "pkcs12" directive in man page). 78 | ca ca.crt 79 | cert server.crt 80 | key server.key # This file should be kept secret 81 | 82 | # Diffie hellman parameters. 83 | # Generate your own with: 84 | # openssl dhparam -out dh2048.pem 2048 85 | dh dh.pem 86 | 87 | # Network topology 88 | # Should be subnet (addressing via IP) 89 | # unless Windows clients v2.0.9 and lower have to 90 | # be supported (then net30, i.e. a /30 per client) 91 | # Defaults to net30 (not recommended) 92 | ;topology subnet 93 | 94 | # Configure server mode and supply a VPN subnet 95 | # for OpenVPN to draw client addresses from. 96 | # The server will take 10.8.0.1 for itself, 97 | # the rest will be made available to clients. 98 | # Each client will be able to reach the server 99 | # on 10.8.0.1. Comment this line out if you are 100 | # ethernet bridging. See the man page for more info. 101 | server 10.8.0.0 255.255.255.0 102 | 103 | # Maintain a record of client <-> virtual IP address 104 | # associations in this file. If OpenVPN goes down or 105 | # is restarted, reconnecting clients can be assigned 106 | # the same virtual IP address from the pool that was 107 | # previously assigned. 108 | ifconfig-pool-persist /var/log/openvpn/ipp.txt 109 | 110 | # Configure server mode for ethernet bridging. 111 | # You must first use your OS's bridging capability 112 | # to bridge the TAP interface with the ethernet 113 | # NIC interface. Then you must manually set the 114 | # IP/netmask on the bridge interface, here we 115 | # assume 10.8.0.4/255.255.255.0. Finally we 116 | # must set aside an IP range in this subnet 117 | # (start=10.8.0.50 end=10.8.0.100) to allocate 118 | # to connecting clients. Leave this line commented 119 | # out unless you are ethernet bridging. 120 | ;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100 121 | 122 | # Configure server mode for ethernet bridging 123 | # using a DHCP-proxy, where clients talk 124 | # to the OpenVPN server-side DHCP server 125 | # to receive their IP address allocation 126 | # and DNS server addresses. You must first use 127 | # your OS's bridging capability to bridge the TAP 128 | # interface with the ethernet NIC interface. 129 | # Note: this mode only works on clients (such as 130 | # Windows), where the client-side TAP adapter is 131 | # bound to a DHCP client. 132 | ;server-bridge 133 | 134 | # Push routes to the client to allow it 135 | # to reach other private subnets behind 136 | # the server. Remember that these 137 | # private subnets will also need 138 | # to know to route the OpenVPN client 139 | # address pool (10.8.0.0/255.255.255.0) 140 | # back to the OpenVPN server. 141 | ;push "route 192.168.10.0 255.255.255.0" 142 | ;push "route 192.168.20.0 255.255.255.0" 143 | 144 | # To assign specific IP addresses to specific 145 | # clients or if a connecting client has a private 146 | # subnet behind it that should also have VPN access, 147 | # use the subdirectory "ccd" for client-specific 148 | # configuration files (see man page for more info). 149 | 150 | # EXAMPLE: Suppose the client 151 | # having the certificate common name "Thelonious" 152 | # also has a small subnet behind his connecting 153 | # machine, such as 192.168.40.128/255.255.255.248. 154 | # First, uncomment out these lines: 155 | ;client-config-dir ccd 156 | ;route 192.168.40.128 255.255.255.248 157 | # Then create a file ccd/Thelonious with this line: 158 | # iroute 192.168.40.128 255.255.255.248 159 | # This will allow Thelonious' private subnet to 160 | # access the VPN. This example will only work 161 | # if you are routing, not bridging, i.e. you are 162 | # using "dev tun" and "server" directives. 163 | 164 | # EXAMPLE: Suppose you want to give 165 | # Thelonious a fixed VPN IP address of 10.9.0.1. 166 | # First uncomment out these lines: 167 | ;client-config-dir ccd 168 | ;route 10.9.0.0 255.255.255.252 169 | # Then add this line to ccd/Thelonious: 170 | # ifconfig-push 10.9.0.1 10.9.0.2 171 | 172 | # Suppose that you want to enable different 173 | # firewall access policies for different groups 174 | # of clients. There are two methods: 175 | # (1) Run multiple OpenVPN daemons, one for each 176 | # group, and firewall the TUN/TAP interface 177 | # for each group/daemon appropriately. 178 | # (2) (Advanced) Create a script to dynamically 179 | # modify the firewall in response to access 180 | # from different clients. See man 181 | # page for more info on learn-address script. 182 | ;learn-address ./script 183 | 184 | # If enabled, this directive will configure 185 | # all clients to redirect their default 186 | # network gateway through the VPN, causing 187 | # all IP traffic such as web browsing and 188 | # and DNS lookups to go through the VPN 189 | # (The OpenVPN server machine may need to NAT 190 | # or bridge the TUN/TAP interface to the internet 191 | # in order for this to work properly). 192 | ;push "redirect-gateway def1 bypass-dhcp" 193 | 194 | # Certain Windows-specific network settings 195 | # can be pushed to clients, such as DNS 196 | # or WINS server addresses. CAVEAT: 197 | # http://openvpn.net/faq.html#dhcpcaveats 198 | # The addresses below refer to the public 199 | # DNS servers provided by opendns.com. 200 | ;push "dhcp-option DNS 208.67.222.222" 201 | ;push "dhcp-option DNS 208.67.220.220" 202 | 203 | # Uncomment this directive to allow different 204 | # clients to be able to "see" each other. 205 | # By default, clients will only see the server. 206 | # To force clients to only see the server, you 207 | # will also need to appropriately firewall the 208 | # server's TUN/TAP interface. 209 | ;client-to-client 210 | 211 | # Uncomment this directive if multiple clients 212 | # might connect with the same certificate/key 213 | # files or common names. This is recommended 214 | # only for testing purposes. For production use, 215 | # each client should have its own certificate/key 216 | # pair. 217 | # 218 | # IF YOU HAVE NOT GENERATED INDIVIDUAL 219 | # CERTIFICATE/KEY PAIRS FOR EACH CLIENT, 220 | # EACH HAVING ITS OWN UNIQUE "COMMON NAME", 221 | # UNCOMMENT THIS LINE OUT. 222 | ;duplicate-cn 223 | 224 | # The keepalive directive causes ping-like 225 | # messages to be sent back and forth over 226 | # the link so that each side knows when 227 | # the other side has gone down. 228 | # Ping every 10 seconds, assume that remote 229 | # peer is down if no ping received during 230 | # a 120 second time period. 231 | keepalive 10 120 232 | 233 | # For extra security beyond that provided 234 | # by SSL/TLS, create an "HMAC firewall" 235 | # to help block DoS attacks and UDP port flooding. 236 | # 237 | # Generate with: 238 | # openvpn --genkey tls-auth ta.key 239 | # 240 | # The server and each client must have 241 | # a copy of this key. 242 | # The second parameter should be '0' 243 | # on the server and '1' on the clients. 244 | tls-auth ta.key 0 # This file is secret 245 | 246 | # Select a cryptographic cipher. 247 | # This config item must be copied to 248 | # the client config file as well. 249 | # Note that v2.4 client/server will automatically 250 | # negotiate AES-256-GCM in TLS mode. 251 | # See also the ncp-cipher option in the manpage 252 | cipher AES-256-CBC 253 | auth SHA256 254 | 255 | # Enable compression on the VPN link and push the 256 | # option to the client (v2.4+ only, for earlier 257 | # versions see below) 258 | ;compress lz4-v2 259 | ;push "compress lz4-v2" 260 | 261 | # For compression compatible with older clients use comp-lzo 262 | # If you enable it here, you must also 263 | # enable it in the client config file. 264 | ;comp-lzo 265 | 266 | # The maximum number of concurrently connected 267 | # clients we want to allow. 268 | ;max-clients 100 269 | 270 | # It's a good idea to reduce the OpenVPN 271 | # daemon's privileges after initialization. 272 | # 273 | # You can uncomment this out on 274 | # non-Windows systems. 275 | user nobody 276 | group nogroup 277 | 278 | # The persist options will try to avoid 279 | # accessing certain resources on restart 280 | # that may no longer be accessible because 281 | # of the privilege downgrade. 282 | persist-key 283 | persist-tun 284 | 285 | # Output a short status file showing 286 | # current connections, truncated 287 | # and rewritten every minute. 288 | status /var/log/openvpn/openvpn-status.log 289 | 290 | # By default, log messages will go to the syslog (or 291 | # on Windows, if running as a service, they will go to 292 | # the "\Program Files\OpenVPN\log" directory). 293 | # Use log or log-append to override this default. 294 | # "log" will truncate the log file on OpenVPN startup, 295 | # while "log-append" will append to it. Use one 296 | # or the other (but not both). 297 | ;log /var/log/openvpn/openvpn.log 298 | ;log-append /var/log/openvpn/openvpn.log 299 | 300 | # Set the appropriate level of log 301 | # file verbosity. 302 | # 303 | # 0 is silent, except for fatal errors 304 | # 4 is reasonable for general usage 305 | # 5 and 6 can help to debug connection problems 306 | # 9 is extremely verbose 307 | verb 3 308 | 309 | # Silence repeating messages. At most 20 310 | # sequential messages of the same message 311 | # category will be output to the log. 312 | ;mute 20 313 | 314 | # Notify the client that when the server restarts so it 315 | # can automatically reconnect. 316 | explicit-exit-notify 1 --------------------------------------------------------------------------------