Compare commits
6 Commits
14c3ebe2cc
...
6e7a28c2ae
Author | SHA1 | Date | |
---|---|---|---|
6e7a28c2ae | |||
d3db3af028 | |||
d9dd334988 | |||
5d57ca8dce | |||
7e508f906f | |||
3ac1b27b4c |
@ -22,13 +22,13 @@ metallb_bgp_aggregation_length: 24
|
||||
|
||||
## Nginx Ingress ##
|
||||
### Internal ###
|
||||
internal_ingress_class: "ghp-internal-nginx"
|
||||
internal_ingress_class: "{{ namespace }}-internal-nginx"
|
||||
internal_loadbalancer_ip: "192.168.250.0"
|
||||
### External ###
|
||||
internal_ingress_class: "ghp-external-nginx"
|
||||
external_ingress_class: "{{ namespace }}-external-nginx"
|
||||
external_loadbalancer_ip: "192.168.250.10"
|
||||
### Local ###
|
||||
internal_ingress_class: "ghp-local-nginx"
|
||||
local_ingress_class: "{{ namespace }}-local-nginx"
|
||||
local_loadbalancer_ip: "192.168.250.20"
|
||||
|
||||
## External-dns ##
|
||||
|
46
inventory/ghp/sample/group_vars/k8s/keycloak.yaml
Normal file
46
inventory/ghp/sample/group_vars/k8s/keycloak.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
keycloak_values: {}
|
||||
|
||||
keycloak_realms: {}
|
||||
# - id: myrealm
|
||||
# realm: myrealm
|
||||
|
||||
keycloak_clients: {}
|
||||
# - client_id: gitea
|
||||
# realm: myrealm
|
||||
# public_client: true
|
||||
# - client_id: gitea
|
||||
# realm: myrealm
|
||||
# public_client: false
|
||||
|
||||
keycloak_clients_default_protocol_mappings: {}
|
||||
# - config:
|
||||
# access.token.claim: true
|
||||
# claim.name: "groups"
|
||||
# id.token.claim: true
|
||||
# jsonType.label: String
|
||||
# user.attribute: groups
|
||||
# userinfo.token.claim: true
|
||||
# name: groups
|
||||
# protocol: openid-connect
|
||||
# protocolMapper: oidc-usermodel-attribute-mapper
|
||||
|
||||
keycloak_groups: {}
|
||||
# - name: admins
|
||||
# realm: myrealm
|
||||
# - name: devops
|
||||
# realm: myrealm
|
||||
|
||||
keycloak_users: {}
|
||||
# - username: John Doe
|
||||
# realm: myrealm
|
||||
# firstName: John
|
||||
# lastName: Doe
|
||||
# credentials:
|
||||
# - type: password
|
||||
# value: my_very_strong_password
|
||||
# temporary: true
|
||||
# groups:
|
||||
# - name: admins
|
||||
# state: present
|
||||
# - name: devops
|
||||
# state: present
|
@ -1,43 +1 @@
|
||||
nextcloud_values:
|
||||
nextcloud:
|
||||
configs:
|
||||
mail.fix.config.php: |-
|
||||
<?php
|
||||
$CONFIG = array (
|
||||
"mail_smtptimeout" => 60,
|
||||
);
|
||||
fix.config.php: |-
|
||||
<?php
|
||||
$CONFIG = array (
|
||||
'trusted_proxies' => ['{{ web_proxy_internal_ip }}'],
|
||||
'overwriteprotocol' => 'https',
|
||||
'overwrite.cli.url' => 'https://nextcloud.{{ domain }}',
|
||||
'mail_smtpstreamoptions' =>
|
||||
array (
|
||||
'ssl' =>
|
||||
array (
|
||||
'allow_self_signed' => true,
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
rgw.config.php: |-
|
||||
<?php
|
||||
$CONFIG = array (
|
||||
'objectstore_multibucket' => array(
|
||||
'class' => '\\OC\\Files\\ObjectStore\\S3',
|
||||
'arguments' => array(
|
||||
'bucket' => 'nextcloud',
|
||||
'autocreate' => true,
|
||||
'key' => 'K4PNZLSTLIDQJMZUV27P',
|
||||
'secret' => 'iPScsni8RS2aT9MFymfQYLPD7W8dVrRqFpafBKDc',
|
||||
'hostname' => 'sds1-osd1.lan',
|
||||
'port' => 8080,
|
||||
'use_ssl' => false,
|
||||
'num_buckets' => 16,
|
||||
'region' => 'us-east-1',
|
||||
'use_path_style' => true
|
||||
),
|
||||
),
|
||||
);
|
||||
nextcloud_values: {}
|
||||
|
@ -3,85 +3,91 @@
|
||||
connection: local
|
||||
tasks:
|
||||
- name: Deploy MetalLB
|
||||
import_role:
|
||||
import_role:
|
||||
name: metallb
|
||||
when: metallb_enabled | default(true)
|
||||
tags: metallb
|
||||
|
||||
|
||||
- name: Deploy External Ingress Nginx
|
||||
import_role:
|
||||
import_role:
|
||||
name: external-ingress-nginx
|
||||
when: external_ingress_nginx_enabled | default(true)
|
||||
tags:
|
||||
tags:
|
||||
- external-ingress-nginx
|
||||
- ingress-nginx
|
||||
|
||||
- name: Deploy Internal Ingress Nginx
|
||||
import_role:
|
||||
import_role:
|
||||
name: internal-ingress-nginx
|
||||
when: internal_ingress_nginx_enabled | default(true)
|
||||
tags:
|
||||
tags:
|
||||
- internal-ingress-nginx
|
||||
- ingress-nginx
|
||||
|
||||
- name: Deploy Local Ingress Nginx
|
||||
import_role:
|
||||
import_role:
|
||||
name: local-ingress-nginx
|
||||
when: local_ingress_nginx_enabled | default(true)
|
||||
tags:
|
||||
tags:
|
||||
- local-ingress-nginx
|
||||
- ingress-nginx
|
||||
|
||||
- name: Deploy Internal DNS
|
||||
import_role:
|
||||
import_role:
|
||||
name: internal-dns
|
||||
when: internal_dns_enabled | default(true)
|
||||
tags:
|
||||
when:
|
||||
- internal_dns_enabled | default(true)
|
||||
- domain is defined
|
||||
tags:
|
||||
- internal-dns
|
||||
- dns
|
||||
|
||||
|
||||
- name: Deploy Local DNS
|
||||
import_role:
|
||||
import_role:
|
||||
name: local-dns
|
||||
when: local_dns_enabled | default(true)
|
||||
tags:
|
||||
when:
|
||||
- local_dns_enabled | default(true)
|
||||
- local_domain is defined
|
||||
tags:
|
||||
- local-dns
|
||||
- dns
|
||||
|
||||
- name: Deploy Service DNS
|
||||
import_role:
|
||||
import_role:
|
||||
name: service-dns
|
||||
when: service_dns_enabled | default(true)
|
||||
tags:
|
||||
when:
|
||||
- service_dns_enabled | default(true)
|
||||
- domain is defined
|
||||
tags:
|
||||
- service-dns
|
||||
- dns
|
||||
|
||||
- name: Deploy Cert-manager
|
||||
import_role:
|
||||
import_role:
|
||||
name: cert-manager
|
||||
when: cert_manager_enabled | default(true)
|
||||
tags: cert-manager
|
||||
|
||||
|
||||
- name: Deploy NFS-client-provisioner
|
||||
import_role:
|
||||
import_role:
|
||||
name: nfs-client-provisioner
|
||||
when: nfs_client_provisioner_enabled | default(true)
|
||||
tags: nfs-client-provisioner
|
||||
|
||||
|
||||
- name: Deploy CSI Ceph RBD
|
||||
import_role:
|
||||
import_role:
|
||||
name: ceph-csi-rbd
|
||||
when: ceph_csi_rbd_enabled | default(false)
|
||||
tags: ceph-csi-rbd
|
||||
|
||||
- name: Deploy CSI CephFS
|
||||
import_role:
|
||||
import_role:
|
||||
name: ceph-csi-cephfs
|
||||
when: ceph_csi_cephfs_enabled | default(false)
|
||||
tags: ceph-csi-cephfs
|
||||
|
||||
- name: Deploy Metrics-server
|
||||
import_role:
|
||||
import_role:
|
||||
name: metrics-server
|
||||
when: metrics_server_enabled | default(true)
|
||||
tags: metrics-server
|
||||
|
5
playbooks/ghp/keycloak.yaml
Normal file
5
playbooks/ghp/keycloak.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
- hosts: k8s
|
||||
connection: local
|
||||
roles:
|
||||
- keycloak
|
@ -3,19 +3,25 @@
|
||||
connection: local
|
||||
tasks:
|
||||
- name: Deploy PostgreSQL
|
||||
import_role:
|
||||
import_role:
|
||||
name: postgres
|
||||
when: postgres_enabled | default(true)
|
||||
tags: postgres
|
||||
|
||||
- name: Deploy OpenLDAP
|
||||
import_role:
|
||||
import_role:
|
||||
name: openldap
|
||||
when: openldap_enabled | default(true)
|
||||
tags: openldap
|
||||
|
||||
- name: Deploy MinIO
|
||||
import_role:
|
||||
import_role:
|
||||
name: minio
|
||||
when: minio_enabled | default(true)
|
||||
tags: minio
|
||||
|
||||
- name: Deploy Keycloak
|
||||
import_role:
|
||||
name: keycloak
|
||||
when: keycloak_enabled | default(false)
|
||||
tags: keycloak
|
||||
|
@ -10,7 +10,7 @@ internal_dns_default_values:
|
||||
zone: "{{ internal_domain | default(domain) }}"
|
||||
tsigSecret: "{{ k8s_tsig }}"
|
||||
tsigSecretAlg: "{{ internal_dns_tsigSecretAlg | default('hmac-sha512') }}"
|
||||
tsigKeyname: "{{ internal_dns_tsigKeyname | default('k8s') }}"
|
||||
tsigKeyname: "{{ internal_dns_tsigKeyname | default(namespace) }}"
|
||||
tsigAxfr: true
|
||||
## Possible units [ns, us, ms, s, m, h], see more https://golang.org/pkg/time/#ParseDuration
|
||||
minTTL: "30s"
|
||||
|
63
roles/keycloak/defaults/main.yaml
Normal file
63
roles/keycloak/defaults/main.yaml
Normal file
@ -0,0 +1,63 @@
|
||||
keycloak_enabled: true
|
||||
keycloak_publish: false
|
||||
keycloak_console_publish: false
|
||||
keycloak_use_external_db: true
|
||||
keycloak_chart_ref: "codecentric/keycloakx"
|
||||
keycloak_short_name: "keycloak"
|
||||
keycloak_console_short_name: "console"
|
||||
keycloak_default_values:
|
||||
command:
|
||||
- /opt/keycloak/bin/kc.sh
|
||||
- start
|
||||
- --http-enabled=true
|
||||
- --http-port=8080
|
||||
- --hostname={{ keycloak_short_name }}.{{ domain }}
|
||||
- --hostname-strict=false
|
||||
- --hostname-strict-https=false
|
||||
database:
|
||||
database: "keycloak"
|
||||
hostname: "{{ postgres_db_team | default(namespace) }}-postgres.{{ postgres_db_namespace | default(namespace) }}"
|
||||
username: "{{ keycloak_db_username | default(omit) }}"
|
||||
password: "{{ keycloak_db_password | default(omit) }}"
|
||||
port: 5432
|
||||
vendor: postgres
|
||||
extraEnv: |
|
||||
- name: KEYCLOAK_ADMIN
|
||||
value: admin
|
||||
- name: KEYCLOAK_ADMIN_PASSWORD
|
||||
value: {{ keycloak_admin_password }}
|
||||
- name: JAVA_OPTS_APPEND
|
||||
value: >-
|
||||
-Djgroups.dns.query={{ keycloak_short_name }}-keycloakx-headless
|
||||
ingress:
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
enabled: true
|
||||
ingressClassName: "{{ external_ingress_class if minio_publish else internal_ingress_class }}"
|
||||
rules:
|
||||
- host: "{{ keycloak_short_name }}.{{ domain }}"
|
||||
paths:
|
||||
- path: /auth/
|
||||
pathType: Prefix
|
||||
servicePort: http
|
||||
tls:
|
||||
- hosts:
|
||||
- "{{ keycloak_short_name }}.{{ domain }}"
|
||||
secretName: "{{ keycloak_short_name }}.{{ domain }}-tls"
|
||||
|
||||
keycloak_realms: {}
|
||||
keycloak_clients: {}
|
||||
keycloak_clients_default_protocol_mappings: {}
|
||||
# - config:
|
||||
# access.token.claim: true
|
||||
# claim.name: "groups"
|
||||
# id.token.claim: true
|
||||
# jsonType.label: String
|
||||
# user.attribute: groups
|
||||
# userinfo.token.claim: true
|
||||
# name: groups
|
||||
# protocol: openid-connect
|
||||
# protocolMapper: oidc-usermodel-attribute-mapper
|
||||
|
||||
keycloak_users: {}
|
||||
keycloak_groups: {}
|
96
roles/keycloak/tasks/main.yaml
Normal file
96
roles/keycloak/tasks/main.yaml
Normal file
@ -0,0 +1,96 @@
|
||||
- name: Import secret.yaml to obtain secrets
|
||||
include_tasks: secrets.yaml
|
||||
when:
|
||||
- keycloak_use_external_db
|
||||
- postgres_enabled is defined and postgres_enabled
|
||||
|
||||
- set_fact:
|
||||
keycloak_combined_values: "{{ keycloak_default_values | combine(keycloak_values, recursive=true) }}"
|
||||
|
||||
- name: Deploy Keycloak
|
||||
kubernetes.core.helm:
|
||||
release_namespace: "{{ keycloak_namespace | default(namespace) }}"
|
||||
release_name: "{{ keycloak_name | default('keycloak') }}"
|
||||
chart_ref: "{{ keycloak_chart_ref }}"
|
||||
chart_version: "{{ keycloak_version | default(omit) }}"
|
||||
release_values: "{{ keycloak_combined_values | from_yaml }}"
|
||||
|
||||
- name: Wait Keycloak until HTTP status is 200
|
||||
uri:
|
||||
url: "https://{{ keycloak_short_name }}.{{ domain }}/auth"
|
||||
return_content: yes
|
||||
validate_certs: no
|
||||
status_code:
|
||||
- 200
|
||||
until: uri_output.status == 200
|
||||
retries: 24 # Retries for 24 * 5 seconds = 120 seconds = 2 minutes
|
||||
delay: 5 # Every 5 seconds
|
||||
register: uri_output
|
||||
|
||||
- name: Create or update Keycloak client, authentication with credentials
|
||||
community.general.keycloak_client:
|
||||
client_id: admin-cli
|
||||
auth_keycloak_url: "https://{{ keycloak_short_name }}.{{ domain }}/auth"
|
||||
auth_realm: master
|
||||
auth_username: admin
|
||||
auth_password: "{{ keycloak_admin_password }}"
|
||||
state: present
|
||||
- name: Create or update Keycloak realms
|
||||
community.general.keycloak_realm:
|
||||
auth_client_id: admin-cli
|
||||
auth_keycloak_url: "https://{{ keycloak_short_name }}.{{ domain }}/auth"
|
||||
auth_realm: master
|
||||
auth_username: admin
|
||||
auth_password: "{{ keycloak_admin_password }}"
|
||||
id: "{{ item.id }}"
|
||||
realm: "{{ item.realm }}"
|
||||
state: "{{ item.state | default('present') }}"
|
||||
enabled: "{{ item.enabled | default(true) }}"
|
||||
loop: "{{ keycloak_realms }}"
|
||||
- name: Create or update Keycloak clients
|
||||
community.general.keycloak_client:
|
||||
auth_client_id: admin-cli
|
||||
auth_keycloak_url: "https://{{ keycloak_short_name }}.{{ domain }}/auth"
|
||||
auth_realm: master
|
||||
auth_username: admin
|
||||
auth_password: "{{ keycloak_admin_password }}"
|
||||
client_id: "{{ item.client_id + '-public' if item.public_client else item.client_id }}"
|
||||
realm: "{{ item.realm }}"
|
||||
name: "{{ \"'${client_\" + item.client_id + \"'\" if item.public_client else \"'${client_\" + item.client_id + \"_public'\" }}"
|
||||
protocol: openid-connect
|
||||
public_client: "{{ item.public_client | default(false) }}"
|
||||
standard_flow_enabled: "{{ item.standard_flow_enabled | default(true) }}"
|
||||
implicit_flow_enabled: "{{ item.implicit_flow_enabled | default(true) }}"
|
||||
direct_access_grants_enabled: "{{ item.direct_access_grants_enabled | default(true) }}"
|
||||
state: "{{ item.state | default('present') }}"
|
||||
protocol_mappers: "{{ keycloak_clients_default_protocol_mappings }}"
|
||||
loop: "{{ keycloak_clients }}"
|
||||
- name: Create Keycloak groups
|
||||
community.general.keycloak_group:
|
||||
auth_client_id: admin-cli
|
||||
auth_keycloak_url: "https://{{ keycloak_short_name }}.{{ domain }}/auth"
|
||||
auth_realm: master
|
||||
auth_username: admin
|
||||
auth_password: "{{ keycloak_admin_password }}"
|
||||
realm: "{{ item.realm }}"
|
||||
name: "{{ item.name }}"
|
||||
state: "{{ item.state | default('present') }}"
|
||||
loop: "{{ keycloak_groups }}"
|
||||
- name: Create Keycloak users
|
||||
community.general.keycloak_user:
|
||||
auth_client_id: admin-cli
|
||||
auth_keycloak_url: "https://{{ keycloak_short_name }}.{{ domain }}/auth"
|
||||
auth_realm: master
|
||||
auth_username: admin
|
||||
auth_password: "{{ keycloak_admin_password }}"
|
||||
realm: "{{ item.realm }}"
|
||||
state: "{{ item.state | default('present') }}"
|
||||
username: "{{ item.username }}"
|
||||
firstName: "{{ item.firstName }}"
|
||||
lastName: "{{ item.lastName }}"
|
||||
email: "{{ item.email | default( item.username + '@' + domain) }}"
|
||||
enabled: "{{ item.enabled | default(true) }}"
|
||||
emailVerified: "{{ item.emailVerified | default(true) }}"
|
||||
credentials: "{{ item.credentials }}"
|
||||
groups: "{{ item.groups }}"
|
||||
loop: "{{ keycloak_users }}"
|
25
roles/keycloak/tasks/secrets.yaml
Normal file
25
roles/keycloak/tasks/secrets.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
- block:
|
||||
- name: Set DB namespace for secret lookup
|
||||
set_fact:
|
||||
db_namespace: "{{ keycloak_db_namespace | default(postgres_db_namespace) | default(postgres_namespace) | default(postgres_operator_namespace) | default(namespace) }}"
|
||||
|
||||
- name: Set DB secret name for lookup
|
||||
set_fact:
|
||||
db_secret_name: "keycloak.{{ postgres_db_team | default(namespace) }}-postgres.credentials.postgresql.acid.zalan.do"
|
||||
|
||||
- name: Lookup Keycloak DB secret
|
||||
set_fact:
|
||||
keycloak_db_secret: "{{ lookup('k8s', kind='Secret', namespace=db_namespace, resource_name=db_secret_name) }}"
|
||||
|
||||
- debug:
|
||||
msg: "{{ keycloak_db_secret }}"
|
||||
verbosity: 2
|
||||
|
||||
- name: Set Keycloak DB username
|
||||
set_fact:
|
||||
keycloak_db_username: "{{ keycloak_db_secret.data.username | b64decode }}"
|
||||
|
||||
- name: Set Keycloak DB password
|
||||
set_fact:
|
||||
keycloak_db_password: "{{ keycloak_db_secret.data.password | b64decode }}"
|
||||
|
@ -10,7 +10,7 @@ local_dns_default_values:
|
||||
zone: "{{ local_domain }}"
|
||||
tsigSecret: "{{ k8s_tsig }}"
|
||||
tsigSecretAlg: "{{ local_dns_tsigSecretAlg | default('hmac-sha512') }}"
|
||||
tsigKeyname: "{{ local_dns_tsigKeyname | default('k8s') }}"
|
||||
tsigKeyname: "{{ local_dns_tsigKeyname | default(namespace) }}"
|
||||
tsigAxfr: true
|
||||
## Possible units [ns, us, ms, s, m, h], see more https://golang.org/pkg/time/#ParseDuration
|
||||
minTTL: "30s"
|
||||
|
@ -1,3 +1,6 @@
|
||||
postgres_enabled: true
|
||||
postgres_operator_enabled: true
|
||||
postgres_operator_ui_enabled: true
|
||||
postgres_operator_chart_ref: "ghp/postgres-operator"
|
||||
postgres_operator_ui_chart_ref: "ghp/postgres-operator-ui"
|
||||
postgres_operator_ui_short_name: "postgres-operator-ui"
|
||||
@ -64,6 +67,7 @@ postgres_db_definitions:
|
||||
roundcube: []
|
||||
harbor: []
|
||||
mastodon: []
|
||||
keycloak: []
|
||||
databases:
|
||||
gitea: gitea
|
||||
bitwarden: bitwarden
|
||||
@ -75,6 +79,7 @@ postgres_db_definitions:
|
||||
harbor_notary_server: harbor
|
||||
harbor_notary_signer: harbor
|
||||
mastodon: mastodon
|
||||
keycloak: keycloak
|
||||
preparedDatabases:
|
||||
peertube:
|
||||
defaultUsers: true
|
||||
|
@ -44,6 +44,7 @@
|
||||
|
||||
- set_fact:
|
||||
postgres_operator_combined_values: "{{ postgres_operator_default_values | combine(postgres_operator_values, recursive=true) }}"
|
||||
when: postgres_operator_enabled
|
||||
|
||||
- name: Deploy Postgres Operator
|
||||
kubernetes.core.helm:
|
||||
@ -54,9 +55,11 @@
|
||||
chart_version: "{{ postgres_operator_version | default(omit) }}"
|
||||
release_values: "{{ postgres_operator_combined_values | from_yaml }}"
|
||||
wait: true
|
||||
when: postgres_operator_enabled
|
||||
|
||||
- set_fact:
|
||||
postgres_operator_ui_combined_values: "{{ postgres_operator_ui_default_values | combine(postgres_operator_ui_values, recursive=true) }}"
|
||||
when: postgres_operator_ui_enabled
|
||||
|
||||
- name: Deploy Postgres Operator UI
|
||||
kubernetes.core.helm:
|
||||
@ -67,6 +70,7 @@
|
||||
chart_version: "{{ postgres_operator_ui_version | default(omit) }}"
|
||||
release_values: "{{ postgres_operator_ui_combined_values | from_yaml }}"
|
||||
wait: true
|
||||
when: postgres_operator_ui_enabled
|
||||
|
||||
- name: Create Postgres databases
|
||||
k8s:
|
||||
|
@ -15,6 +15,7 @@ default_accounts:
|
||||
- { name: harbor_admin }
|
||||
- { name: systemuser }
|
||||
- { name: minio_admin }
|
||||
- { name: keycloak_admin }
|
||||
|
||||
secret_keys:
|
||||
- { name: peertube }
|
||||
|
@ -21,13 +21,10 @@
|
||||
cleanup: true
|
||||
detach: false
|
||||
container_default_behavior: no_defaults
|
||||
command: "keymgr -t k8s hmac-sha512"
|
||||
command: "keymgr -t {{ namespace }} hmac-sha512"
|
||||
register: knot_container_output
|
||||
when: k8s_tsig_test_grep.stdout == '0'
|
||||
|
||||
- debug:
|
||||
msg: "{{ knot_container_output }}"
|
||||
|
||||
- name: Set k8s_key
|
||||
set_fact:
|
||||
k8s_key: "{{ knot_container_output.container.Output | from_yaml }}"
|
||||
|
@ -10,7 +10,7 @@ service_dns_default_values:
|
||||
zone: "{{ service_domain | default(domain) }}"
|
||||
tsigSecret: "{{ k8s_tsig }}"
|
||||
tsigSecretAlg: "{{ service_dns_tsigSecretAlg | default('hmac-sha512') }}"
|
||||
tsigKeyname: "{{ service_dns_tsigKeyname | default('k8s') }}"
|
||||
tsigKeyname: "{{ service_dns_tsigKeyname | default(namespace) }}"
|
||||
tsigAxfr: true
|
||||
## Possible units [ns, us, ms, s, m, h], see more https://golang.org/pkg/time/#ParseDuration
|
||||
minTTL: "30s"
|
||||
|
Loading…
Reference in New Issue
Block a user