diff --git a/src/conf-mode/vyos-config-ssh.py b/src/conf-mode/vyos-config-ssh.py
index be7af64be..6a520fc2c 100755
--- a/src/conf-mode/vyos-config-ssh.py
+++ b/src/conf-mode/vyos-config-ssh.py
@@ -1,224 +1,293 @@
 #!/usr/bin/env python3
 #
 # Copyright (C) 2018 VyOS maintainers and contributors
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License version 2 or later as
 # published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #
 
 import sys
 import os
-import time
+
+import jinja2
 
 from vyos.config import Config
 from vyos.util import ConfigError
 
 config_file = r'/etc/ssh/sshd_config'
 
+# Please be careful if you edit the template.
+config_tmpl = """
+
+### Autogenerated by vyos-config-ssh.py ###
+
+# Non-configurable defaults
+Protocol 2
+HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_dsa_key
+HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /etc/ssh/ssh_host_ed25519_key
+UsePrivilegeSeparation yes
+KeyRegenerationInterval 3600
+ServerKeyBits 1024
+SyslogFacility AUTH
+LoginGraceTime 120
+StrictModes yes
+RSAAuthentication yes
+PubkeyAuthentication yes
+IgnoreRhosts yes
+RhostsRSAAuthentication no
+HostbasedAuthentication no
+PermitEmptyPasswords no
+ChallengeResponseAuthentication no
+X11Forwarding yes
+X11DisplayOffset 10
+PrintMotd no
+PrintLastLog yes
+TCPKeepAlive yes
+Banner /etc/issue.net
+Subsystem sftp /usr/lib/openssh/sftp-server
+UsePAM yes
+HostKey /etc/ssh/ssh_host_key
+
+# Specifies whether sshd should look up the remote host name,
+# and to check that the resolved host name for the remote IP
+# address maps back to the very same IP address.
+UseDNS {{ host_validation }}
+
+# Specifies the port number that sshd listens on.  The default is 22.
+# Multiple options of this type are permitted.
+Port {{ port }}
+
+# Gives the verbosity level that is used when logging messages from sshd
+LogLevel {{ log_level }}
+
+# Specifies whether root can log in using ssh
+PermitRootLogin {{ allow_root }}
+
+# Specifies whether password authentication is allowed
+PasswordAuthentication {{ password_authentication }}
+
+{% if listen_on -%}
+# Specifies the local addresses sshd should listen on
+{% for a in listen_on -%}
+ListenAddress {{ a }}
+{% endfor -%}
+{% endif %}
+
+{% if ciphers -%}
+# Specifies the ciphers allowed. Multiple ciphers must be comma-separated.
+#
+# NOTE: As of now, there is no 'multi' node for 'ciphers', thus we have only one :/
+Ciphers {{ ciphers }}
+{% endif %}
+
+{% if mac -%}
+# Specifies the available MAC (message authentication code) algorithms. The MAC
+# algorithm is used for data integrity protection. Multiple algorithms must be
+# comma-separated.
+#
+# NOTE: As of now, there is no 'multi' node for 'mac', thus we have only one :/
+MACs {{ mac }}
+{% endif %}
+
+{% if key_exchange -%}
+# Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must
+# be comma-separated.
+#
+# NOTE: As of now, there is no 'multi' node for 'key-exchange', thus we have only one :/
+KexAlgorithms {{ key_exchange }}
+{% endif %}
+
+{% if allow_users -%}
+# This keyword can be followed by a list of user name patterns, separated by spaces.
+# If specified, login is allowed only for user names that match one of the patterns. 
+# Only user names are valid, a numerical user ID is not recognized.
+AllowUsers {{ allow_users | join(" ") }}
+{% endif %}
+
+{% if allow_groups -%}
+# This keyword can be followed by a list of group name patterns, separated by spaces.
+# If specified, login is allowed only for users whose primary group or supplementary
+# group list matches one of the patterns. Only group names are valid, a numerical group
+# ID is not recognized.
+AllowGroups {{ allow_groups | join(" ") }}
+{% endif %}
+
+{% if deny_users -%}
+# This keyword can be followed by a list of user name patterns, separated by spaces.
+# Login is disallowed for user names that match one of the patterns. Only user names
+# are valid, a numerical user ID is not	recognized.
+DenyUsers {{ deny_users | join(" ") }}
+{% endif %}
+
+{% if deny_groups -%}
+# This keyword can be followed by a list of group name patterns, separated by spaces.
+# Login is disallowed for users whose primary group or supplementary group list matches
+# one of the patterns. Only group names are valid, a numerical group ID is not recognized.
+DenyGroups {{ deny_groups | join(" ") }}
+{% endif %}
+"""
+
+default_config_data = {
+    'port' : '22',
+    'log_level': 'INFO',
+    'allow_root': 'no',
+    'password_authentication': 'yes',
+    'host_validation': 'yes'
+}
+
 def get_config():
