# 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 -c yourls-init # 初期化ログ(初回のみ) kubectl logs -c nginx kubectl logs -c yourls ``` ### データベース接続の確認 ```bash kubectl exec -it -c yourls -- env | grep YOURLS_DB ``` ### 管理画面にアクセスしてもテーブルが作成されない `database.user`に指定したDBユーザーに`CREATE`/`ALTER`権限があるか確認してください(初回アクセス時の自動テーブル作成に必要です)。 ### 永続ボリュームの確認 ```bash kubectl get pvc kubectl describe pvc ``` ## セキュリティに関する注意事項 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)