diff --git a/functional_tests/features/ssh.feature b/functional_tests/features/ssh.feature
new file mode 100644
index 000000000..adc191cd4
--- /dev/null
+++ b/functional_tests/features/ssh.feature
@@ -0,0 +1,43 @@
+#
+# This file is part of FreedomBox.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+
+@apps @ssh @backups
+Feature: Secure Shell Server
+ Run secure shell server.
+
+Background:
+ Given I'm a logged in user
+ Given the ssh application is installed
+
+Scenario: Enable ssh application
+ Given the ssh application is disabled
+ When I enable the ssh application
+ Then the ssh service should be running
+
+Scenario: Disable ssh application
+ Given the ssh application is enabled
+ When I disable the ssh application
+ Then the ssh service should not be running
+
+# TODO: Improve this to actually check that earlier ssh certificate has been
+# restored.
+Scenario: Backup and restore ssh
+ Given the ssh application is enabled
+ When I create a backup of the ssh app data
+ And I export the ssh app data backup
+ And I restore the ssh app data backup
+ Then the ssh service should be running
diff --git a/functional_tests/support/interface.py b/functional_tests/support/interface.py
index d9895d3d4..a043e242a 100644
--- a/functional_tests/support/interface.py
+++ b/functional_tests/support/interface.py
@@ -28,7 +28,7 @@ from .service import wait_for_page_update
sys_modules = [
'avahi', 'backups', 'bind', 'cockpit', 'config', 'datetime', 'diagnostics',
'dynamicdns', 'firewall', 'letsencrypt', 'monkeysphere', 'names',
- 'networks', 'pagekite', 'power', 'security', 'snapshot', 'upgrades',
+ 'networks', 'pagekite', 'power', 'security', 'snapshot', 'ssh', 'upgrades',
'users'
]
diff --git a/plinth/modules/ssh/__init__.py b/plinth/modules/ssh/__init__.py
index d37da3a83..0ad72c68b 100644
--- a/plinth/modules/ssh/__init__.py
+++ b/plinth/modules/ssh/__init__.py
@@ -25,6 +25,8 @@ from plinth import service as service_module
from plinth.menu import main_menu
from plinth.views import ServiceView
+from .manifest import backup
+
version = 1
is_essential = True
diff --git a/plinth/modules/ssh/manifest.py b/plinth/modules/ssh/manifest.py
new file mode 100644
index 000000000..0391f5a76
--- /dev/null
+++ b/plinth/modules/ssh/manifest.py
@@ -0,0 +1,34 @@
+#
+# This file is part of FreedomBox.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+"""
+Application manifest for ssh.
+"""
+
+from plinth.modules.backups.api import validate as validate_backup
+
+backup = validate_backup({
+ 'secrets': {
+ 'files': [
+ '/etc/ssh/ssh_host_ecdsa_key',
+ '/etc/ssh/ssh_host_ecdsa_key.pub',
+ '/etc/ssh/ssh_host_ed25519_key',
+ '/etc/ssh/ssh_host_ed25519_key.pub',
+ '/etc/ssh/ssh_host_rsa_key',
+ '/etc/ssh/ssh_host_rsa_key.pub'
+ ]
+ }
+})