VS Code 自动化部署到 Linux:非 Root 用户、SSH 密钥与 Systemd 实战,提升效率与安全

如果手动将应用程序部署到远程服务器,过程可能会非常繁琐。通过自动化该过程,您可以节省时间并避免重复步骤,从而专注于编码。在本指南中,我们将设置一个便捷的工作流程,其中 Visual Studio Code (VS Code) 任务会自动构建您的应用程序,使用 SSH 密钥认证将文件安全地传输到远程 Linux 服务器(使用非 root 用户),并使用 systemd 服务重新启动应用程序。这不仅简化了部署,还通过消除对 root 登录或基于密码的 SSH 的需求来提高安全性。使用专用的非特权用户为保护您的服务器免受攻击者攻击增加了一道额外的屏障。并且通过依赖 SSH 密钥而不是密码,我们完全降低了 SSH 上的暴力破解风险。让我们深入了解分步设置过程。

1. 创建专用的非 Root 用户进行部署

root 用户身份部署或运行应用程序是一种不良做法,因此我们将在远程服务器上创建一个新用户(例如 vscodeuser​)来拥有和运行我们的应用程序。使用非 root 帐户可以限制帐户被盗用时可能造成的损害,并且出于安全考虑,建议这样做。此用户将用于 SSH 登录和运行应用程序的服务。

在远程服务器上,以 root 用户(或具有 sudo 权限的管理员用户)身份登录,然后运行以下命令添加新用户(将 vscodeuser​ 替换为您想要的用户名):

sudo adduser vscodeuser

此命令将以交互方式提示您输入密码和用户详细信息。选择一个强密码(尽管我们很快将配置基于密钥的登录,因此 SSH 不需要密码)。您可以接受用户信息的默认值或跳过它们。完成后,将创建一个新帐户及其主目录(例如 /home/vscodeuser​)。

可选: 如果您希望此用户具有执行管理任务的 sudo 权限,请将其添加到 sudo 组(在 Debian/Ubuntu 上):

sudo usermod -aG sudo vscodeuser

但是,对于纯粹的部署用户,通常不需要授予 sudo 权限。

为什么不使用 root? 默认情况下,每个 Unix/Linux 系统都有一个 root 帐户,攻击者通常会将其作为目标。禁止直接 root SSH 访问并改用普通用户意味着攻击者必须首先攻破非 root 帐户,然后才能提升权限,从而增加了一层额外的安全性。完全禁用 root 用户的 SSH 登录,并使用经过密钥认证的非特权帐户进行远程访问,这被认为是一种非常好的做法。

2. 为新用户设置 SSH 密钥认证

接下来,我们将为 vscodeuser​ 启用 SSH 公钥认证,这样我们就可以无需密码登录。基于密钥的登录不仅更方便(在我们的自动化任务中无需密码提示),而且比密码登录更安全,尤其是在您完全禁用服务器上的密码身份验证的情况下。

在您的本地计算机上, 您需要一个 SSH 密钥对(一个私钥和一个公钥)。如果您已经有一个想要使用的 SSH 密钥,则可以跳过生成新密钥的步骤。否则,请生成一个新的密钥对(我们将在步骤 4 中介绍)。现在,假设您已准备好公钥(例如,在本地系统上的 ~/.ssh/id_rsa.pub​ 中)。

在远程服务器上, 为新用户授权您的公钥:

您的远程服务器现在已配置为允许 vscodeuser​ 使用 SSH 密钥登录。我们有效地执行了与 ssh-copy-id​ 实用程序相同的步骤:创建 ~/.ssh​,将密钥添加到 authorized_keys​,并修复权限。如果 ssh-copy-id​ 在您的本地系统上可用,您可以使用它一次性自动完成此步骤,因为许多教程都推荐这种便捷方法:

# 从您的本地计算机运行:
ssh-copy-id vscodeuser@your_server_ip

ssh-copy-id​ 命令将提示您输入用户密码(仅此一次),然后将您的公钥传输到服务器,并为您设置文件权限。之后,您应该能够无需密码通过 SSH 登录。

安全提示: 由于我们现在为 vscodeuser​ 设置了基于密钥的身份验证,因此请考虑在 SSH 服务器上禁用密码身份验证并禁止 root 登录。编辑 /etc/ssh/sshd_config​ 并设置 PasswordAuthentication no​ 和 PermitRootLogin no​,然后重新启动 SSH。这可确保所有登录都必须使用密钥(攻击者无法再进行暴力破解密码,并且无法直接针对 root 帐户)。您将以 vscodeuser​ 身份登录,并在需要 root 权限时使用 sudo​。

