mirror of
https://github.com/thegeneralist01/config.git
synced 2026-05-30 08:37:01 +02:00
Compare commits
7 commits
4f4995cf75
...
6e1e8c1b8f
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e1e8c1b8f | |||
| 8659b0fba3 | |||
| 3f7345d214 | |||
| 563c1a6a7b | |||
| 8c73ef4505 | |||
| fdcb7ed8c4 | |||
| 5119867eaa |
18 changed files with 137 additions and 395 deletions
105
flake.lock
generated
105
flake.lock
generated
|
|
@ -44,25 +44,6 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"calorie-tracker": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1771309191,
|
|
||||||
"narHash": "sha256-Y83E1JrimzUPQ1a7FpOd9dIQFJFucbV4lYPI7ik3Piw=",
|
|
||||||
"ref": "refs/heads/master",
|
|
||||||
"rev": "8cf458087edb5f2ff7e3563d4bb6e489c3264d1d",
|
|
||||||
"revCount": 2,
|
|
||||||
"type": "git",
|
|
||||||
"url": "file:///home/thegeneralist/calorie-tracker"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "file:///home/thegeneralist/calorie-tracker"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fenix": {
|
"fenix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
@ -100,6 +81,22 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-compat_2": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747046372,
|
||||||
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"systems": "systems_2"
|
"systems": "systems_2"
|
||||||
|
|
@ -157,7 +154,7 @@
|
||||||
"ghostty": {
|
"ghostty": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
"flake-utils": "flake-utils_2",
|
"flake-utils": "flake-utils",
|
||||||
"nixpkgs-stable": "nixpkgs-stable",
|
"nixpkgs-stable": "nixpkgs-stable",
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable",
|
"nixpkgs-unstable": "nixpkgs-unstable",
|
||||||
"zig": "zig",
|
"zig": "zig",
|
||||||
|
|
@ -177,6 +174,28 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"helium": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat_2",
|
||||||
|
"flake-utils": "flake-utils_2",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1772006043,
|
||||||
|
"narHash": "sha256-TZfnQqC2kvP6eDlDrKjbClijnpCPEcoCiopdy3M3ib4=",
|
||||||
|
"owner": "AlvaroParker",
|
||||||
|
"repo": "helium-nix",
|
||||||
|
"rev": "2bcf84a8e83984e3b7054d29d8890d7ae903c91f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "AlvaroParker",
|
||||||
|
"repo": "helium-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"home-manager": {
|
"home-manager": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
@ -270,11 +289,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771008912,
|
"lastModified": 1755186698,
|
||||||
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
|
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a82ccc39b39b621151d6732718e3e250109076fa",
|
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -317,22 +336,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
|
||||||
"lastModified": 1755186698,
|
|
||||||
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_3": {
|
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1769789167,
|
"lastModified": 1769789167,
|
||||||
"narHash": "sha256-kKB3bqYJU5nzYeIROI82Ef9VtTbu4uA3YydSk/Bioa8=",
|
"narHash": "sha256-kKB3bqYJU5nzYeIROI82Ef9VtTbu4uA3YydSk/Bioa8=",
|
||||||
|
|
@ -351,34 +354,34 @@
|
||||||
"readlater-bot": {
|
"readlater-bot": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils_3",
|
"flake-utils": "flake-utils_3",
|
||||||
"nixpkgs": "nixpkgs_3"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1771250778,
|
"lastModified": 1772524468,
|
||||||
"narHash": "sha256-lmWwzbuMer8vjGXh37p79dSctaFNjTBW6Cp0T5R+ZiE=",
|
"narHash": "sha256-h/NmNoiBVPzxm/yDhl+Z8PaFJeDtPz8Ef7NQeZgn8TE=",
|
||||||
"ref": "refs/heads/master",
|
"owner": "thegeneralist01",
|
||||||
"rev": "181c03915b93d21c5d15a1375d3bc621b2992700",
|
"repo": "bookkeeper",
|
||||||
"revCount": 17,
|
"rev": "e1afcc51485ed9b80211a2c48a3e93ef4d6b35f5",
|
||||||
"type": "git",
|
"type": "github"
|
||||||
"url": "file:///home/thegeneralist/infofeeder-bot"
|
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"type": "git",
|
"owner": "thegeneralist01",
|
||||||
"url": "file:///home/thegeneralist/infofeeder-bot"
|
"repo": "bookkeeper",
|
||||||
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"agenix": "agenix",
|
"agenix": "agenix",
|
||||||
"calorie-tracker": "calorie-tracker",
|
|
||||||
"fenix": "fenix",
|
"fenix": "fenix",
|
||||||
"ghostty": "ghostty",
|
"ghostty": "ghostty",
|
||||||
|
"helium": "helium",
|
||||||
"home-manager": "home-manager",
|
"home-manager": "home-manager",
|
||||||
"homebrew-cask": "homebrew-cask",
|
"homebrew-cask": "homebrew-cask",
|
||||||
"homebrew-core": "homebrew-core",
|
"homebrew-core": "homebrew-core",
|
||||||
"nix-darwin": "nix-darwin",
|
"nix-darwin": "nix-darwin",
|
||||||
"nix-homebrew": "nix-homebrew",
|
"nix-homebrew": "nix-homebrew",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs",
|
||||||
"readlater-bot": "readlater-bot"
|
"readlater-bot": "readlater-bot"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
10
flake.nix
10
flake.nix
|
|
@ -42,12 +42,14 @@
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
readlater-bot = {
|
helium = {
|
||||||
url = "git+file:///home/thegeneralist/infofeeder-bot";
|
# url = "github:FKouhai/helium2nix/main";
|
||||||
|
url = "github:AlvaroParker/helium-nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
calorie-tracker = {
|
readlater-bot = {
|
||||||
url = "git+file:///home/thegeneralist/calorie-tracker";
|
url = "github:thegeneralist01/bookkeeper";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,10 @@ in {
|
||||||
"internal.${domain}" = {
|
"internal.${domain}" = {
|
||||||
group = "acme";
|
group = "acme";
|
||||||
};
|
};
|
||||||
"archive.${domain}" = {
|
"plex.${domain}" = {
|
||||||
group = "acme";
|
group = "acme";
|
||||||
};
|
};
|
||||||
"crawler.${domain}" = {
|
"archive.${domain}" = {
|
||||||
group = "acme";
|
group = "acme";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
let
|
|
||||||
acmeDomain = "thegeneralist01.com";
|
|
||||||
domain = "crawler.${acmeDomain}";
|
|
||||||
|
|
||||||
ssl = {
|
|
||||||
forceSSL = true;
|
|
||||||
quic = true;
|
|
||||||
useACMEHost = domain;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
services.nginx.virtualHosts.${domain} = ssl // {
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
addr = "100.86.129.23";
|
|
||||||
port = 443;
|
|
||||||
ssl = true;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
addr = "100.86.129.23";
|
|
||||||
port = 80;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:8001";
|
|
||||||
recommendedProxySettings = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_set_header Upgrade $http_upgrade;
|
|
||||||
proxy_set_header Connection $connection_upgrade;
|
|
||||||
|
|
||||||
# tell nginx not to buffer the response. send it as it comes.
|
|
||||||
proxy_buffering off;
|
|
||||||
|
|
||||||
# give jellyfin plenty of time to transcode
|
|
||||||
proxy_read_timeout 3600s;
|
|
||||||
proxy_send_timeout 3600s;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -9,7 +9,7 @@ let
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
imports = [ ./archivebox.nix ./crawler-site.nix ];
|
imports = [ ./archivebox.nix ];
|
||||||
|
|
||||||
services.nginx.virtualHosts.${domain} = ssl // {
|
services.nginx.virtualHosts.${domain} = ssl // {
|
||||||
listen = [
|
listen = [
|
||||||
|
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
{ pkgs, inputs, ... }:
|
|
||||||
let
|
|
||||||
sourceDir = "${inputs.calorie-tracker}";
|
|
||||||
appDir = "/var/lib/calorie-tracker/app";
|
|
||||||
dataDir = "/var/lib/calorie-tracker";
|
|
||||||
port = 4322;
|
|
||||||
|
|
||||||
acmeDomain = "thegeneralist01.com";
|
|
||||||
domain = "calorie.${acmeDomain}";
|
|
||||||
|
|
||||||
ssl = {
|
|
||||||
forceSSL = true;
|
|
||||||
quic = true;
|
|
||||||
useACMEHost = acmeDomain;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
systemd.services.calorie-tracker = {
|
|
||||||
description = "Calorie Tracker";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
NODE_ENV = "production";
|
|
||||||
HOST = "127.0.0.1";
|
|
||||||
PORT = toString port;
|
|
||||||
DATABASE_URL = "file:${dataDir}/dev.db";
|
|
||||||
PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING = "1";
|
|
||||||
|
|
||||||
PRISMA_FMT_BINARY = "${pkgs.prisma-engines}/bin/prisma-fmt";
|
|
||||||
PRISMA_SCHEMA_ENGINE_BINARY = "${pkgs.prisma-engines}/bin/schema-engine";
|
|
||||||
PRISMA_QUERY_ENGINE_BINARY = "${pkgs.prisma-engines}/bin/query-engine";
|
|
||||||
PRISMA_QUERY_ENGINE_LIBRARY = "${pkgs.prisma-engines}/lib/libquery_engine.node";
|
|
||||||
};
|
|
||||||
|
|
||||||
path = with pkgs; [
|
|
||||||
bash
|
|
||||||
coreutils
|
|
||||||
gnused
|
|
||||||
nodejs_22
|
|
||||||
prisma
|
|
||||||
prisma-engines
|
|
||||||
rsync
|
|
||||||
sqlite
|
|
||||||
];
|
|
||||||
|
|
||||||
preStart = ''
|
|
||||||
mkdir -p ${appDir}
|
|
||||||
rsync -a --delete --exclude ".git" --exclude "node_modules" --exclude "dist" --exclude ".astro" ${sourceDir}/ ${appDir}/
|
|
||||||
chmod -R u+rwX ${appDir}
|
|
||||||
|
|
||||||
cd ${appDir}
|
|
||||||
|
|
||||||
if [ ! -f .env ]; then
|
|
||||||
cp .env.example .env
|
|
||||||
fi
|
|
||||||
|
|
||||||
sed -i 's#^DATABASE_URL=.*#DATABASE_URL="file:${dataDir}/dev.db"#' .env
|
|
||||||
|
|
||||||
if [ ! -d node_modules ] || [ ! -d node_modules/@astrojs/node ] || [ ! -d node_modules/server-destroy ] || [ ! -d node_modules/@vite-pwa/astro ] || [ ! -d node_modules/@astrojs/check ]; then
|
|
||||||
npm ci --include=dev --no-fund --no-audit
|
|
||||||
fi
|
|
||||||
|
|
||||||
sqlite3 "${dataDir}/dev.db" < ${./schema.sql}
|
|
||||||
|
|
||||||
npm run prisma:generate
|
|
||||||
rm -rf dist
|
|
||||||
npm run build
|
|
||||||
'';
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
User = "thegeneralist";
|
|
||||||
Group = "users";
|
|
||||||
StateDirectory = "calorie-tracker";
|
|
||||||
StateDirectoryMode = "0750";
|
|
||||||
# Keep working dir on the guaranteed StateDirectory path so preStart can
|
|
||||||
# create ${appDir} on first boot/deploy before ExecStart runs.
|
|
||||||
WorkingDirectory = dataDir;
|
|
||||||
ExecStart = "${pkgs.nodejs_22}/bin/node ${appDir}/dist/server/entry.mjs";
|
|
||||||
KillMode = "mixed";
|
|
||||||
Restart = "always";
|
|
||||||
RestartSec = 5;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# services.nginx.virtualHosts.${domain} = ssl // {
|
|
||||||
# locations."/" = {
|
|
||||||
# proxyPass = "http://127.0.0.1:${toString port}";
|
|
||||||
# proxyWebsockets = true;
|
|
||||||
# recommendedProxySettings = true;
|
|
||||||
# extraConfig = ''
|
|
||||||
# proxy_read_timeout 300s;
|
|
||||||
# proxy_send_timeout 300s;
|
|
||||||
# '';
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
}
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
||||||
PRAGMA foreign_keys = ON;
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "User" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"username" TEXT NOT NULL UNIQUE,
|
|
||||||
"email" TEXT NOT NULL UNIQUE,
|
|
||||||
"passwordHash" TEXT NOT NULL,
|
|
||||||
"isAdmin" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"emailVerifiedAt" DATETIME,
|
|
||||||
"locale" TEXT NOT NULL DEFAULT 'en',
|
|
||||||
"dayCutoffMinutes" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"weekStartsOn" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"scheduledDeletionAt" DATETIME,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "Session" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"tokenHash" TEXT NOT NULL UNIQUE,
|
|
||||||
"rememberDevice" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"lastActiveAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"expiresAt" DATETIME NOT NULL,
|
|
||||||
"recentAuthAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "Session_userId_idx" ON "Session"("userId");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "Goal" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"userId" TEXT NOT NULL UNIQUE,
|
|
||||||
"type" TEXT NOT NULL DEFAULT 'MAINTAIN_WEIGHT',
|
|
||||||
"calorieFormula" TEXT NOT NULL DEFAULT 'MIFFLIN_ST_JEOR',
|
|
||||||
"dailyCalorieTarget" INTEGER,
|
|
||||||
"proteinGramsTarget" INTEGER,
|
|
||||||
"carbsGramsTarget" INTEGER,
|
|
||||||
"fatGramsTarget" INTEGER,
|
|
||||||
"adaptiveSuggestions" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"requiresApproval" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "UserSettings" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"userId" TEXT NOT NULL UNIQUE,
|
|
||||||
"waterGoalLiters" REAL NOT NULL DEFAULT 2,
|
|
||||||
"useMetricDistance" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"precisionMode" TEXT NOT NULL DEFAULT 'BASIC',
|
|
||||||
"weekStartConfigurable" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"remindersEnabled" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"reminderQuietHoursStart" TEXT DEFAULT '22:00',
|
|
||||||
"reminderQuietHoursEnd" TEXT DEFAULT '07:00',
|
|
||||||
"pwaInstallPromptDismissed" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"pwaUpdateToastEnabled" INTEGER NOT NULL DEFAULT 1,
|
|
||||||
"aiPhotoEstimationEnabled" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"aiPhotoConsentAt" DATETIME,
|
|
||||||
"aiPhotoConsentPolicy" TEXT,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "Product" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"ownerUserId" TEXT,
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"brand" TEXT,
|
|
||||||
"barcode" TEXT,
|
|
||||||
"qrCode" TEXT,
|
|
||||||
"region" TEXT,
|
|
||||||
"packageSizeLabel" TEXT,
|
|
||||||
"servingSizeLabel" TEXT,
|
|
||||||
"calories" REAL,
|
|
||||||
"protein" REAL,
|
|
||||||
"carbs" REAL,
|
|
||||||
"fat" REAL,
|
|
||||||
"source" TEXT NOT NULL DEFAULT 'MANUAL',
|
|
||||||
"isAiEstimated" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"isGlobal" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"publicationStatus" TEXT NOT NULL DEFAULT 'LOCAL_ONLY',
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"publishedAt" DATETIME,
|
|
||||||
FOREIGN KEY ("ownerUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "Product_ownerUserId_idx" ON "Product"("ownerUserId");
|
|
||||||
CREATE INDEX IF NOT EXISTS "Product_isGlobal_publicationStatus_idx" ON "Product"("isGlobal", "publicationStatus");
|
|
||||||
CREATE INDEX IF NOT EXISTS "Product_barcode_brand_region_idx" ON "Product"("barcode", "brand", "region");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "ProductSubmission" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"productId" TEXT NOT NULL,
|
|
||||||
"submittedById" TEXT NOT NULL,
|
|
||||||
"reviewedById" TEXT,
|
|
||||||
"labelPhotoUrl" TEXT,
|
|
||||||
"status" TEXT NOT NULL DEFAULT 'PENDING',
|
|
||||||
"reason" TEXT,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"reviewedAt" DATETIME,
|
|
||||||
FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY ("submittedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY ("reviewedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "ProductSubmission_productId_status_idx" ON "ProductSubmission"("productId", "status");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "ProductContribution" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"productId" TEXT NOT NULL,
|
|
||||||
"contributorId" TEXT NOT NULL,
|
|
||||||
"payloadJson" TEXT NOT NULL,
|
|
||||||
"status" TEXT NOT NULL DEFAULT 'PENDING',
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"reviewedAt" DATETIME,
|
|
||||||
"reviewedById" TEXT,
|
|
||||||
FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY ("contributorId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "ProductContribution_productId_status_idx" ON "ProductContribution"("productId", "status");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "ModerationAuditLog" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"actorUserId" TEXT NOT NULL,
|
|
||||||
"targetType" TEXT NOT NULL,
|
|
||||||
"targetId" TEXT NOT NULL,
|
|
||||||
"action" TEXT NOT NULL,
|
|
||||||
"reason" TEXT,
|
|
||||||
"beforeJson" TEXT,
|
|
||||||
"afterJson" TEXT,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY ("actorUserId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "ModerationAuditLog_targetType_targetId_idx" ON "ModerationAuditLog"("targetType", "targetId");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "MealEntry" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
"productId" TEXT,
|
|
||||||
"mealType" TEXT NOT NULL,
|
|
||||||
"consumedAt" DATETIME NOT NULL,
|
|
||||||
"quantityValue" REAL NOT NULL,
|
|
||||||
"quantityUnit" TEXT NOT NULL,
|
|
||||||
"calories" REAL NOT NULL,
|
|
||||||
"protein" REAL NOT NULL,
|
|
||||||
"carbs" REAL NOT NULL,
|
|
||||||
"fat" REAL NOT NULL,
|
|
||||||
"snapshotJson" TEXT NOT NULL,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
|
||||||
FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE SET NULL ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "MealEntry_userId_consumedAt_idx" ON "MealEntry"("userId", "consumedAt");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "WaterEntry" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
"amountMl" INTEGER NOT NULL,
|
|
||||||
"consumedAt" DATETIME NOT NULL,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "WaterEntry_userId_consumedAt_idx" ON "WaterEntry"("userId", "consumedAt");
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS "ActivityEntry" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"method" TEXT NOT NULL,
|
|
||||||
"durationMinutes" INTEGER,
|
|
||||||
"distanceKm" REAL,
|
|
||||||
"intensity" REAL,
|
|
||||||
"caloriesBurned" REAL NOT NULL,
|
|
||||||
"startedAt" DATETIME NOT NULL,
|
|
||||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
||||||
);
|
|
||||||
CREATE INDEX IF NOT EXISTS "ActivityEntry_userId_startedAt_idx" ON "ActivityEntry"("userId", "startedAt");
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
./cache
|
./cache
|
||||||
./archive
|
./archive
|
||||||
./forgejo
|
./forgejo
|
||||||
./calorie-tracker
|
|
||||||
];
|
];
|
||||||
|
|
||||||
age.secrets.password.file = ./password.age;
|
age.secrets.password.file = ./password.age;
|
||||||
|
|
@ -109,6 +108,11 @@
|
||||||
repo_path = "/home/thegeneralist/obsidian";
|
repo_path = "/home/thegeneralist/obsidian";
|
||||||
token_file = config.age.secrets.readlaterBotSyncToken.path;
|
token_file = config.age.secrets.readlaterBotSyncToken.path;
|
||||||
};
|
};
|
||||||
|
sync_x = {
|
||||||
|
source_project_path = "/home/thegeneralist/bookkeeper/vendor/extract-x-bookmarks";
|
||||||
|
python_bin = "/home/thegeneralist/bookkeeper/vendor/extract-x-bookmarks/.venv/bin/python3";
|
||||||
|
work_dir = "/home/thegeneralist/bookkeeper/.sync-x-work";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{ pkgs, lib, ... }:
|
{ pkgs, lib, ... }:
|
||||||
let
|
let
|
||||||
subdomains = [ "internal" "archive" "crawler" "r" "b" "s" "p" "q" "cloud" ];
|
subdomains = [ "internal" "archive" "plex" ];
|
||||||
|
|
||||||
mainZoneFile = pkgs.writeText "thegeneralist01.zone" ''
|
mainZoneFile = pkgs.writeText "thegeneralist01.zone" ''
|
||||||
$ORIGIN thegeneralist01.com.
|
$ORIGIN thegeneralist01.com.
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,7 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
# fileSystems."/mnt/usb" = {
|
# fileSystems."/mnt/usb" = {
|
||||||
# device = "/dev/disk/by-uuid/AADEEA03DEE9C7A1";
|
# device = "/dev/disk/by-label/TURTLEBAT";
|
||||||
# fsType = "ntfs-3g";
|
|
||||||
# options = [
|
# options = [
|
||||||
# "rw"
|
# "rw"
|
||||||
# "noatime"
|
# "noatime"
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,38 @@ let
|
||||||
quic = true;
|
quic = true;
|
||||||
useACMEHost = domain;
|
useACMEHost = domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
plexDebUrl = "http://thegeneralist01.com/plexmediaserver_1.43.0.10492-121068a07_arm64.deb";
|
||||||
|
plexDebSha256 = "1fkh09b46q70kicjprxf0v507idhg2jh3pk97nhbxj1jagkhgck2";
|
||||||
|
plex = pkgs.stdenv.mkDerivation {
|
||||||
|
pname = "plexmediaserver";
|
||||||
|
version = "1.43.0.10492-121068a07";
|
||||||
|
|
||||||
|
src = pkgs.fetchurl {
|
||||||
|
url = plexDebUrl;
|
||||||
|
sha256 = plexDebSha256;
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkgs.dpkg ];
|
||||||
|
|
||||||
|
unpackPhase = ''
|
||||||
|
runHook preUnpack
|
||||||
|
dpkg-deb -x $src .
|
||||||
|
runHook postUnpack
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r usr/* $out/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
plex
|
|
||||||
];
|
|
||||||
|
|
||||||
services.plex = {
|
services.plex = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
package = plex;
|
||||||
# openFirewall = true;
|
# openFirewall = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,6 @@ in
|
||||||
"thegeneralist01.com" = "http://localhost:80";
|
"thegeneralist01.com" = "http://localhost:80";
|
||||||
"www.thegeneralist01.com" = "http://localhost:80";
|
"www.thegeneralist01.com" = "http://localhost:80";
|
||||||
"cache.thegeneralist01.com" = "http://localhost:80";
|
"cache.thegeneralist01.com" = "http://localhost:80";
|
||||||
"calorie.thegeneralist01.com" = "http://localhost:4322";
|
|
||||||
"git.thegeneralist01.com" = "http://localhost:3000";
|
"git.thegeneralist01.com" = "http://localhost:3000";
|
||||||
};
|
};
|
||||||
default = "http_status:404";
|
default = "http_status:404";
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
settings = {
|
settings = {
|
||||||
# theme = "tokyonight";
|
# theme = "tokyonight";
|
||||||
theme = config.theme.ghosttyTheme;
|
theme = config.theme.ghosttyTheme;
|
||||||
|
# theme = if config.onLinux then "GruvboxDarkHard" else "Gruvbox Dark Hard";
|
||||||
font-family = "Berkeley Mono";
|
font-family = "Berkeley Mono";
|
||||||
font-size = 16;
|
font-size = 16;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ in {
|
||||||
yq-go
|
yq-go
|
||||||
eza
|
eza
|
||||||
fzf
|
fzf
|
||||||
|
fd
|
||||||
gh
|
gh
|
||||||
fastfetch
|
fastfetch
|
||||||
carapace
|
carapace
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ lib, ... }: {
|
{ lib, config, ... }: {
|
||||||
options.theme = {
|
options.theme = {
|
||||||
batTheme = lib.mkOption {
|
batTheme = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
ghosttyTheme = lib.mkOption {
|
ghosttyTheme = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "Gruvbox Dark Hard";
|
default = if config.onLinux then "GruvboxDarkHard" else "Gruvbox Dark Hard";
|
||||||
description = "Theme name for Ghostty.";
|
description = "Theme name for Ghostty.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ pkgs, lib, config, ...}: let
|
{ inputs, pkgs, lib, config, ...}: let
|
||||||
inherit (lib) attrValues;
|
inherit (lib) attrValues;
|
||||||
in {
|
in {
|
||||||
environment.systemPackages = attrValues {
|
environment.systemPackages = attrValues {
|
||||||
|
|
@ -11,6 +11,11 @@ in {
|
||||||
} ++ (if (!config.isServer) then (attrValues {
|
} ++ (if (!config.isServer) then (attrValues {
|
||||||
inherit (pkgs) protonup-qt
|
inherit (pkgs) protonup-qt
|
||||||
xsane
|
xsane
|
||||||
simple-scan;
|
simple-scan
|
||||||
}) else []);
|
|
||||||
|
obsidian
|
||||||
|
tor-browser;
|
||||||
|
}) else []) ++ (if (!config.isServer) then [
|
||||||
|
inputs.helium.packages.${pkgs.system}.default
|
||||||
|
] else []);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
modules/linux/tor.nix
Normal file
24
modules/linux/tor.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
services.tor = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
# WE DO NOT WANT GERMAN NODES ANYWHERE IN THE CIRCUIT!!!!
|
||||||
|
ExcludeExitNodes = "{de}";
|
||||||
|
ExcludeNodes = "{de}";
|
||||||
|
StrictNodes = 1;
|
||||||
|
|
||||||
|
# optionally also avoid unknown-geoip nodes
|
||||||
|
GeoIPExcludeUnknown = 1;
|
||||||
|
|
||||||
|
# listen on socks5 port for local apps (like transmission/qbittorrent)
|
||||||
|
SOCKSPort = "9050";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.transmission = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
proxy = "socks5://127.0.0.1:9050"; # assuming tor daemon
|
||||||
|
proxy-auth-enabled = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{ pkgs, lib, config, ... }: let
|
{ pkgs, lib, ... }: let
|
||||||
inherit (lib) optionalAttrs;
|
inherit (lib) optionalAttrs;
|
||||||
in {
|
in {
|
||||||
virtualisation.vmware.guest.enable = true;
|
virtualisation.vmware.guest.enable = true;
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.fuzzel ];
|
environment.systemPackages = [ pkgs.fuzzel ];
|
||||||
programs.niri.enable = config.isServer;
|
programs.niri.enable = true;
|
||||||
|
|
||||||
services.xserver = {
|
services.xserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -24,7 +24,7 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
windowManager.i3 = optionalAttrs (!config.isServer) {
|
windowManager.i3 = optionalAttrs (false) {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.i3;
|
package = pkgs.i3;
|
||||||
configFile = ../dotfiles/i3/config;
|
configFile = ../dotfiles/i3/config;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue