PCを閉じても自動化を止めない|VPSでPythonとn8nを24時間動かす入門

夜、ノートPCを閉じて寝たら、朝に動くはずだったPythonのスクリプト(=やりたい処理を順番に書いておき、まとめて実行できるファイル)もn8nのワークフローも、止まっていた……。そんな経験はありませんか?

私も、自動化を始めたばかりのころ、この「PCを閉じると全部止まる」問題に何度も引っかかりました。cronの設定は合っているのに、PCがスリープしていたら当然動かないんですよね。

この記事では、VPS(ブイピーエス)という「ネット上に借りる小さなLinuxのパソコン」を使って、Pythonのスクリプトとn8nを、自分のPCとは関係なく24時間動かすところまで、一緒にやってみましょう。ターミナルやSSHをほとんど触ったことがない方でも進められるように、1ステップ=1操作で、どこで何を打つかを毎回書いていきます。

🎯
この記事のゴール
  • VPSに安全にログインできるようにする(鍵でログイン、パスワードログインは止める)
  • Pythonのスクリプトを、毎朝決まった時刻にVPSで自動実行する
  • n8n(=画面上で「ノード」というブロックをつないで、自動化の流れを作れるツール)をVPSでDockerを使って常駐させ、自分のPCのブラウザから安全に開く
  • 「ちゃんと動いているか」を自分で確認できるようにする
🧰
必要なもの
  • 自分のPC(Windows / Mac どちらでも)。ターミナルを使います(Windowsは「PowerShell」、Macは「ターミナル」)
  • VPSの契約(OSはUbuntuやDebianなどのLinuxを選びます。選び方は下で説明します)
  • VPSのIPアドレスと、最初のログイン情報(契約後に管理画面やメールで案内されることが多いです。環境により異なります)
  • 所要時間の目安:はじめての方で2〜3時間くらい。休憩をはさみながら、1日で全部やらなくても大丈夫です
🔎
この記事の検証について(大事なので先に書きます)

今回の動作確認は、本物のVPSではありません。手元のLinuxマシンの中に、VPSに見立てた Debian 13(systemd 257)のコンテナを作り、そこで確かめました。主なバージョンは次のとおりです。

  • Debian 13(trixie)/OpenSSH 10.0p2/Python 3.13.5
  • Docker Engine 29.9.2/Docker Compose v5.6.1/n8n 2.45.7(Docker 入門の記事の検証環境とは、Docker と Compose のバージョンがちがいます。バージョンは環境によって異なります)

実際に動かして確かめたもの(鍵ログイン、パスワードログインの停止、cronとsystemdタイマーでのPython実行、n8nのDocker常駐・自動再起動・データの保存・タイムゾーン・バックアップ)は「検証時の出力」として載せています。

一方、本物のVPSでの動き、ファイアウォール(ufw)の有効化、SSHトンネル、Dockerのインストール手順などは、今回の環境では確かめられていません。これらは「公式情報」「例」「環境により異なります」と書き分けています。表示の中のIPアドレス(=ネットワーク上のコンピューターの住所にあたる番号)やホスト名は、説明用のダミー(203.0.113.10 など)に置き換えています。

🔰
連載の Lv4 の記事とのつながり

この記事は、連載の Lv4 で1つずつ学んだことを、本物の VPS の上でまとめて使う記事です。くわしい説明は、それぞれの記事にあります。

  • SSH の鍵でログインする(STEP 5〜6):Lv4 の「SSH 入門」の記事
  • 作業用ユーザー・SSH の強化・ufw(STEP 4・7・8):Lv4 の「VPS を借りたら最初にやること」の記事。STEP 7 のファイル名が 00-hardening.conf なのは、その記事の「ファイル名を 10-hardening.conf にする理由」と同じで、ほかの設定ファイルより先に読ませるためです
  • cron と systemd タイマー(STEP 10):Lv3 の「cron 入門」の記事と、Lv4 の「systemd timer と cron の違い」の記事
  • Docker と compose・データの置き場所(STEP 11〜12・14):Lv4 の「Docker 入門」の記事

Docker 入門の記事では、自分のパソコンに Debian の docker.io を入れました。この記事の STEP 11 は、Docker 社の公式の入れ方(docker-ce)です。VPS では、どちらか一方だけを使ってください。同じパソコンに docker.io が入っている場合は、公式ドキュメントのとおり、先に古いパッケージ(=ソフトをインストールしやすいように、ひとまとめにしたもの)を消してから入れます。

書き方も、ほかの Lv4 の記事と少しちがいます。この記事は、自分の PC(Windows は PowerShell、Mac はターミナル)と VPS を行き来するので、どちらで打つかを 💻 自分のPCで・🖥 VPSで と毎回書いています。

💡
用語メモ
  • コンテナ:アプリと、動かすのに必要なものをひとまとめにした箱。Docker で動かします
  • フルパス(絶対パス):/home/kaito/memo.txt のように、いちばん上の / から書いた場所
  • コンソール(管理画面のコンソール):VPS の会社の Web 画面から開ける、サーバーを直接操作できる画面。SSH でつながらないときの非常口です

用語で迷ったら、連載のまとめ記事の「よく出てくる用語ミニ辞典」でも確かめられます。


全体の流れ

先に、この記事で進める順番を並べておきます。迷子になったら、ここに戻ってきてくださいね。

  1. VPSを用意する(選び方の見方)
  2. 初めてVPSにログインする
  3. アップデートとタイムゾーン(=どの地域の時刻を使うかの設定)の設定
  4. 作業用のユーザーを作る
  5. SSH鍵を作って、VPSに登録する
  6. 鍵でログインできるか確かめる
  7. パスワードでのログインを止める
  8. ファイアウォールで、SSHだけ通す
  9. Pythonのスクリプトを置く
  10. cronで毎朝自動実行する(別の方法:systemdタイマー)
  11. Dockerを入れる
  12. n8nをDockerで起動する
  13. 自分のPCからn8nの画面を開く
  14. 止まっていないか確認する・バックアップする

