diff --git a/Dockerfile b/Dockerfile index 4925b1a..ee19f3f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,24 @@ -FROM node:lts as build +FROM node:lts as web # Reduce npm log spam and colour during install within Docker ENV NPM_CONFIG_LOGLEVEL=warn ENV NPM_CONFIG_COLOR=false WORKDIR /home/node/app -COPY --chown=node:node . /home/node/app/ +COPY --chown=node:node web /home/node/app/ RUN npm install RUN npm run typecheck RUN npm run build -FROM nginx:stable as production -WORKDIR /home/node/app -# Copy nginx config -COPY --chown=nobody:nogroup nginx.conf /etc/nginx/conf.d/default.conf -# Copy what we've installed/built from production -COPY --chown=nobody:nogroup --from=build /home/node/app/build /usr/share/nginx/html/ +FROM denoland/deno:1.42.3 as build-server -# Caching directory -RUN mkdir -p /var/run/nginx-cache && chown nobody:nogroup /var/run/nginx-cache +WORKDIR /app + +COPY server /app +COPY --from=web /home/node/app/build /app/web + +RUN deno cache server.ts + +USER deno +CMD ["run", "--unstable-kv", "--allow-net", "--allow-read", "server.ts"] diff --git a/justfile b/justfile new file mode 100644 index 0000000..eb0838d --- /dev/null +++ b/justfile @@ -0,0 +1,5 @@ +build: + docker build -t code.tjo.space/tjo-space/tjo.space:latest . + +run: + docker run -p 8080:8080 code.tjo.space/tjo-space/tjo.space:latest diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 28ee3f0..0000000 --- a/nginx.conf +++ /dev/null @@ -1,55 +0,0 @@ -proxy_cache_path /var/run/nginx-cache/jscache levels=1:2 keys_zone=jscache:100m inactive=30d use_temp_path=off max_size=100m; - -server { - listen 80 default_server; - server_name _; - resolver 9.9.9.9 1.1.1.1 8.8.8.8; - - location / { - root /usr/share/nginx/html; - index index.html index.htm; - } - - location /.well-known/ { - root /usr/share/nginx/html; - default_type application/json; - add_header Access-Control-Allow-Origin *; - } - - # Plausible Analytics - # https://plausible.io/docs/proxy/guides/nginx - set $plausible_script_url https://plausible.io/js/script.js; # Change this if you use a different variant of the script - set $plausible_event_url https://plausible.io/api/event; - location = /js/script.js { - proxy_pass $plausible_script_url; - proxy_set_header Host plausible.io; - - # Tiny, negligible performance improvement. Very optional. - proxy_buffering on; - - # Cache the script for 6 hours, as long as plausible.io returns a valid response - proxy_cache jscache; - proxy_cache_valid 200 6h; - proxy_cache_use_stale updating error timeout invalid_header http_500; - - # Optional. Adds a header to tell if you got a cache hit or miss - add_header X-Cache $upstream_cache_status; - } - location = /api/event { - proxy_pass $plausible_event_url; - proxy_set_header Host plausible.io; - proxy_buffering on; - proxy_http_version 1.1; - - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - } - - # redirect server error pages to the static page /50x.html - # - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root /usr/share/nginx/html; - } -} diff --git a/docs/architecture.md b/server/deno.json similarity index 100% rename from docs/architecture.md rename to server/deno.json diff --git a/server/server.ts b/server/server.ts new file mode 100644 index 0000000..87585c4 --- /dev/null +++ b/server/server.ts @@ -0,0 +1,92 @@ +import { Hono } from "https://deno.land/x/hono@v4.2.5/mod.ts"; +import { serveStatic } from "https://deno.land/x/hono@v4.2.5/middleware.ts"; + +const cache = await Deno.openKv(); +const app = new Hono(); + +// .well-known for matrix +app.get("/.well-known/matrix/client", (c) => + c.json({ + "m.homeserver": { + base_url: "https://matrix.chat.tjo.space", + }, + }), +); +app.get("/.well-known/matrix/server", (c) => + c.json({ + "m.server": "matrix.chat.tjo.space:443", + }), +); +app.get("/.well-known/matrix/support", (c) => + c.json({ + contacts: [ + { + matrix_id: "@tine:tjo.space", + email_address: "tine@tjo.space", + role: "m.role.admin", + }, + ], + }), +); + +// .well-known for webfinger - tailscale +app.get("/.well-known/webfinger", (c) => { + console.log(c.req.query); + + const resource = c.req.query("resource"); + if (!resource) { + c.status(400); + return c.json({ error: "Missing resource query parameter" }); + } + + const [scheme] = resource.split(":"); + if (scheme !== "acct") { + c.status(400); + return c.json({ error: "Only acct scheme is supported" }); + } + + return c.json({ + subject: resource, + links: [ + { + rel: "http://schemas.openid.net/specs/connect/1.0/issuer", + href: `https://id.tjo.space/application/o/tailscalecom/`, + }, + ], + }); +}); + +// Serve plausible analytics +app.get("/js/script.js", async (c) => { + c.header("Content-Type", "text/javascript"); + + // Check if we have the script cached + const cachedScript = await cache.get(["plausible", "script"]); + if (cachedScript.value) { + return c.body(cachedScript.value); + } + + const response = await fetch("https://plausible.io/js/plausible.js"); + const script = await response.text(); + + // Cache for 24 hours if we got the script + if (response.status === 200) { + await cache.set(["plausible", "script"], script, { + expireIn: 1000 * 60 * 60 * 24, + }); + } + + return c.body(script); +}); +app.get("/api/event", (c) => { + const request = new Request(c.req.raw); + request.headers.delete("Cookie"); + request.headers.set("X-Forwarded-For", c.req.header("host") || ""); + return fetch("https://plausible.io/api/event", request); +}); + +// Serve website +app.use("*", serveStatic({ root: "./web" })); + +// Start server +Deno.serve({ port: 8080, hostname: "0.0.0.0" }, app.fetch); diff --git a/.gitignore b/web/.gitignore similarity index 100% rename from .gitignore rename to web/.gitignore diff --git a/babel.config.js b/web/babel.config.js similarity index 100% rename from babel.config.js rename to web/babel.config.js diff --git a/blog/2019-05-28-first-blog-post.md b/web/blog/2019-05-28-first-blog-post.md similarity index 100% rename from blog/2019-05-28-first-blog-post.md rename to web/blog/2019-05-28-first-blog-post.md diff --git a/blog/authors.yml b/web/blog/authors.yml similarity index 100% rename from blog/authors.yml rename to web/blog/authors.yml diff --git a/docs/hardware.md b/web/docs/architecture.md similarity index 100% rename from docs/hardware.md rename to web/docs/architecture.md diff --git a/docs/home.md b/web/docs/hardware.md similarity index 100% rename from docs/home.md rename to web/docs/hardware.md diff --git a/static/.nojekyll b/web/docs/home.md similarity index 100% rename from static/.nojekyll rename to web/docs/home.md diff --git a/docusaurus.config.js b/web/docusaurus.config.js similarity index 100% rename from docusaurus.config.js rename to web/docusaurus.config.js diff --git a/i18n/en/code.json b/web/i18n/en/code.json similarity index 100% rename from i18n/en/code.json rename to web/i18n/en/code.json diff --git a/i18n/en/docusaurus-plugin-content-blog/options.json b/web/i18n/en/docusaurus-plugin-content-blog/options.json similarity index 100% rename from i18n/en/docusaurus-plugin-content-blog/options.json rename to web/i18n/en/docusaurus-plugin-content-blog/options.json diff --git a/i18n/en/docusaurus-plugin-content-docs/current.json b/web/i18n/en/docusaurus-plugin-content-docs/current.json similarity index 100% rename from i18n/en/docusaurus-plugin-content-docs/current.json rename to web/i18n/en/docusaurus-plugin-content-docs/current.json diff --git a/i18n/en/docusaurus-theme-classic/footer.json b/web/i18n/en/docusaurus-theme-classic/footer.json similarity index 100% rename from i18n/en/docusaurus-theme-classic/footer.json rename to web/i18n/en/docusaurus-theme-classic/footer.json diff --git a/i18n/en/docusaurus-theme-classic/navbar.json b/web/i18n/en/docusaurus-theme-classic/navbar.json similarity index 100% rename from i18n/en/docusaurus-theme-classic/navbar.json rename to web/i18n/en/docusaurus-theme-classic/navbar.json diff --git a/i18n/sl/code.json b/web/i18n/sl/code.json similarity index 100% rename from i18n/sl/code.json rename to web/i18n/sl/code.json diff --git a/i18n/sl/docusaurus-theme-classic/footer.json b/web/i18n/sl/docusaurus-theme-classic/footer.json similarity index 100% rename from i18n/sl/docusaurus-theme-classic/footer.json rename to web/i18n/sl/docusaurus-theme-classic/footer.json diff --git a/i18n/sl/docusaurus-theme-classic/navbar.json b/web/i18n/sl/docusaurus-theme-classic/navbar.json similarity index 100% rename from i18n/sl/docusaurus-theme-classic/navbar.json rename to web/i18n/sl/docusaurus-theme-classic/navbar.json diff --git a/package-lock.json b/web/package-lock.json similarity index 100% rename from package-lock.json rename to web/package-lock.json diff --git a/package.json b/web/package.json similarity index 94% rename from package.json rename to web/package.json index 835512a..e9792e2 100644 --- a/package.json +++ b/web/package.json @@ -12,8 +12,7 @@ "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", - "typecheck": "tsc", - "build:docker": "docker build -t tjo-space ." + "typecheck": "tsc" }, "dependencies": { "@docusaurus/core": "2.4.1", diff --git a/sidebars.js b/web/sidebars.js similarity index 100% rename from sidebars.js rename to web/sidebars.js diff --git a/src/components/HomepageFeatures/index.tsx b/web/src/components/HomepageFeatures/index.tsx similarity index 100% rename from src/components/HomepageFeatures/index.tsx rename to web/src/components/HomepageFeatures/index.tsx diff --git a/src/components/HomepageFeatures/styles.module.css b/web/src/components/HomepageFeatures/styles.module.css similarity index 100% rename from src/components/HomepageFeatures/styles.module.css rename to web/src/components/HomepageFeatures/styles.module.css diff --git a/src/components/NavbarItems/CustomStatusNavbarItem.tsx b/web/src/components/NavbarItems/CustomStatusNavbarItem.tsx similarity index 100% rename from src/components/NavbarItems/CustomStatusNavbarItem.tsx rename to web/src/components/NavbarItems/CustomStatusNavbarItem.tsx diff --git a/src/components/NavbarItems/ServicesNavbarItem.tsx b/web/src/components/NavbarItems/ServicesNavbarItem.tsx similarity index 100% rename from src/components/NavbarItems/ServicesNavbarItem.tsx rename to web/src/components/NavbarItems/ServicesNavbarItem.tsx diff --git a/src/css/custom.css b/web/src/css/custom.css similarity index 100% rename from src/css/custom.css rename to web/src/css/custom.css diff --git a/src/pages/index.module.css b/web/src/pages/index.module.css similarity index 100% rename from src/pages/index.module.css rename to web/src/pages/index.module.css diff --git a/src/pages/index.tsx b/web/src/pages/index.tsx similarity index 100% rename from src/pages/index.tsx rename to web/src/pages/index.tsx diff --git a/src/pages/request-access.md b/web/src/pages/request-access.md similarity index 100% rename from src/pages/request-access.md rename to web/src/pages/request-access.md diff --git a/src/services.tsx b/web/src/services.tsx similarity index 100% rename from src/services.tsx rename to web/src/services.tsx diff --git a/src/theme/NavbarItem/ComponentTypes.js b/web/src/theme/NavbarItem/ComponentTypes.js similarity index 100% rename from src/theme/NavbarItem/ComponentTypes.js rename to web/src/theme/NavbarItem/ComponentTypes.js diff --git a/web/static/.nojekyll b/web/static/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/static/.well-known/matrix/client b/web/static/.well-known/matrix/client similarity index 100% rename from static/.well-known/matrix/client rename to web/static/.well-known/matrix/client diff --git a/static/.well-known/matrix/server b/web/static/.well-known/matrix/server similarity index 100% rename from static/.well-known/matrix/server rename to web/static/.well-known/matrix/server diff --git a/static/.well-known/matrix/support b/web/static/.well-known/matrix/support similarity index 100% rename from static/.well-known/matrix/support rename to web/static/.well-known/matrix/support diff --git a/static/.well-known/webfinger b/web/static/.well-known/webfinger similarity index 100% rename from static/.well-known/webfinger rename to web/static/.well-known/webfinger diff --git a/static/img/icon.svg b/web/static/img/icon.svg similarity index 100% rename from static/img/icon.svg rename to web/static/img/icon.svg diff --git a/static/img/logo-dark.svg b/web/static/img/logo-dark.svg similarity index 100% rename from static/img/logo-dark.svg rename to web/static/img/logo-dark.svg diff --git a/static/img/logo-light.svg b/web/static/img/logo-light.svg similarity index 100% rename from static/img/logo-light.svg rename to web/static/img/logo-light.svg diff --git a/static/img/logo.svg b/web/static/img/logo.svg similarity index 100% rename from static/img/logo.svg rename to web/static/img/logo.svg diff --git a/static/img/undraw_chat_tjo_space.svg b/web/static/img/undraw_chat_tjo_space.svg similarity index 100% rename from static/img/undraw_chat_tjo_space.svg rename to web/static/img/undraw_chat_tjo_space.svg diff --git a/static/img/undraw_cloud_tjo_space.svg b/web/static/img/undraw_cloud_tjo_space.svg similarity index 100% rename from static/img/undraw_cloud_tjo_space.svg rename to web/static/img/undraw_cloud_tjo_space.svg diff --git a/static/img/undraw_code_tjo_space.svg b/web/static/img/undraw_code_tjo_space.svg similarity index 100% rename from static/img/undraw_code_tjo_space.svg rename to web/static/img/undraw_code_tjo_space.svg diff --git a/static/img/undraw_mail_tjo_space.svg b/web/static/img/undraw_mail_tjo_space.svg similarity index 100% rename from static/img/undraw_mail_tjo_space.svg rename to web/static/img/undraw_mail_tjo_space.svg diff --git a/static/img/undraw_media_tjo_space.svg b/web/static/img/undraw_media_tjo_space.svg similarity index 100% rename from static/img/undraw_media_tjo_space.svg rename to web/static/img/undraw_media_tjo_space.svg diff --git a/static/img/undraw_paperless_tjo_space.svg b/web/static/img/undraw_paperless_tjo_space.svg similarity index 100% rename from static/img/undraw_paperless_tjo_space.svg rename to web/static/img/undraw_paperless_tjo_space.svg diff --git a/static/img/undraw_rss_tjo_space.svg b/web/static/img/undraw_rss_tjo_space.svg similarity index 100% rename from static/img/undraw_rss_tjo_space.svg rename to web/static/img/undraw_rss_tjo_space.svg diff --git a/static/img/undraw_search_tjo_space.svg b/web/static/img/undraw_search_tjo_space.svg similarity index 100% rename from static/img/undraw_search_tjo_space.svg rename to web/static/img/undraw_search_tjo_space.svg diff --git a/static/img/undraw_send_tjo_space.svg b/web/static/img/undraw_send_tjo_space.svg similarity index 100% rename from static/img/undraw_send_tjo_space.svg rename to web/static/img/undraw_send_tjo_space.svg diff --git a/static/img/undraw_vault_tjo_space.svg b/web/static/img/undraw_vault_tjo_space.svg similarity index 100% rename from static/img/undraw_vault_tjo_space.svg rename to web/static/img/undraw_vault_tjo_space.svg diff --git a/static/img/undraw_vpn_tjo_space.svg b/web/static/img/undraw_vpn_tjo_space.svg similarity index 100% rename from static/img/undraw_vpn_tjo_space.svg rename to web/static/img/undraw_vpn_tjo_space.svg diff --git a/static/img/undraw_yt_tjo_space.svg b/web/static/img/undraw_yt_tjo_space.svg similarity index 100% rename from static/img/undraw_yt_tjo_space.svg rename to web/static/img/undraw_yt_tjo_space.svg diff --git a/tsconfig.json b/web/tsconfig.json similarity index 100% rename from tsconfig.json rename to web/tsconfig.json