3. 验证 SSH 权限和所有权

让我们仔细检查新用户的 SSH 配置是否正确,因为这是常见的故障点。在远程服务器上(以 root 用户身份或通过 sudo):

您可以使用以下命令进行验证:

ls -l /home/vscodeuser/.ssh
ls -l /home/vscodeuser/.ssh/authorized_keys

您应该看到指示所有者和权限的输出,例如:

drwx------ 2 vscodeuser vscodeuser 4096 May 24 00:30 .ssh
-rw------- 1 vscodeuser vscodeuser  382 May 24 00:30 authorized_keys

如果出现任何问题(例如,文件归 root 所有或具有更广泛的权限),请使用步骤 2 中的 chmod​ 和 chown​ 命令进行修复。正确的文件模式至关重要,因为默认情况下,SSH 服务器的 StrictModes 设置会在权限过于开放或所有权不正确时拒绝使用密钥。

此时,尝试从本地计算机登录以测试设置(您可能需要先生成或指定您的私钥,我们将在下一步中执行此操作):

# 在本地计算机上
ssh vscodeuser@your_server_ip

如果一切设置正确,您应该能够登录到服务器而无需提示输入密码。(如果您确实收到提示,则表示密钥身份验证失败——请重新检查前面的步骤。)

4. 在本地计算机上生成和使用 SSH 密钥对

如果您尚未在本地开发计算机上创建 SSH 密钥对,请立即创建。私钥保留在您的本地计算机上(妥善保管!),而公钥是我们安装在服务器上的那个。我们将演示使用 RSA 密钥(这很常见),但您也可以使用 Ed25519 密钥。最新版本的 ssh-keygen​ 默认使用 3072 位 RSA 密钥,这对于大多数用例来说是安全的。

在您的本地计算机上,打开一个终端并运行:

ssh-keygen -t rsa -b 4096 -C "VSCode Deploy Key"

系统将提示您选择保存密钥的文件位置。按 Enter 接受默认值(保存为 ~/.ssh/id_rsa​ 和 ~/.ssh/id_rsa.pub​),或指定自定义路径(例如,~/.ssh/id_vscode_deploy​ 用于特定于项目的密钥)。接下来,您可以输入密码短语来保护私钥。建议使用密码短语以确保安全(它会加密磁盘上的私钥),但如果您确实设置了密码短语,则需要使用 SSH 代理,以便自动化过程可以在没有手动输入密码短语的情况下使用密钥。为简单起见,您可以选择不设置密码短语(只需按 Enter)——但请记住,这意味着如果有人获得了您的密钥文件,他们就可以使用它。(如果您确实设置了密码短语,VS Code 可以利用 SSH 代理提示您一次并缓存它。)

完成后,您将拥有两个文件,例如:

如果您在此步骤中生成了新密钥,则需要返回步骤 2 并将公钥放在服务器上(放入 /home/vscodeuser/.ssh/authorized_keys​ 中)。您可以使用 ssh-copy-id​ 或如前所述的手动复制。一旦服务器拥有公钥,请再次测试登录:

ssh vscodeuser@your_server_ip -i ~/.ssh/id_rsa

(如果您没有将其保存为默认密钥,-i​ 选项指定要使用的私钥文件。)这应该可以让您无需密码即可登录。从现在开始,我们的 VS Code 任务可以使用此密钥自动进行身份验证。

为清楚起见,以下是密钥文件的外观(示例):

现在,vscodeuser​ 的基于 SSH 密钥的身份验证已正常工作,我们可以继续设置应用程序在此用户控制下运行并自动化部署。

5. 为应用程序设置 Systemd 服务(用户服务)

与其在服务器上手动运行应用程序,不如将其设置为 systemd 服务。这样,它可以在启动时启动,在发生故障时重新启动,并且可以通过单个命令轻松控制(启动/停止/重新启动)。我们将创建一个在我们的 vscodeuser​(非 root)帐户下运行的服务,使用 systemd 的用户服务功能。

使用 systemd 用户服务意味着该服务与用户绑定,并且不需要 root 权限即可管理。将单元文件放在 ~/.config/systemd/user/​ 中允许该用户无需 sudo 即可启动/停止它。这非常适合我们的部署场景:我们希望 vscodeuser​(以及我们通过 SSH 以该用户身份进行的自动化)能够重新启动应用程序,而无需授予完全的 root 访问权限。