自分のPCとVPSの違い

まず用語をざっくり押さえよう

はじめて見る言葉が多いと思うので、この記事で出てくる用語を一言でまとめました。全部覚えなくて大丈夫です。出てきたときに見返してください。

用語 ひとことで言うと
VPS ネット上に借りる、自分専用の小さなLinuxのパソコン(サーバー)
ターミナル 文字でコンピューターに命令を出す画面
SSH 離れたパソコン(VPS)に、ターミナルから安全につなぐ仕組み
SSH鍵 パスワードの代わりに使う「鍵のペア」。秘密鍵は自分のPCに置いて誰にも渡さない。公開鍵はVPSに登録する
root(ルート) Linuxの「何でもできる管理者」のユーザー
sudo(スードゥ) ふだんのユーザーが、一時的に管理者の権限でコマンドを実行するための言葉
ポート パソコンの「入口の番号」。SSHはふつう22番
ファイアウォール / ufw 入口(ポート)の門番。ufwは、Ubuntuなどで使える門番の設定ツール
cron 決まった時刻にコマンドを実行してくれる仕組み
systemd Linuxで、プログラムの起動や常駐を管理する仕組み。タイマー機能もある
venv Pythonの「プロジェクト専用の部屋」。入れたパッケージがほかと混ざらない
Docker / コンテナ アプリを「箱(コンテナ)」に入れて、どこでも同じように動かす仕組み
ボリューム コンテナを消しても残る、データの保存場所

そもそもVPSが必要?GAS・n8nクラウド版との比べ方

いきなりVPSに進む前に、「本当にVPSが必要か」を一度考えておきましょう。24時間動かす方法は、VPSだけではありません。

方法 24時間動く? 自分で管理すること 向いている人
自分のPC PCがスリープ・電源OFFだと止まる ほぼなし まず試したい人
GAS(時間主導型トリガー) 動く(Googleのサーバー上) ほぼなし Googleのサービス中心の自動化
n8nのクラウド版 動く(n8n側のサーバー上) ほぼなし n8nだけ使えればいい人
VPS 動く(借りたサーバー上) OSの更新・セキュリティ設定・バックアップ Pythonもn8nも自由に動かしたい人

GASで足りるなら、GASのほうがずっと楽です。設定はGASを毎日自動で動かす|時間主導型トリガーの設定手順で整理しています。道具の使い分け全体は、自動化スタック総覧|GAS・n8n・Python・Notionの使い分けも参考になります。

⚠️
n8nの公式ドキュメントにも注意書きがあります

n8nの公式ドキュメントでは、自分のサーバーでn8nを動かす(セルフホスト)には、サーバーやコンテナの設定・セキュリティの知識が必要で、慣れていない場合はクラウド版をすすめる、と書かれています。この記事では、n8nの画面をインターネットに公開しない、いちばん安全寄りの形で進めます。


STEP 1:VPSを用意する(選ぶときの見方)

VPSは、たくさんの会社が提供しています。この記事では特定のサービスはすすめませんが、選ぶときは次の4つを見てみてください。

見るところ 考え方
メモリ Pythonの小さなスクリプトだけなら少なめでも動きます。n8nもDockerで動かすなら、余裕のあるプランを選ぶと安心です(必要な量は、使い方により異なります)
OS UbuntuかDebianを選ぶと、この記事のコマンドがそのまま使いやすいです
リージョン(場所) 日本から使うなら、日本のリージョンだと操作の反応が速いことが多いです
料金の仕組み 月ごとの定額か、使った時間ごとか。止めていても料金がかかる場合があるので、契約前に確認しましょう

契約したら、IPアドレス(例:203.0.113.10)と、最初にログインするユーザー名とパスワードを控えておきます。最初のユーザー名は root のことが多いですが、サービスによって違います(環境により異なります)。

💡
契約画面で「SSH鍵の登録」ができる場合

VPSによっては、契約時の画面で公開鍵を登録できます。その場合はSTEP 5の登録作業を省けることがありますが、この記事ではどのVPSでも使えるように、手で登録する方法を説明します。


STEP 2:初めてVPSにログインする

💻 自分のPCのターミナルで入力します(Windowsは「PowerShell」、Macは「ターミナル」を開きます)。203.0.113.10 は、自分のVPSのIPアドレスに置き換えてください。

  • 1
ssh root@203.0.113.10

こう表示されればOK(例)

初めてつなぐときは、「この相手につないでいいですか?」と確認されます。yes と入力してEnterを押し、続けてVPSのパスワードを入力します(入力しても画面には何も表示されませんが、ちゃんと入力されています)。

  • 1
  • 2
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
root@203.0.113.10's password:

最後に root@...:~# のような表示に変われば、VPSの中に入れています。ここから先は、このターミナルで打つコマンドはVPSで実行されることを意識してくださいね。

うまくいかないとき

  • Connection timed out:IPアドレスの打ち間違いか、VPSがまだ起動していない可能性があります。管理画面で状態を確認しましょう
  • Permission denied:ユーザー名かパスワードの間違いです。最初のユーザー名が root ではないVPSもあります
  • Windowsで ssh が見つからない:Windows 10/11 には、SSHのクライアントが標準で用意されています(Microsoftの公式情報)。見つからない場合は、Windowsの「オプション機能」で「OpenSSH クライアント」を追加します(環境により異なります。今回は未検証です)

STEP 3:アップデートとタイムゾーンの設定

🖥 VPSで(rootでログインしている状態で)入力します。1行ずつ実行してください。

  • 1
apt update

  • 1
apt upgrade -y

apt update は「最新の部品リストをもらう」、apt upgrade は「実際に部品を新しくする」コマンドです。数分かかることがあります。

