Changes
5 changed files (+324/-80)
-
demo/.terraform.lock.hcl (new)
-
@@ -0,0 +1,20 @@# This file is maintained automatically by "tofu init". # Manual edits may be lost in future updates. provider "registry.opentofu.org/hashicorp/aws" { version = "5.100.0" constraints = "~> 5.82" hashes = [ "h1:zef23ac/YWw9O2FepFWRs+my9iWWUkniL4dT4LnCKjU=", "zh:1a41f3ee26720fee7a9a0a361890632a1701b5dc1cf5355dc651ddbe115682ff", "zh:30457f36690c19307921885cc5e72b9dbeba369445815903acd5c39ac0e41e7a", "zh:42c22674d5f23f6309eaf3ac3a4f1f8b66b566c1efe1dcb0dd2fb30c17ce1f78", "zh:4cc271c795ff8ce6479ec2d11a8ba65a0a9ed6331def6693f4b9dccb6e662838", "zh:60932aa376bb8c87cd1971240063d9d38ba6a55502c867fdbb9f5361dc93d003", "zh:864e42784bde77b18393ebfcc0104cea9123da5f4392e8a059789e296952eefa", "zh:9750423138bb01ecaa5cec1a6691664f7783d301fb1628d3b64a231b6b564e0e", "zh:e5d30c4dec271ef9d6fe09f48237ec6cfea1036848f835b4e47f274b48bda5a7", "zh:e62bd314ae97b43d782e0841b13e68a3f8ec85cc762004f973ce5ce7b6cdbfd0", "zh:ea851a3c072528a4445ac6236ba2ce58ffc99ec466019b0bd0e4adde63a248e4", ] }
-
-
-
@@ -0,0 +1,2 @@SPDX-FileCopyrightText: 2026 Shota FUJI <pockawoooh@gmail.com> SPDX-License-Identifier: AGPL-3.0-only
-
-
demo/aws.tf (new)
-
@@ -0,0 +1,177 @@# S3+Cloudfront 構成のサイトインフラ。独自ドメインを CNAME で Cloudfront の # ドメインに向ける前提。 # # 一回 `tofu apply` を実行してタイムアウトで異常終了を待ってから `tofu output` # を実行し、 `domain_cert_validations.resource_record_*` の内容を DNS に追記。 # その後再度 `tofu apply` を実行する。 # # SPDX-FileCopyrightText: 2026 Shota FUJI <pockawoooh@gmail.com> # SPDX-License-Identifier: AGPL-3.0-only variable "domain" { type = string default = "demo.yamori.pocka.jp" } variable "aws_region" { type = string default = "ap-northeast-1" } terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.82" } } required_version = ">= 1.2.0" } provider "aws" { region = var.aws_region default_tags { tags = { Service = "Yamori" Module = "Demo" } } } provider "aws" { alias = "us_east_1" region = "us-east-1" default_tags { tags = { Service = "Yamori" Module = "Docs" } } } resource "aws_s3_bucket" "origin" { bucket = "demo.yamori.pocka.jp" } output "s3_bucket_name" { value = aws_s3_bucket.origin.id } data "aws_iam_policy_document" "s3_cf_read_policy" { statement { sid = "AllowCloudfrontReadonly" principals { type = "Service" identifiers = ["cloudfront.amazonaws.com"] } actions = ["s3:GetObject"] resources = ["${aws_s3_bucket.origin.arn}/*"] condition { test = "StringEquals" variable = "aws:SourceArn" values = [aws_cloudfront_distribution.cdn.arn] } } } resource "aws_s3_bucket_policy" "allow_read_from_cloudfront" { bucket = aws_s3_bucket.origin.id policy = data.aws_iam_policy_document.s3_cf_read_policy.json } resource "aws_acm_certificate" "domain_cert" { # CloudFront で使う ACM は us-east-1 にある必要がある。 # https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-requirements.html provider = aws.us_east_1 domain_name = var.domain validation_method = "DNS" lifecycle { create_before_destroy = true } } output "domain_cert_validations" { value = aws_acm_certificate.domain_cert.domain_validation_options } locals { cf_origin_id = "yamori_demo_cdn" } resource "aws_cloudfront_origin_access_control" "s3_oac" { name = "yamori_demo_static_website" origin_access_control_origin_type = "s3" signing_behavior = "always" signing_protocol = "sigv4" } resource "aws_cloudfront_function" "spa_rewrite" { name = "yamori_demo__spa_rewrite" runtime = "cloudfront-js-2.0" code = file("${path.module}/aws/cf_spa_rewrite.js") } resource "aws_cloudfront_distribution" "cdn" { origin { domain_name = aws_s3_bucket.origin.bucket_regional_domain_name origin_id = local.cf_origin_id origin_access_control_id = aws_cloudfront_origin_access_control.s3_oac.id } enabled = true is_ipv6_enabled = true default_root_object = "index.html" http_version = "http2and3" aliases = [var.domain] viewer_certificate { acm_certificate_arn = aws_acm_certificate.domain_cert.arn ssl_support_method = "sni-only" } default_cache_behavior { # AWS が管理している CacheOptimized ポリシー cache_policy_id = "658327ea-f89d-4fab-a63d-7e88639e58f6" allowed_methods = ["GET", "HEAD", "OPTIONS"] cached_methods = ["GET", "HEAD"] target_origin_id = local.cf_origin_id compress = true viewer_protocol_policy = "redirect-to-https" min_ttl = 0 default_ttl = 31536000 max_ttl = 31536000 function_association { event_type = "viewer-request" function_arn = aws_cloudfront_function.spa_rewrite.arn } } restrictions { geo_restriction { locations = [] restriction_type = "none" } } } output "cloudfront_distribution_id" { value = aws_cloudfront_distribution.cdn.id } output "cloudfront_domain" { value = aws_cloudfront_distribution.cdn.domain_name }
-
-
-
@@ -0,0 +1,29 @@// SPDX-License-Identifier: AGPL-3.0-only // Copyright 2026 Shota FUJI // // This program is free software: you can redistribute it and/or modify it under the terms // of the GNU Affero General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A // PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License along // with this program. If not, see <http://www.gnu.org/licenses/>. var NO_REWRITE_PATTERN = /.+\..+$/; function handler(event) { var request = event.request; var uri = request.uri; var segments = uri.split("/"); var lastSegment = segments[segments.length - 1]; if (!lastSegment || NO_REWRITE_PATTERN.test(lastSegment)) { return request; } request.uri = "/index.html"; return request; }
-
-
-
@@ -69,90 +69,106 @@]; }; apps = { # nix run .#docs # -------------- # ドキュメントの開発サーバを起動する。オプションは "--" の後に指定する。 # 例: nix run .#docs -- --help docs = let server = pkgs.symlinkJoin { name = "server-docs"; nativeBuildInputs = [ pkgs.makeWrapper ]; paths = [ (pkgs.python3.withPackages ( python: with python; [ python.mkdocs python.mkdocs-material ] )) ]; postBuild = '' wrapProgram $out/bin/mkdocs \ --add-flags 'serve' \ --add-flags '--config-file' \ --add-flags 'docs/mkdocs.yml' ''; }; in { apps = let deploy = dir: { type = "app"; program = "${server}/bin/mkdocs"; program = pkgs.lib.getExe ( pkgs.writeShellApplication { name = "deploy-${dir}"; text = '' CF_DIST_ID=$(tofu -chdir=${dir} output -json | jq -r ".cloudfront_distribution_id.value") S3_BUCKET_NAME=$(tofu -chdir=${dir} output -json | jq -r ".s3_bucket_name.value") rclone sync \ ${packages.${dir}} \ ":s3:$S3_BUCKET_NAME" \ --s3-provider=AWS \ --s3-env-auth \ --s3-region="$AWS_DEFAULT_REGION" \ --checksum aws cloudfront create-invalidation \ --distribution-id "$CF_DIST_ID" --paths '/*' ''; runtimeInputs = with pkgs; [ packages.${dir} # Tool for building, changing, and versioning infrastructure # https://opentofu.org/ opentofu # Unified tool to manage your AWS services # https://aws.amazon.com/cli/ awscli2 # Lightweight and flexible command-line JSON processor # https://jqlang.github.io/jq/ jq # Command line program to sync files and directories to and from major cloud storage # https://rclone.org/ rclone ]; } ); }; in { # nix run .#docs # -------------- # ドキュメントの開発サーバを起動する。オプションは "--" の後に指定する。 # 例: nix run .#docs -- --help docs = let server = pkgs.symlinkJoin { name = "server-docs"; nativeBuildInputs = [ pkgs.makeWrapper ]; paths = [ (pkgs.python3.withPackages ( python: with python; [ python.mkdocs python.mkdocs-material ] )) ]; postBuild = '' wrapProgram $out/bin/mkdocs \ --add-flags 'serve' \ --add-flags '--config-file' \ --add-flags 'docs/mkdocs.yml' ''; }; in { type = "app"; program = "${server}/bin/mkdocs"; }; # nix run .#deploy-docs # --------------------- # ドキュメントをビルドしてデプロイをする。 # リポジトリルートから実行する必要がある。 # "docs/" で Tofu を実行して環境をセットアップしていないと失敗する。 deploy-docs = { type = "app"; program = pkgs.lib.getExe ( pkgs.writeShellApplication { name = "deploy-docs"; text = '' CF_DIST_ID=$(tofu -chdir=docs output -json | jq -r ".cloudfront_distribution_id.value") S3_BUCKET_NAME=$(tofu -chdir=docs output -json | jq -r ".s3_bucket_name.value") rclone sync \ ${packages.docs} \ ":s3:$S3_BUCKET_NAME" \ --s3-provider=AWS \ --s3-env-auth \ --s3-region="$AWS_DEFAULT_REGION" \ --checksum aws cloudfront create-invalidation \ --distribution-id "$CF_DIST_ID" --paths '/*' ''; runtimeInputs = with pkgs; [ packages.docs # Tool for building, changing, and versioning infrastructure # https://opentofu.org/ opentofu # Unified tool to manage your AWS services # https://aws.amazon.com/cli/ awscli2 # Lightweight and flexible command-line JSON processor # https://jqlang.github.io/jq/ jq # Command line program to sync files and directories to and from major cloud storage # https://rclone.org/ rclone ]; } ); # nix run .#deploy-docs # --------------------- # ドキュメントをビルドしてデプロイをする。 # リポジトリルートから実行する必要がある。 # "docs/" で Tofu を実行して環境をセットアップしていないと失敗する。 deploy-docs = deploy "docs"; # nix run .#deploy-demo # --------------------- # デモをビルドしてデプロイをする。 # リポジトリルートから実行する必要がある。 # "demo/" で Tofu を実行して環境をセットアップしていないと失敗する。 deploy-demo = deploy "demo"; tf = { type = "app"; program = pkgs.lib.getExe pkgs.opentofu; }; }; }; devShell = pkgs.mkShell { packages =
-