fix: cleanup flake and repo
This commit is contained in:
parent
17d708eb7a
commit
9a5256e8f0
7 changed files with 197 additions and 530 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -10,6 +10,7 @@
|
|||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
*.har
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
|
|
|
|||
32
README.md
32
README.md
|
|
@ -4,6 +4,8 @@ Personal site for Jet Pham.
|
|||
|
||||
The site is a small Vite app with a terminal-style UI, ANSI-rendered text, and a WebGL2 Conway's Game of Life background.
|
||||
|
||||
It also ships as a Nix flake with a reusable NixOS module for serving the static frontend and the Q+A API on a host.
|
||||
|
||||
## Features
|
||||
|
||||
- ASCII/ANSI-inspired visual style with the IBM VGA font
|
||||
|
|
@ -53,9 +55,39 @@ npm run build
|
|||
## Structure
|
||||
|
||||
```text
|
||||
api/ Q+A backend
|
||||
module.nix NixOS module
|
||||
src/ frontend app
|
||||
```
|
||||
|
||||
## NixOS module
|
||||
|
||||
Import the module from the flake and point it at the host-managed secret files you want to use.
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.website.url = "github:jetpham/website";
|
||||
|
||||
outputs = { self, nixpkgs, website, ... }: {
|
||||
nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
modules = [
|
||||
website.nixosModules.default
|
||||
({ config, ... }: {
|
||||
services.jetpham-website = {
|
||||
enable = true;
|
||||
domain = "jetpham.com";
|
||||
webhookSecretFile = config.age.secrets.webhook-secret.path;
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Optional Tor support is configured by setting `services.jetpham-website.tor.enable = true;` and providing the three onion key file paths.
|
||||
|
||||
## Notes
|
||||
|
||||
- The homepage and Q+A page are the intended public pages.
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
$ bun run lint && tsc --noEmit
|
||||
$ eslint .
|
||||
121
flake.lock
generated
121
flake.lock
generated
|
|
@ -1,53 +1,8 @@
|
|||
{
|
||||
"nodes": {
|
||||
"agenix": {
|
||||
"inputs": {
|
||||
"darwin": "darwin",
|
||||
"home-manager": "home-manager",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1770165109,
|
||||
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744478979,
|
||||
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"ref": "master",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
|
|
@ -63,27 +18,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1745494811,
|
||||
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1774386573,
|
||||
|
|
@ -100,46 +34,10 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1744536153,
|
||||
"narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774581174,
|
||||
"narHash": "sha256-258qgkMkYPkJ9qpIg63Wk8GoIbVjszkGGPU1wbVHYTk=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "a313afc75b85fc77ac154bf0e62c36f68361fd0b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
|
|
@ -156,21 +54,6 @@
|
|||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
|
|
|||
93
flake.nix
93
flake.nix
|
|
@ -2,93 +2,38 @@
|
|||
description = "Jet Pham's personal website";
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
agenix.url = "github:ryantm/agenix";
|
||||
agenix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
flake-utils,
|
||||
agenix,
|
||||
}:
|
||||
(flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
overlays = [ (import rust-overlay) ];
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
agenixPkg = agenix.packages.${system}.default;
|
||||
rustToolchain = pkgs.rust-bin.selectLatestNightlyWith (
|
||||
toolchain:
|
||||
toolchain.default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
targets = [ "wasm32-unknown-unknown" ];
|
||||
}
|
||||
);
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
cargo = rustToolchain;
|
||||
rustc = rustToolchain;
|
||||
};
|
||||
|
||||
cgol-wasm = rustPlatform.buildRustPackage {
|
||||
pname = "cgol-wasm";
|
||||
version = "0.1.0";
|
||||
src = ./cgol;
|
||||
cargoLock.lockFile = ./cgol/Cargo.lock;
|
||||
doCheck = false;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.wasm-bindgen-cli
|
||||
pkgs.binaryen
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
lib = pkgs.lib;
|
||||
websiteSrc = lib.fileset.toSource {
|
||||
root = ./.;
|
||||
fileset = lib.fileset.unions [
|
||||
./index.html
|
||||
./package-lock.json
|
||||
./package.json
|
||||
./public
|
||||
./src
|
||||
./tsconfig.json
|
||||
./vite-plugin-ansi.ts
|
||||
./vite.config.ts
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
cargo build --release --frozen --target wasm32-unknown-unknown
|
||||
wasm-bindgen --target web --out-dir pkg target/wasm32-unknown-unknown/release/cgol.wasm
|
||||
wasm-opt pkg/cgol_bg.wasm -o pkg/cgol_bg.wasm -O4 \
|
||||
--enable-bulk-memory --enable-nontrapping-float-to-int \
|
||||
--enable-sign-ext --low-memory-unused --converge
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out
|
||||
cp pkg/cgol_bg.wasm $out/
|
||||
cp pkg/cgol.js $out/
|
||||
cp pkg/cgol.d.ts $out/
|
||||
cp pkg/cgol_bg.wasm.d.ts $out/ 2>/dev/null || true
|
||||
cat > $out/package.json <<'EOF'
|
||||
{
|
||||
"name": "cgol",
|
||||
"type": "module",
|
||||
"version": "0.1.0",
|
||||
"files": ["cgol_bg.wasm", "cgol.js", "cgol.d.ts"],
|
||||
"main": "cgol.js",
|
||||
"types": "cgol.d.ts",
|
||||
"sideEffects": ["./snippets/*"]
|
||||
}
|
||||
EOF
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
|
||||
# Stage 2: Build the website with npm
|
||||
website = pkgs.buildNpmPackage {
|
||||
pname = "jet-website";
|
||||
version = "0.1.0";
|
||||
src = pkgs.lib.cleanSource ./.;
|
||||
npmDepsHash = "sha256-O4ZUSYyVWOxP15saIadsaZuRO47Y0AvsL4pwvo5b76U=";
|
||||
|
||||
# Inject the Nix-built WASM before npm install resolves file: dep
|
||||
postPatch = ''
|
||||
mkdir -p cgol/pkg
|
||||
cp -r ${cgol-wasm}/* cgol/pkg/
|
||||
'';
|
||||
src = websiteSrc;
|
||||
npmDepsHash = "sha256-UDz4tXNvEa8uiDDGg16K9JbNeQZR3BsVNKtuOgcyurQ=";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
|
@ -110,7 +55,6 @@
|
|||
{
|
||||
packages = {
|
||||
default = website;
|
||||
cgol-wasm = cgol-wasm;
|
||||
inherit qa-api;
|
||||
};
|
||||
devShells.default = pkgs.mkShell {
|
||||
|
|
@ -119,12 +63,11 @@
|
|||
git
|
||||
curl
|
||||
openssl
|
||||
agenixPkg
|
||||
typescript-language-server
|
||||
rust-analyzer
|
||||
rustc
|
||||
cargo
|
||||
pkg-config
|
||||
wasm-pack
|
||||
binaryen
|
||||
rustToolchain
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
218
module.nix
218
module.nix
|
|
@ -1,27 +1,118 @@
|
|||
self:
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.jetpham-website;
|
||||
package = self.packages.x86_64-linux.default;
|
||||
qaApi = self.packages.x86_64-linux.qa-api;
|
||||
webhookSecretPath =
|
||||
if cfg.webhookSecretFile != null then
|
||||
cfg.webhookSecretFile
|
||||
else
|
||||
config.age.secrets.webhook-secret.path;
|
||||
package = cfg.package;
|
||||
qaApi = cfg.apiPackage;
|
||||
apiListen = "${cfg.apiListenAddress}:${toString cfg.apiListenPort}";
|
||||
caddyCommonConfig = ''
|
||||
header Cross-Origin-Opener-Policy "same-origin"
|
||||
header Cross-Origin-Embedder-Policy "require-corp"
|
||||
|
||||
handle /api/* {
|
||||
reverse_proxy ${apiListen}
|
||||
}
|
||||
|
||||
handle /qa/rss.xml {
|
||||
reverse_proxy ${apiListen}
|
||||
}
|
||||
|
||||
handle {
|
||||
root * ${package}
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
${cfg.caddy.extraConfig}
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.services.jetpham-website = {
|
||||
enable = lib.mkEnableOption "Jet Pham's personal website";
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = self.packages.${pkgs.system}.default;
|
||||
defaultText = lib.literalExpression "self.packages.${pkgs.system}.default";
|
||||
description = "Static site package served by Caddy.";
|
||||
};
|
||||
|
||||
apiPackage = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = self.packages.${pkgs.system}.qa-api;
|
||||
defaultText = lib.literalExpression "self.packages.${pkgs.system}.qa-api";
|
||||
description = "Q&A API package run by systemd.";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "jetpham.com";
|
||||
description = "Domain to serve the website on.";
|
||||
};
|
||||
|
||||
tor.enable = lib.mkEnableOption "Tor hidden service for the website";
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Open HTTP and HTTPS ports when Caddy is enabled.";
|
||||
};
|
||||
|
||||
apiListenAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "Address for the local Q&A API listener.";
|
||||
};
|
||||
|
||||
apiListenPort = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 3003;
|
||||
description = "Port for the local Q&A API listener.";
|
||||
};
|
||||
|
||||
caddy.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Serve the static site and reverse proxy the API through Caddy.";
|
||||
};
|
||||
|
||||
caddy.extraConfig = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = "Extra Caddy directives appended inside the virtual host block.";
|
||||
};
|
||||
|
||||
tor = {
|
||||
enable = lib.mkEnableOption "Tor hidden service for the website";
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8888;
|
||||
description = "Local Caddy port exposed through the onion service.";
|
||||
};
|
||||
|
||||
onionSecretKeyFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "Path to the Tor hidden service secret key file.";
|
||||
};
|
||||
|
||||
onionPublicKeyFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "Path to the Tor hidden service public key file.";
|
||||
};
|
||||
|
||||
onionHostnameFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "Path to the Tor hidden service hostname file.";
|
||||
};
|
||||
};
|
||||
|
||||
qaNotifyEmail = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
|
|
@ -42,36 +133,31 @@ in
|
|||
};
|
||||
|
||||
webhookSecretFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
type = lib.types.path;
|
||||
description = "File containing the WEBHOOK_SECRET for MTA Hook authentication.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
age.secrets.webhook-secret = lib.mkIf (cfg.webhookSecretFile == null) {
|
||||
file = "${self}/secrets/webhook-secret.age";
|
||||
mode = "0400";
|
||||
};
|
||||
assertions = [
|
||||
{
|
||||
assertion =
|
||||
!cfg.tor.enable
|
||||
|| (
|
||||
cfg.tor.onionSecretKeyFile != null
|
||||
&& cfg.tor.onionPublicKeyFile != null
|
||||
&& cfg.tor.onionHostnameFile != null
|
||||
);
|
||||
message = "services.jetpham-website.tor requires onionSecretKeyFile, onionPublicKeyFile, and onionHostnameFile.";
|
||||
}
|
||||
];
|
||||
|
||||
age.secrets.tor-onion-secret-key = lib.mkIf cfg.tor.enable {
|
||||
file = "${self}/secrets/tor-onion-secret-key.age";
|
||||
owner = "tor";
|
||||
group = "tor";
|
||||
mode = "0400";
|
||||
};
|
||||
age.secrets.tor-onion-public-key = lib.mkIf cfg.tor.enable {
|
||||
file = "${self}/secrets/tor-onion-public-key.age";
|
||||
owner = "tor";
|
||||
group = "tor";
|
||||
mode = "0444";
|
||||
};
|
||||
age.secrets.tor-onion-hostname = lib.mkIf cfg.tor.enable {
|
||||
file = "${self}/secrets/tor-onion-hostname.age";
|
||||
owner = "tor";
|
||||
group = "tor";
|
||||
mode = "0444";
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = lib.mkIf (cfg.caddy.enable && cfg.openFirewall) [
|
||||
80
|
||||
443
|
||||
];
|
||||
|
||||
services.caddy.enable = cfg.caddy.enable;
|
||||
|
||||
services.tor = lib.mkIf cfg.tor.enable {
|
||||
enable = true;
|
||||
|
|
@ -81,7 +167,7 @@ in
|
|||
port = 80;
|
||||
target = {
|
||||
addr = "127.0.0.1";
|
||||
port = 8888;
|
||||
port = cfg.tor.port;
|
||||
};
|
||||
}
|
||||
];
|
||||
|
|
@ -90,39 +176,45 @@ in
|
|||
|
||||
systemd.services.tor-onion-keys = lib.mkIf cfg.tor.enable {
|
||||
description = "Copy Tor onion keys into place";
|
||||
after = [ "agenix.service" ];
|
||||
before = [ "tor.service" ];
|
||||
wantedBy = [ "tor.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
dir="/var/lib/tor/onion/jetpham-website"
|
||||
mkdir -p "$dir"
|
||||
cp ${config.age.secrets.tor-onion-secret-key.path} "$dir/hs_ed25519_secret_key"
|
||||
cp ${config.age.secrets.tor-onion-public-key.path} "$dir/hs_ed25519_public_key"
|
||||
cp ${config.age.secrets.tor-onion-hostname.path} "$dir/hostname"
|
||||
cp ${cfg.tor.onionSecretKeyFile} "$dir/hs_ed25519_secret_key"
|
||||
cp ${cfg.tor.onionPublicKeyFile} "$dir/hs_ed25519_public_key"
|
||||
cp ${cfg.tor.onionHostnameFile} "$dir/hostname"
|
||||
chown -R tor:tor "$dir"
|
||||
chmod 700 "$dir"
|
||||
chmod 400 "$dir/hs_ed25519_secret_key"
|
||||
chmod 444 "$dir/hs_ed25519_public_key" "$dir/hostname"
|
||||
'';
|
||||
};
|
||||
# Q&A API systemd service
|
||||
|
||||
systemd.services.jetpham-qa-api = {
|
||||
description = "Jet Pham Q&A API";
|
||||
after = [ "network.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = "jetpham-qa";
|
||||
WorkingDirectory = "/var/lib/jetpham-qa";
|
||||
Environment = [
|
||||
"QA_DB_PATH=/var/lib/jetpham-qa/qa.db"
|
||||
"QA_NOTIFY_EMAIL=${cfg.qaNotifyEmail}"
|
||||
"QA_MAIL_DOMAIN=${cfg.qaMailDomain}"
|
||||
"QA_REPLY_DOMAIN=${cfg.qaReplyDomain}"
|
||||
];
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectHome = true;
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = [ "/var/lib/jetpham-qa" ];
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
LoadCredential = "webhook-secret:${webhookSecretPath}";
|
||||
LoadCredential = "webhook-secret:${cfg.webhookSecretFile}";
|
||||
};
|
||||
script = ''
|
||||
if [ ! -s "$CREDENTIALS_DIRECTORY/webhook-secret" ]; then
|
||||
|
|
@ -131,50 +223,20 @@ in
|
|||
fi
|
||||
|
||||
export WEBHOOK_SECRET="$(cat "$CREDENTIALS_DIRECTORY/webhook-secret")"
|
||||
exec ${qaApi}/bin/jetpham-qa-api
|
||||
exec ${lib.getExe qaApi}
|
||||
'';
|
||||
};
|
||||
|
||||
services.caddy.virtualHosts.${cfg.domain} = {
|
||||
extraConfig = ''
|
||||
header Cross-Origin-Opener-Policy "same-origin"
|
||||
header Cross-Origin-Embedder-Policy "require-corp"
|
||||
|
||||
handle /api/* {
|
||||
reverse_proxy 127.0.0.1:3003
|
||||
}
|
||||
|
||||
handle /qa/rss.xml {
|
||||
reverse_proxy 127.0.0.1:3003
|
||||
}
|
||||
|
||||
handle {
|
||||
root * ${package}
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
'';
|
||||
services.caddy.virtualHosts.${cfg.domain} = lib.mkIf cfg.caddy.enable {
|
||||
extraConfig = caddyCommonConfig;
|
||||
};
|
||||
|
||||
services.caddy.virtualHosts."http://:8888" = lib.mkIf cfg.tor.enable {
|
||||
services.caddy.virtualHosts."http://:${toString cfg.tor.port}" =
|
||||
lib.mkIf (cfg.caddy.enable && cfg.tor.enable)
|
||||
{
|
||||
extraConfig = ''
|
||||
bind 127.0.0.1
|
||||
header Cross-Origin-Opener-Policy "same-origin"
|
||||
header Cross-Origin-Embedder-Policy "require-corp"
|
||||
|
||||
handle /api/* {
|
||||
reverse_proxy 127.0.0.1:3003
|
||||
}
|
||||
|
||||
handle /qa/rss.xml {
|
||||
reverse_proxy 127.0.0.1:3003
|
||||
}
|
||||
|
||||
handle {
|
||||
root * ${package}
|
||||
try_files {path} /index.html
|
||||
file_server
|
||||
}
|
||||
${caddyCommonConfig}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
|
|||
252
tor.har
252
tor.har
|
|
@ -1,252 +0,0 @@
|
|||
{
|
||||
"log": {
|
||||
"version": "1.2",
|
||||
"creator": {
|
||||
"name": "Firefox",
|
||||
"version": "140.8.0"
|
||||
},
|
||||
"browser": {
|
||||
"name": "Firefox",
|
||||
"version": "140.8.0"
|
||||
},
|
||||
"pages": [
|
||||
{
|
||||
"id": "page_1",
|
||||
"pageTimings": {
|
||||
"onContentLoad": 1578,
|
||||
"onLoad": 1578
|
||||
},
|
||||
"startedDateTime": "2026-03-26T20:03:41.824-07:00",
|
||||
"title": "http://jet7tetd43snvjx3ng5jrhuwm2yhyp76tjtct5mtofg64apokcgq7fqd.onion/"
|
||||
}
|
||||
],
|
||||
"entries": [
|
||||
{
|
||||
"startedDateTime": "2026-03-26T20:03:41.824-07:00",
|
||||
"request": {
|
||||
"bodySize": 0,
|
||||
"method": "GET",
|
||||
"url": "http://jet7tetd43snvjx3ng5jrhuwm2yhyp76tjtct5mtofg64apokcgq7fqd.onion/",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"headers": [
|
||||
{
|
||||
"name": "Host",
|
||||
"value": "jet7tetd43snvjx3ng5jrhuwm2yhyp76tjtct5mtofg64apokcgq7fqd.onion"
|
||||
},
|
||||
{
|
||||
"name": "User-Agent",
|
||||
"value": "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0"
|
||||
},
|
||||
{
|
||||
"name": "Accept",
|
||||
"value": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Language",
|
||||
"value": "en-US,en;q=0.5"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Encoding",
|
||||
"value": "gzip, deflate, br, zstd"
|
||||
},
|
||||
{
|
||||
"name": "Sec-GPC",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "Connection",
|
||||
"value": "keep-alive"
|
||||
},
|
||||
{
|
||||
"name": "Upgrade-Insecure-Requests",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "Sec-Fetch-Dest",
|
||||
"value": "document"
|
||||
},
|
||||
{
|
||||
"name": "Sec-Fetch-Mode",
|
||||
"value": "navigate"
|
||||
},
|
||||
{
|
||||
"name": "Sec-Fetch-Site",
|
||||
"value": "none"
|
||||
},
|
||||
{
|
||||
"name": "Priority",
|
||||
"value": "u=0, i"
|
||||
},
|
||||
{
|
||||
"name": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-cache"
|
||||
}
|
||||
],
|
||||
"cookies": [],
|
||||
"queryString": [],
|
||||
"headersSize": 521
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"statusText": "OK",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"headers": [
|
||||
{
|
||||
"name": "Server",
|
||||
"value": "Caddy"
|
||||
},
|
||||
{
|
||||
"name": "Date",
|
||||
"value": "Fri, 27 Mar 2026 03:03:43 GMT"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
"cookies": [],
|
||||
"content": {
|
||||
"mimeType": "text/plain",
|
||||
"size": 0,
|
||||
"text": ""
|
||||
},
|
||||
"redirectURL": "",
|
||||
"headersSize": 90,
|
||||
"bodySize": 90
|
||||
},
|
||||
"cache": {},
|
||||
"timings": {
|
||||
"blocked": 894,
|
||||
"dns": 0,
|
||||
"connect": 894,
|
||||
"ssl": 0,
|
||||
"send": 0,
|
||||
"wait": 617,
|
||||
"receive": 0
|
||||
},
|
||||
"time": 2405,
|
||||
"_securityState": "insecure",
|
||||
"serverIPAddress": "0.0.0.0",
|
||||
"connection": "80",
|
||||
"pageref": "page_1"
|
||||
},
|
||||
{
|
||||
"startedDateTime": "2026-03-26T20:03:43.440-07:00",
|
||||
"request": {
|
||||
"bodySize": 0,
|
||||
"method": "GET",
|
||||
"url": "http://jet7tetd43snvjx3ng5jrhuwm2yhyp76tjtct5mtofg64apokcgq7fqd.onion/favicon.ico",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"headers": [
|
||||
{
|
||||
"name": "Host",
|
||||
"value": "jet7tetd43snvjx3ng5jrhuwm2yhyp76tjtct5mtofg64apokcgq7fqd.onion"
|
||||
},
|
||||
{
|
||||
"name": "User-Agent",
|
||||
"value": "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0"
|
||||
},
|
||||
{
|
||||
"name": "Accept",
|
||||
"value": "image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Language",
|
||||
"value": "en-US,en;q=0.5"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Encoding",
|
||||
"value": "gzip, deflate, br, zstd"
|
||||
},
|
||||
{
|
||||
"name": "Referer",
|
||||
"value": "http://jet7tetd43snvjx3ng5jrhuwm2yhyp76tjtct5mtofg64apokcgq7fqd.onion/"
|
||||
},
|
||||
{
|
||||
"name": "Sec-GPC",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "Connection",
|
||||
"value": "keep-alive"
|
||||
},
|
||||
{
|
||||
"name": "Sec-Fetch-Dest",
|
||||
"value": "image"
|
||||
},
|
||||
{
|
||||
"name": "Sec-Fetch-Mode",
|
||||
"value": "no-cors"
|
||||
},
|
||||
{
|
||||
"name": "Sec-Fetch-Site",
|
||||
"value": "same-origin"
|
||||
},
|
||||
{
|
||||
"name": "Priority",
|
||||
"value": "u=6"
|
||||
},
|
||||
{
|
||||
"name": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-cache"
|
||||
}
|
||||
],
|
||||
"cookies": [],
|
||||
"queryString": [],
|
||||
"headersSize": 589
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"statusText": "OK",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"headers": [
|
||||
{
|
||||
"name": "Server",
|
||||
"value": "Caddy"
|
||||
},
|
||||
{
|
||||
"name": "Date",
|
||||
"value": "Fri, 27 Mar 2026 03:03:43 GMT"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
"cookies": [],
|
||||
"content": {
|
||||
"mimeType": "text/plain",
|
||||
"size": 0,
|
||||
"text": ""
|
||||
},
|
||||
"redirectURL": "",
|
||||
"headersSize": 90,
|
||||
"bodySize": 90
|
||||
},
|
||||
"cache": {},
|
||||
"timings": {
|
||||
"blocked": 0,
|
||||
"dns": 0,
|
||||
"connect": 0,
|
||||
"ssl": 0,
|
||||
"send": 0,
|
||||
"wait": 604,
|
||||
"receive": 0
|
||||
},
|
||||
"time": 604,
|
||||
"_securityState": "insecure",
|
||||
"serverIPAddress": "0.0.0.0",
|
||||
"connection": "80",
|
||||
"pageref": "page_1"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue