Closed4

リモートWebサーバへのSSHファイル転送を自動化

Yuichiroh AraiYuichiroh Arai

プロトタイプを気軽にリモートWebサーバにアップロードする用。
https://[ドメイン]/[プロジェクト名]/[日付]/
みたいにサブディレクトリの日付を変えて履歴を追えるようにする。

環境

  • Windows 11
  • Node.JS
  • Next.js / Nuxt / Astro など
  • さくらのレンタルサーバー
Yuichiroh AraiYuichiroh Arai

SSH接続

秘密/公開鍵ペア作成

ssh-keygen

特にオプションは指定しない。
最近の暗号化形式のデフォルトは rsa ではなく ed25519

C:\Users\[ユーザー名]/.ssh/に秘密鍵id_ed25519と公開鍵id_ed25519.pubが作られる。

さくらのレンタルサーバに公開鍵を登録

  1. サーバーコントロールパネルにアクセス
  2. サーバー情報 -> SSH公開鍵 -> 新規追加
  3. 下記内容で登録
    • 追加方法 -> 作成済みの公開鍵を登録
    • 公開鍵 -> id_ed25519.pub のテキストをコピペ
    • コメント -> 鍵ペアを識別しやすくする用

SSH Config

sshコマンドを簡略化するために~/.ssh/configにSSH Configを作成する

Host [接続名]
  User [ユーザー名]
  Port 22
  HostName [ドメイン名].sakura.ne.jp
  IdentityFile ~/.ssh/id_ed25519

接続名はdevにしたので、

ssh dev

だけで接続できるようになります

Yuichiroh AraiYuichiroh Arai

ビルド設定

日付などを元にバージョン文字列を作成

アップロード先のサブディレクトリを/[プロジェクト名]/[バージョン文字列]としたいので、日付を元にバージョン文字列を作成する。

export const getVersion = () => {
  // YY-MM-DD
  const date = new Date().toLocaleDateString('sv-SE')
  const revision = ''
  return revision !== '' ? `${date}-${rev}` : date
}

同じ日に2つ以上のバージョンを作成する場合は末尾に_[数字]を追加する。
2025-06-012025-06-01_1のような文字列が作られる。

これを、Next.js / Nuxt / Astro などでビルドする時に利用する。
一例としてAstroでの使用例を挙げるが、Next.js / Nuxtでも考え方は同じ。

Astroのビルド例

astro.config.mjs
import { defineConfig } from 'astro/config'
const PROJECT_NAME = 'project'
const base = `/${PROJECT_NAME}/${getVersion()}/`
export default defineConfig({
  base,
})

astro devで開発中はhttp://localhost:4321/project/2025-06-01/のようなサブディレクトリで実行される。
astro buildでビルドすると/dist/にサブディレクトリを含まずに出力される。

ちなみに、Astroの設定ファイルで指定したbaseの値はimport.meta.env.BASE_URLで参照できる。

<a href={${import.meta.env.BASE_URL}about/}>
  <img src={`${import.meta.env.BASE_URL}images/about.svg`} alt='' />
</a>

BASE_URLが切り替わっても上記のようにしておくと柔軟に対応できる。
publicにファイルを格納する場合もサブディレクトリを意識する必要はない。

ただし、CSSからpublic内のファイルを参照したい場合はSassの変数を使ったひと工夫が必要。

astro.config.mjs
export default defineConfig({
vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: `$base-url: '${BASE}';`
        },
      },
    },
  },
})

これで、SCSSの全ファイルの先頭に$base-urlが挿入されるのでどこからでも参照できるようになる。

background-image: url("#{$base-url + 'images/bg.webp'}");
Yuichiroh AraiYuichiroh Arai

SSHファイル転送のスクリプト

Node.jsでファイル転送のスクリプトを書く。

  1. リモートサーバのサブディレクトリを中身ごと削除(存在しなければ無視される)
  2. サブディレクトリを作成
  3. サブディレクトリにファイル転送

の順番で処理を行う。

共有したくない情報を環境変数に移す

ファイル転送のスクリプトをGitで管理すると、リモートサーバの情報なども共有されることになる。
他のメンバーに見られて困る場合はローカル開発環境の環境変数に格納しておく。
今回は環境変数に格納する情報を以下の2つとする。

%DEV_SSH_NAME%

SSHの接続名、今回はdev
隠すほどでもないけど、他のメンバーが別の接続名を使いたい場合にも便利かもしれない。

%DEV_SSH_DIR%

リモートサーバの転送先のベースディレクトリ。
今回はさくらのレンタルサーバの例として/home/[ユーザー名]/www/とする。
このベースディレクトリがhttps://[ドメイン]/に対応するので、この文字列にサブディレクトリを足して最終的な転送先が決まる。

スクリプト

コマンド実行のところだけを抜粋。
実際はexecにコールバックを渡して処理を順番に行う。

import child_process from 'child_process'
const { exec } = child_process

const PROJECT_NAME = 'project'
const SRC_DIR = './dist/'
const DEST_DIR = `${PROJECT_NAME}/${getVersion()}/`

// 1. サブディレクトリを中身ごと削除
exec(`ssh %DEV_SSH_NAME% "rm -rf %DEV_SSH_DIR%${DEST_DIR}/"`)

// 2. サブディレクトリを作成
exec(`ssh %DEV_SSH_NAME% "mkdir -pv %DEV_SSH_DIR%${DEST_DIR}/"`)

// 3. サブディレクトリにファイル転送
exec(`scp -r ${SRC_DIR}* %DEV_SSH_NAME%:%DEV_SSH_DIR%${DEST_DIR}/`)

これをnpm-scriptsに登録してビルド後に実行させる。

このスクラップは3ヶ月前にクローズされました