From b9dc8650531077ee2fa8cb60d798f469c221aedf Mon Sep 17 00:00:00 2001 From: thepra Date: Thu, 1 Oct 2026 08:09:45 +0200 Subject: [PATCH] net10, pointed at PrivaPub, and deployed as a static site to decepub.thepra.dev The project referenced ../SocialPub/SocialPub/SocialPub.ClientModels, a path that has not existed since the server became PrivaPub; it references ../SocialPub/PrivaPub.ClientModels now, and CI clones SocialPub beside it. Retargeted to net10.0 with the Microsoft packages at 10.0.9. BlazorDownloadFileFast moves to 1.0.0.1 because 0.2.0 used IJSUnmarshalledRuntime, which .NET 9 removed. The Visual Studio bundler and web compiler packages are gone; the bundle they produced, css/style.min.css, is committed and stays the stylesheet, and its stale .gz is deleted because .NET's static-asset compression writes that path itself. AppConfiguration.ApiBaseAddress (https://privapub.thepra.dev) is the API client's base address; the template's placeholder OIDC section and the Toolbelt.Blazor.HotKeys script tag, whose package is not referenced, are removed. The vhost sends noindex while the feed shows the prototype's mock posts. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB --- .gitea/workflows/build.yml | 26 ++++++++++ .gitea/workflows/deploy.yml | 72 ++++++++++++++++++++++++++ Extensions/ExtensionMethods.cs | 4 +- Models/AppConfiguration.cs | 3 +- Models/PageSettings.cs | 4 +- Program.cs | 5 +- Services/CoalescingStringLocalizer.cs | 4 +- decePubClient.csproj | 23 ++++---- deploy/max/setup.sh | 37 +++++++++++++ deploy/nginx/decepub-headers.conf | 5 ++ deploy/nginx/decepub.thepra.dev.conf | 56 ++++++++++++++++++++ global.json | 7 +++ wwwroot/appsettings.json | 14 +---- wwwroot/css/style.min.css.gz | Bin 28371 -> 0 bytes wwwroot/index.html | 1 - 15 files changed, 226 insertions(+), 35 deletions(-) create mode 100644 .gitea/workflows/build.yml create mode 100644 .gitea/workflows/deploy.yml create mode 100755 deploy/max/setup.sh create mode 100644 deploy/nginx/decepub-headers.conf create mode 100644 deploy/nginx/decepub.thepra.dev.conf create mode 100644 global.json delete mode 100644 wwwroot/css/style.min.css.gz diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..0b2d814 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,26 @@ +name: Build + +on: + push: + branches: [master] + pull_request: + +jobs: + build: + name: Build + runs-on: build + steps: + - uses: actions/checkout@v4 + with: + path: decePubClient + + - name: Fetch PrivaPub's client models beside it + env: + READ_TOKEN: ${{ secrets.THEPRA_READ_TOKEN }} + run: | + rm -rf SocialPub + git -c http.extraHeader="Authorization: token $READ_TOKEN" clone -q --depth 1 \ + https://git.thepra.dev/thepra/SocialPub.git SocialPub + + - name: Build + run: dotnet build decePubClient/decePubClient.csproj -c Release diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..eb7f667 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,72 @@ +name: Deploy + +on: + workflow_dispatch: + push: + tags: + - 'v*' + +env: + WEB_ROOT: /var/www/decepub.thepra.dev + BACKUPS: /var/backups/decepub.thepra.dev + PUBLIC_URL: https://decepub.thepra.dev + +jobs: + site: + name: decepub.thepra.dev + runs-on: build + steps: + - uses: actions/checkout@v4 + with: + path: decePubClient + + - name: Fetch PrivaPub's client models beside it + env: + READ_TOKEN: ${{ secrets.THEPRA_READ_TOKEN }} + run: | + rm -rf SocialPub + git -c http.extraHeader="Authorization: token $READ_TOKEN" clone -q --depth 1 \ + https://git.thepra.dev/thepra/SocialPub.git SocialPub + + - name: Resolve the build identity + run: | + echo "BUILD_COMMIT=$(echo "$GITHUB_SHA" | cut -c1-8)" >> "$GITHUB_ENV" + echo "BUILD_REF=${GITHUB_REF_NAME:-master}" >> "$GITHUB_ENV" + echo "BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_ENV" + + - name: Publish + run: | + rm -rf "$GITHUB_WORKSPACE/publish" + dotnet publish decePubClient/decePubClient.csproj -c Release -o "$GITHUB_WORKSPACE/publish" + printf '{"commit":"%s","buildRef":"%s","builtAt":"%s"}\n' "$BUILD_COMMIT" "$BUILD_REF" "$BUILD_TIME" \ + > "$GITHUB_WORKSPACE/publish/wwwroot/build.json" + + - name: Assert the publish actually produced a site + run: | + W="$GITHUB_WORKSPACE/publish/wwwroot" + for f in index.html appsettings.json build.json _framework/blazor.webassembly.js css/style.min.css; do + [ -e "$W/$f" ] || { echo "::error::publish output is missing $f"; exit 1; } + done + ls "$W/_framework" | grep -q '\.wasm$' || { echo "::error::no .wasm in _framework"; exit 1; } + echo "publish OK, $(du -sh "$W" | cut -f1)" + + - name: Snapshot the live directory + run: | + STAMP=$(date +%Y%m%d-%H%M%S) + rsync -a "$WEB_ROOT/" "$BACKUPS/site-$STAMP/" + echo "SNAPSHOT=$BACKUPS/site-$STAMP" >> "$GITHUB_ENV" + ls -1dt "$BACKUPS"/site-* 2>/dev/null | tail -n +4 | xargs -r rm -rf || true + + - name: Sync + run: rsync -a --delete "$GITHUB_WORKSPACE/publish/wwwroot/" "$WEB_ROOT/" + + - name: Verify what is being served, roll back on failure + run: | + served=$(curl -fsS "$PUBLIC_URL/build.json" | python3 -c "import json,sys; print(json.load(sys.stdin).get('commit',''))" || true) + code=$(curl -s -o /dev/null -w '%{http_code}' "$PUBLIC_URL/some/client/route") + if [ "$served" != "$BUILD_COMMIT" ] || [ "$code" != "200" ]; then + echo "::error::served build '$served' (expected '$BUILD_COMMIT'), fallback route answered $code - rolling back" + rsync -a --delete "$SNAPSHOT/" "$WEB_ROOT/" + exit 1 + fi + echo "::notice::serving $served" diff --git a/Extensions/ExtensionMethods.cs b/Extensions/ExtensionMethods.cs index da33399..07d1a21 100644 --- a/Extensions/ExtensionMethods.cs +++ b/Extensions/ExtensionMethods.cs @@ -1,4 +1,4 @@ -using Blazored.LocalStorage; +using Blazored.LocalStorage; using collAnon.Client.Services; @@ -11,7 +11,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; -using SocialPub.ClientModels; +using PrivaPub.ClientModels; using System.Collections.Specialized; using System.ComponentModel; diff --git a/Models/AppConfiguration.cs b/Models/AppConfiguration.cs index db7e396..727aac5 100644 --- a/Models/AppConfiguration.cs +++ b/Models/AppConfiguration.cs @@ -1,6 +1,7 @@ -namespace decePubClient.Models; +namespace decePubClient.Models; public class AppConfiguration { public string Version { get; set; } + public string ApiBaseAddress { get; set; } } \ No newline at end of file diff --git a/Models/PageSettings.cs b/Models/PageSettings.cs index 12c540b..f318d7c 100644 --- a/Models/PageSettings.cs +++ b/Models/PageSettings.cs @@ -1,5 +1,5 @@ - -using SocialPub.ClientModels.Resources; + +using PrivaPub.ClientModels.Resources; using System.ComponentModel.DataAnnotations; diff --git a/Program.cs b/Program.cs index 2cce5c6..348c28e 100644 --- a/Program.cs +++ b/Program.cs @@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Authentication; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using SocialPub.ClientModels; +using PrivaPub.ClientModels; using collAnon.Client.Services; var builder = WebAssemblyHostBuilder.CreateDefault(args); @@ -51,9 +51,10 @@ builder.Services.AddOptions() .AddLogging(lb => lb.SetMinimumLevel(LogLevel.Debug)) .AddIndexedDb(); +var apiBaseAddress = builder.Configuration["AppConfiguration:ApiBaseAddress"]; builder.Services.AddHttpClient("default", client => { - client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress); + client.BaseAddress = new Uri(string.IsNullOrEmpty(apiBaseAddress) ? builder.HostEnvironment.BaseAddress : apiBaseAddress.TrimEnd('/') + "/"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); }); diff --git a/Services/CoalescingStringLocalizer.cs b/Services/CoalescingStringLocalizer.cs index bbde6d1..1370585 100644 --- a/Services/CoalescingStringLocalizer.cs +++ b/Services/CoalescingStringLocalizer.cs @@ -1,8 +1,8 @@ -using decePubClient.Resources; +using decePubClient.Resources; using Microsoft.Extensions.Localization; -using SocialPub.ClientModels.Resources; +using PrivaPub.ClientModels.Resources; namespace collAnon.Client.Services { diff --git a/decePubClient.csproj b/decePubClient.csproj index 404da06..f5151fa 100644 --- a/decePubClient.csproj +++ b/decePubClient.csproj @@ -1,7 +1,7 @@ - + - net7.0 + net10.0 disable enable service-worker-assets.js @@ -10,18 +10,15 @@ - - - - - - - - - + + + + + + - + @@ -77,7 +74,7 @@ - + diff --git a/deploy/max/setup.sh b/deploy/max/setup.sh new file mode 100755 index 0000000..71a832c --- /dev/null +++ b/deploy/max/setup.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# One-time root setup on Max for decePubClient at decepub.thepra.dev (static files, no unit). Idempotent. +# rsync -a -e $MAX/ssh.sh deploy/ root@nuvola.xyz:/root/decepub-deploy/ +# $MAX/run.sh bash /root/decepub-deploy/max/setup.sh +set -euo pipefail +SRC="${1:-/root/decepub-deploy}" +HOST=decepub.thepra.dev +RUNNER=build-runner +ACME=/root/.acme.sh/acme.sh + +echo "== directories" +install -d -o "$RUNNER" -g www-data -m 755 /var/www/$HOST +install -d -o "$RUNNER" -g "$RUNNER" -m 750 /var/backups/$HOST + +echo "== nginx snippet and bootstrap vhost" +install -m 644 "$SRC/nginx/decepub-headers.conf" /etc/nginx/snippets/decepub-headers.conf +if [ -f /root/.acme.sh/${HOST}_ecc/fullchain.cer ]; then + install -m 644 "$SRC/nginx/$HOST.conf" /etc/nginx/sites-available/$HOST.conf +else + awk '/^server \{/{n++} n==1' "$SRC/nginx/$HOST.conf" > /etc/nginx/sites-available/$HOST.conf +fi +ln -sf /etc/nginx/sites-available/$HOST.conf /etc/nginx/sites-enabled/$HOST.conf +nginx -t +systemctl reload nginx + +echo "== certificate" +if [ -f /root/.acme.sh/${HOST}_ecc/fullchain.cer ]; then + echo "$HOST: certificate present" +else + $ACME --issue --server letsencrypt -d $HOST -w /var/www/acme --renew-hook "systemctl reload nginx" +fi + +echo "== full vhost" +install -m 644 "$SRC/nginx/$HOST.conf" /etc/nginx/sites-available/$HOST.conf +nginx -t +systemctl reload nginx +echo "setup complete" diff --git a/deploy/nginx/decepub-headers.conf b/deploy/nginx/decepub-headers.conf new file mode 100644 index 0000000..ae227f4 --- /dev/null +++ b/deploy/nginx/decepub-headers.conf @@ -0,0 +1,5 @@ +add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; +add_header X-Content-Type-Options "nosniff" always; +add_header Referrer-Policy "strict-origin-when-cross-origin" always; +add_header X-Frame-Options "SAMEORIGIN" always; +add_header X-Robots-Tag "noindex, nofollow" always; diff --git a/deploy/nginx/decepub.thepra.dev.conf b/deploy/nginx/decepub.thepra.dev.conf new file mode 100644 index 0000000..4712a10 --- /dev/null +++ b/deploy/nginx/decepub.thepra.dev.conf @@ -0,0 +1,56 @@ +server { + listen 80; + listen [::]:80; + server_name decepub.thepra.dev; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/acme; + default_type "text/plain"; + } + + location / { + return 301 https://$host$request_uri; + } +} + +server { + listen 443 ssl; + listen 8444 ssl proxy_protocol; + listen [::]:443 ssl; + server_name decepub.thepra.dev; + http2 on; + + include /etc/nginx/ssl.conf; + ssl_certificate /root/.acme.sh/decepub.thepra.dev_ecc/fullchain.cer; + ssl_certificate_key /root/.acme.sh/decepub.thepra.dev_ecc/decepub.thepra.dev.key; + include /etc/nginx/snippets/decepub-headers.conf; + + access_log /var/log/nginx/decepub.thepra.dev.access.log; + error_log /var/log/nginx/decepub.thepra.dev.error.log; + + root /var/www/decepub.thepra.dev; + index index.html; + gzip_static on; + open_file_cache off; + + location ^~ /.well-known/acme-challenge/ { + root /var/www/acme; + default_type "text/plain"; + } + + location = /index.html { expires -1; } + location = /build.json { expires -1; } + location = /appsettings.json { expires -1; } + location = /service-worker.js { expires -1; } + location = /service-worker-assets.js { expires -1; } + + location ^~ /_framework/ { + expires 1h; + try_files $uri =404; + } + + location / { + expires -1; + try_files $uri $uri/ /index.html; + } +} diff --git a/global.json b/global.json new file mode 100644 index 0000000..d46d21e --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "10.0.100", + "rollForward": "latestFeature", + "allowPrerelease": false + } +} diff --git a/wwwroot/appsettings.json b/wwwroot/appsettings.json index 64df850..d4507fe 100644 --- a/wwwroot/appsettings.json +++ b/wwwroot/appsettings.json @@ -1,16 +1,6 @@ { - "Local": { - "Authority": "https://openidconnect.net", - "ClientId": "1234.locahost", - "RedirectUri": "", - "MetadataUrl": "", - "PostLogoutRedirectUri": "", - "ResponseType": "", - "ResponseMode": "", - "AdditionalProviderParameters": [], - "DefaultScopes": [] - }, "AppConfiguration": { - "Version": "0.1" + "Version": "0.1", + "ApiBaseAddress": "https://privapub.thepra.dev" } } diff --git a/wwwroot/css/style.min.css.gz b/wwwroot/css/style.min.css.gz deleted file mode 100644 index 9aae4c81a3fb96265d940b90b304b832a0fa4a76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28371 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 diff --git a/wwwroot/index.html b/wwwroot/index.html index 1884d42..9bdc092 100644 --- a/wwwroot/index.html +++ b/wwwroot/index.html @@ -22,7 +22,6 @@ -