続けて、時刻を日本時間にします。cronの「毎朝7時」は、このサーバーの時刻が基準になるので大事です。

  • 1
timedatectl set-timezone Asia/Tokyo

  • 1
date

こう表示されればOK(例)

  • 1
Sat Oct 31 09:09:15 JST 2026

最後に JST と出ていれば、日本時間になっています。

うまくいかないとき

  • 途中で青い画面の質問が出たら:多くはそのままEnterで進めて大丈夫ですが、内容は環境により異なります
  • この記事の検証環境(コンテナ)では timedatectl が使えなかったため、別の方法で日本時間に設定しました。timedatectl の動作自体は未検証です

STEP 4:作業用のユーザーを作る

rootは「何でもできる」ぶん、打ち間違い1つで大事故になりかねません。ふだんの作業用に、自分のユーザーを作りましょう。ここでは例として kaito にしますが、好きな名前に置き換えてください。

🖥 VPSで(rootのまま)入力します。

  • 1
adduser kaito

パスワードを2回聞かれるので、新しいパスワードを決めて入力します(あとで sudo を使うときに必要です。忘れないように控えておきましょう)。名前などの質問は、Enterで飛ばしてかまいません。

次に、このユーザーが sudo(管理者の権限)を使えるようにします。

  • 1
usermod -aG sudo kaito

  • 1
id kaito

こう表示されればOK(検証時の出力)

  • 1
uid=1000(kaito) gid=1000(kaito) groups=1000(kaito),27(sudo),100(users)

27(sudo) が入っていれば成功です。

うまくいかないとき

  • adduser: command not found:useradd -m -s /bin/bash kaito と passwd kaito で作る方法もあります(環境により異なります)
  • 検証では、adduser をパスワードの質問なしで実行するオプション付きで動かしました。表示される質問の内容は、OSのバージョンにより異なります

STEP 5:SSH鍵を作って、VPSに登録する

ここからが、安全なログインの準備です。パスワードの代わりに「鍵」でログインできるようにします。

5-1. 自分のPCで鍵を作る

💻 自分のPCで、新しいターミナルを開いて入力します(VPSにつないでいるターミナルではありません。ここ、間違えやすいので注意です)。

  • 1
ssh-keygen -t ed25519

保存場所を聞かれたら、そのままEnter。パスフレーズ(鍵を使うときの合言葉)を聞かれたら、設定しておくのがおすすめです。空のままEnterでも作れます。

こう表示されればOK(例)

  • 1
  • 2
Your identification has been saved in /Users/kaito/.ssh/id_ed25519
Your public key has been saved in /Users/kaito/.ssh/id_ed25519.pub

  • id_ed25519:秘密鍵。誰にも渡さない、自分のPCから出さない
  • id_ed25519.pub:公開鍵。こちらをVPSに登録する

5-2. 公開鍵をVPSに登録する

💻 自分のPCで入力します。kaito と 203.0.113.10 は自分のものに置き換えてください。途中で、STEP 4で決めた kaito のパスワードを聞かれます。

Macの場合(Linuxも同じ):

  • 1
cat ~/.ssh/id_ed25519.pub | ssh kaito@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Windows(PowerShell)の場合:

  • 1
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh kaito@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

公開鍵の中身を、VPSの ~/.ssh/authorized_keys(ログインを許可する鍵のリスト)の末尾に書き足すコマンドです。

こう表示されればOK

パスワードを入力したあと、何も表示されずに元の画面に戻れば成功です。Linux同士の組み合わせで、同じコマンドで登録できることを確認しました。Windows(PowerShell)のコマンドは未検証です。

うまくいかないとき

  • No such file or directory:5-1で鍵が作られていないか、保存場所を変えています。ls ~/.ssh で確認しましょう
  • パスワードで弾かれる:VPSによっては、最初からパスワードでのログインが止められていることがあります。その場合は、管理画面から公開鍵を登録します(環境により異なります)

STEP 6:鍵でログインできるか確かめる

💻 自分のPCで入力します。

  • 1
ssh kaito@203.0.113.10

今度は、VPSのパスワードを聞かれずにログインできれば成功です(5-1でパスフレーズを設定した場合は、パスフレーズを聞かれます)。

続けて、🖥 VPSで、sudo が使えるかも確かめておきます。

  • 1
sudo whoami

こう表示されればOK(例)

  • 1
root

kaito のパスワードを聞かれ、最後に root と出れば、管理者の権限を使えています。

うまくいかないとき

  • まだパスワードを聞かれる:公開鍵の登録がうまくいっていません。STEP 5-2をもう一度やり直しましょう
  • kaito is not in the sudoers file:STEP 4の usermod -aG sudo kaito を、rootでやり直します

STEP 7:パスワードでのログインを止める

🚨
締め出しに注意(ここが一番大事です)

この設定をすると、パスワードではログインできなくなります。必ず、STEP 6で「鍵でログインできる」「sudoが使える」の2つを確認してから進めてください。

そして作業中は、今つないでいるターミナルを閉じないこと。設定を変えたあと、別のターミナルでログインできるのを確かめてから閉じます。

🖥 VPSで(kaito でログインしたターミナルで)、設定ファイルを新しく作ります。

  • 1
sudo nano /etc/ssh/sshd_config.d/00-hardening.conf

nano は、ターミナルで使えるメモ帳のようなものです。開いた画面に、次の3行を書きます。

  • 1
  • 2
  • 3
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no

  • PasswordAuthentication no:パスワードでのログインを止める
  • PermitRootLogin no:rootで直接ログインできないようにする
  • KbdInteractiveAuthentication no:キーボードでの入力によるログイン方式も止める

書けたら、Ctrl + O → Enterで保存、Ctrl + X で閉じます。

次に、設定の書き間違いがないかを確認します。

  • 1
sudo sshd -t

何も表示されなければOKです。続けて、設定が実際にどう効いているかを確認します。

  • 1
sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|kbdinteractiveauthentication) '

こう表示されればOK(検証時の出力)

  • 1
  • 2
  • 3
permitrootlogin no
passwordauthentication no
kbdinteractiveauthentication no

3つとも no なら、設定を反映します。

  • 1
sudo systemctl reload ssh

最後に、💻 自分のPCで新しいターミナルを開き、もう一度ログインできるか確かめます。

  • 1
ssh kaito@203.0.113.10

鍵でログインできれば完了です。検証では、パスワードだけでログインしようとすると、次のように断られることも確認しました。

パスワードでログインしようとしたときの出力(検証時の出力)

  • 1
kaito@203.0.113.10: Permission denied (publickey).

うまくいかないとき

  • sshd -T で passwordauthentication yes のまま:VPSによっては、/etc/ssh/sshd_config.d/ に別の設定ファイル(例:50-cloud-init.conf)があり、そちらが先に効いていることがあります。SSHの設定は「先に読まれた値が優先」なので、この記事ではファイル名を 00- で始めています。ls /etc/ssh/sshd_config.d/ で中身を確認しましょう(環境により異なります)
  • reload でエラーになる:OSによっては sudo systemctl restart ssh を使います(環境により異なります)
  • 万一ログインできなくなったら:多くのVPSには、管理画面からブラウザで操作できる「コンソール」機能があります。そこからログインして設定を戻せることがあります(環境により異なります)

STEP 8:ファイアウォールで、SSHだけ通す

ファイアウォールは「入口の門番」です。使う入口(ここではSSHの22番)だけ開けて、ほかは閉じておきます。

📝
このSTEPは未検証です

今回の検証環境(コンテナ)では、ufwを有効にする操作が、Linuxの機能の制限でエラーになりました。そのため、以下はufwの一般的な使い方の紹介です。本物のVPSでの動きは、環境により異なります。

🖥 VPSで入力します。ufwが入っていない場合(Debianなど)は、先に入れます。

  • 1
sudo apt install -y ufw

必ず先に、SSHを許可します(この順番を逆にすると、締め出される原因になります)。

  • 1
sudo ufw allow OpenSSH

  • 1
sudo ufw enable

  • 1
sudo ufw status verbose

こう表示されればOK(例)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Status: active
Default: deny (incoming), allow (outgoing), deny (routed)

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere

そして、ここでも新しいターミナルからログインできるかを確かめてから、今のターミナルを閉じましょう。

うまくいかないとき

  • VPSの管理画面にも、別のファイアウォール機能があることがあります。両方で22番が開いているか確認しましょう(環境により異なります)
  • n8nの5678番は、ここでは開けません。n8nは、STEP 13の方法で安全に開きます

STEP 9:Pythonのスクリプトを置く

ここから、いよいよ自動化の本番です。まずは、動いたことがわかるだけのダミーのスクリプトで試します。

🖥 VPSで、作業用のフォルダと、ログを置くフォルダを作ります。

  • 1
mkdir -p ~/auto/logs

  • 1
cd ~/auto

venv(Python専用の部屋)を作ります。

  • 1
python3 -m venv venv

ensurepip is not available のようなエラーが出たら、sudo apt install -y python3-venv を実行してから、もう一度試してください(OSにより異なります)。

スクリプトを作ります。

  • 1
nano ~/auto/hello.py

次の内容を貼り付けて保存します(Ctrl + O → Enter、Ctrl + X)。

  • 1
  • 2
  • 3
  • 4
from datetime import datetime
import sys

print(f"{datetime.now().isoformat(timespec='seconds')} hello from VPS (python {sys.version.split()[0]})")

手で1回動かしてみます。Pythonもスクリプトも、フルパス(絶対パス)で書くのがポイントです。

  • 1
/home/kaito/auto/venv/bin/python /home/kaito/auto/hello.py

こう表示されればOK(検証時の出力)

  • 1
2026-10-31T09:10:39 hello from VPS (python 3.13.5)

うまくいかないとき

  • No such file or directory:/home/kaito の部分を、自分のユーザー名に直しているか確認しましょう。echo $HOME で自分のホームフォルダがわかります
  • 自分のPCで使っていたスクリプトを持ってくる場合、pip install したパッケージは、VPSのvenvにも入れ直す必要があります(/home/kaito/auto/venv/bin/pip install パッケージ名)

STEP 10:cronで毎朝自動実行する

cronの基本(5つの時刻の書き方、絶対パス、ログの残し方)は、連載の Lv3 の cron 入門の記事でくわしく説明しています。ここでは、VPSで動かすための最短の手順だけ書きます。

🖥 VPSで入力します。

  • 1
crontab -e

初めて開くと、使うエディターを聞かれることがあります。迷ったら nano を選びましょう(表示は環境により異なります)。

開いた画面の一番下に、次の1行を書いて保存します。まずはテストのため「毎分」にしています。

  • 1
* * * * * /home/kaito/auto/venv/bin/python /home/kaito/auto/hello.py >> /home/kaito/auto/logs/cron.log 2>&1

  • 最初の * * * * *:毎分実行する
  • >> ...cron.log:出力をログファイルに追記する
  • 2>&1:エラーも同じログに残す

登録できたか確認します。

  • 1
crontab -l

2〜3分待ってから、ログを見てみましょう。

  • 1
cat ~/auto/logs/cron.log

こう表示されればOK(検証時の出力)

  • 1
  • 2
  • 3
  • 4
2026-10-31T09:11:01 hello from VPS (python 3.13.5)
2026-10-31T09:12:01 hello from VPS (python 3.13.5)
2026-10-31T09:13:01 hello from VPS (python 3.13.5)
2026-10-31T09:14:01 hello from VPS (python 3.13.5)

毎分1行ずつ増えていれば、cronが動いています。確認できたら、crontab -e でもう一度開き、本番の時刻に書き換えます。毎朝7時なら、こうです。

  • 1
