コンテナ構成を考えベースコンテナを作成

広く公開するサービスではなく、個人用途で利用するだけなら、外部からのアクセスをTailscale前提で構築するほうが便利ですね。なら、むしろ推奨される構成です。Tailscaleのネットワーク内にいる端末しかアクセスできないので、インターネットには一切公開されません。MagicDNSとHTTPS証明書はTailscaleが自動管理するので、自己署名証明書の煩わしさもありません。

規模により2つのアプローチ

Tailscale前提にするにしても、作成するコンテナ数に応じて、2つのアプローチが考えられます。

A) 各コンテナにTailscale(シンプル)

[端末] → Tailscale → [immichコンテナ:Tailscale] https://immich.tail.ts.net
                    [nextcloudコンテナ:Tailscale] https://nextcloud.tail.ts.net
  • 各コンテナが独立したTailscaleノードになる
  • コンテナごとにTailscaleの認証が必要
  • ノード数が増える(無料プランは最大100台)

B) ホストにTailscale + リバースプロキシ(スマート)

[端末] → Tailscale → [ホスト:Tailscale+Caddy] → immichコンテナ
                                                 → nextcloudコンテナ
  • Tailscaleはホスト1台分だけ
  • Caddyがhttps://immich→コンテナへ自動振り分け
  • 証明書管理も一元化

Caddyは設定がシンプルで、Tailscale連携も公式でサポートされているため、個人用途でコンテナ数が増える予定ならこの構成が適しています。次のようなイメージです。

[端末] 
  ↓ Tailscale
[Ubuntuホスト]
  ├── Tailscale(ホストのみ)
  ├── Caddyコンテナ(リバースプロキシ)
  │     ↓ LXD内部ネットワーク(lxdbr0)
  ├── immichコンテナ
  ├── nextcloudコンテナ
  └── ...

それぞれの特徴

100以上のサービスを利用する予定ならCaddy一元化が良いでしょうが、個人用途でコンテナが10個以下なら、各コンテナにTailscaleのプランAのほうが却ってトラブルが少ないかもしれません。

Caddy一元化各コンテナにTailscale
管理シンプルコンテナ増えると煩雑
認証系トラブル設定次第で解決可能ほぼ発生しない
Tailscaleノード数1サービス数分
個人100台制限余裕気にしなくていい

ここでは認証系のトラブルが発生しにくい、シンプルな構成で進めていきます。

[端末]
↓ Tailscale
[Ubuntuホスト] ← Tailscale済み
│ https://host.tail.ts.net:8443 → LXD UI

├── immichコンテナ
│ └── Tailscale → https://immich.tail.ts.net
├── nextcloudコンテナ
│ └── Tailscale → https://nextcloud.tail.ts.net
└── ...

ベースコンテナを作成

Dockerが不要な最小構成コンテナと、Dockerが必要なコンテナをベースコンテナとして準備します。

lxd-base-minimal:nano、Tailscale
lxd-base-docker:nano + Tailscale + Docker

lxd-base-minimalコンテナ作成

LXD-UIで作成し、コンテナ内に入って作業します。

lxc exec lxd-base-minimal -- bash
apt update && apt upgrade -y
apt install -y nano curl

# Tailscaleインストール
curl -fsSL https://tailscale.com/install.sh | sh
# ここでスナップショット → コピー
# tailscale up --authkey=... は各コンテナで実行

lxd-base-dockerコンテナ作成

lxd-base-minimalコンテナをコピーして作業します。
こちらはNestingAllowにしてから起動します。

lxc exec lxd-base-docker -- bash
# Dockerインストール
curl -fsSL https://get.docker.com | sh

TailscaleのAuth Key発行

各コンテナでTailscaleの認証が必要になるので、使い捨てのAuth Keyを発行しておきます。

Auth Keyの取得・使用手順

  1. Tailscale管理画面にログイン: Admin console にアクセスします。
  2. Settings > Keysへ移動: サイドバーの「Settings」から「Keys」を選択します。
  3. キーを生成: 「Generate auth key…」をクリックしてキーを作成します。
  4. 設定の選択: 必要に応じて、期限なし(Reusable)やタグ付け(Tags)などのオプションを設定し、キーをコピーして保存します。

Linkwardenセットアップ

導入するサービスに応じて、ベースとなるコンテナをコピーし立ち上げます。linkwardenの例で行います。Dockerでインストールする予定なので、lxd-base-dockerコンテナをコピーします。

lxc exec linkwarden -- bash
tailscale up --authkey=tskey-auth-xxxx
tailscale serve --bg http://localhost:3000

その後、Linkwardenをインストールします。

#!/bin/bash
set -euo pipefail

INSTALL_DIR="/opt/linkwarden"

# ── TailscaleのMagicDNS名を自動取得 ──────────────
TAILSCALE_URL=$(tailscale status --json | python3 -c "
import json, sys
data = json.load(sys.stdin)
dns = data.get('MagicDNSSuffix', '')
name = data.get('Self', {}).get('HostName', '')
print(f'https://{name}.{dns}' if dns and name else 'http://localhost:3000')
")
echo "🌐 NEXTAUTH_URL: $TAILSCALE_URL"

# ── シークレットキー自動生成 ──────────────────────
NEXTAUTH_SECRET=$(openssl rand -base64 36)
POSTGRES_PASSWORD=$(openssl rand -base64 24 | tr -dc 'a-zA-Z0-9' | head -c 32)

# ── インストールディレクトリ ──────────────────────
mkdir -p "$INSTALL_DIR"
cd "$INSTALL_DIR"

# ── .env 生成 ────────────────────────────────────
cat > .env <<EOF
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
NEXTAUTH_URL=${TAILSCALE_URL}
EOF
chmod 600 .env

# ── docker-compose.yml 生成 ──────────────────────
cat > docker-compose.yml <<'COMPOSE'
services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    env_file: .env
    environment:
      POSTGRES_DB: linkwarden
      POSTGRES_USER: linkwarden
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U linkwarden -d linkwarden"]
      interval: 10s
      timeout: 5s
      retries: 5

  linkwarden:
    image: ghcr.io/linkwarden/linkwarden:latest
    restart: unless-stopped
    env_file: .env
    environment:
      DATABASE_URL: postgresql://linkwarden:${POSTGRES_PASSWORD}@postgres:5432/linkwarden
    ports:
      - "3000:3000"
    volumes:
      - linkwarden_data:/data/data
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:
  linkwarden_data:
COMPOSE

# ── 起動 ─────────────────────────────────────────
docker compose pull
docker compose up -d

echo ""
echo "════════════════════════════════════════"
echo "  ✅  Linkwarden 起動完了"
echo "════════════════════════════════════════"
echo ""
echo "  🌐 アクセスURL : $TAILSCALE_URL"
echo "  📂 インストール先: $INSTALL_DIR"
echo ""
echo "  ログ確認 : docker compose -f $INSTALL_DIR/docker-compose.yml logs -f"
echo "  停止     : docker compose -f $INSTALL_DIR/docker-compose.yml down"
echo "  更新     : docker compose -f $INSTALL_DIR/docker-compose.yml pull && docker compose -f $INSTALL_DIR/docker-compose.yml up -d"
echo ""
タイトルとURLをコピーしました