Compare commits

...

48 commits
main ... temp

Author SHA1 Message Date
Christian Fraß d128b923fc Merge remote-tracking branch 'origin/main' into temp 2024-06-09 11:07:12 +02:00
Christian Fraß 8864cf0c2d [fix] role:authelia 2024-06-06 14:46:44 +02:00
Christian Fraß 8ede5e7329 [fix] role:vikunja 2024-06-06 14:34:02 +02:00
Christian Fraß 2ccb0bc28f [fix] role:vikunja 2024-06-06 14:10:35 +02:00
Christian Fraß 9196b1539f [fix] role:vikunja 2024-06-06 14:07:11 +02:00
Christian Fraß 2110729297 [fix] role:authelia 2024-06-06 13:55:17 +02:00
Christian Fraß 45500be987 [fix] role:nginx 2024-06-06 13:51:31 +02:00
Christian Fraß f55f317cef [fix] role:nginx 2024-06-06 13:47:26 +02:00
Christian Fraß a7e2a6d3cb Merge branch 'dev-vikunja' into temp 2024-06-05 20:02:00 +02:00
Christian Fraß ae1b708c5a [res] 2024-06-05 20:01:59 +02:00
Christian Fraß 93cf4a2895 [fix] role:vikunja 2024-06-05 20:00:46 +02:00
Christian Fraß 156f94fb3f [fix] role:authelia:vardef 2024-06-05 20:00:23 +02:00
Christian Fraß c62ae6e42f [fix] role:authelia-for-vikunja 2024-06-04 10:04:20 +02:00
Christian Fraß cc922b910d [mod] role:vikunja:more config variables 2024-06-04 10:04:01 +02:00
Christian Fraß e442272e18 [add] role:postgresql-for-vikunja 2024-06-04 10:03:33 +02:00
Christian Fraß 70bd2098b0 [add] role:authelia-for-vikunja [add] vikunja [add] vikunja-and-nginx 2024-06-04 08:52:31 +02:00
Christian Fraß 2153340faf [mod] role:authelia:add var "password_reset_custom_url" 2024-06-03 23:55:51 +02:00
Christian Fraß a4163dd401 [fix] role:tlscert_acme_inwx:pseudoqueue 2024-06-03 23:54:59 +02:00
Christian Fraß d148cc28d1 [mod] role:system_basics:add tmux installation 2024-06-03 23:54:26 +02:00
Christian Fraß 19e2708393 [mod] todo 2024-06-03 23:53:53 +02:00
Christian Fraß e0529a0346 [mod] role:authelia 2024-06-01 19:26:06 +02:00
Christian Fraß 46375e9dd0 [fix] role:tlscert_acme_inwx 2024-06-01 18:41:52 +02:00
Christian Fraß 53c31d1187 Merge branch 'dev-nginx-hardening_1' into temp 2024-06-01 18:16:47 +02:00
Christian Fraß 35688eddaf [fix] roles with ufw incocation 2024-06-01 17:23:42 +02:00
Christian Fraß 8c7b10f852 [fix] roles with ufw incocation 2024-06-01 17:17:40 +02:00
Christian Fraß abdd13264f [fix] role:nginx 2024-06-01 16:25:51 +02:00
Christian Fraß 72cec2758c [fix] role:nginx 2024-06-01 16:17:11 +02:00
Christian Fraß 1bae250945 [fix] role:nginx 2024-06-01 16:06:35 +02:00
Christian Fraß a9c55a548c Merge branch 'dev-ufw_1' into temp 2024-06-01 15:01:00 +02:00
Christian Fraß 6416259488 Merge branch 'dev-unattended-updates_1' into temp 2024-06-01 15:00:47 +02:00
Christian Fraß ed300b7fdb [mod] role:tlscert_acme_inwx 2024-06-01 13:38:39 +02:00
Christian Fraß fbbca1615f [mod] role:system-basics 2024-06-01 13:38:14 +02:00
Christian Fraß 5c4df42844 [fix] role:tlscert_acme_inwx 2024-06-01 13:26:46 +02:00
Christian Fraß 1cb7fe5e68 [fix] role:tlscert_acme_inwx 2024-06-01 13:17:35 +02:00
Christian Fraß 04de638925 [fix] role:tlscert_acme_inwx 2024-06-01 13:10:22 +02:00
Christian Fraß f95123a21c [fix] role:tlscert_acme_inwx 2024-06-01 13:04:50 +02:00
Christian Fraß 19ceef7f45 [fix] role:unattended-upgrades 2024-06-01 13:00:09 +02:00
Christian Fraß d515cc6cec [fix] role:ufw 2024-06-01 12:56:18 +02:00
Christian Fraß 643ec848f0 [fix] role:system-basics:root 2024-06-01 12:52:16 +02:00
Christian Fraß b1ef98bc00 [fix] role:tlscert_acme_inwx 2024-06-01 12:49:30 +02:00
Christian Fraß 17b581aa61 Merge branch 'dev-tls_auto' into temp 2024-06-01 12:34:00 +02:00
Christian Fraß d18600bf91 [mod] role:tlscert_acme_inwx:revise inwx 2024-06-01 08:53:52 +02:00
Christian Fraß 9806adb9ab [mod] role:tlscert_acme_inwx:rename tls-renew to tls-get 2024-05-31 08:50:13 +02:00
Christian Fraß 7b3d5829ae [mod] role:tlscert_acme_inwx 2024-05-31 08:24:45 +02:00
Christian Fraß 0aa3cb5303 [mod] role:tlscert_acme_inwx:eigene umsetzung und automatische erneuerung 2024-05-30 22:56:56 +02:00
Christian Fraß f25589f56b [int] 2024-05-30 18:44:28 +02:00
Christian Fraß 6239a095b6 [res] 2024-05-20 22:41:50 +02:00
Christian Fraß 8fa7340959 Merge remote-tracking branch 'origin/dev-ufw' into temp 2024-05-20 22:40:15 +02:00
21 changed files with 629 additions and 3 deletions

