about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.build.yml49
-rw-r--r--.gitignore2
-rw-r--r--flake.nix3
-rw-r--r--internal/builder/builder.go2
-rw-r--r--netlify.toml29
-rw-r--r--nix/default.nix2
-rw-r--r--static/.well-known/webfinger1
-rw-r--r--vercel.json59
8 files changed, 95 insertions, 52 deletions
diff --git a/.build.yml b/.build.yml
deleted file mode 100644
index 8554649..0000000
--- a/.build.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-image: nixos/unstable
-sources:
-  - https://git.sr.ht/~alanpearce/website
-secrets:
-  - ce767f7f-3ac0-43fb-b225-fccbc9cdfaba
-  - 5a04c7f9-bba4-40ab-b54c-a2daae2989e8
-  - d0a0edd6-1d39-4959-b346-71f64af36a73
-environment:
-  NIX_CONFIG: |
-    experimental-features = nix-command flakes
-    max-jobs = 4
-    extra-substituters = https://binarycache.alanpearce.eu
-    extra-trusted-public-keys = binarycache.alanpearce.eu:ZwqO3XMuajPictjwih8OY2+RXnOKpjZEZFHJjGSxAI4=
-  FLY_APP: alanpearce-eu
-packages:
-  - nixos.just
-  - nixos.skopeo
-  - nixos.flyctl
-  - nixos.sentry-cli
-  - nixos.flake-checker
-  - nixos.hut
-tasks:
-  - check: |
-      cd website
-      flake-checker
-
-  - build: |
-      echo "VerifyHostKeyDNS yes" >> ~/.ssh/config
-      cd website
-      nix build .#website
-      nix build .#checks.x86_64-linux.hyperlink
-      just docker-image-fly
-      nix copy --substitute-on-destination \
-        --to ssh://nixremote@linde.alanpearce.eu \
-        .
-
-  - deploy: |
-      if [[ "$GIT_REF" != "refs/heads/main" ]]
-      then
-        exit
-      fi
-      cd website
-      sudo mkdir /etc/containers
-      echo '{"default":[{"type":"insecureAcceptAnything"}]}' | sudo tee /etc/containers/policy.json > /dev/null
-      fly auth docker
-      just docker-image-fly \
-        print-docker-tag \
-        push-to-registry \
-        deploy
diff --git a/.gitignore b/.gitignore
index 6c9ee49..88424a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,5 @@ go.work
 /website/
 /.pre-commit-config.yaml
 /result
+.vercel
+/.netlify/
diff --git a/flake.nix b/flake.nix
index 1f605d5..949ccf4 100644
--- a/flake.nix
+++ b/flake.nix
@@ -45,6 +45,7 @@
                 go-tools
                 gomod2nix.packages.${system}.default
                 gci
+                nodePackages.vercel
                 netlify-cli
                 sentry-cli
               ] ++ commonShellPackages;