0 7 * * * /home/kaito/auto/venv/bin/python /home/kaito/auto/hello.py >> /home/kaito/auto/logs/cron.log 2>&1

これで、PCを閉じていても、毎朝7時にVPSでスクリプトが動きます。

うまくいかないとき

  • crontab: command not found:cronが入っていません。sudo apt install -y cron で入れます(OSにより異なります)
  • ログが増えない:cron自体が動いたかは、sudo journalctl -u cron -n 20 で確認できます。検証では、次のような行が出ていました

  • 1
CRON[1097]: (kaito) CMD (/home/kaito/auto/venv/bin/python /home/kaito/auto/hello.py >> /home/kaito/auto/logs/cron.log 2>&1)

  • 7時ちょうどに動かない:STEP 3のタイムゾーンを確認しましょう。タイムゾーンを変えたあとは、念のため sudo systemctl restart cron でcronを再起動しておくと安心です(検証ではそうしました)

別の方法:systemdタイマーで動かす

cronの代わりに、systemdタイマーを使う方法もあります。設定ファイルは2つに増えますが、「最後にいつ動いたか」「成功したか」を systemctl で確認しやすいのが良いところです。cronで動いているなら、無理に切り替えなくて大丈夫です。

cron systemdタイマー
設定 1行で書ける ファイルが2つ(サービスとタイマー)
ログ 自分でファイルに残す journalctl で見られる
実行の記録 確認しにくい systemctl status で成功・失敗がわかる
止まっていた間の分 実行されない Persistent=true で、起動後に実行できる(公式情報)

🖥 VPSで、1つ目のファイル(何を実行するか)を作ります。

  • 1
sudo nano /etc/systemd/system/hello.service

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
[Unit]
Description=Run hello.py once

[Service]
Type=oneshot
User=kaito
WorkingDirectory=/home/kaito/auto
ExecStart=/home/kaito/auto/venv/bin/python /home/kaito/auto/hello.py

2つ目のファイル(いつ実行するか)を作ります。こちらもまずはテストで「毎分」にしています。

  • 1
sudo nano /etc/systemd/system/hello.timer

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
[Unit]
Description=Run hello.py every minute (test)

[Timer]
OnCalendar=*-*-* *:*:00
Persistent=true

[Install]
WantedBy=timers.target

書き間違いがないか確認してから、タイマーを有効にします。

  • 1
sudo systemd-analyze verify /etc/systemd/system/hello.service /etc/systemd/system/hello.timer

  • 1
sudo systemctl daemon-reload

  • 1
sudo systemctl enable --now hello.timer

  • 1
sudo systemctl list-timers hello.timer

こう表示されればOK(検証時の出力)

  • 1
  • 2
NEXT                        LEFT LAST PASSED UNIT        ACTIVATES
Sat 2026-10-31 09:12:00 JST  49s -         - hello.timer hello.service

数分後に、実行の記録を見てみます。

  • 1
sudo journalctl -u hello.service -n 8

検証時の出力(一部)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
Oct 31 09:12:01 vps systemd[1]: Starting hello.service - Run hello.py once...
Oct 31 09:12:01 vps python[1085]: 2026-10-31T09:12:01 hello from VPS (python 3.13.5)
Oct 31 09:12:01 vps systemd[1]: hello.service: Deactivated successfully.
Oct 31 09:12:01 vps systemd[1]: Finished hello.service - Run hello.py once.
Oct 31 09:13:30 vps systemd[1]: Starting hello.service - Run hello.py once...
Oct 31 09:13:30 vps python[1091]: 2026-10-31T09:13:30 hello from VPS (python 3.13.5)

よく見ると、2回目は 09:13:30 と、ちょうど0秒ではありませんでした。systemdのタイマーは、標準では最大1分ほど実行がずれることがあります(AccuracySec の初期値が1分。公式情報)。秒単位で正確さが必要でなければ、気にしなくて大丈夫です。

本番で毎朝7時にするなら、hello.timer の OnCalendar を次のように直し、sudo systemctl daemon-reload を実行します。

  • 1
OnCalendar=*-*-* 07:00:00

systemd-analyze calendar '*-*-* 07:00:00' と打つと、次に動く時刻を表示してくれるので、書き方の確認に便利です(検証では「Next elapse: Sun 2026-11-01 07:00:00 JST」と表示されました)。

📝
cronとタイマー、両方入れたままにしない

検証のため両方を動かしましたが、実際にはどちらか1つにしましょう。両方あると、同じスクリプトが2回動きます。


STEP 11:Dockerを入れる

ここからは、n8nを動かす準備です。n8nは、Docker(アプリを箱に入れて動かす仕組み)で動かすのが、公式でもすすめられている方法です。

📝
このSTEPは公式手順の紹介です(未検証)

今回の検証環境では、Dockerを公式のパッケージ(静的バイナリ)で入れたため、以下のapt(Ubuntu向け)の手順そのものは試していません。最新の手順は、Docker公式の「Install Docker Engine on Ubuntu」のページで確認してください。Debianの場合は、URLの ubuntu の部分が debian になります。

🖥 VPSで、1行ずつ実行します(Docker公式ドキュメントのUbuntu向け手順)。

  • 1
sudo apt update

  • 1
sudo apt install -y ca-certificates curl

  • 1
sudo install -m 0755 -d /etc/apt/keyrings

  • 1
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc

  • 1
sudo chmod a+r /etc/apt/keyrings/docker.asc

次のブロックは、まとめて全部コピーして貼り付けます(途中で区切ると動きません)。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

  • 1
sudo apt update

  • 1
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

インストールできたか確認します。

  • 1
sudo docker compose version

こう表示されればOK(例。数字は時期により異なります)

  • 1
Docker Compose version v5.6.1

