diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
index 4ad75419d54accc4c3e9b8bc15eb7f4b249d0e33..471e100836f6211d97d8897802d0a71f9a3e06cb 100644
--- a/Sources/App/DependencyRegistrator.swift
+++ b/Sources/App/DependencyRegistrator.swift
@@ -64,6 +64,7 @@ struct DependencyRegistrator {
 
         /// Restore / Backup
 
+        container.register(SFTPService.mock)
         container.register(iCloudServiceMock() as iCloudInterface)
         container.register(DropboxServiceMock() as DropboxInterface)
         container.register(GoogleDriveServiceMock() as GoogleDriveInterface)
@@ -121,6 +122,7 @@ struct DependencyRegistrator {
 
         container.register(
             BackupCoordinator(
+                sftpFactory: BackupSFTPController.init,
                 passphraseFactory: BackupPassphraseController.init(_:_:)
             ) as BackupCoordinating)
 
@@ -161,9 +163,9 @@ struct DependencyRegistrator {
 
         container.register(
             RestoreCoordinator(
-                sftpFactory: SFTPController.init,
                 successFactory: RestoreSuccessController.init,
                 chatListFactory: ChatListController.init,
+                sftpFactory: RestoreSFTPController.init(_:),
                 restoreFactory: RestoreController.init(_:_:),
                 passphraseFactory: RestorePassphraseController.init(_:)
             ) as RestoreCoordinating)
diff --git a/Sources/BackupFeature/Controllers/BackupConfigController.swift b/Sources/BackupFeature/Controllers/BackupConfigController.swift
index a901e6b9668fc89df2cd1ae1184ca655fa8bdb1b..4a2b5974435f6f5417cc53e8d3998920f1510611 100644
--- a/Sources/BackupFeature/Controllers/BackupConfigController.swift
+++ b/Sources/BackupFeature/Controllers/BackupConfigController.swift
@@ -122,7 +122,7 @@ final class BackupConfigController: UIViewController {
 
         screenView.sftpButton
             .publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewModel.didTapService(.sftp, self) }
+            .sink { [unowned self] in coordinator.toSFTP(from: self) }
             .store(in: &cancellables)
 
         screenView.iCloudButton
diff --git a/Sources/SFTPFeature/SFTPController.swift b/Sources/BackupFeature/Controllers/BackupSFTPController.swift
similarity index 74%
rename from Sources/SFTPFeature/SFTPController.swift
rename to Sources/BackupFeature/Controllers/BackupSFTPController.swift
index 47b8c5423ef6819859ab699320a5593b880fbc13..f0f851863ed28da1159dddd3b5a5d548ff1c3f61 100644
--- a/Sources/SFTPFeature/SFTPController.swift
+++ b/Sources/BackupFeature/Controllers/BackupSFTPController.swift
@@ -1,10 +1,14 @@
+import HUD
 import UIKit
 import Combine
+import DependencyInjection
 
-public final class SFTPController: UIViewController {
-    lazy private var screenView = SFTPView()
+public final class BackupSFTPController: UIViewController {
+    @Dependency private var hud: HUDType
 
-    private let viewModel = SFTPViewModel()
+    lazy private var screenView = BackupSFTPView()
+
+    private let viewModel = BackupSFTPViewModel()
     private var cancellables = Set<AnyCancellable>()
 
     public override func loadView() {
@@ -29,6 +33,17 @@ public final class SFTPController: UIViewController {
     }
 
     private func setupBindings() {
+        viewModel.hudPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [hud] in hud.update(with: $0) }
+            .store(in: &cancellables)
+
+        viewModel.popPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+                navigationController?.popViewController(animated: true)
+            }.store(in: &cancellables)
+
         screenView.hostField
             .textPublisher
             .receive(on: DispatchQueue.main)
diff --git a/Sources/BackupFeature/Coordinator/BackupCoordinator.swift b/Sources/BackupFeature/Coordinator/BackupCoordinator.swift
index 9dbd110e659f066dd25d5bda897ebccc14047748..c79cdcdb18d2d04197d92d6207affebb567b2f4f 100644
--- a/Sources/BackupFeature/Coordinator/BackupCoordinator.swift
+++ b/Sources/BackupFeature/Coordinator/BackupCoordinator.swift
@@ -8,6 +8,8 @@ public protocol BackupCoordinating {
         from: UIViewController
     )
 
+    func toSFTP(from: UIViewController)
+
     func toPassphrase(
         from: UIViewController,
         cancelClosure: @escaping EmptyClosure,
@@ -16,24 +18,27 @@ public protocol BackupCoordinating {
 }
 
 public struct BackupCoordinator: BackupCoordinating {
+    var pushPresenter: Presenting = PushPresenter()
     var bottomPresenter: Presenting = BottomPresenter()
 
-    var passphraseFactory: (
-        @escaping EmptyClosure,
-        @escaping StringClosure
-    ) -> UIViewController
+    var sftpFactory: () -> UIViewController
+    var passphraseFactory: (@escaping EmptyClosure, @escaping StringClosure) -> UIViewController
 
     public init(
-        passphraseFactory: @escaping (
-            @escaping EmptyClosure,
-            @escaping StringClosure
-        ) -> UIViewController
+        sftpFactory: @escaping () -> UIViewController,
+        passphraseFactory: @escaping (@escaping EmptyClosure, @escaping StringClosure) -> UIViewController
     ) {
+        self.sftpFactory = sftpFactory
         self.passphraseFactory = passphraseFactory
     }
 }
 
 public extension BackupCoordinator {
+    func toSFTP(from parent: UIViewController) {
+        let screen = sftpFactory()
+        pushPresenter.present(screen, from: parent)
+    }
+
     func toDrawer(
         _ screen: UIViewController,
         from parent: UIViewController
diff --git a/Sources/BackupFeature/Service/BackupService.swift b/Sources/BackupFeature/Service/BackupService.swift
index 0c163e4d92d470a7e3bcaf86cac1c9be0bf26176..b914322433260bbb798de1d18ad4712043f6415b 100644
--- a/Sources/BackupFeature/Service/BackupService.swift
+++ b/Sources/BackupFeature/Service/BackupService.swift
@@ -152,9 +152,7 @@ extension BackupService {
                     }.store(in: &cancellables)
             }
         case .sftp:
-            if !sftpService.isAuthorized() {
-                // TODO
-            }
+            break
         }
     }
 }
@@ -209,7 +207,25 @@ extension BackupService {
         }
 
         if sftpService.isAuthorized() {
-            // TODO
+            let host = ""
+            let username = ""
+            let password = ""
+
+            let completion: SFTPFetchResult = { result in
+                switch result {
+                case .success(let settings):
+                    if let settings = settings {
+                        print("")
+                    } else {
+                        print("")
+                    }
+                case .failure(let error):
+                    print(error.localizedDescription)
+                }
+            }
+
+            let authParams = SFTPAuthParams(host, username, password)
+            sftpService.fetch((authParams, completion))
         }
 
         if dropboxService.isAuthorized() {
diff --git a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8368713e723419159be8c112d8ffa729dae5d79a
--- /dev/null
+++ b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
@@ -0,0 +1,68 @@
+import HUD
+import Models
+import Combine
+import Foundation
+import SFTPFeature
+import DependencyInjection
+
+struct BackupSFTPViewState {
+    var host: String = ""
+    var username: String = ""
+    var password: String = ""
+    var isButtonEnabled: Bool = false
+}
+
+final class BackupSFTPViewModel {
+    @Dependency private var service: SFTPService
+
+    var hudPublisher: AnyPublisher<HUDStatus, Never> {
+        hudSubject.eraseToAnyPublisher()
+    }
+
+    var popPublisher: AnyPublisher<Void, Never> {
+        popSubject.eraseToAnyPublisher()
+    }
+
+    var statePublisher: AnyPublisher<BackupSFTPViewState, Never> {
+        stateSubject.eraseToAnyPublisher()
+    }
+
+    private let popSubject = PassthroughSubject<Void, Never>()
+    private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
+    private let stateSubject = CurrentValueSubject<BackupSFTPViewState, Never>(.init())
+
+    func didEnterHost(_ string: String) {
+        stateSubject.value.host = string
+        validate()
+    }
+
+    func didEnterUsername(_ string: String) {
+        stateSubject.value.username = string
+        validate()
+    }
+
+    func didEnterPassword(_ string: String) {
+        stateSubject.value.password = string
+        validate()
+    }
+
+    func didTapLogin() {
+        hudSubject.send(.on(nil))
+
+        let host = stateSubject.value.host
+        let username = stateSubject.value.username
+        let password = stateSubject.value.password
+
+        let authParams = SFTPAuthParams(host, username, password)
+        service.justAuthenticate(authParams)
+        hudSubject.send(.none)
+        popSubject.send(())
+    }
+
+    private func validate() {
+        stateSubject.value.isButtonEnabled =
+        !stateSubject.value.host.isEmpty &&
+        !stateSubject.value.username.isEmpty &&
+        !stateSubject.value.password.isEmpty
+    }
+}
diff --git a/Sources/SFTPFeature/SFTPView.swift b/Sources/BackupFeature/Views/BackupSFTPView.swift
similarity index 98%
rename from Sources/SFTPFeature/SFTPView.swift
rename to Sources/BackupFeature/Views/BackupSFTPView.swift
index 3e62e4caeb0eca188fd1dad4db740545f0b3f045..3a88917aafaa46786efd5c5ffce3fb3285cd1a63 100644
--- a/Sources/SFTPFeature/SFTPView.swift
+++ b/Sources/BackupFeature/Views/BackupSFTPView.swift
@@ -2,7 +2,7 @@ import UIKit
 import Shared
 import InputField
 
-final class SFTPView: UIView {
+final class BackupSFTPView: UIView {
     let titleLabel = UILabel()
     let subtitleLabel = UILabel()
     let hostField = OutlinedInputField()
diff --git a/Sources/RestoreFeature/Controllers/RestoreListController.swift b/Sources/RestoreFeature/Controllers/RestoreListController.swift
index 4a5f22f2bdca94a16f23f126d8b41f88c1dcdbe2..803e46e79d1f6dd9e543a8ee34c18fbb5c3bd105 100644
--- a/Sources/RestoreFeature/Controllers/RestoreListController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreListController.swift
@@ -1,8 +1,8 @@
 import HUD
-import DrawerFeature
 import Shared
 import UIKit
 import Combine
+import DrawerFeature
 import DependencyInjection
 
 public final class RestoreListController: UIViewController {
@@ -88,7 +88,7 @@ public final class RestoreListController: UIViewController {
         screenView.sftpButton
             .publisher(for: .touchUpInside)
             .sink { [unowned self] in
-                coordinator.toSFTP(from: self)
+                coordinator.toSFTP(using: ndf, from: self)
             }.store(in: &cancellables)
     }
 
diff --git a/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift b/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..024b2df411105415aa94825d46a19c59112dda84
--- /dev/null
+++ b/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
@@ -0,0 +1,89 @@
+import HUD
+import UIKit
+import Combine
+import DependencyInjection
+
+public final class RestoreSFTPController: UIViewController {
+    @Dependency private var hud: HUDType
+    @Dependency private var coordinator: RestoreCoordinating
+
+    lazy private var screenView = RestoreSFTPView()
+
+    private let ndf: String
+    private let viewModel = RestoreSFTPViewModel()
+    private var cancellables = Set<AnyCancellable>()
+
+    public override func loadView() {
+        view = screenView
+    }
+
+    public init(_ ndf: String) {
+        self.ndf = ndf
+        super.init(nibName: nil, bundle: nil)
+    }
+
+    required init?(coder: NSCoder) { nil }
+
+    public override func viewDidLoad() {
+        super.viewDidLoad()
+        setupNavigationBar()
+        setupBindings()
+    }
+
+    private func setupNavigationBar() {
+        navigationItem.backButtonTitle = ""
+
+        let back = UIButton.back()
+        back.addTarget(self, action: #selector(didTapBack), for: .touchUpInside)
+
+        navigationItem.leftBarButtonItem = UIBarButtonItem(
+            customView: UIStackView(arrangedSubviews: [back])
+        )
+    }
+
+    private func setupBindings() {
+        viewModel.hudPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [hud] in hud.update(with: $0) }
+            .store(in: &cancellables)
+
+        viewModel.backupPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+                coordinator.toRestoreReplacing(using: ndf, with: $0, from: self)
+            }.store(in: &cancellables)
+
+        screenView.hostField
+            .textPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in viewModel.didEnterHost($0) }
+            .store(in: &cancellables)
+
+        screenView.usernameField
+            .textPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in viewModel.didEnterUsername($0) }
+            .store(in: &cancellables)
+
+        screenView.passwordField
+            .textPublisher
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in viewModel.didEnterPassword($0) }
+            .store(in: &cancellables)
+
+        viewModel.statePublisher
+            .receive(on: DispatchQueue.main)
+            .map(\.isButtonEnabled)
+            .sink { [unowned self] in screenView.loginButton.isEnabled = $0 }
+            .store(in: &cancellables)
+
+        screenView.loginButton
+            .publisher(for: .touchUpInside)
+            .sink { [unowned self] in viewModel.didTapLogin() }
+            .store(in: &cancellables)
+    }
+
+    @objc private func didTapBack() {
+        navigationController?.popViewController(animated: true)
+    }
+}
diff --git a/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift b/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift
index 3a63883c13726d9c398f270534760ffcc0c98d21..a76b5c744ca8e00c5c192a9f9b729d60c5403f79 100644
--- a/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift
+++ b/Sources/RestoreFeature/Coordinator/RestoreCoordinator.swift
@@ -4,29 +4,31 @@ import Shared
 import Presentation
 
 public protocol RestoreCoordinating {
-    func toSFTP(from: UIViewController)
     func toChats(from: UIViewController)
     func toSuccess(from: UIViewController)
+    func toSFTP(using: String, from: UIViewController)
     func toDrawer(_: UIViewController, from: UIViewController)
     func toPassphrase(from: UIViewController, _: @escaping StringClosure)
     func toRestore(using: String, with: RestoreSettings, from: UIViewController)
+    func toRestoreReplacing(using: String, with: RestoreSettings, from: UIViewController)
 }
 
 public struct RestoreCoordinator: RestoreCoordinating {
     var pushPresenter: Presenting = PushPresenter()
     var bottomPresenter: Presenting = BottomPresenter()
     var replacePresenter: Presenting = ReplacePresenter()
+    var replaceLastPresenter: Presenting = ReplacePresenter(mode: .replaceLast)
 
-    var sftpFactory: () -> UIViewController
     var successFactory: () -> UIViewController
     var chatListFactory: () -> UIViewController
+    var sftpFactory: (String) -> UIViewController
     var restoreFactory: (String, RestoreSettings) -> UIViewController
     var passphraseFactory: (@escaping StringClosure) -> UIViewController
 
     public init(
-        sftpFactory: @escaping () -> UIViewController,
         successFactory: @escaping () -> UIViewController,
         chatListFactory: @escaping () -> UIViewController,
+        sftpFactory: @escaping (String) -> UIViewController,
         restoreFactory: @escaping (String, RestoreSettings) -> UIViewController,
         passphraseFactory: @escaping (@escaping StringClosure) -> UIViewController
     ) {
@@ -48,6 +50,15 @@ public extension RestoreCoordinator {
         pushPresenter.present(screen, from: parent)
     }
 
+    func toRestoreReplacing(
+        using ndf: String,
+        with settings: RestoreSettings,
+        from parent: UIViewController
+    ) {
+        let screen = restoreFactory(ndf, settings)
+        replaceLastPresenter.present(screen, from: parent)
+    }
+
     func toChats(from parent: UIViewController) {
         let screen = chatListFactory()
         replacePresenter.present(screen, from: parent)
@@ -70,8 +81,8 @@ public extension RestoreCoordinator {
         bottomPresenter.present(screen, from: parent)
     }
 
-    func toSFTP(from parent: UIViewController) {
-        let screen = sftpFactory()
+    func toSFTP(using ndf: String, from parent: UIViewController) {
+        let screen = sftpFactory(ndf)
         pushPresenter.present(screen, from: parent)
     }
 }
diff --git a/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift
index 301ad92afe128971bb38b7099aafce4081c85625..d0119b84211abd97bbbfff022455fb84a1db9b7c 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift
@@ -6,22 +6,24 @@ import Combine
 import BackupFeature
 import DependencyInjection
 
-import SFTPFeature
 import iCloudFeature
 import DropboxFeature
 import GoogleDriveFeature
 
 final class RestoreListViewModel {
-    @Dependency private var sftpService: SFTPService
     @Dependency private var icloudService: iCloudInterface
     @Dependency private var dropboxService: DropboxInterface
     @Dependency private var googleDriveService: GoogleDriveInterface
 
-    var hud: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() }
-    var didFetchBackup: AnyPublisher<RestoreSettings, Never> { backupSubject.eraseToAnyPublisher() }
+    var hud: AnyPublisher<HUDStatus, Never> {
+        hudSubject.eraseToAnyPublisher()
+    }
 
-    private var dropboxAuthCancellable: AnyCancellable?
+    var didFetchBackup: AnyPublisher<RestoreSettings, Never> {
+        backupSubject.eraseToAnyPublisher()
+    }
 
+    private var dropboxAuthCancellable: AnyCancellable?
     private let hudSubject = PassthroughSubject<HUDStatus, Never>()
     private let backupSubject = PassthroughSubject<RestoreSettings, Never>()
 
diff --git a/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7bf34b4c75f1ec8691aba8a11de89e3438db847b
--- /dev/null
+++ b/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
@@ -0,0 +1,81 @@
+import HUD
+import Models
+import Combine
+import Foundation
+import SFTPFeature
+import DependencyInjection
+
+struct RestoreSFTPViewState {
+    var host: String = ""
+    var username: String = ""
+    var password: String = ""
+    var isButtonEnabled: Bool = false
+}
+
+final class RestoreSFTPViewModel {
+    @Dependency private var service: SFTPService
+
+    var hudPublisher: AnyPublisher<HUDStatus, Never> {
+        hudSubject.eraseToAnyPublisher()
+    }
+
+    var backupPublisher: AnyPublisher<RestoreSettings, Never> {
+        backupSubject.eraseToAnyPublisher()
+    }
+
+    var statePublisher: AnyPublisher<RestoreSFTPViewState, Never> {
+        stateSubject.eraseToAnyPublisher()
+    }
+
+    private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none)
+    private let backupSubject = PassthroughSubject<RestoreSettings, Never>()
+    private let stateSubject = CurrentValueSubject<RestoreSFTPViewState, Never>(.init())
+
+    func didEnterHost(_ string: String) {
+        stateSubject.value.host = string
+        validate()
+    }
+
+    func didEnterUsername(_ string: String) {
+        stateSubject.value.username = string
+        validate()
+    }
+
+    func didEnterPassword(_ string: String) {
+        stateSubject.value.password = string
+        validate()
+    }
+
+    func didTapLogin() {
+        hudSubject.send(.on(nil))
+
+        let host = stateSubject.value.host
+        let username = stateSubject.value.username
+        let password = stateSubject.value.password
+
+        let completion: SFTPFetchResult = { result in
+            switch result {
+            case .success(let backup):
+                self.hudSubject.send(.none)
+
+                if let backup = backup {
+                    self.backupSubject.send(backup)
+                } else {
+                    self.backupSubject.send(.init(cloudService: .sftp))
+                }
+            case .failure(let error):
+                self.hudSubject.send(.error(.init(with: error)))
+            }
+        }
+
+        let authParams = SFTPAuthParams(host, username, password)
+        service.fetch((authParams, completion))
+    }
+
+    private func validate() {
+        stateSubject.value.isButtonEnabled =
+        !stateSubject.value.host.isEmpty &&
+        !stateSubject.value.username.isEmpty &&
+        !stateSubject.value.password.isEmpty
+    }
+}
diff --git a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
index 663d3529b44012f24408c11ff1ad223cb5a58a7d..0a7d988ef270cbcfabbe6d1e929809ba3c24e9c9 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
@@ -8,7 +8,6 @@ import Integration
 import BackupFeature
 import DependencyInjection
 
-import SFTPFeature
 import iCloudFeature
 import DropboxFeature
 import GoogleDriveFeature
@@ -39,7 +38,6 @@ extension RestorationStep: Equatable {
 }
 
 final class RestoreViewModel {
-    @Dependency private var sftpService: SFTPService
     @Dependency private var iCloudService: iCloudInterface
     @Dependency private var dropboxService: DropboxInterface
     @Dependency private var googleService: GoogleDriveInterface
diff --git a/Sources/RestoreFeature/Views/RestoreSFTPView.swift b/Sources/RestoreFeature/Views/RestoreSFTPView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..de41e3719f0cac00cb59ccc303c9d062fae1f22d
--- /dev/null
+++ b/Sources/RestoreFeature/Views/RestoreSFTPView.swift
@@ -0,0 +1,76 @@
+import UIKit
+import Shared
+import InputField
+
+final class RestoreSFTPView: UIView {
+    let titleLabel = UILabel()
+    let subtitleLabel = UILabel()
+    let hostField = OutlinedInputField()
+    let usernameField = OutlinedInputField()
+    let passwordField = OutlinedInputField()
+    let loginButton = CapsuleButton()
+    let stackView = UIStackView()
+
+    init() {
+        super.init(frame: .zero)
+        backgroundColor = Asset.neutralWhite.color
+
+        titleLabel.textColor = Asset.neutralDark.color
+        titleLabel.text = Localized.AccountRestore.Sftp.title
+        titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
+
+        let paragraph = NSMutableParagraphStyle()
+        paragraph.alignment = .left
+        paragraph.lineHeightMultiple = 1.15
+
+        let attString = NSAttributedString(
+            string: Localized.AccountRestore.Sftp.subtitle,
+            attributes: [
+                .foregroundColor: Asset.neutralBody.color,
+                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+                .paragraphStyle: paragraph
+            ])
+
+        subtitleLabel.numberOfLines = 0
+        subtitleLabel.attributedText = attString
+
+        hostField.setup(title: Localized.AccountRestore.Sftp.host)
+        usernameField.setup(title: Localized.AccountRestore.Sftp.username)
+        passwordField.setup(title: Localized.AccountRestore.Sftp.password, sensitive: true)
+
+        loginButton.set(style: .brandColored, title: Localized.AccountRestore.Sftp.login)
+
+        stackView.spacing = 30
+        stackView.axis = .vertical
+        stackView.distribution = .fillEqually
+        stackView.addArrangedSubview(hostField)
+        stackView.addArrangedSubview(usernameField)
+        stackView.addArrangedSubview(passwordField)
+        stackView.addArrangedSubview(loginButton)
+
+        addSubview(titleLabel)
+        addSubview(subtitleLabel)
+        addSubview(stackView)
+
+        titleLabel.snp.makeConstraints {
+            $0.top.equalTo(safeAreaLayoutGuide).offset(15)
+            $0.left.equalToSuperview().offset(38)
+            $0.right.equalToSuperview().offset(-41)
+        }
+
+        subtitleLabel.snp.makeConstraints {
+            $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+            $0.left.equalToSuperview().offset(38)
+            $0.right.equalToSuperview().offset(-41)
+        }
+
+        stackView.snp.makeConstraints {
+            $0.top.equalTo(subtitleLabel.snp.bottom).offset(28)
+            $0.left.equalToSuperview().offset(38)
+            $0.right.equalToSuperview().offset(-38)
+            $0.bottom.lessThanOrEqualToSuperview()
+        }
+    }
+
+    required init?(coder: NSCoder) { nil }
+}
diff --git a/Sources/SFTPFeature/SFTPService.swift b/Sources/SFTPFeature/SFTPService.swift
index 7181c915a13c1e8fb9f6f849763cdf315ce9b369..30b92573a75e1cc4fc956e3f68f8433aa59f9e13 100644
--- a/Sources/SFTPFeature/SFTPService.swift
+++ b/Sources/SFTPFeature/SFTPService.swift
@@ -1,15 +1,49 @@
+import Models
+import Foundation
+
+public typealias SFTPAuthParams = (String, String, String)
+public typealias SFTPFetchResult = (Result<RestoreSettings?, Error>) -> Void
+public typealias SFTPFetchParams = (SFTPAuthParams, SFTPFetchResult)
+
 public struct SFTPService {
     public var isAuthorized: () -> Bool
-    public var downloadMetadata: (@escaping (String) -> Void) -> Void
+    public var fetch: (SFTPFetchParams) -> Void
+    public var justAuthenticate: (SFTPAuthParams) -> Void
 }
 
 public extension SFTPService {
+    static var mock = SFTPService(
+        isAuthorized: {
+            false
+        },
+        fetch: { (authParams, completion) in
+            print("^^^ RestoreSFTP Host: \(authParams.0)")
+            print("^^^ RestoreSFTP Username: \(authParams.1)")
+            print("^^^ RestoreSFTP Password: \(authParams.2)")
+
+            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+                completion(.success(.init(
+                    backup: .init(id: "ASDF", date: Date.distantPast, size: 100_000_000),
+                    cloudService: .sftp
+                )))
+            }
+        },
+        justAuthenticate: { host, username, password in
+            // TODO: Store these params on the keychain
+        })
+
     static var live = SFTPService(
         isAuthorized: {
+            /// If it has host/username/password on keychain
+            /// means its authorized, not that is working
+            ///
             true
         },
-        downloadMetadata: { completion in
-            completion("MOCK")
+        fetch: { (authParams, completion) in
+            // TODO: Store host/username/password on keychain
+        },
+        justAuthenticate: { host, username, password in
+            // TODO: Store host/username/password on keychain
         }
     )
 }
diff --git a/Sources/SFTPFeature/SFTPViewModel.swift b/Sources/SFTPFeature/SFTPViewModel.swift
deleted file mode 100644
index f429f25140050c8cee4aec38ad66247ef99eb40d..0000000000000000000000000000000000000000
--- a/Sources/SFTPFeature/SFTPViewModel.swift
+++ /dev/null
@@ -1,56 +0,0 @@
-import Combine
-import Foundation
-
-struct SFTPViewState {
-    var host: String = ""
-    var username: String = ""
-    var password: String = ""
-    var isButtonEnabled: Bool = false
-}
-
-final class SFTPViewModel {
-    var statePublisher: AnyPublisher<SFTPViewState, Never> {
-        stateSubject.eraseToAnyPublisher()
-    }
-
-    private let stateSubject = CurrentValueSubject<SFTPViewState, Never>(.init())
-
-    func didEnterHost(_ string: String) {
-        stateSubject.value.host = string
-        validate()
-    }
-
-    func didEnterUsername(_ string: String) {
-        stateSubject.value.username = string
-        validate()
-    }
-
-    func didEnterPassword(_ string: String) {
-        stateSubject.value.password = string
-        validate()
-    }
-
-    func didTapLogin() {
-
-
-//        do {
-//            let session = try SSH(host: stateSubject.value.host)
-//            try session.authenticate(
-//                username: stateSubject.value.username,
-//                password: stateSubject.value.password
-//            )
-//
-//            let sftp = try session.openSftp()
-//            try sftp.download(remotePath: "", localURL: URL(string: "")!)
-//        } catch {
-//            print(error.localizedDescription)
-//        }
-    }
-
-    private func validate() {
-        stateSubject.value.isButtonEnabled =
-        !stateSubject.value.host.isEmpty &&
-        !stateSubject.value.username.isEmpty &&
-        !stateSubject.value.password.isEmpty
-    }
-}