@@ -53,7 +54,7 @@
           checks = rec {
             default = hyperlink;
             hyperlink = pkgs.runCommandLocal "hyperlink" { } ''
-              ${pkgs.hyperlink}/bin/hyperlink ${packages.website}/website/public
+              ${pkgs.hyperlink}/bin/hyperlink ${packages.website}/public
               touch $out
             '';
             pre-commit-check = pre-commit-hooks.lib.${system}.run {
diff --git a/internal/builder/builder.go b/internal/builder/builder.go
index 55e68d2..7c69af0 100644
--- a/internal/builder/builder.go
+++ b/internal/builder/builder.go
@@ -172,7 +172,7 @@ func build(outDir string, config config.Config) error {
 	if err != nil {
 		return errors.WithMessage(err, "could not render 404 page")
 	}
-	if err := outputToFile(notFound, privateDir, "404.html"); err != nil {
+	if err := outputToFile(notFound, publicDir, "404.html"); err != nil {
 		return err
 	}
 
diff --git a/netlify.toml b/netlify.toml
new file mode 100644
index 0000000..d733f41
--- /dev/null
+++ b/netlify.toml
@@ -0,0 +1,29 @@
+[build]
+  publish = "website/public"
+
+[[headers]]
+  for = "/*"
+  [headers.values]
+    x-content-type-options = "nosniff"
+    x-xss-protection = "1; mode=block"
+    referrer-policy = "strict-origin-when-cross-origin"
+    strict-transport-security = "max-age=63072000; includeSubDomains; preload"
+    cache-control = '''
+      max-age=300,
+      s-maxage=86400,
+      state-while-revalidate
+    '''
+    content-security-policy = '''
+      default-src 'none';
+      img-src 'self' https://gc.zgo.at;
+      object-src 'none';
+      script-src 'self' https://gc.zgo.at;
+      style-src
+      'sha256-a4TPKWHB0aSu7cV10GthTEySTJ0w4r0bw6Q8JsNYMbk='
+      'sha256-gyxzfgCOxeAAL8URUdaW2nHYDOr9bzbwFjgSqi7D+8U=';
+      form-action 'none';
+      base-uri 'self';
+      connect-src https://alanpearce-eu.goatcounter.com/count;
+      frame-ancestors 'https://kagi.com';
+      require-trusted-types-for "'script'"
+'''
diff --git a/nix/default.nix b/nix/default.nix
index 62caed6..095b3f7 100644
--- a/nix/default.nix
+++ b/nix/default.nix
@@ -58,7 +58,7 @@ with pkgs; rec {
         ];
       };
     } ''
-    ${builder}/bin/build -s $src -d $out/website
+    ${builder}/bin/build -s $src -d $out
   '';
   server = buildGoApplication {
     pname = "server";
diff --git a/static/.well-known/webfinger b/static/.well-known/webfinger
new file mode 100644
index 0000000..b2e3d7d
--- /dev/null
+++ b/static/.well-known/webfinger
@@ -0,0 +1 @@
+{"subject":"acct:alan@alanpearce.eu","links":[{"rel":"http://openid.net/specs/connect/1.0/issuer","href":"https://id.alanpearce.eu/"}]}
\ No newline at end of file
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..aebaf54
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,59 @@
+{
+  "$schema": "https://openapi.vercel.sh/vercel.json",
+  "buildCommand": null,
+  "framework": null,
+  "outputDirectory": "website/public",
+  "cleanUrls": false,
+  "trailingSlash": false,
+  "redirects": [
+    {
+      "source": "/.well-known/openid-configuration",
+      "destination": "https://id.alanpearce.eu/.well-known/openid-configuration",
+      "permanent": false
+    }
+  ],
+  "headers": [
+    {
+      "source": "/.well-known/webfinger",
+      "headers": [
+        {
+          "key": "Content-Type",
+          "value": "application/jrd+json"
+        }
+      ]
+    },
+    {
+      "source": "/(.*)",
+      "headers": [
+        {
+          "key": "X-Frame-Options",
+          "value": "DENY"
+        },
+        {
+          "key": "X-Content-Type-Options",
+          "value": "nosniff"
+        },
+        {
+          "key": "X-XSS-Protection",
+          "value": "1; mode=block"
+        },
+        {
+          "key": "Referrer-Policy",
+          "value": "strict-origin-when-cross-origin"
+        },
+        {
+          "key": "Strict-Transport-Security",
+          "value": "max-age=63072000; includeSubDomains; preload"
+        },
+        {
+          "key": "Content-Security-Policy",
+          "value": "default-src 'none'; img-src 'self' https://gc.zgo.at; object-src 'none'; script-src https://gc.zgo.at; style-src 'sha256-a4TPKWHB0aSu7cV10GthTEySTJ0w4r0bw6Q8JsNYMbk=' 'sha256-gyxzfgCOxeAAL8URUdaW2nHYDOr9bzbwFjgSqi7D+8U='; form-action 'none'; base-uri 'self'; frame-ancestors https://kagi.com; connect-src https://alanpearce-eu.goatcounter.com/count"
+        },
+        {
+          "key": "Cache-Control",
+          "value": "max-age=14400, s-maxage=86400, state-while-revalidate"
+        }
+      ]
+    }
+  ]
+}