- PHP 96.6%
- Blade 1.6%
- Shell 1.2%
- JavaScript 0.4%
- CSS 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Deploy admin panel / deploy (push) Successful in 18s
|
||
| .forgejo/workflows | ||
| app | ||
| bootstrap | ||
| config | ||
| database | ||
| public | ||
| resources | ||
| routes | ||
| scripts | ||
| storage | ||
| tests | ||
| .editorconfig | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| artisan | ||
| composer.json | ||
| composer.lock | ||
| Containerfile.dev | ||
| package-lock.json | ||
| package.json | ||
| phpunit.xml | ||
| README.md | ||
| vite.config.js | ||
Kannuki_sanの作業場 管理画面
記事、制作物、固定ページ、分類、公開設定を管理するLaravel 13 + Filament 5アプリです。このリポジトリだけがDB migrationを所有します。
ローカル開発
./scripts/reset-local-db.sh
./scripts/dev.sh
既定では公開サイトリポジトリと同じ親ディレクトリにある../runtimeを共有します。リポジトリを別々の場所へcloneする場合は、公開側と同じ共有先を指定できます。ホスト側の配置やディレクトリ名は固定されていません。
export MYWEB_RUNTIME_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/myweb"
export MYWEB_MEDIA_DIR="$MYWEB_RUNTIME_DIR/media"
http://127.0.0.1:8001/adminを開きます。ダミー管理者はadmin@example.test、初期パスワードはtekutime-localです。これはローカル専用で、本番では絶対に使いません。初回ログイン時にTOTP設定が必須です。
公開サイトも同時に起動すると、管理画面で更新した共有SQLiteの内容が公開側へ反映されます。
本番デプロイの要点
LXCは現在の運用例であり、必須ではありません。通常のLinuxサーバー、VM、コンテナでも動作します。管理画面は公開サイトとは別のWeb公開範囲、資格情報、実行ユーザーで運用してください。以下のDB名、DBユーザー、hostname、S3設定はすべて環境ごとに置き換える値です。
- Caddy、PHP 8.3以上、PHP-FPM、Composer、
php-mysql php-mbstring php-xml php-curl php-zip php-intl php-opcacheを導入する。 - 管理専用DBユーザーには対象DB内の必要なDDL/DMLだけを許可し、他DBや
GRANT OPTIONを与えない。 .envは本番専用とし、APP_ENV=production、APP_DEBUG=false、本番専用APP_KEY、安全なsession/cache設定を使う。php artisan migrate --forceは管理側の承認済みリリースからだけ実行する。- 管理者を個別作成して
is_admin=1を確認する。共有アカウントは作らない。 - FilamentのTOTP MFAを必須とし、recovery情報をパスワードマネージャーへ保管する。
- WebサーバーはLAN/VPNインターフェースだけでlistenする。管理hostnameを公開DNSへ登録しない。外出時はTailscale等のVPNを使う。
- Login/MFA失敗、公開・更新・削除をログへ残し、ログとMariaDBを定期バックアップする。
制作物と記事では、サムネイル、本文画像、MP4/WebM動画、添付・配布ファイルをアップロードできます。YouTube・ニコニコ動画は埋め込みコードではなく視聴URLを登録します。トップ右側の注目枠も画像または動画を管理画面から登録できます。
「制作物ページ」では、すべての制作物にマニュアル、ライセンス、FAQなどの子ページを追加できます。親ページを指定すると多段の階層になり、同じ制作物内のURL名は重複できません。親を削除した場合、子ページ自体は残って制作物直下へ移ります。非公開ページと、非公開の親を持つページは公開サイトへ表示されません。
本番では非公開のS3互換ストレージを使います。管理画面には読み書き用資格情報、公開サイトには別の読み取り専用資格情報を与えます。ストレージ自体は公開DNSへ接続しません。管理側.envには次のように設定します。
MEDIA_DISK=s3
MEDIA_TEMPORARY_DISK=local
MEDIA_IMAGE_MAX_KB=20480
MEDIA_VIDEO_MAX_KB=524288
MEDIA_DOWNLOAD_MAX_KB=2097152
AWS_ACCESS_KEY_ID=ADMIN_READ_WRITE_KEY
AWS_SECRET_ACCESS_KEY=ADMIN_READ_WRITE_SECRET
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=site-media
AWS_URL=
AWS_ENDPOINT=http://storage.internal:8333
AWS_USE_PATH_STYLE_ENDPOINT=true
storage.internalは説明用hostnameです。実際の内部DNS名または非公開IPへ変更してください。SeaweedFS以外でも、Laravel Flysystem S3 adapterと互換性のあるストレージを利用できます。
削除・差し替え時は、その記事・制作物が所有するS3 prefix内のファイルだけを削除します。bucket自体は公開せず、公開LXCのLaravelが公開状態と登録用途を確認した後にSeaweedFSから配信します。大容量ファイルはNextcloudなどの外部共有URLを使います。アップロード上限はPHP-FPMと管理側Caddyにも同じ値を設定してください。
制作物ページから届いた不具合・内容修正・質問は「不具合・意見」にだけ表示され、公開ページには表示されません。状態は「新規」「確認中」「対応済み」「終了」で管理します。記事の投稿は別の「コメント」で管理し、公開・非表示・スパムの切り替えと管理者返信ができます。制作物の公開更新履歴は「更新履歴」で管理します。
公開DBユーザーには公開コンテンツと公開コメント・更新履歴へのSELECT、コメントと制作物報告へのINSERTだけを許可します。次のSQLではexample_database、example_public_user、public-app.internalを実環境の値へ置き換えてください。
GRANT SELECT ON example_database.categories TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.posts TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.works TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.pages TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.site_settings TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.comments TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.work_updates TO 'example_public_user'@'public-app.internal';
GRANT SELECT ON example_database.work_pages TO 'example_public_user'@'public-app.internal';
GRANT INSERT ON example_database.comments TO 'example_public_user'@'public-app.internal';
GRANT INSERT ON example_database.content_reports TO 'example_public_user'@'public-app.internal';
GRANT INSERT ON example_database.download_events TO 'example_public_user'@'public-app.internal';
公開サイト内の添付・配布ファイルは、個人情報やIPアドレスを保存せず、ダウンロード開始回数だけをdownload_eventsへ追記します。管理画面の「ダウンロード集計」で累計・今日・過去30日・ファイル別の回数を確認できます。公開側のDBユーザーには、このテーブルへのINSERTだけを追加してください。
Forgejo Actions
同梱するworkflowは現在の管理者向けのデプロイ例であり、アプリケーションの動作要件ではありません。自動デプロイする場合は管理環境専用のdeploy鍵とdeployユーザーを使用し、公開環境・配布環境の鍵、DB管理者資格情報、別サービスのcredentialを共有しません。