View file

@ -0,0 +1,5 @@
{
"var_authelia_for_vikunja_vikunja_url_base": "https://vikunja.example.org",
"var_authelia_for_vikunja_client_id": "vikunja",
"var_authelia_for_vikunja_client_secret": "REPLACE_ME"
}

View file

@ -0,0 +1,10 @@
## Beschreibung
Um [Vikunja](../vikunja) gegen [Authelia](../authelia) authentifizieren zu lassen
## Verweise
- [Vikunja-Dokumentation | OpenID](https://vikunja.io/docs/openid/)
- [Vikunja-Dokumentation | OpenID example configurations for Authelia](https://vikunja.io/docs/openid-example-configurations/#authelia)
- [Authelia-Dokumentation | Vikunja Integration](https://www.authelia.com/integration/openid-connect/vikunja/)

View file

@ -0,0 +1,25 @@
[
{
"name": "configuration | emplace",
"become": true,
"ansible.builtin.template": {
"src": "authelia-client-conf.json.j2",
"dest": "/etc/authelia/conf.d/clients/vikunja.json"
}
},
{
"name": "configuration | apply",
"become": true,
"ansible.builtin.command": {
"cmd": "/usr/bin/authelia-conf-compose"
}
},
{
"name": "restart service",
"become": true,
"ansible.builtin.systemd_service": {
"state": "restarted",
"name": "authelia"
}
}
]

View file

@ -0,0 +1,17 @@
{
"client_id": "{{var_authelia_for_vikunja_client_id}}",
"client_secret": "{{var_authelia_for_vikunja_client_secret}}",
"client_name": "Vikunja",
"public": false,
"authorization_policy": "one_factor",
"redirect_uris": [
"{{var_authelia_for_vikunja_vikunja_url_base}}/auth/openid/authelia"
],
"scopes": [
"openid",
"email",
"profile"
],
"userinfo_signed_response_alg": "none",
"token_endpoint_auth_method": "client_secret_basic"
}

View file

@ -12,7 +12,10 @@
}, },
{ {
"name": "generate dhparams file", "name": "generate dhparams file",
"ansible.builtin.command": "openssl dhparam -out /etc/nginx/dhparam 4096", "become": true,
"ansible.builtin.command": {
"cmd": "openssl dhparam -out /etc/nginx/dhparam 4096"
},
"args": { "args": {
"creates": "/etc/nginx/dhparam" "creates": "/etc/nginx/dhparam"
} }

View file

@ -0,0 +1,5 @@
{
"var_postgresql_for_vikunja_username": "vikunja_user",
"var_postgresql_for_vikunja_password": "REPLACE_ME",
"var_postgresql_for_vikunja_schema": "vikunja"
}

View file

@ -0,0 +1,49 @@
[
{
"name": "packages",
"become": true,
"ansible.builtin.apt": {
"update_cache": true,
"pkg": [
"acl",
"python3-psycopg2"
]
}
},
{
"name": "user",
"become": true,
"become_user": "postgres",
"community.postgresql.postgresql_user": {
"state": "present",
"name": "{{var_postgresql_for_vikunja_username}}",
"password": "{{var_postgresql_for_vikunja_password}}"
},
"environment": {
"PGOPTIONS": "-c password_encryption=scram-sha-256"
}
},
{
"name": "schema",
"become": true,
"become_user": "postgres",
"community.postgresql.postgresql_db": {
"state": "present",
"name": "{{var_postgresql_for_vikunja_schema}}",
"owner": "{{var_postgresql_for_vikunja_username}}"
}
},
{
"name": "rights",
"become": true,
"become_user": "postgres",
"community.postgresql.postgresql_privs": {
"state": "present",
"db": "{{var_postgresql_for_vikunja_schema}}",
"objs": "ALL_IN_SCHEMA",
"roles": "{{var_postgresql_for_vikunja_username}}",
"privs": "ALL",
"grant_option": true
}
}
]

View file

@ -3,7 +3,6 @@
"var_tlscert_acme_inwx_acme_account_key_path": "/etc/letsencrypt/key", "var_tlscert_acme_inwx_acme_account_key_path": "/etc/letsencrypt/key",
"var_tlscert_acme_inwx_inwx_account_username": "REPLACE_ME", "var_tlscert_acme_inwx_inwx_account_username": "REPLACE_ME",
"var_tlscert_acme_inwx_inwx_account_password": "REPLACE_ME", "var_tlscert_acme_inwx_inwx_account_password": "REPLACE_ME",
"var_tlscert_acme_inwx_domain_base": "example.org", "var_tlscert_acme_inwx_domain": "foo.example.org",
"var_tlscert_acme_inwx_domain_path": "foo",
"var_tlscert_acme_inwx_ssl_directory": "/etc/ssl" "var_tlscert_acme_inwx_ssl_directory": "/etc/ssl"
} }

View file

@ -0,0 +1,133 @@
#!/usr/bin/env python3
import sys as _sys
import os as _os
import json as _json
import pathlib as _pathlib
import argparse as _argparse
def file_read(path):
handle = open(path, "r")
content = handle.read()
handle.close()
return content
def main():
## args
argument_parser = _argparse.ArgumentParser()
argument_parser.add_argument(
"-c",
"--conf-path",
type = str,
dest = "conf_path",
metavar = "<conf-path>",
default = _os.path.join(str(_pathlib.Path.home()), ".tls-get-conf.json"),
)
argument_parser.add_argument(
dest = "domain",
metavar = "<domain>",
help = "the domain for which the TLS certificate shall be generated"
)
argument_parser.add_argument(
"-t",
"--target-directory",
dest = "target_directory",
type = str,
metavar = "<target-directory>",
default = "/etc/ssl",
)
argument_parser.add_argument(
"-x",
"--challenge-prefix",
dest = "challenge_prefix",
type = str,
metavar = "<challenge-prefix>",
default = "_acme-challenge",
help = "which subdomain to use for ACME challanges",
)
argument_parser.add_argument(
"-w",
"--delay",
dest = "delay",
type = float,
default = 60.0,
metavar = "<delay>",
help = "seconds to wait at end of certbot auth hook",
)
argument_parser.add_argument(
"-q",
"--dry-run",
dest = "dry_run",
action = "store_true",
default = False,
help = "whether to only print the command on stdout instead of executing it",
)
args = argument_parser.parse_args()
## vars
conf = _json.loads(file_read(args.conf_path))
le_dir = "/etc/letsencrypt/live"
## exec
command_certbot = " ".join(
[
"certbot",
"certonly",
("--email='%s'" % conf["acme_account"]["email"]),
# ("--work-dir='%s'" % conf["misc"]["working_directory"]),
"--preferred-challenges='dns'",
"--non-interactive",
"--agree-tos",
("--domain='%s'" % args.domain),
"--manual",
(
"--manual-auth-hook='%s'"
% " ".join(
[
"/usr/local/bin/inwx",
("--username=\"%s\"" % conf["inwx_account"]["username"]),
("--password=\"%s\"" % conf["inwx_account"]["password"]),
"certbot-hook",
("--delay=%.4f" % args.delay),
]
)
),
(
"--post-hook='%s'"
% " ".join(
[
"/usr/local/bin/inwx",
("--username=\"%s\"" % conf["inwx_account"]["username"]),
("--password=\"%s\"" % conf["inwx_account"]["password"]),
"delete",
("--domain=\"%s\"" % (args.challenge_prefix + "." + args.domain)),
("--type=\"TXT\""),
]
)
),
]
)
if (args.dry_run):
_sys.stdout.write(command_certbot + "\n")
else:
_os.system(command_certbot)
subjects = [
{"source_name": "privkey", "target_directory": "private"},
{"source_name": "cert", "target_directory": "certs"},
{"source_name": "chain", "target_directory": "chains"},
{"source_name": "fullchain", "target_directory": "fullchains"},
]
for subject in subjects:
_os.system(
"mkdir --parents %s && cp --dereference %s %s"
% (
_os.path.join(args.target_directory, subject["target_directory"]),
_os.path.join(le_dir, args.domain, "%s.pem" % subject["source_name"]),
_os.path.join(args.target_directory, subject["target_directory"], "%s.pem" % args.domain),
)
)
main()

View file

@ -1,3 +1,8 @@
## Beschreibung
- richtet die regelmäßige TLS-Zertifikats-Erstellung für eine Domäne und führt eine Erstellung direkt aus
## Verweise ## Verweise
- [Digital Ocean | How To Acquire a Let's Encrypt Certificate Using Ansible](https://www.digitalocean.com/community/tutorials/how-to-acquire-a-let-s-encrypt-certificate-using-ansible-on-ubuntu-18-04) - [Digital Ocean | How To Acquire a Let's Encrypt Certificate Using Ansible](https://www.digitalocean.com/community/tutorials/how-to-acquire-a-let-s-encrypt-certificate-using-ansible-on-ubuntu-18-04)

View file

@ -0,0 +1,12 @@
{
"acme_account": {
"email": "{{var_tlscert_acme_inwx_acme_account_email}}"
},
"inwx_account": {
"username": "{{var_tlscert_acme_inwx_inwx_account_username}}",
"password": "{{var_tlscert_acme_inwx_inwx_account_password}}"
},
"misc": {
"working_directory": "/tmp/acme"
}
}

View file

@ -0,0 +1,3 @@
{
"var_vikunja_and_nginx_domain": "vikunja.example.org"
}

View file

@ -0,0 +1,3 @@
## Verweise
- [Vikunja-Dokumentation](https://vikunja.io/docs/reverse-proxy/#nginx)

View file

@ -0,0 +1,35 @@
[
{
"name": "deactivate default site",
"become": true,
"ansible.builtin.file": {
"state": "absent",
"dest": "/etc/nginx/sites-enabled/default"
}
},
{
"name": "emplace configuration | data",
"become": true,
"ansible.builtin.template": {
"src": "conf.j2",
"dest": "/etc/nginx/sites-available/{{var_vikunja_and_nginx_domain}}"
}
},
{
"name": "emplace configuration | link",
"become": true,
"ansible.builtin.file": {
"state": "link",
"src": "/etc/nginx/sites-available/{{var_vikunja_and_nginx_domain}}",
"dest": "/etc/nginx/sites-enabled/{{var_vikunja_and_nginx_domain}}"
}
},
{
"name": "restart nginx",
"become": true,
"ansible.builtin.systemd_service": {
"state": "restarted",
"name": "nginx"
}
}
]

View file

@ -0,0 +1,16 @@
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen [::]:443 ssl;
server_name {{var_vikunja_and_nginx_domain}};
ssl_certificate /etc/ssl/fullchains/{{var_vikunja_and_nginx_domain}}.pem;
ssl_certificate_key /etc/ssl/private/{{var_vikunja_and_nginx_domain}}.pem;
location / {
proxy_pass http://localhost:3456;
client_max_body_size 20M;
}
}

View file

@ -0,0 +1,30 @@
{
"var_vikunja_version": "0.23.0",
"var_vikunja_architecture": "amd64",
"var_vikunja_domain": "vikunja.example.org",
"var_vikunja_directory": "/opt/vikunja",
"var_vikunja_user": "vikunja",
"var_vikunja_timezone": "Europe/Berlin",
"var_vikunja_default_language": "de",
"var_vikunja_database_kind": "sqlite",
"var_vikunja_database_data_sqlite_path": "data.sqlite",
"var_vikunja_database_data_postgresql_host": "postgresql.example.org",
"var_vikunja_database_data_postgresql_port": 5432,
"var_vikunja_database_data_postgresql_username": "vikunja_user",
"var_vikunja_database_data_postgresql_password": "REPLACE_ME",
"var_vikunja_database_data_postgresql_schema": "vikunja",
"var_vikunja_authentication_kind": "internal",
"var_vikunja_authentication_data_authelia_provider_id": "authelia",
"var_vikunja_authentication_data_authelia_provider_name": "Authelia",
"var_vikunja_authentication_data_authelia_client_id": "vikunja",
"var_vikunja_authentication_data_authelia_client_secret": "REPLACE_ME",
"var_vikunja_authentication_data_authelia_url_base": "https://authelia.example.org",
"var_vikunja_mail_sending_enabled": true,
"var_vikunja_mail_sending_smtp_host": "smtp.example.org",
"var_vikunja_mail_sending_smtp_port": 587,
"var_vikunja_mail_sending_smtp_authtype": "plain",
"var_vikunja_mail_sending_smtp_force_tls": false,
"var_vikunja_mail_sending_smtp_username": "REPLACE_ME",
"var_vikunja_mail_sending_smtp_password": "REPLACE_ME",
"var_vikunja_mail_sending_sender": "vikunja@example.org"
}

9
roles/vikunja/info.md Normal file
View file

@ -0,0 +1,9 @@
## Beschreibung
- Einrichtung der Aufgaben-Verwaltung [Vikunja](https://vikunja.io/)
## Verweise
- [git-Repository](https://kolaente.dev/vikunja/vikunja)
- [Konfiguration](https://vikunja.io/docs/config-options/)

View file

@ -0,0 +1,65 @@
[
{
"name": "user",
"ansible.builtin.user": {
"name": "{{var_vikunja_user}}",
"create_home": true,
"home": "{{var_vikunja_directory}}"
}
},
{
"name": "download",
"become": true,
"become_user": "{{var_vikunja_user}}",
"ansible.builtin.get_url": {
"url": "https://dl.vikunja.io/vikunja/{{var_vikunja_version}}/vikunja-v{{var_vikunja_version}}-linux-{{var_vikunja_architecture}}-full.zip",
"dest": "/tmp/vikunja.zip"
}
},
{
"name": "unpack",
"become": true,
"become_user": "{{var_vikunja_user}}",
"ansible.builtin.unarchive": {
"remote_src": true,
"src": "/tmp/vikunja.zip",
"dest": "{{var_vikunja_directory}}"
}
},
{
"name": "link",
"become": true,
"become_user": "{{var_vikunja_user}}",
"ansible.builtin.file": {
"state": "link",
"src": "{{var_vikunja_directory}}/vikunja-v{{var_vikunja_version}}-linux-{{var_vikunja_architecture}}",
"dest": "{{var_vikunja_directory}}/vikunja"
}
},
{
"name": "conf",
"become": true,
"become_user": "{{var_vikunja_user}}",
"ansible.builtin.template": {
"src": "config.json.j2",
"dest": "{{var_vikunja_directory}}/config.json"
}
},
{
"name": "systemd-unit",
"become": true,
"ansible.builtin.template": {
"src": "systemd-unit.j2",
"dest": "/etc/systemd/system/vikunja.service"
}
},
{
"name": "apply",
"become": true,
"ansible.builtin.systemd_service": {
"state": "restarted",
"enabled": true,
"name": "vikunja"
}
}
]

View file

@ -0,0 +1,63 @@
{
"service": {
"publicurl": "https://{{var_vikunja_domain}}",
"rootpath": "{{var_vikunja_directory}}",
"timezone": "{{var_vikunja_timezone}}"
},
"defaultsettings": {
"language": "{{var_vikunja_default_language}}",
"timezone": "{{var_vikunja_timezone}}"
},
"database": {
{% if var_vikunja_database_kind == 'sqlite' %}
"type": "sqlite",
"path": "{{var_vikunja_database_data_sqlite_path}}"
{% endif %}
{% if var_vikunja_database_kind == 'postgresql' %}
"type": "postgres",
"host": "{{var_vikunja_database_data_postgresql_host}}",
"port": {{var_vikunja_database_data_postgresql_port | string}},
"user": "{{var_vikunja_database_data_postgresql_username}}",
"password": "{{var_vikunja_database_data_postgresql_password}}",
"database": "{{var_vikunja_database_data_postgresql_schema}}"
{% endif %}
},
"auth": {
{% if var_vikunja_authentication_kind == 'internal' %}
"local": {
"enabled": true
},
"openid": {
"enabled": false
}
{% endif %}
{% if var_vikunja_authentication_kind == 'authelia' %}
"local": {
"enabled": false
},
"openid": {
"enabled": true,
"redirecturl": "https://{{var_vikunja_domain}}/auth/openid/",
"providers": [
{
"name": "Authelia",
"authurl": "{{var_vikunja_authentication_data_authelia_url_base}}",
"clientid": "{{var_vikunja_authentication_data_authelia_client_id}}",
"clientsecret": "{{var_vikunja_authentication_data_authelia_client_secret}}",
"scope": "openid profile email"
}
]
}
{% endif %}
},
"mailer": {
"enabled": {{var_vikunja_mail_sending_enabled | to_json}},
"host": "{{var_vikunja_mail_sending_smtp_host}}",
"port": {{var_vikunja_mail_sending_smtp_port | string}},
"autthtype": "{{var_vikunja_mail_sending_smtp_authtype}}",
"username": "{{var_vikunja_mail_sending_smtp_username}}",
"password": "{{var_vikunja_mail_sending_smtp_password}}",
"fromemail": "{{var_vikunja_mail_sending_sender}}",
"forcessl": {{var_vikunja_mail_sending_smtp_force_tls | to_json}}
}
}

View file

@ -0,0 +1,16 @@
[Unit]
Description=Vikunja
After=syslog.target
After=network.target
[Service]
User={{var_vikunja_user}}
Group={{var_vikunja_user}}
RestartSec=2s
Type=simple
WorkingDirectory={{var_vikunja_directory}}
ExecStart=/usr/bin/vikunja
Restart=always
[Install]
WantedBy=multi-user.target

123
roles/vikunja/vardef.json Normal file
View file

@ -0,0 +1,123 @@
{
"version": {
"type": "string",
"mandatory": false
},
"architecture": {
"type": "string",
"mandatory": false
},
"domain": {
"type": "string",
"mandatory": false
},
"directory": {
"type": "string",
"mandatory": false
},
"user": {
"type": "string",
"mandatory": false
},
"timezone": {
"type": "string",
"mandatory": false
},
"default_language": {
"type": "string",
"mandatory": false,
"description": "ISO 639-1"
},
"database_kind": {
"type": "string",
"mandatory": false,
"options": [
"sqlite",
"postgresql"
]
},
"database_data_sqlite_path": {
"type": "string",
"mandatory": false
},
"database_data_postgresql_host": {
"type": "string",
"mandatory": false
},
"database_data_postgresql_port": {
"type": "integer",
"mandatory": false
},
"database_data_postgresql_username": {
"type": "string",
"mandatory": false
},
"database_data_postgresql_password": {
"type": "string",
"mandatory": false
},
"database_data_postgresql_schema": {
"type": "string",
"mandatory": false
},
"authentication_kind": {
"type": "string",
"mandatory": false,
"options": [
"internal",
"authelia"
]
},
"authentication_data_authelia_provider_id": {
"type": "string",
"mandatory": false
},
"authentication_data_authelia_provider_name": {
"type": "string",
"mandatory": false
},
"authentication_data_authelia_client_id": {
"type": "string",
"mandatory": false
},
"authentication_data_authelia_client_secret": {
"type": "string",
"mandatory": false
},
"authentication_data_authelia_url_base": {
"type": "string",
"mandatory": false
},
"mail_sending_enabled": {
"type": "string",
"mandatory": false
},
"mail_sending_smtp_host": {
"type": "string",
"mandatory": false
},
"mail_sending_smtp_port": {
"type": "integer",
"mandatory": false
},
"mail_sending_smtp_authtype": {
"type": "string",
"mandatory": false
},
"mail_sending_smtp_force_tls": {
"type": "boolean",
"mandatory": false
},
"mail_sending_smtp_username": {
"type": "string",
"mandatory": false
},
"mail_sending_smtp_password": {
"type": "string",
"mandatory": false
},
"mail_sending_sender": {
"type": "string",
"mandatory": false
}
}