Files
yourls/README.md
T
claude de1a4144b5
Helm Chart Release / release-chart (push) Successful in 7s
feat: チャートをゼロから再設計(外部DB前提のYOURLS+Nginx構成に作り直し)
旧チャートは存在しないDocker Hubイメージ(yourls/yourls)を参照し、Bitnami MySQL
サブチャートに依存するなど正しく動作しない状態だったため、YOURLS公式イメージ
(docker.io/yourls, container-entrypoint.sh/config-container.php)の実装を確認した上で
WordPressチャートと同一方針(外部DB、emptyDir+PVC分離、fsGroup非root実行、
real IP取得対応)でスクラッチから再構築した。
2026-09-12 07:56:17 +09:00

257 lines
11 KiB
Markdown

# YOURLS with Nginx Helm Chart
[YOURLS](https://yourls.org/)(Your Own URL Shortener)をNginx + PHP-FPMの構成でKubernetesにデプロイするHelmチャートです。Raspberry Piなどのベアメタル(ARM)クラスタでの運用を想定しています。
## 主な機能
- Nginx(alpine-perl) + YOURLS公式イメージ(fpm-alpine)のマルチコンテナPod構成
- 外部MySQL/MariaDBを利用(サブチャート非同梱。WordPress/phpfpmチャートと同一方針)
- YOURLS本体はemptyDirに展開する使い捨て構成(bitnami方式)。管理画面から追加した
プラグイン・カスタムページ・言語ファイルのみPVCで永続化
- 非root実行(uid/gid 82 = www-data)+ 読み取り専用ルートファイルシステムマウントによる多層防御
- Ingress/LoadBalancer両対応、ベアメタル環境での実クライアントIP取得に対応
- secret-manager等の外部Secretからのパスワード参照(`existingSecret`)、`extraEnvFrom`/`extraEnv`による環境変数の追加注入
- helm upgradeを跨いでもCookie暗号化キー・自動生成パスワードがローテーションしない設計
## アーキテクチャとセキュリティ
### ストレージ構成
```
/var/www/html/ ← emptyDir (Pod再起動で消える。YOURLS本体を都度展開)
├── admin/, includes/, css/, js/, images/, yourls-*.php ... (イメージから展開)
└── user/
├── config.php ← 環境変数から都度生成(永続化しない)
├── plugins/ ┐
├── pages/ ├─ PVCの該当パスをsubPathマウント(永続化)
└── languages/ ┘
```
`user/config.php`はYOURLS公式イメージ同梱の`config-container.php`をコピーしただけのもので、中身は`getenv()`で環境変数を読むだけのテンプレートです。YOURLS本体がこのファイルに書き込むことはないため、Pod起動のたびに生成し直しても情報は失われません。これにより`values.yaml`の変更が再起動のたびに確実に反映されます。
### セキュリティ上の利点
- YOURLS本体のコードはPodごとに公式イメージからクリーンに展開され、実行時に改ざんされても再起動で元に戻る
- `yourls`/`yourls-init`コンテナは非root(uid/gid 82)・`allowPrivilegeEscalation: false`・全capability drop
- `yourls`コンテナの`/var/www/html`マウントは読み取り専用(`user/plugins`等の永続領域のみ書き込み可)
- DB接続情報を保持する`user/config.php`・内部処理用の`includes/`ディレクトリへの直接アクセスをNginx側で拒否(多層防御。通常はfastcgi経由でPHPとして実行されるため到達しない)
- `automountServiceAccountToken: false`(不要なKubernetes APIトークンをPodにマウントしない)
## 前提条件
- Kubernetes 1.19+
- Helm 3.0+
- 到達可能な外部MySQL/MariaDB(YOURLS用データベースを別途用意)
- PersistentVolumeプロビジョナー(永続化を有効にする場合)
## ディレクトリ構造
```
yourls/
├── Chart.yaml
├── values.yaml
├── templates/
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── pvc.yaml
│ ├── ingress.yaml
│ └── NOTES.txt
└── README.md
```
## インストール方法
### 1. データベースの準備
外部MySQL/MariaDB上に、YOURLS用のデータベースとユーザーを作成してください(テーブルは初回admin画面アクセス時に自動作成されるため、当該ユーザーに`CREATE`/`ALTER`権限が必要です)。
```sql
CREATE DATABASE yourls CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'yourls'@'%' IDENTIFIED BY 'securepassword';
GRANT ALL PRIVILEGES ON yourls.* TO 'yourls'@'%';
FLUSH PRIVILEGES;
```
### 2. インストール
```bash
helm install my-yourls . \
--set yourls.site="https://sho.rt" \
--set yourls.admin.username=admin \
--set yourls.admin.password='SecureAdminPassword' \
--set database.host=mysql.example.svc.cluster.local \
--set database.user=yourls \
--set database.password='securepassword'
```
または `values.yaml` をカスタマイズしてインストール:
```bash
helm install my-yourls . -f values.yaml
```
## 設定パラメータ
### イメージ設定
| パラメータ | 説明 | デフォルト値 |
|-----------|------|-------------|
| `image.nginx.tag` | Nginxイメージのタグ | `1.31.5-alpine-perl` |
| `image.yourls.tag` | YOURLSイメージのタグ(`docker.io/yourls`) | `1.10.6-fpm-alpine` |
### YOURLS設定
| パラメータ | 説明 | デフォルト値 |
|-----------|------|-------------|
| `yourls.site` | YOURLSインスタンスのURL(固定値。末尾スラッシュなし) | `https://your-own-domain-here.com` |
| `yourls.admin.username` | 管理者ユーザー名 | `admin` |
| `yourls.admin.password` | 管理者パスワード(空の場合は自動生成・Secretに保存) | `""` |
| `yourls.admin.existingSecret` | 管理者パスワードを既存Secretから取得する場合の名前 | `""` |
| `yourls.admin.existingSecretKey` | 上記Secret内のキー名 | `password` |
| `yourls.cookiekey` | Cookie暗号化キー(空の場合は自動生成・以後のupgradeでも保持) | `""` |
| `yourls.privateMode` | `true`: 管理画面ログイン必須(推奨) / `false`: 統計等を公開 | `true` |
| `yourls.hoursOffset` | サーバーのタイムゾーンオフセット(時間) | `0` |
| `yourls.lang` | 管理画面の表示言語 | `""` |
### データベース設定
| パラメータ | 説明 | デフォルト値 |
|-----------|------|-------------|
| `database.host` | MySQL/MariaDBのホスト名 | `mysql.example.svc.cluster.local` |
| `database.port` | ポート番号 | `3306` |
| `database.name` | データベース名 | `yourls` |
| `database.user` | DBユーザー名 | `yourls` |
| `database.password` | DBパスワード(本番はexistingSecret推奨) | `changeme` |
| `database.existingSecret` | DBパスワードを既存Secretから取得する場合の名前 | `""` |
| `database.existingSecretKey` | 上記Secret内のキー名 | `password` |
| `database.tablePrefix` | テーブル接頭辞 | `yourls_` |
### 外部Secret連携・追加環境変数
| パラメータ | 説明 | デフォルト値 |
|-----------|------|-------------|
| `extraEnvFrom` | 既存Secret/ConfigMapを丸ごとenvFromで注入(`cred-*`等) | `[]` |
| `extraEnv` | 個別の環境変数を追加(value/valueFrom使用可)。`YOURLS_DEBUG`等、values化していない項目はこちら | `[]` |
### Service / Ingress設定
| パラメータ | 説明 | デフォルト値 |
|-----------|------|-------------|
| `service.type` | Serviceタイプ(VIPが希少なため既定はClusterIP) | `ClusterIP` |
| `service.externalTrafficPolicy` | LoadBalancer/NodePort時のみ有効。`Local`で実IPを透過 | `Local` |
| `ingress.enabled` | Ingressの有効化 | `false` |
| `ingress.hostname` | ホスト名 | `yourls.example.com` |
| `ingress.tls` | `true`でTLSを自動設定(hostnameを使用) | `false` |
### 永続化設定
| パラメータ | 説明 | デフォルト値 |
|-----------|------|-------------|
| `persistence.enabled` | `user/plugins`,`user/pages`,`user/languages`の永続化 | `true` |
| `persistence.size` | PVCのサイズ | `1Gi` |
| `persistence.storageClass` | StorageClass名 | `""`(クラスタ既定) |
## 使用例
### Ingressでの公開(TLS付き)
```bash
helm install my-yourls . \
--set yourls.site="https://sho.rt" \
--set database.host=mysql.example.svc.cluster.local \
--set database.password='securepassword' \
--set ingress.enabled=true \
--set ingress.hostname=sho.rt \
--set ingress.className=nginx \
--set ingress.tls=true \
--set ingress.annotations."cert-manager\.io/cluster-issuer"=letsencrypt-issuer
```
### secret-managerチャートが配布するSecretをDBパスワードに使う
```bash
helm install my-yourls . \
--set database.existingSecret=cred-mysql \
--set database.existingSecretKey=MYSQL_PASSWORD
```
### 管理者パスワードの確認(自動生成時)
```bash
kubectl get secret my-yourls-yourls-nginx-secret \
-o jsonpath="{.data.admin-password}" | base64 -d; echo
```
## 初期化の動作
### 新規インストール時
1. `yourls-init` initContainerがYOURLS本体のコアファイルをemptyDirへ展開
2. `user/plugins`,`user/pages`,`user/languages`のPVCが空であれば、YOURLS同梱のデフォルト内容(サンプルプラグイン等)を投入
3. `user/config.php`を環境変数駆動のテンプレートから生成
4. Pod起動後、`{yourls.site}/admin/`へ初回アクセスするとYOURLSが自動的にテーブルを作成
### 再起動時
- コアファイルは毎回クリーンに再展開される(emptyDirは使い捨てのため)
- `user/plugins`等のPVCは既に中身があればそのまま保持され、デフォルト内容で上書きされない
- `user/config.php`も毎回再生成されるため、`values.yaml`のDB接続情報等の変更が確実に反映される
## アップグレード
```bash
helm upgrade my-yourls . -f values.yaml
```
`yourls.cookiekey`や自動生成された`yourls.admin.password`は、Secretの既存値を参照して引き継がれるため、明示的に固定していなくても`helm upgrade`のたびに変わることはありません。
## アンインストール
```bash
helm uninstall my-yourls
```
PVCは`helm uninstall`では削除されません。完全にデータを削除する場合は手動で削除してください。
```bash
kubectl delete pvc my-yourls-yourls-nginx-pvc
```
## トラブルシューティング
### Podの状態確認
```bash
kubectl get pods -l app.kubernetes.io/name=yourls-nginx
kubectl logs <pod-name> -c yourls-init # 初期化ログ(初回のみ)
kubectl logs <pod-name> -c nginx
kubectl logs <pod-name> -c yourls
```
### データベース接続の確認
```bash
kubectl exec -it <pod-name> -c yourls -- env | grep YOURLS_DB
```
### 管理画面にアクセスしてもテーブルが作成されない
`database.user`に指定したDBユーザーに`CREATE`/`ALTER`権限があるか確認してください(初回アクセス時の自動テーブル作成に必要です)。
### 永続ボリュームの確認
```bash
kubectl get pvc
kubectl describe pvc <pvc-name>
```
## セキュリティに関する注意事項
1. **デフォルトの管理者パスワード・DBパスワードは必ず変更してください**(`yourls.admin.password`/`database.password`を明示指定するか、`existingSecret`を利用)
2. **`yourls.site`を実際のドメインに設定してください**(短縮URL生成に使う固定値です)
3. **本番環境では必ずHTTPSを有効化してください**(`ingress.tls: true`、または前段のLB/CDNでTLS終端)
4. **`yourls.privateMode`は既定で`true`です**(管理画面ログインなしでの短縮URL作成・統計閲覧を許可する場合のみ`false`に変更してください。詳細: https://yourls.org/privatepublic)