在远程服务器上(以 vscodeuser身份登录):

有了 systemd 服务,您就有了一种管理应用程序进程的可靠方法。vscodeuser​ 现在可以使用简单的命令控制服务(无需 root)。例如,如果您更新了应用程序二进制文件,可以使用以下命令重新启动服务:

# (以 vscodeuser 身份运行,或通过 SSH 以 vscodeuser 身份运行)
systemctl --user restart myapp.service

这正是我们将在下一步中从 VS Code 自动化的操作。

6. 使用 VS Code 任务自动化构建和部署

现在是神奇的部分:配置 VS Code 以通过一个命令或键盘快捷键执行所有这些步骤(构建、部署、重新启动)。VS Code 有一个内置的任务运行器,可以调用外部工具和脚本。我们将使用 tasks.json 配置来定义一系列任务:

通过链接这些任务,您可以一次性完成整个部署。这可以节省时间并确保一致性(不会忘记某个步骤),从而有效地在您的编辑器中实现一个简单的类似 CI/CD 的管道。

打开您工作区的 .vscode/tasks.json​(如果不存在则创建它)。定义类似于以下示例的任务(实际上你可以用&&将命令连接起来,但是不能分行。):

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build App",
            "type": "shell",
            "command": "go build -o myapp .",
            "group": { "kind": "build", "isDefault": true },
            "problemMatcher": []
        },
        {
            "label": "Deploy App",
            "type": "shell",
            "command": "rsync -avz ./myapp vscodeuser@your-server-ip:/home/vscodeuser/myapp/",
            "dependsOn": "Build App",
            "problemMatcher": []
        },
        {
            "label": "Restart App Service",
            "type": "shell",
            "command": "ssh vscodeuser@your-server-ip 'systemctl --user restart myapp.service'",
            "dependsOn": "Deploy App",
            "problemMatcher": []
        }
    ]
}

让我们分解一下这里发生的事情:

添加这些任务后,您可以在 VS Code 中执行它们。例如,打开命令面板 (⇧⌘P / Ctrl+Shift+P) 并运行“Tasks: Run Task (任务:运行任务) ”,然后选择 "Restart App Service"。这将触发整个链:构建 → 部署 → 重启。如果您将某个任务标记为构建组,还可以绑定一个键或使用默认的构建快捷方式 (Ctrl+Shift+B)。

工作原理: VS Code 的任务运行器允许对任务进行分组和排序。在我们的配置中,"Restart App Service" 是最终的编排任务。运行它会导致其依赖项 "Deploy App" 首先运行,而后者又会首先运行 "Build App"。任务按顺序运行,每个任务仅在前一个任务成功后才运行。这可确保您的应用程序仅在正确编译和同步新构建后才重新启动。所有输出(构建输出、rsync 进度等)都将在集成终端中可见,因此您可以监控正在发生的情况。

注意: 上述任务假定为非交互式环境(无密码提示)。我们通过使用 SSH 密钥来设置它。如果您确实为私钥设置了密码短语,请确保代理正在缓存它(例如,如果您在 Windows 上,则为 Pageant 或 Windows OpenSSH 代理;在 macOS/Linux 上,则为 ssh-agent)。否则,任务可能会因等待您输入密码短语而挂起。VS Code 中的一个解决方案是使用 "presentation": { "reveal": "always", "focus": false, "panel": "shared" }​ 设置以确保显示终端,但最好事先解锁密钥。

总结

通过此配置,您的部署工作流程将大大简化。您可以编写代码,然后在 VS Code 中通过一个命令或按键自动执行以下操作:

所有这些都无需每次手动 SSH,无需输入密码,也无需为您的用户授予不必要的 root 权限。非 root 用户 vscodeuser​ 管理自己的服务,从而提高了安全性(应用程序不会意外地以 root 用户身份运行,攻击者也无法直接针对 root 登录)。基于密钥的 SSH 身份验证意味着自动化任务可以安全运行,并且您已经消除了服务器上暴力破解密码攻击的风险。

此设置非常适合独立开发人员或小型团队:就像拥有一个轻量级的部署管道。而且这一切都是通过您控制的简单工具和脚本配置的。此外,通过使用 VS Code 任务,您可以将整个构建/部署过程保留在编辑器中——这既方便又不易出错(不会忘记复制文件或重新启动服务)。

你可能也感兴趣