最近回台灣,之前用 Tailscale 和沒在用的 Android 手機來充當 VPN,但無奈 Android 手機的穩定性看起來不夠(也可能我選的手機太低階),經常還是連不上所以還是買了一年的鯊魚。後來就想考慮用一台迷你電腦來放,但真的迷你電腦等級的又太誇張,所以最後選擇在日本買全套組的 Raspberry Pi 5 8GB 帶回台灣放。這篇紀錄一下弄的過程。

在 Raspberry Pi 5 上面安裝 Ubuntu 和 Docker

我買的沒有預裝 Raspberry Pi OS(應該通常不會裝?但我好像看到有人說會),也沒認真去研究到底有沒有差,似乎有人說 Raspberry Pi OS 有避免太常寫資料到 SD 卡來延長壽命,不過我還是選了 Ubuntu Server 比較熟悉。使用不困難,用 Raspberry Pi Imager 選擇型號、OS、SD 卡就好了。

安裝 Docker 也是按照官方教學,主要要避免的是跑去裝 Desktop(畢竟用 Ubuntu Server 也沒桌面可用)。

安裝並啟用 Tailscale

Tailscale 是一個建虛擬區域網路的好工具,印象中以前好像沒 CLI 的功能(或我沒注意到),但現在有 CLI 之後變得很方便,網站上就直接告訴你要怎麼下了。

如果要當 VPN 要開 Exit Node Mode,然後到網站上去啟用後,之後筆電手機就可以開 Tailscale 程式然後把 Exit Node 指到這台就變成 VPN 了。

為了方便,我把這台機器在 Tailscale 中的虛擬區域網路 IP 登記到 Cloudflare,這樣就可以用一個 Domain 去看。由於是虛擬區域網路,也不擔心被別人看到 IP 打進來。(但記得不要開到 Proxy。)

登記的 Domain 像是 foo.some.host*.foo.some.host,第二個是為了後面 Reverse Proxy 準備。

安裝 Portainer

因為不想每次動 Docker 都要連進去 SSH,找到 Portainer 這個開源可商用專案,

安裝上也滿簡單,按照官方教學就能順順的完成,會在第一次使用時建立帳號密碼。

安裝 Nginx Proxy Manager

又考慮到我還是比較喜歡用 Domain,加上我覺得我會放很多 Web-based 的軟體到這台機器,比起記 Port 我還是更偏好用 Domain,因此 Reverse Proxy 不可或缺。

這個教學說建議用 Docker Compose 去建,但我猜應該從 Portainer 去弄也沒問題。

建好之後登入帳號密碼是 [email protected]changeme,登入後才會提示更改。

這兩個弄好之後,先來嘗試把 Portainer 掛到 portainer.foo.some.host 下。。

結果居然連不上,查了一下才知道 Docker Compose 建起來的會有自己的 Network,所以要把其他 Container 串進來才可以連線

安裝 n8n

n8n 也是我很常用到的東西,雖然我在另外一台 VPS 也有裝,但有些需要台灣 IP 的 Workflow 可能要跑在這台上。我個人使用的 Docker Compose 檔案如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
version: "3.8"

volumes:
db_storage:
n8n_storage:

services:
postgres:
image: postgres:16
restart: always
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
- POSTGRES_NON_ROOT_USER
- POSTGRES_NON_ROOT_PASSWORD
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}",
]
interval: 5s
timeout: 5s
retries: 10

n8n:
image: docker.n8n.io/n8nio/n8n
restart: always
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
- DB_POSTGRESDB_USER=${POSTGRES_NON_ROOT_USER}
- DB_POSTGRESDB_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD}
- WEBHOOK_URL=https:// <YOUR DOMAIN> /
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_PRUNE_MAX_COUNT=30
- EXECUTIONS_DATA_MAX_AGE=24
- EXECUTIONS_DATA_SAVE_ON_SUCCESS=all
- EXECUTIONS_DATA_SAVE_ON_ERROR=all
- N8N_RUNNERS_ENABLED=true
ports:
- 5678:5678
links:
- postgres
volumes:
- n8n_storage:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy

裡面有調整一下資料自動清除,以免一沒注意就直接報掉了。

init-data.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
set -e;


if [ -n "${POSTGRES_NON_ROOT_USER:-}" ] && [ -n "${POSTGRES_NON_ROOT_PASSWORD:-}" ]; then
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER ${POSTGRES_NON_ROOT_USER} WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_NON_ROOT_USER};
GRANT CREATE ON SCHEMA public TO ${POSTGRES_NON_ROOT_USER};
EOSQL
else
echo "SETUP INFO: No Environment variables given!"
fi

.env

1
2
3
4
5
6
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=n8n

POSTGRES_NON_ROOT_USER=nonroot
POSTGRES_NON_ROOT_PASSWORD=nonroot

一樣 docker compose up 完要去 Portainer 裡面串網路,之後一樣加新的 Nginx Proxy Host 就好了。

後記

原本想用 Cloudflare Tunnel 來變成外部可以直接開,但想想也不是很必要(畢竟應該只有我用,加上我主要也是用 VPN 功能,所以後來就沒弄這塊,等之後有需要再來研究。

這次弄下來覺得 Portainer 其實也滿好用的,比起 Docker Desktop,Portainer 耗的資源看起來更小,而且對我來說也相對好用,還不用多裝一個軟體。OrbStack 似乎優勢是在會幫每個 Container 建立一個 orb.local 的 Domain 和虛擬機器的功能,前者我滿喜歡的,但看來用 Portainer 和 Nginx Proxy Manager 也能達到差不多的效果,後者我就沒用到了。這樣看來 Portainer + Nginx Proxy Manager 確實滿好用的(?)