-    ssh = {}
+    ssh = default_config_data
     conf = Config()
-    conf.set_level('service ssh')
-    if not conf.exists(''):
-        return ssh
-
-    if conf.exists('access-control allow'):
-        ssh.setdefault('allowed-users', [])
-        allow_user = []
-        allow_user = conf.return_values('access-control allow user')
-        for user in allow_user:
-            ssh['allowed-users'].append(user)
-
-        ssh.setdefault('allowed-groups', [])
-        allow_group = []
-        allow_group = conf.return_values('access-control allow group')
-        for group in allow_group:
-            ssh['allowed-groups'].append(group)
-
-    if conf.exists('access-control deny'):
-        ssh.setdefault('deny-users', [])
-        deny_user = []
-        deny_user = conf.return_values('access-control deny user')
-        for user in deny_user:
-            ssh['deny-users'].append(user)
-
-        ssh.setdefault('deny-groups', [])
-        deny_group = []
-        deny_group = conf.return_values('access-control deny group')
-        for group in deny_group:
-            ssh['deny-groups'].append(group)
+    if not conf.exists('service ssh'):
+        return None
+    else:
+        conf.set_level('service ssh')
+
+    if conf.exists('access-control allow-users'):
+        # Retrieve ',' separated list for allowed users and convert it to a list.
+        # The current VyOS CLI implementation should be improved to rather use multi nodes
+        # instead of a ',' separated input.
+        allow_user = conf.return_value('access-control allow-users')
+        tmp = allow_user.split(',')
+        users = []
+        for u in tmp:
+            users.append(u)
+
+        ssh.setdefault('allow_users', users)
+
+    if conf.exists('access-control allow-groups'):
+        # Retrieve ',' separated list for allowed groups and convert it to a list.
+        # The current VyOS CLI implementation should be improved to rather use multi nodes
+        # instead of a ',' separated input.
+        allow_group = conf.return_value('access-control allow-groups')
+        tmp = allow_group.split(',')
+        groups = []
+        for g in tmp:
+            groups.append(g)
+
+        ssh.setdefault('allow_groups', groups)
+
+    if conf.exists('access-control deny-groups'):
+        # Retrieve ',' separated list for denied users and convert it to a list.
+        # The current VyOS CLI implementation should be improved to rather use multi nodes
+        # instead of a ',' separated input.
+        deny_user = conf.return_value('access-control deny-users')
+        tmp = deny_user.split(',')
+        users = []
+        for u in tmp:
+            users.append(u)
+
+        ssh.setdefault('deny_users', users)
+
+    if conf.exists('access-control deny-groups'):
+        # Retrieve ',' separated list for denied groups and convert it to a list.
+        # The current VyOS CLI implementation should be improved to rather use multi nodes
+        # instead of a ',' separated input.
+        deny_group = conf.return_value('access-control deny-groups')
+        tmp = deny_group.split(',')
+        groups = []
+        for g in tmp:
+            groups.append(g)
+
+        ssh.setdefault('deny_groups', groups)
 
     if conf.exists('allow-root'):