うまくいかないとき

  • permission denied ... docker.sock:sudo を付け忘れています。この記事では、すべて sudo docker ... で実行します
  • 以前に別の方法でDockerを入れている:公式ドキュメントでは、古いパッケージを先に削除するよう案内されています

STEP 12:n8nをDockerで起動する

🖥 VPSで、n8n用のフォルダを作って移動します。

  • 1
mkdir -p ~/n8n

  • 1
cd ~/n8n

設定ファイル compose.yaml を作ります。

  • 1
nano compose.yaml

次の内容を貼り付けて保存します。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
services:
  n8n:
    image: docker.n8n.io/n8nio/n8n:2.45.7
    container_name: n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - GENERIC_TIMEZONE=Asia/Tokyo
      - TZ=Asia/Tokyo
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:

1行ずつの意味は、こうです。

設定 意味
image: ...n8n:2.45.7 使うn8nのバージョン。検証で使ったものに固定しています。更新するときはここを書き換えます
restart: unless-stopped 落ちたら自動で立ち上げ直す。ただし、自分で止めたときは勝手に起動しない
"127.0.0.1:5678:5678" VPSの中からだけ5678番で開けるようにする。インターネットには公開しない
GENERIC_TIMEZONE n8nのスケジュール(Schedule Trigger など)が使うタイムゾーン(公式情報)
TZ コンテナの中の時刻(date などが返す時刻)のタイムゾーン(公式情報)
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS 設定ファイルの権限を安全な形にする(公式の例に含まれている設定)
n8n_data:/home/node/.n8n ワークフローなどのデータを、コンテナを消しても残る「ボリューム」に保存する

⚠️
127.0.0.1: を消して "5678:5678" にしない

Docker公式ドキュメントには、Dockerでポートを公開すると、ufwのルールを通り抜けてしまうという注意があります。つまり、ufwで閉じたつもりでも、n8nの画面がインターネットに丸見えになる可能性があります。この記事の書き方なら、VPSの中からしか開けません。

起動します。

  • 1
sudo docker compose up -d

-d は「裏で動かし続ける」という意味です。初回はn8nのダウンロードがあるので、少し時間がかかります。

30秒ほど待ってから、状態を確認します。

  • 1
sudo docker compose ps

こう表示されればOK(検証時の出力)

  • 1
  • 2
NAME      IMAGE                            COMMAND                  SERVICE   CREATED         STATUS          PORTS
n8n       docker.n8n.io/n8nio/n8n:2.45.7   "tini -- /docker-ent…"   n8n       9 minutes ago   Up 25 seconds   127.0.0.1:5678->5678/tcp

STATUS が Up で、PORTS が 127.0.0.1:5678->5678/tcp になっていれば成功です。ログでも確認してみましょう。

  • 1
sudo docker compose logs --tail 20 n8n

検証時の出力(一部)

  • 1
  • 2
  • 3
n8n  | Version: 2.45.7
n8n  | Editor is now accessible via:
n8n  | http://localhost:5678

タイムゾーンが効いているかも見ておきます。

  • 1
sudo docker exec n8n date

検証時の出力

  • 1
Sat Oct 31 09:05:10 JST 2026

うまくいかないとき

  • STATUS が Restarting を繰り返す:sudo docker compose logs n8n でエラーを確認しましょう。compose.yaml のインデント(行頭のスペース)のずれも、よくある原因です。sudo docker compose config --quiet で、書式に問題がないかを確認できます(問題がなければ何も表示されません)
  • メモリが足りない:VPSのプランによっては、n8nの起動が遅かったり失敗したりすることがあります(環境により異なります)

STEP 13:自分のPCからn8nの画面を開く

n8nはVPSの中からしか開けない設定にしたので、自分のPCからはSSHトンネルという方法で開きます。SSHの安全な通り道を使って、「自分のPCの5678番」を「VPSの5678番」につなぐイメージです。

💻 自分のPCで、新しいターミナルを開いて入力します。

  • 1
ssh -L 5678:localhost:5678 kaito@203.0.113.10

ログインできたら、このターミナルは開いたままにして、自分のPCのブラウザで次を開きます。

  • 1
http://localhost:5678

n8nの画面が表示されれば成功です。初めて開いたときは、管理者(オーナー)のアカウントを作る画面が表示されます(n8nの公式情報)。

使い終わったら、トンネル用のターミナルで exit と打てば、トンネルが閉じます。トンネルを閉じても、n8nはVPSで動き続けます。ここが、自分のPCで動かしていたときとの一番の違いですね。

SSHトンネルでn8nを開く仕組み

📝
このSTEPの確認範囲

SSHトンネル(ssh -L)は、OpenSSHの標準の機能です。今回の検証では、VPSに見立てた環境の中で、http://127.0.0.1:5678/ がHTTP 200で応答することまでは確認しましたが、別のPCからトンネル経由でブラウザで開く操作は未検証です。

うまくいかないとき

  • ブラウザで開けない:トンネル用のターミナルを閉じていないか、ssh -L の行を打ち間違えていないか確認しましょう
  • bind: Address already in use:自分のPCで、すでに5678番を使っています(自分のPCでもn8nを動かしている、など)。ssh -L 15678:localhost:5678 [email protected] のように左側の番号を変えて、http://localhost:15678 を開きます

n8nの基本操作は、n8nとは?最初のワークフローを1本つくるで紹介しています。VPSに移したら、まずはSchedule Triggerを使ったワークフローを1本動かしてみましょう。


STEP 14:止まっていないか確認する・バックアップする

動いているかの確認コマンド

🖥 VPSで、次のコマンドを覚えておくと安心です。

確認したいこと コマンド
n8nが動いているか sudo docker ps
n8nのログ sudo docker compose logs --tail 50 n8n(~/n8n で実行)
systemdタイマーの予定と前回の実行 sudo systemctl list-timers
Pythonのジョブの成功・失敗 sudo systemctl status hello.service
cronのジョブのログ tail -n 20 ~/auto/logs/cron.log
Docker自体が動いているか sudo systemctl status docker

