Add etherpad, update codex
This commit is contained in:
parent
176d2a7723
commit
aa2b38d3bf
8 changed files with 206 additions and 14 deletions
57
flake.nix
57
flake.nix
|
|
@ -45,6 +45,61 @@
|
|||
};
|
||||
};
|
||||
|
||||
overlay-etherpad-fixes = final: prev: {
|
||||
unstable = prev.unstable // {
|
||||
etherpad-lite = prev.unstable.etherpad-lite.overrideAttrs (old: {
|
||||
patches =
|
||||
(old.patches or [ ])
|
||||
++ [
|
||||
./pkgs/patches/etherpad-plugin-index-keys.patch
|
||||
./pkgs/patches/etherpad-declarative-plugin-packages.patch
|
||||
./pkgs/patches/etherpad-plugin-package-bootstrap-path.patch
|
||||
];
|
||||
postInstall =
|
||||
(old.postInstall or "")
|
||||
+ ''
|
||||
# Declaratively include ep_author_hover plugin so Etherpad can load it
|
||||
# without runtime writes to the Nix store.
|
||||
mkdir -p $out/lib/etherpad-lite/src/plugin_packages/ep_author_hover
|
||||
tar -xzf ${
|
||||
prev.fetchurl {
|
||||
url = "https://registry.npmjs.org/ep_author_hover/-/ep_author_hover-1.0.12.tgz";
|
||||
hash = "sha256-6/gJTB2GTep/n2ShrNqjzbIW121PYmyTDo/i8LpxjYA=";
|
||||
}
|
||||
} \
|
||||
--strip-components=1 \
|
||||
-C $out/lib/etherpad-lite/src/plugin_packages/ep_author_hover \
|
||||
package
|
||||
|
||||
# Declaratively include ep_images_extended plugin so Etherpad can load it
|
||||
# without runtime writes to the Nix store.
|
||||
mkdir -p $out/lib/etherpad-lite/src/plugin_packages/ep_images_extended
|
||||
tar -xzf ${
|
||||
prev.fetchurl {
|
||||
url = "https://registry.npmjs.org/ep_images_extended/-/ep_images_extended-1.1.2.tgz";
|
||||
hash = "sha256-0RPnfQbeqepOPoML2dO7y77yySwQfD04anQdEKwyHNg=";
|
||||
}
|
||||
} \
|
||||
--strip-components=1 \
|
||||
-C $out/lib/etherpad-lite/src/plugin_packages/ep_images_extended \
|
||||
package
|
||||
|
||||
# ep_images_extended directly requires mime-db at startup.
|
||||
mkdir -p $out/lib/etherpad-lite/src/node_modules/mime-db
|
||||
tar -xzf ${
|
||||
prev.fetchurl {
|
||||
url = "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz";
|
||||
hash = "sha256-tzFKqRPRjkcLki8Kv8HOvmebNq/5hyaGBR7oye+CqZk=";
|
||||
}
|
||||
} \
|
||||
--strip-components=1 \
|
||||
-C $out/lib/etherpad-lite/src/node_modules/mime-db \
|
||||
package
|
||||
'';
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
overlay-local = final: prev: {
|
||||
codex = prev.callPackage ./pkgs/codex/package.nix { };
|
||||
beads =
|
||||
|
|
@ -122,7 +177,7 @@
|
|||
inherit openclaw-flake;
|
||||
};
|
||||
modules = [
|
||||
({ ... }: { nixpkgs.overlays = [ openclaw-flake.overlays.default ]; })
|
||||
({ ... }: { nixpkgs.overlays = [ overlay-unstable overlay-etherpad-fixes openclaw-flake.overlays.default ]; })
|
||||
home-manager.nixosModules.home-manager
|
||||
./hosts/ruil/configuration.nix
|
||||
sops-nix.nixosModules.sops
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
{ pkgs, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
sops.secrets.etherpad-env = {
|
||||
owner = "etherpad";
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
users.users.etherpad = {
|
||||
isSystemUser = true;
|
||||
group = "etherpad";
|
||||
|
|
@ -15,6 +20,12 @@
|
|||
dbSettings = {
|
||||
filename = "/var/lib/etherpad-lite/rusty.db";
|
||||
};
|
||||
users = {
|
||||
hunner = {
|
||||
password = "\${ETHERPAD_ADMIN_PASSWORD}";
|
||||
is_admin = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Etherpad on etherpad.hunner.dev (Cloudflare proxy -> nginx -> localhost:9001).
|
||||
|
|
@ -27,9 +38,10 @@
|
|||
Type = "simple";
|
||||
User = "etherpad";
|
||||
Group = "etherpad";
|
||||
EnvironmentFile = [ config.sops.secrets.etherpad-env.path ];
|
||||
StateDirectory = "etherpad-lite";
|
||||
WorkingDirectory = "/var/lib/etherpad-lite";
|
||||
ExecStart = "${pkgs.etherpad-lite}/bin/etherpad-lite --settings /etc/etherpad-lite/settings.json --sessionkey /var/lib/etherpad-lite/SESSIONKEY.txt --apikey /var/lib/etherpad-lite/APIKEY.txt";
|
||||
ExecStart = "${pkgs.unstable.etherpad-lite}/bin/etherpad-lite --settings /etc/etherpad-lite/settings.json --sessionkey /var/lib/etherpad-lite/SESSIONKEY.txt --apikey /var/lib/etherpad-lite/APIKEY.txt";
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ openclaw-env: ENC[AES256_GCM,data:pJq+HdqlNjx0qeVHhPcnZk9FNm7/eMWm8vZ3ROnQ00qR4l
|
|||
searx-env: ENC[AES256_GCM,data:dJ8JGxTWBdrli340Yjs5bA7X25NjExj5Mxp2T49jVEv/pafTtyMWf7Tvonzv+krCe1k/Zsh7KuWoJxXXOOGjRLPP1eQMMJunoL/P6JXruX+ZkBN5XbYB/UdWdkUrcvdDSyMcofZwgqYdDUy6J5ZlvcnmvuIM,iv:DuzG234PInaT/2CYQp9fzGh0EBYrxA7cto5uI4tGSkQ=,tag:1PNQKboKl6N7SULlUeAcgA==,type:str]
|
||||
searx-nginx-basic-auth: ENC[AES256_GCM,data:v22LhW/PksCnfheQ5dYF4n0pLNdGEe8q/bp0aoP/ZRcUFsSWZSdt6Wuj3BdpW7Hl/vJiWysxDX/0mi1GQ7flZz0+lmIWe29hSroJljAccMrafL6CY7r2awk+IC5Z2hNmbvLxbHzyN9U8mExazeNuWq0=,iv:OpSkH4C0eAF6CrRJRmQRtC9j+0WEKLM1a0rNeGtROaY=,tag:7nbFtk02bgB0glANehZXTw==,type:str]
|
||||
vaultwarden-env: ENC[AES256_GCM,data:C1oXLf+XchounepkJdGskeh3mlIvZYNFOK8Ec7wkPUnysEBXpVjtdfvbWZLkIzlcIn9BxM7pQLGDpn+7vogZA47JA07TkIVef9xrYYytLDYkox6+G/Acd36tuMKrTRWNko/wWX/YQQdHTGLLlBvP56YMQOSQ6mq5w86VK7QDmPFZTeobt3n4neHDIRjxkEWqNQg5x8zVPYbRqeg6rN2ES/hnd9jTzetx2lYH1zU8IncIGnkzw5C/5L8TysmHygWE5cX2CsA+2slkQHMYdQ3cZNFswP793jiAQB2BWXKUE8jyRc7S5XeUzfhFsg6pFdo9m0Om1nF2Hku/sYKaml3U+Fcma5BctuMpaPMAWh20n4wGS9rcIaF3SxwhCTHmk/IFOX/s8eK4,iv:B4DpR2JZQTuDOfCCR9x4uPWH4HyfXVDVYEZ2JZCdDf0=,tag:jwovvzMPLInaQHCxV4fTGw==,type:str]
|
||||
etherpad-env: ENC[AES256_GCM,data:MVkJbwFJdHOf5MixPQlrobGJTEuscrAvbDjpvxa+cf+ARmqMOoFLh9ectt+hWmZiqw3y6pwjHB7VVBdyRczkL5NgkukUSqIZStU1bDjM5JzA4D93DarVmg==,iv:CT2GtstuEU4Ek9ilYl3g1lx7wpHBj8KFc3EhvF+NAGc=,tag:lNkXC09AdvR9b6HTmJDeEQ==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age17sdp0gguexd88qel74fa4zeckxh93gqpkayz366fz6yvjauw7vcq7w6y45
|
||||
|
|
@ -25,7 +26,7 @@ sops:
|
|||
VHorQzNrMFJLaFpSalZZdjNraXhlSVUKwWLesTzMxsEB45hWWzhZGWc1cDm/gmvF
|
||||
MAytSLiBcieAkRKZoklyk/llbnq7kycvpZCU/sQrjKqmoHkC+TF3BQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-02-24T23:59:42Z"
|
||||
mac: ENC[AES256_GCM,data:qnbTTnrl84U55wzKMrp7e/gvxrj5TZCH4LC7X+waPEVEpz7jsJ/10gezCU5H6v6lkXCrfJ9CZgupRrFMI+yrndLVtqXyrdUkMWeq6GehzKd9Li2VbnfVu1zfjF5gRX4xyOxjfa3NDvHhfWQOUrTlXQyd4YIJUs0Q4cLjpaT1DH0=,iv:7CGp7qqWNdRsnFfLyqstkxledpWH7b0PuPdVxvWxcQg=,tag:8t2iyWYshX0YMWtRtccclA==,type:str]
|
||||
lastmodified: "2026-03-01T04:39:37Z"
|
||||
mac: ENC[AES256_GCM,data:0DldqSb1rph8SVjvzW9CRg4CCkwaP1ym88cRMoQHcwxrURvPquHoChTiWW8TLm0fhP4XadC9FCbs930x9aKvG2coY7WzTi7hA2C7VJb28dvUGr+etYriDpvIF4BybYMPPAhQXL6cSebt836OrNW4thyk5vEEnClUolQgsBONa50=,iv:7EkBD8BQSQn0ImiNUEq2eR1SjIwWyba8ZE4Eh3oDuFs=,tag:CRjsEOVMhGEPx4356RmMjg==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.11.0
|
||||
|
|
|
|||
16
justfile
16
justfile
|
|
@ -16,17 +16,21 @@ deploy-sudo host:
|
|||
sudo nixos-rebuild switch \
|
||||
--flake .#{{host}}
|
||||
|
||||
# Shortcut: deploy ruil (remote)
|
||||
# Shortcut helper: deploy locally when host matches this machine, otherwise deploy remotely.
|
||||
deploy-auto host target:
|
||||
if [ "$(hostname -s)" = "{{host}}" ]; then just deploy-sudo {{host}}; else just deploy-remote {{host}} {{target}}; fi
|
||||
|
||||
# Shortcut: deploy ruil
|
||||
deploy-ruil:
|
||||
just deploy-remote ruil root@ruil.hunnur.com
|
||||
just deploy-auto ruil root@ruil.hunnur.com
|
||||
|
||||
# Shortcut: deploy liminal (local)
|
||||
# Shortcut: deploy liminal
|
||||
deploy-liminal:
|
||||
just deploy-sudo liminal
|
||||
just deploy-auto liminal root@liminal
|
||||
|
||||
# Shortcut: deploy zima (local)
|
||||
# Shortcut: deploy zima
|
||||
deploy-zima:
|
||||
just deploy-sudo zima
|
||||
just deploy-auto zima root@zima
|
||||
|
||||
# Update flake lock file
|
||||
update:
|
||||
|
|
|
|||
|
|
@ -19,19 +19,20 @@
|
|||
}:
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "codex";
|
||||
version = "0.104.0";
|
||||
version = "0.107.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "openai";
|
||||
repo = "codex";
|
||||
tag = "rust-v${finalAttrs.version}";
|
||||
#hash = lib.fakeHash;
|
||||
hash = "sha256-spWb/msjl9am7E4UkZfEoH0diFbvAfydJKJQM1N1aoI=";
|
||||
hash = "sha256-FJWEe5uV9jC6vDopmx6XcIcrye2ZwlgpZhWNILXUkHo=";
|
||||
};
|
||||
|
||||
sourceRoot = "${finalAttrs.src.name}/codex-rs";
|
||||
|
||||
cargoHash = "sha256-8XNOqkr03+tI+gqJRR65iWYQ0zsqAiDl2V5bwPoWAcA=";
|
||||
#cargoHash = lib.fakeHash;
|
||||
cargoHash = "sha256-LbKiGMokzHSPsXumhO8PFqqeWb4E2CPa7Xv+FjTZwlE=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
clang
|
||||
|
|
|
|||
51
pkgs/patches/etherpad-declarative-plugin-packages.patch
Normal file
51
pkgs/patches/etherpad-declarative-plugin-packages.patch
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
--- a/src/static/js/pluginfw/plugins.ts
|
||||
+++ b/src/static/js/pluginfw/plugins.ts
|
||||
@@ -123,6 +123,8 @@
|
||||
}));
|
||||
};
|
||||
|
||||
+const declarativePluginDir = path.join(settings.root, 'src', 'plugin_packages');
|
||||
+
|
||||
exports.getPackages = async () => {
|
||||
const {linkInstaller} = require("./installer");
|
||||
const plugins = await linkInstaller.listPlugins();
|
||||
@@ -136,6 +138,39 @@
|
||||
newDependencies[plugin.name] = plugin;
|
||||
}
|
||||
|
||||
+ // Also allow declarative plugins pre-bundled into src/plugin_packages by
|
||||
+ // Nix overlays (without requiring live-plugin-manager runtime state).
|
||||
+ try {
|
||||
+ const entries = await fs.readdir(declarativePluginDir, {withFileTypes: true});
|
||||
+ for (const entry of entries) {
|
||||
+ if (!entry.isDirectory()) continue;
|
||||
+
|
||||
+ const pluginName = entry.name;
|
||||
+ if (!pluginName.startsWith(exports.prefix) || pluginName === 'ep_etherpad-lite') continue;
|
||||
+ if (newDependencies[pluginName]) continue;
|
||||
+
|
||||
+ const pluginPath = path.join(declarativePluginDir, pluginName);
|
||||
+ try {
|
||||
+ const pkg = JSON.parse(await fs.readFile(path.join(pluginPath, 'package.json'), 'utf8'));
|
||||
+ await fs.access(path.join(pluginPath, 'ep.json'));
|
||||
+
|
||||
+ newDependencies[pluginName] = {
|
||||
+ name: pluginName,
|
||||
+ version: pkg.version || '0.0.0',
|
||||
+ path: pluginPath,
|
||||
+ realPath: pluginPath,
|
||||
+ location: pluginPath,
|
||||
+ };
|
||||
+ } catch (err) {
|
||||
+ logger.warn(
|
||||
+ `Skipping declarative plugin ${pluginName}: ${err.message || err.toString()}`,
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (err) {
|
||||
+ // plugin_packages directory is optional in upstream installs.
|
||||
+ }
|
||||
+
|
||||
newDependencies['ep_etherpad-lite'] = {
|
||||
name: 'ep_etherpad-lite',
|
||||
version: getEpVersion(),
|
||||
57
pkgs/patches/etherpad-plugin-index-keys.patch
Normal file
57
pkgs/patches/etherpad-plugin-index-keys.patch
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
diff --git a/src/static/js/pluginfw/installer.ts b/src/static/js/pluginfw/installer.ts
|
||||
index 0fd8949be..22d2d6850 100644
|
||||
--- a/src/static/js/pluginfw/installer.ts
|
||||
+++ b/src/static/js/pluginfw/installer.ts
|
||||
@@ -175,9 +175,17 @@ export const getAvailablePlugins = async (maxCacheAge: number | false) => {
|
||||
return availablePlugins;
|
||||
}
|
||||
|
||||
- const pluginsLoaded: AxiosResponse<MapArrayType<PackageInfo>> = await axios.get(`${settings.updateServer}/plugins.json`, {headers})
|
||||
- availablePlugins = pluginsLoaded.data;
|
||||
+ const pluginsLoaded: AxiosResponse<MapArrayType<PackageInfo>> = await axios.get(`${settings.updateServer}/plugins.json`, {headers});
|
||||
+ const normalizedPlugins: MapArrayType<PackageInfo> = {};
|
||||
+ for (const key in pluginsLoaded.data) {
|
||||
+ const plugin = pluginsLoaded.data[key];
|
||||
+ const normalizedKey = plugin?.name || key;
|
||||
+ normalizedPlugins[normalizedKey] = plugin;
|
||||
+ }
|
||||
+
|
||||
+ availablePlugins = normalizedPlugins;
|
||||
cacheTimestamp = nowTimestamp;
|
||||
+
|
||||
return availablePlugins;
|
||||
};
|
||||
|
||||
@@ -191,22 +199,25 @@ export const search = (searchTerm: string, maxCacheAge: number) => getAvailable
|
||||
}
|
||||
|
||||
for (const pluginName in results) {
|
||||
+ const plugin = results[pluginName];
|
||||
+ const pluginIdentifier = plugin?.name || pluginName;
|
||||
+
|
||||
// for every available plugin
|
||||
// TODO: Also search in keywords here!
|
||||
- if (pluginName.indexOf(plugins.prefix) !== 0) continue;
|
||||
+ if (pluginIdentifier.indexOf(plugins.prefix) !== 0) continue;
|
||||
|
||||
- if (searchTerm && !~results[pluginName].name.toLowerCase().indexOf(searchTerm) &&
|
||||
- (typeof results[pluginName].description !== 'undefined' &&
|
||||
- !~results[pluginName].description.toLowerCase().indexOf(searchTerm))
|
||||
+ if (searchTerm && !~plugin.name.toLowerCase().indexOf(searchTerm) &&
|
||||
+ (typeof plugin.description !== 'undefined' &&
|
||||
+ !~plugin.description.toLowerCase().indexOf(searchTerm))
|
||||
) {
|
||||
- if (typeof results[pluginName].description === 'undefined') {
|
||||
- logger.debug(`plugin without Description: ${results[pluginName].name}`);
|
||||
+ if (typeof plugin.description === 'undefined') {
|
||||
+ logger.debug(`plugin without Description: ${plugin.name}`);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
- res[pluginName] = results[pluginName];
|
||||
+ res[pluginIdentifier] = plugin;
|
||||
}
|
||||
|
||||
return res;
|
||||
11
pkgs/patches/etherpad-plugin-package-bootstrap-path.patch
Normal file
11
pkgs/patches/etherpad-plugin-package-bootstrap-path.patch
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
--- a/src/templates/padBootstrap.js
|
||||
+++ b/src/templates/padBootstrap.js
|
||||
@@ -31,7 +31,7 @@
|
||||
window.plugins.baseURL = basePath;
|
||||
await window.plugins.update(new Map([
|
||||
<% for (const module of pluginModules) { %>
|
||||
- [<%- JSON.stringify(module) %>, require("../../src/plugin_packages/"+<%- JSON.stringify(module) %>)],
|
||||
+ [<%- JSON.stringify(module) %>, require("./src/plugin_packages/"+<%- JSON.stringify(module) %>)],
|
||||
<% } %>
|
||||
]));
|
||||
// Mechanism for tests to register hook functions (install fake plugins).
|
||||
Loading…
Add table
Add a link
Reference in a new issue