-        ssh.setdefault('allow-root', True)
+        ssh['allow-root'] = 'yes'
 
     if conf.exists('ciphers'):
+        # TODO: OpenSSH supports having multiple Ciphers configured. VyOS CLI
+        # yet has no multi node for this. See T632 in phabricator.
         ciphers = conf.return_value('ciphers')
         ssh.setdefault('ciphers', ciphers)
 
     if conf.exists('disable-host-validation'):
-        ssh.setdefault('disable-host-validation', True)
+        ssh['host_validation'] = 'no'
 
     if conf.exists('disable-password-authentication'):
-        ssh.setdefault('disable-password-authentication', True)
+        ssh['password_authentication'] = 'no'
 
     if conf.exists('key-exchange'):
+        # TODO: OpenSSH supports having multiple KEYX methods configured. VyOS CLI
+        # yet has no multi node for this. See T632 in phabricator.
         kex = conf.return_value('key-exchange')
-        ssh.setdefault('key-exchange', kex)
+        ssh.setdefault('key_exchange', kex)
 
     if conf.exists('listen-address'):
-        ssh.setdefault('listen-address', [])
-        addresses = []
+        # We can listen on both IPv4 and IPv6 addresses
+        # Maybe there could be a check in the future if the configured IP address
+        # is configured on this system at all?
         addresses = conf.return_values('listen-address')
+        listen = []
+
         for addr in addresses:
-            ssh['listen-address'].append(addr)
+            listen.append(addr)
+
+        ssh.setdefault('listen_on', listen)
 
     if conf.exists('loglevel'):
-        level = conf.return_value('loglevel')
-        ssh.setdefault('loglevel', level)
+        ssh['log_level'] = conf.return_value('loglevel')
 
     if conf.exists('mac'):
+        # TODO: OpenSSH supports having multiple MACs configured. VyOS CLI
+        # yet has no multi node for this. See T632 in phabricator.
         mac = conf.return_value('mac')
         ssh.setdefault('mac', mac)
 
     if conf.exists('port'):
         port = conf.return_value('port')
         ssh.setdefault('port', port)
 
-    print(ssh)
     return ssh
 
 def verify(ssh):
-    return None
-
-def generate(ssh):
-    config_header = '### Autogenerated by vyos-config-ssh.py on {tm} ###\n'.format(tm=time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()))
-
-    # write new configuration file
-    f = open(config_file, 'w')
-    f.write(config_header)
-    f.write('\n')
-
-    if 'port' in ssh.keys():
-        f.write('Port {0}\n'.format(ssh['port']))
-    else:
-        f.write('Port 22\n')
-
-    f.write('Protocol 2\n')
-    f.write('HostKey /etc/ssh/ssh_host_rsa_key\n')
-    f.write('HostKey /etc/ssh/ssh_host_dsa_key\n')
-    f.write('HostKey /etc/ssh/ssh_host_ecdsa_key\n')
-    f.write('HostKey /etc/ssh/ssh_host_ed25519_key\n')
-    f.write('UsePrivilegeSeparation yes\n')
-    f.write('\n')
-    f.write('KeyRegenerationInterval 3600\n')
-    f.write('ServerKeyBits 1024\n')
-    f.write('\n')
-    f.write('SyslogFacility AUTH\n')
+    if ssh is None:
+        return None
 
     if 'loglevel' in ssh.keys():