本当に自動で立ち上がるのか、試した結果

「restart: unless-stopped で本当に戻ってくるの?」と気になったので、検証環境で試してみました。

試したこと 結果(検証時)
n8nのコンテナのプロセスを強制終了 数秒で自動的に立ち上がった(再起動回数が1に増えた)
Docker自体を再起動(サーバー再起動の代わり) n8nも自動で起動した
docker compose stop で自分で止めてから、Dockerを再起動 n8nは止まったまま(unless-stopped の名前どおり)
docker compose down → up -d データ(設定ファイル)は消えずに残っていた

本物のVPSの再起動でも、Docker自体が自動で起動する設定になっていれば同じように戻る想定ですが、VPSの再起動そのものは未検証です。公式ドキュメントでは、Debian系ではDockerのサービスは自動で起動すると説明されています。

n8nのデータをバックアップする

n8nのワークフローや認証情報は、ボリュームに入っています。🖥 VPSで、~/n8n に移動してから、一度n8nを止めてバックアップを取ります。

  • 1
cd ~/n8n

  • 1
sudo docker compose stop

  • 1
sudo docker run --rm --user root --entrypoint tar -v n8n_n8n_data:/data:ro -v "$PWD":/backup docker.n8n.io/n8nio/n8n:2.45.7 czf /backup/n8n-backup.tar.gz -C /data .

  • 1
sudo docker compose start

  • 1
ls -l n8n-backup.tar.gz

こう表示されればOK(検証時の出力)

  • 1
-rw-r--r-- 1 root root 511834 Oct 31 09:15 n8n-backup.tar.gz

中には、データベース(database.sqlite)や、暗号化の鍵が入った設定ファイル(config)が含まれていました。

⚠️
ボリュームの名前とバックアップの扱い
  • ボリューム名の n8n_n8n_data は、「フォルダ名(n8n)+ _ + compose.yaml に書いた名前(n8n_data)」です。別の名前のフォルダで作った場合は、sudo docker volume ls で名前を確認してください(検証で確認しました)
  • バックアップには、認証情報を復号するための鍵も入っています。パスワードと同じくらい大切に扱いましょう
💡
バックアップのファイルを、ほかの人に読ませない・取りっぱなしにしない

上の ls -l の結果をよく見ると、-rw-r--r-- 1 root root になっています。持ち主は root ですが、最後の r-- は「ほかのユーザーもだれでも読める」という意味です(パーミッションの読み方と、chmod・chown の使い方は、Lv2 の記事で説明しています)。暗号化の鍵が入ったファイルなので、取ったらすぐに、自分(kaito)だけが読める形にしておくと安心です。たとえば sudo chown kaito:kaito n8n-backup.tar.gz で持ち主を自分にしてから、chmod 600 n8n-backup.tar.gz で自分だけが読み書きできる形(-rw-------)にします。そうすると、下の scp も kaito のまま問題なく使えます。

あわせて、次の3つも決めておきましょう。

  • 日付を入れる:毎回同じ名前だと、前回のバックアップを上書きしてしまいます。n8n-backup-$(date +%F).tar.gz のように日付を入れると、何世代か残せます(次の記事で、日付入りのバックアップを作ります)。
  • VPS の外にも置く:VPS が壊れたり、契約が切れたりすると、VPS の中のバックアップも一緒になくなります。下の scp で、自分の PC にもコピーしておきます。
  • 戻せるかを一度確かめる:この記事では、バックアップを取るところまでしか確かめていません。戻す(復元する)手順は未検証です。大事なデータを入れる前に、一度、練習用の環境で戻せるかを試しておくと安心です。

バックアップを自分のPCに持ってくるには、💻 自分のPCで次を実行します(未検証。一般的な scp の使い方です)。

  • 1
scp kaito@203.0.113.10:~/n8n/n8n-backup.tar.gz .

あわせて、Pythonのスクリプト(~/auto)も、自分のPCやGitで管理しておくと、VPSを作り直すときに困りません。

🤖 詰まったらAIに聞こう:VPS で cron や n8n が動かない

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
Linuxの初心者です。VPS(Debian)で、Pythonの定時実行やn8n(Docker)を動かそうとしていますが、うまくいきません。
原因の候補と、確かめる順番を教えてください。
n8nの画面はインターネットに公開しない(127.0.0.1だけ)形のまま直したいです。

【使っている環境】例:VPSのDebian 13、自分のPCはWindowsのPowerShell
【どのSTEPで詰まったか】例:STEP 12
【打ったコマンド】ここに貼る
【表示されたエラーや結果】ここに貼る(IPアドレスは伏せる)
【sudo docker compose ps / sudo docker logs n8n の最後の30行】ここに貼る

🔒
AIに貼る前に:秘密情報やパスワードは貼らない

VPS の IP アドレスやパスワード、compose.yaml に書いた暗号化キー(N8N_ENCRYPTION_KEY など)や API キーは、貼る前に必ず「***」に置き換えてください。SSH の秘密鍵(.pub がついていないほう)の中身は、どんなときも貼りません。docker logs にも、メールアドレスや URL が出ることがあります。


次のステップ:n8nをインターネットに公開したくなったら

外部のサービスからWebhookを受けたい場合など、n8nをインターネットから開ける形にしたくなることもあると思います。ただし、ここは一気に難易度が上がるので、この記事では概要と注意点だけにとどめます。

  • HTTPS(暗号化)は必須:ドメインを用意し、「リバースプロキシ」(外からの通信を受けて、n8nに中継する役のソフト)でHTTPSにするのが一般的な形です
  • 認証が必要:n8nの管理画面が誰でも開ける状態にならないよう、アカウントのパスワード管理や、必要に応じた追加の認証を考えます
  • ポートの開け方に注意:上で書いたとおり、Dockerのポート公開はufwを通り抜けることがあります(Docker公式情報)。公開するのはリバースプロキシの443番などだけにして、n8nの5678番は 127.0.0.1 のままにしておくのが基本です
  • n8n側の設定も変わる:公開するURLに合わせて、Webhook用のURLなどの設定が必要になります(n8nの公式ドキュメントを確認してください)