-        f.write('LogLevel {0}\n'.format(ssh['loglevel']))
-    else:
-        f.write('LogLevel INFO\n')
-
-    f.write('\n')
-    f.write('LoginGraceTime 120\n')
-
-    if 'allow-root' in ssh.keys():
-        f.write('PermitRootLogin yes\n')
-    else:
-        f.write('PermitRootLogin no\n')
-
-    f.write('StrictModes yes\n')
-    f.write('\n')
-    f.write('RSAAuthentication yes\n')
-    f.write('PubkeyAuthentication yes\n')
-    f.write('\n')
-    f.write('IgnoreRhosts yes\n')
-    f.write('RhostsRSAAuthentication no\n')
-    f.write('HostbasedAuthentication no\n')
-    f.write('\n')
-    f.write('PermitEmptyPasswords no\n')
-    f.write('\n')
-    f.write('ChallengeResponseAuthentication no\n')
-    f.write('\n')
-
-    if 'disable-password-authentication' in ssh.keys():
-        f.write('PasswordAuthentication no\n')
-    else:
-        f.write('PasswordAuthentication yes\n')
-
-    f.write('\n')
-    f.write('X11Forwarding yes\n')
-    f.write('X11DisplayOffset 10\n')
-    f.write('PrintMotd no\n')
-    f.write('PrintLastLog yes\n')
-    f.write('TCPKeepAlive yes\n')
-    f.write('\n')
-    f.write('Banner /etc/issue.net\n')
-    f.write('\n')
-    f.write('Subsystem sftp /usr/lib/openssh/sftp-server\n')
-    f.write('\n')
-    f.write('UsePAM yes\n')
-    f.write('HostKey /etc/ssh/ssh_host_key\n')
-
-    if 'disable-host-validation' in ssh.keys():
-        f.write('UseDNS no\n')
-    else:
-        f.write('UseDNS yes\n')
-
-    if 'listen-address' in ssh.keys():
-        for addr in ssh['listen-address']:
-            f.write('ListenAddress {0}\n'.format(addr))
+        allowed_loglevel = 'QUIET, FATAL, ERROR, INFO, VERBOSE'
+        if not ssh['loglevel'] in allowed_loglevel:
+            raise ConfigError('loglevel must be one of "{0}"\n'.format(allowed_loglevel))
 
-    if 'ciphers' in ssh.keys():
-        f.write('Ciphers {0}\n'.format(ssh['ciphers']))
-
-    if 'key-exchange' in ssh.keys():
-        f.write('KexAlgorithms {0}\n'.format(ssh['key-exchange']))
-
-    if 'mac' in ssh.keys():
-        f.write('MACs {0}\n'.format(ssh['mac']))
-
-    if 'allowed-users' in ssh.keys():
-        print('AllowUsers {0}\n'.format(' '.join(str(usr) for usr in ssh['allowed-users'])))
-
-    if 'allowed-groups' in ssh.keys():
-        print('AllowGroups {0}\n'.format(' '.join(str(grp) for grp in ssh['allowed-groups'])))
-
-    if 'deny-users' in ssh.keys():
-        print('DenyUsers {0}\n'.format(' '.join(str(usr) for usr in ssh['deny-users'])))
+    return None
 
-    if 'deny-groups' in ssh.keys():
-        print('DenyGroups {0}\n'.format(' '.join(str(grp) for grp in ssh['deny-groups'])))
+def generate(ssh):
+    if ssh is None:
+        return None
 
-    f.close()
+    tmpl = jinja2.Template(config_tmpl)
+    config_text = tmpl.render(ssh)
+    with open(config_file, 'w') as f:
+        f.write(config_text)
     return None
 
 def apply(ssh):
-    if 'port' in ssh.keys():
-        cmd = "sudo systemctl restart ssh"
+    if ssh is not None and 'port' in ssh.keys():
+        os.system("sudo systemctl restart ssh")
     else:
-        cmd = "sudo systemctl stop ssh"
+        # SSH access is removed in the commit
+        os.system("sudo systemctl stop ssh")
+        os.unlink(config_file)
 
-    os.system(cmd)
     return None
 
 if __name__ == '__main__':
     try:
         c = get_config()
         verify(c)
         generate(c)
         apply(c)
     except ConfigError as e:
         print(e)
         sys.exit(1)