Webhookの考え方は、n8nのトリガー設計|Webhookで始める「起きたら動く」自動化で整理しています。まずは、この記事の「公開しない形」で、Schedule Triggerの定期実行から慣れていくのがおすすめです。


よくある質問

Q. Permission denied (publickey) と出てログインできません

A. 鍵が正しく登録されていないか、ユーザー名が違う可能性があります。ssh [email protected] のユーザー名を確認しましょう。STEP 7の前なら、パスワードでログインしてSTEP 5-2をやり直せます。STEP 7の後なら、VPSの管理画面のコンソール機能を使います(環境により異なります)。

Q. パスワードログインを止めたあと、自分も入れなくなりました

A. 多くのVPSには、管理画面からブラウザで操作できるコンソールがあります。そこからログインして、/etc/ssh/sshd_config.d/00-hardening.conf を見直します(環境により異なります)。こうならないよう、設定後は今のターミナルを閉じずに、新しいターミナルでログインを確認するのが一番の予防です。

Q. cronに書いたのに、スクリプトが動きません

A. まず、Pythonとスクリプトをフルパスで書いているか、行末に >> ログ 2>&1 があるかを確認しましょう。ログファイルにエラーが残っていれば、原因がわかります。くわしい確認方法は、cron入門の記事にまとめています。

Q. n8nのSchedule Triggerが、9時間ずれて動きます

A. GENERIC_TIMEZONE=Asia/Tokyo が設定されているか確認しましょう。compose.yaml を直したら、sudo docker compose up -d で反映します。

Q. ブラウザで http://203.0.113.10:5678 を開いても、n8nが表示されません

A. この記事の設定どおりなら、それで正常です。n8nはVPSの中からだけ開ける設定にしています。STEP 13のSSHトンネルを使って、http://localhost:5678 を開いてください。

Q. VPSを再起動したら、n8nは自動で動きますか?

A. restart: unless-stopped にしていて、Docker自体が自動で起動する設定なら、自動で立ち上がる想定です(検証では、Dockerを再起動するとn8nが戻ることを確認。VPSそのものの再起動は未検証)。ただし、docker compose stop で自分で止めていた場合は、止まったままになります。

Q. docker コマンドで permission denied と出ます

A. sudo を付けて実行してください。sudo なしで使えるようにする設定もありますが、この記事では扱いません。

Q. systemdタイマーが、ちょうど0秒に動きません

A. systemdのタイマーは、標準では最大1分ほど実行がずれることがあります(公式情報。検証でも30秒ほどずれました)。毎朝の処理なら、通常は問題ありません。

Q. バックアップを、毎日自動で取りたいです

A. STEP 14 のコマンドをシェルスクリプトにまとめて、STEP 10 と同じ cron か systemd タイマーで動かす形になります。そのときは、上の💡の箱のとおり、ファイル名に日付を入れ、古いものを消すルールも決めておきましょう。日付入りのバックアップの作り方は、次の記事で説明します。n8n を止めてから取る手順をそのまま自動にすると、そのあいだ n8n が止まるので、使っていない時間(夜中など)にしましょう。

Q. 自分のパソコンに Docker 入門の記事で docker.io を入れています。この記事の手順と混ざりませんか?

A. この記事の Docker は、VPS の中に入れるものなので、自分のパソコンの docker.io とは別です。混ざるのは、同じパソコン(同じ VPS)に、docker.io と、この記事の docker-ce の両方を入れようとしたときです。その場合は、Docker の公式ドキュメントの「古いパッケージを消す」手順を先に行ってください。


チェックリスト

最後に、ここまでできているか確認してみましょう。

VPSのOSをアップデートし、タイムゾーンを Asia/Tokyo にした
作業用のユーザーを作り、sudo が使えることを確認した
SSH鍵でログインできることを確認した
パスワードでのログインとrootのログインを止めた(sshd -T で3つとも no)
設定を変えたあと、新しいターミナルからログインできることを確認した
ファイアウォールで、SSH(22番)だけを許可した
Pythonのスクリプトを、venvのPythonとフルパスで手動実行できた
cron(またはsystemdタイマー)で、ログが増えることを確認し、本番の時刻に直した
n8nの compose.yaml で、ポートを 127.0.0.1:5678:5678 にした
sudo docker compose ps で Up を確認した
SSHトンネルで、自分のPCのブラウザからn8nを開けた
n8nのデータのバックアップを取り、大切に保管した

まとめ

  • PCを閉じても自動化を止めたくないなら、24時間動き続けるVPSに置くのが一つの方法。ただし、GASやn8nのクラウド版で足りるなら、そちらのほうが楽
  • 最初にやるのは安全設定。鍵でログインできるのを確かめてから、パスワードログインを止める。ターミナルは閉じずに、新しいターミナルで確認する
  • Pythonは、venvのPythonとスクリプトをフルパスで書いて、cron(またはsystemdタイマー)で動かす
  • n8nは、Docker Composeで restart: unless-stopped・ボリューム・Asia/Tokyo を設定して常駐。ポートは 127.0.0.1 にして、SSHトンネルで開く
  • この記事の検証は、本物のVPSではなく、VPSに見立てたDebian 13の環境で行った

まずは今日、STEP 1〜7の「安全にログインできる状態」までを目標にしてみましょう。そこまでできれば、あとは自分のPCでやっていた自動化を、少しずつVPSに引っ越していくだけです。


次に読む記事


関連記事