Compare commits

...

12 Commits

Author SHA1 Message Date
Dorian
1c952bb02d chore: bump version to 1.3.4
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 03:05:05 +01:00
Dorian
3dde239177 chore: trigger CI build on VPS runner
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Failing after 15m8s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 02:46:02 +01:00
Dorian
eb6f76c909 chore: trigger CI build on new VPS runner
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Failing after 11m35s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 01:48:05 +01:00
Dorian
101cb5f42d fix: remove duplicate rpcbind from bitcoin-knots container creation
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled
bitcoin.conf already has server=1, rpcbind=0.0.0.0, rpcallowip, listen.
Passing them again via command-line causes bitcoin to try binding port
8332 twice → "Address already in use" → container crashes on every start.

Now only passes pruning/txindex args and dbcache via CLI.
Health check uses cookie auth (-datadir) instead of plaintext password.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:56:26 +01:00
Dorian
449f47da49 fix: BUILD_VERSION from Cargo.toml, kiosk scaling, new apps, Rust warnings
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled
Critical:
- BUILD_VERSION was hardcoded as "1.3.0-alpha" — now reads from Cargo.toml
  This caused ALL ISOs to show v1.3.0 regardless of actual binary version

Kiosk:
- Remove --disable-gpu flags (broke display scaling on some monitors)
- Add --start-fullscreen --window-size for reliable fullscreen

New apps:
- Nostr VPN, FIPS, Routstr, noStrudel, BotFights, NWNN, 484 Kitchen,
  Call the Operator, Arch Presentation, Syntropy Institute, T-0

Rust: suppress dead_code and unused_assignments warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 00:35:52 +01:00
Dorian
8814b03e33 fix: replace actions/checkout in build-iso-dev.yml (THE ACTUAL WORKFLOW)
All checks were successful
Build Archipelago ISO (dev) / build-iso (push) Successful in 46m18s
We were editing build-iso.yml but Gitea runs build-iso-dev.yml.
Replaced actions/checkout@v4 with direct git fetch+rsync.
This is the root cause of stale builds all day.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:33:40 +01:00
Dorian
78e877311d chore: retrigger CI build (runner restored)
All checks were successful
Build Archipelago ISO (dev) / build-iso (push) Successful in 50m29s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 21:39:30 +01:00
Dorian
ae97f4a979 chore: retrigger CI with fixed checkout workflow
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Failing after 14m48s
2026-04-02 21:10:45 +01:00
Dorian
9d1904cddc chore: retrigger CI after .228 repo sync
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:59:16 +01:00
Dorian
c81ef5ad79 chore: trigger CI build with new runner registration
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:49:59 +01:00
Dorian
d243cbb83e android 2026-04-02 20:49:43 +01:00
Dorian
37f5790165 fix: replace actions/checkout with direct git fetch+rsync (no more red cross)
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Failing after 7m58s
actions/checkout@v4 uses a broken Gitea-generated token that always
fails. Replaced with direct git fetch+reset on the local repo, then
rsync to workspace. No more stale builds. Verified with version check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:38:52 +01:00
21 changed files with 271 additions and 53 deletions

View File

@@ -11,33 +11,19 @@ jobs:
timeout-minutes: 60
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
timeout-minutes: 5
continue-on-error: true
- name: Sync from local repo (fallback if checkout failed)
run: |
# Only sync from ~/archy if checkout failed or workspace is empty
if [ -f "CLAUDE.md" ] && [ -d "core" ] && [ -d "neode-ui" ]; then
echo "Checkout succeeded — using checked-out code"
elif [ -d "$HOME/archy/core" ] && [ -d "$HOME/archy/neode-ui" ]; then
echo "Checkout failed — syncing from ~/archy (LAN fallback)..."
rsync -a \
--exclude '.git' --exclude 'node_modules' --exclude 'target' \
--exclude 'image-recipe/build' --exclude 'image-recipe/results' \
--exclude 'web/dist' \
"$HOME/archy/" ./
else
echo "ERROR: No checkout and no local fallback"
exit 1
fi
echo "Workspace verification:"
# Direct fetch + sync (actions/checkout token is broken on this Gitea)
cd /home/archipelago/archy && git fetch origin main && git reset --hard origin/main
echo "=== Source at commit: $(git log --oneline -1) ==="
rsync -a --delete \
--exclude '.git' --exclude 'node_modules' --exclude 'target' \
--exclude 'image-recipe/build' --exclude 'image-recipe/results' \
--exclude 'web/dist' \
/home/archipelago/archy/ "$GITHUB_WORKSPACE/"
cd "$GITHUB_WORKSPACE"
echo "=== Workspace version: $(grep '^version' core/archipelago/Cargo.toml) ==="
[ -f "scripts/first-boot-containers.sh" ] && echo " first-boot-containers.sh: PRESENT" || echo " first-boot-containers.sh: MISSING"
grep -q 'network-alias' scripts/first-boot-containers.sh 2>/dev/null && echo " network-alias fix: PRESENT" || echo " network-alias fix: MISSING"
grep -q 'apache2-utils' image-recipe/build-auto-installer-iso.sh 2>/dev/null && echo " apache2-utils: PRESENT" || echo " apache2-utils: MISSING"
- name: Install ISO build dependencies
run: |

View File

@@ -11,22 +11,19 @@ jobs:
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
clean: true
continue-on-error: true
- name: Sync from local repo (always — checkout token is unreliable)
run: |
# Pull latest into local repo
cd /home/archipelago/archy && git pull origin main 2>/dev/null || true
# Always sync from local repo to ensure latest code
echo "Syncing workspace from local repo..."
# Direct clone using stored credentials (actions/checkout token is broken)
cd /home/archipelago/archy && git fetch origin main && git reset --hard origin/main
echo "=== Source at commit: $(git log --oneline -1) ==="
echo "=== Syncing to workspace ==="
rsync -a --delete --exclude='.git' --exclude='target/' --exclude='node_modules/' \
/home/archipelago/archy/ ./ 2>/dev/null || cp -a /home/archipelago/archy/* . 2>/dev/null || true
echo "Source version: $(grep '^version' core/archipelago/Cargo.toml 2>/dev/null)"
echo "Latest commit: $(cd /home/archipelago/archy && git log --oneline -1 2>/dev/null)"
/home/archipelago/archy/ "$GITHUB_WORKSPACE/" || cp -a /home/archipelago/archy/* "$GITHUB_WORKSPACE/"
cd "$GITHUB_WORKSPACE"
echo "=== Workspace version: $(grep '^version' core/archipelago/Cargo.toml) ==="
echo "=== Key files ==="
echo " first-boot: $([ -f scripts/first-boot-containers.sh ] && echo PRESENT || echo MISSING)"
echo " Cargo.toml: $(grep '^version' core/archipelago/Cargo.toml)"
echo " package.json: $(grep '\"version\"' neode-ui/package.json | head -1)"
- name: Build backend
run: |

Binary file not shown.

View File

@@ -1,6 +1,6 @@
[package]
name = "archipelago"
version = "1.3.3"
version = "1.3.4"
edition = "2021"
description = "Archipelago Bitcoin Node OS - Native backend"
authors = ["Archipelago Team"]

View File

@@ -124,6 +124,12 @@ pub(super) fn get_app_capabilities(app_id: &str) -> Vec<String> {
"--cap-add=DAC_OVERRIDE".to_string(),
"--cap-add=NET_BIND_SERVICE".to_string(),
],
// Nostr VPN and FIPS: mesh networking daemons need TUN + NET_ADMIN
// Note: --device=/dev/net/tun is added separately in install.rs
"nostr-vpn" | "fips" => vec![
"--cap-add=NET_ADMIN".to_string(),
"--cap-add=NET_RAW".to_string(),
],
// Default: standard capabilities for rootless podman containers
// Most apps need file ownership + port binding to function correctly
_ => vec![
@@ -239,6 +245,13 @@ pub(super) fn get_health_check_args(app_id: &str, _rpc_pass: &str) -> Vec<String
"30s",
"3",
),
"routstr" => (
"curl -sf http://localhost:8000/v1/models || exit 1",
"30s",
"3",
),
"nostr-vpn" => ("nvpn status || exit 1", "30s", "3"),
"fips" => ("fipsctl status || exit 1", "30s", "3"),
_ => return vec![],
};
@@ -279,6 +292,9 @@ pub(super) fn get_memory_limit(app_id: &str) -> &'static str {
"dwn" => "256m",
"portainer" => "256m",
"nostr-rs-relay" | "nostr-relay" => "256m",
"routstr" => "512m",
"nostr-vpn" => "256m",
"fips" => "256m",
"nginx-proxy-manager" => "256m",
// Databases
"archy-btcpay-db" | "archy-mempool-db" | "mysql-mempool" => "512m",
@@ -343,6 +359,9 @@ pub(super) fn all_container_names(package_id: &str) -> Vec<String> {
"penpot-postgres".into(), "penpot-valkey".into(),
"penpot-backend".into(), "penpot-exporter".into(), "penpot-frontend".into(),
],
"nostr-vpn" => vec!["nostr-vpn".into(), "archy-nostr-vpn".into()],
"fips" => vec!["fips".into(), "archy-fips".into()],
"routstr" => vec!["routstr".into(), "archy-routstr".into()],
// Default: exact name + archy- prefix
_ => vec![base, archy],
}
@@ -407,6 +426,21 @@ fn read_secret(name: &str, default: &str) -> String {
.unwrap_or_else(|_| default.to_string())
}
/// Read the node-level Nostr secret key (hex) for identity-aware apps.
/// Returns empty string if not yet generated.
fn read_nostr_secret_hex() -> String {
std::fs::read_to_string("/var/lib/archipelago/identity/nostr_secret")
.map(|s| s.trim().to_string())
.unwrap_or_default()
}
/// Read the node-level Nostr public key (hex).
fn read_nostr_pubkey_hex() -> String {
std::fs::read_to_string("/var/lib/archipelago/identity/nostr_pub")
.map(|s| s.trim().to_string())
.unwrap_or_default()
}
/// Get app-specific configuration
/// Returns: (ports, volumes, env_vars, custom_command, custom_args)
pub(super) async fn get_app_config(
@@ -771,6 +805,62 @@ pub(super) async fn get_app_config(
None,
None,
),
"routstr" => {
let nsec = read_nostr_secret_hex();
let mut env = vec![
"DATABASE_URL=sqlite:///app/data/keys.db".to_string(),
];
if !nsec.is_empty() {
env.push(format!("NSEC={}", nsec));
env.push(format!("NOSTR_PUBKEY={}", read_nostr_pubkey_hex()));
}
(
vec!["8200:8000".to_string()],
vec!["/var/lib/archipelago/routstr:/app/data".to_string()],
env,
None,
None,
)
}
"nostr-vpn" => {
let nsec = read_nostr_secret_hex();
let mut env = vec![];
if !nsec.is_empty() {
env.push(format!("NOSTR_SECRET={}", nsec));
env.push(format!("NOSTR_PUBKEY={}", read_nostr_pubkey_hex()));
}
(
vec!["51820:51820/udp".to_string()],
vec!["/var/lib/archipelago/nostr-vpn:/root/.config/nvpn".to_string()],
env,
None,
Some(vec![
"start".to_string(),
"--daemon".to_string(),
]),
)
}
"fips" => {
let nsec = read_nostr_secret_hex();
let mut env = vec![];
if !nsec.is_empty() {
env.push(format!("FIPS_NOSTR_SECRET={}", nsec));
env.push(format!("FIPS_NOSTR_PUBKEY={}", read_nostr_pubkey_hex()));
}
(
vec![
"2121:2121/udp".to_string(),
"8443:8443".to_string(),
],
vec![
"/var/lib/archipelago/fips/config:/etc/fips".to_string(),
"/var/lib/archipelago/fips/run:/run/fips".to_string(),
],
env,
None,
None,
)
}
"dwn" => (
vec!["3100:3000".to_string()],
vec!["/var/lib/archipelago/dwn:/dwn/data".to_string()],

View File

@@ -225,6 +225,11 @@ impl RpcHandler {
}
}
// TUN device for mesh networking apps
if matches!(package_id, "nostr-vpn" | "fips") {
run_args.push("--device=/dev/net/tun");
}
// Create data directories
self.create_data_dirs(package_id, &volumes).await;
@@ -259,6 +264,35 @@ impl RpcHandler {
}
}
// Pre-install: write Nostr identity key files for headless Nostr-aware apps
if matches!(package_id, "nostr-vpn" | "fips") {
let nostr_secret = std::fs::read_to_string("/var/lib/archipelago/identity/nostr_secret")
.map(|s| s.trim().to_string())
.unwrap_or_default();
if !nostr_secret.is_empty() {
let key_dir = match package_id {
"nostr-vpn" => "/var/lib/archipelago/nostr-vpn",
"fips" => "/var/lib/archipelago/fips/config",
_ => unreachable!(),
};
let key_path = match package_id {
"nostr-vpn" => format!("{}/nostr_secret", key_dir),
"fips" => format!("{}/fips.key", key_dir),
_ => unreachable!(),
};
tokio::fs::create_dir_all(key_dir).await.ok();
tokio::fs::write(&key_path, &nostr_secret).await.ok();
// Restrict permissions on key file
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let perms = std::fs::Permissions::from_mode(0o600);
std::fs::set_permissions(&key_path, perms).ok();
}
info!("Wrote Nostr identity key for {}", package_id);
}
}
// Port mappings (skip for host-network containers)
if !is_tailscale {
for port in &ports {

View File

@@ -66,7 +66,8 @@ fi
echo "$BUILD_NUM" | sudo tee "$BUILD_COUNTER_FILE" > /dev/null 2>/dev/null || BUILD_NUM=1
GIT_SHORT=$(cd "$SCRIPT_DIR/.." && git rev-parse --short HEAD 2>/dev/null || echo "dev")
# Version format: major.minor.patch-prerelease (semver)
BUILD_VERSION="1.3.0-alpha"
# Read version from Cargo.toml (single source of truth)
BUILD_VERSION=$(grep '^version' "$SCRIPT_DIR/../core/archipelago/Cargo.toml" 2>/dev/null | head -1 | sed 's/version = "//;s/"//' || echo "0.0.0")
echo "Build #${BUILD_NUM} (${BUILD_VERSION}, commit ${GIT_SHORT})"
# Architecture-dependent variables

View File

@@ -42,12 +42,12 @@ while true; do
--disable-save-password-bubble \
--disable-suggestions-service \
--disable-component-update \
--disable-gpu \
--disable-gpu-compositing \
--disable-gpu-rasterization \
--disable-software-rasterizer \
--num-raster-threads=1 \
--renderer-process-limit=1 \
--enable-gpu-rasterization \
--num-raster-threads=2 \
--renderer-process-limit=2 \
--window-size=9999,9999 \
--window-position=0,0 \
--start-fullscreen \
--disable-background-networking \
--disable-background-timer-throttling \
--disable-backgrounding-occluded-windows \

View File

@@ -514,6 +514,29 @@ server {
default_type application/json;
return 503 '{"error":{"code":"NO_WEB_UI","message":"Tailscale is managed via CLI"}}';
}
location /app/routstr/ {
proxy_pass http://127.0.0.1:8200/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "SAMEORIGIN" always;
proxy_hide_header Content-Security-Policy;
add_header X-Content-Type-Options "nosniff" always;
proxy_set_header Accept-Encoding "";
sub_filter_once on;
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
}
location /app/nostr-vpn/ {
default_type application/json;
return 503 '{"error":{"code":"NO_WEB_UI","message":"Nostr VPN is managed via CLI"}}';
}
location /app/fips/ {
default_type application/json;
return 503 '{"error":{"code":"NO_WEB_UI","message":"FIPS is managed via CLI"}}';
}
location /app/ollama/ {
proxy_pass http://127.0.0.1:11434/;
proxy_http_version 1.1;

View File

@@ -197,6 +197,28 @@ location /app/tailscale/ {
default_type application/json;
return 503 '{"error":{"code":"NO_WEB_UI","message":"Tailscale is managed via CLI"}}';
}
location /app/routstr/ {
proxy_pass http://127.0.0.1:8200/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_hide_header X-Frame-Options;
add_header X-Frame-Options "SAMEORIGIN" always;
proxy_hide_header Content-Security-Policy;
proxy_set_header Accept-Encoding "";
sub_filter_once on;
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
}
location /app/nostr-vpn/ {
default_type application/json;
return 503 '{"error":{"code":"NO_WEB_UI","message":"Nostr VPN is managed via CLI"}}';
}
location /app/fips/ {
default_type application/json;
return 503 '{"error":{"code":"NO_WEB_UI","message":"FIPS is managed via CLI"}}';
}
location /app/ollama/ {
proxy_pass http://127.0.0.1:11434/;
proxy_http_version 1.1;

View File

@@ -1,7 +1,7 @@
{
"name": "neode-ui",
"private": true,
"version": "1.3.3",
"version": "1.3.4",
"type": "module",
"scripts": {
"start": "./start-dev.sh",

View File

@@ -0,0 +1,4 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="64" rx="12" fill="#10b981"/>
<text x="32" y="38" text-anchor="middle" font-family="system-ui" font-size="16" font-weight="700" fill="white">FIPS</text>
</svg>

After

Width:  |  Height:  |  Size: 284 B

View File

@@ -0,0 +1,4 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="64" rx="12" fill="#6366f1"/>
<text x="32" y="38" text-anchor="middle" font-family="system-ui" font-size="18" font-weight="700" fill="white">NV</text>
</svg>

After

Width:  |  Height:  |  Size: 282 B

View File

@@ -0,0 +1,4 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="64" height="64" rx="12" fill="#f59e0b"/>
<text x="32" y="38" text-anchor="middle" font-family="system-ui" font-size="18" font-weight="700" fill="white">R</text>
</svg>

After

Width:  |  Height:  |  Size: 281 B

View File

@@ -38,6 +38,7 @@ export const APP_PORTS: Record<string, number> = {
'fedimintd': 8175,
'fedimint-gateway': 8176,
'nostr-rs-relay': 18081,
'routstr': 8200,
'indeedhub': 7777,
'dwn': 3100,
'endurain': 8080,
@@ -83,6 +84,7 @@ export const HTTPS_PROXY_PATHS: Record<string, string> = {
'penpot': '/app/penpot/',
'grafana': '/app/grafana/',
'indeedhub': '/app/indeedhub/',
'routstr': '/app/routstr/',
}
/** External HTTPS apps -- always loaded directly */
@@ -100,6 +102,7 @@ export const EXTERNAL_URLS: Record<string, string> = {
export const APP_TITLES: Record<string, string> = {
'bitcoin-knots': 'Bitcoin', 'btcpay-server': 'BTCPay Server', 'indeedhub': 'Indeehub',
'botfights': 'BotFights', '484-kitchen': '484 Kitchen', 'arch-presentation': 'Presentation',
'nostr-vpn': 'Nostr VPN', 'fips': 'FIPS', 'routstr': 'Routstr',
'homeassistant': 'Home Assistant', 'uptime-kuma': 'Uptime Kuma',
'nginx-proxy-manager': 'Nginx Proxy Manager', 'nostr-rs-relay': 'Nostr Relay',
'call-the-operator': 'Call The Operator', 'syntropy-institute': 'Syntropy Institute',
@@ -120,6 +123,7 @@ export const NEW_TAB_APPS = new Set([
'onlyoffice',
'nginx-proxy-manager',
'tailscale',
'routstr',
])
/** Sites known to block iframes -- skip the timeout and go straight to fallback */

View File

@@ -15,7 +15,7 @@ export interface SelectedIdentity {
}
function isIdentityAwareApp(id: string): boolean {
return id === 'indeedhub' || id === 'nostrudel'
return id === 'indeedhub' || id === 'nostrudel' || id === 'routstr'
}
export function useAppIdentity(

View File

@@ -39,6 +39,7 @@ export const APP_CATEGORY_MAP: Record<string, string> = {
'homeassistant': 'home', 'lorabell': 'home', 'endurain': 'home',
'searxng': 'community', 'ollama': 'community', 'grafana': 'data',
'nostr-rs-relay': 'nostr', 'nostrudel': 'nostr',
'nostr-vpn': 'networking', 'fips': 'networking', 'routstr': 'community',
'tailscale': 'networking', 'nginx-proxy-manager': 'networking', 'portainer': 'networking',
'uptime-kuma': 'networking', 'dwn': 'data',
'botfights': 'l484', 'nwnn': 'l484', '484-kitchen': 'l484',
@@ -103,7 +104,7 @@ export const WEB_ONLY_APPS: Record<string, PackageDataEntry> = {
export const TAB_LAUNCH_APPS = new Set([
'btcpay-server', 'grafana', 'photoprism', 'homeassistant',
'vaultwarden', 'nextcloud', 'uptime-kuma', 'portainer',
'cryptpad', 'nginx-proxy-manager', 'tailscale',
'cryptpad', 'nginx-proxy-manager', 'tailscale', 'routstr',
])
export function opensInTab(id: string): boolean {

View File

@@ -29,6 +29,9 @@ export function getCuratedAppList(): MarketplaceApp[] {
{ id: 'nostr-rs-relay', title: 'Nostr Relay', version: '0.9.0', category: 'nostr', description: 'Your own Nostr relay. Store events locally, relay for friends, publish over Tor.', icon: '/assets/img/app-icons/nostr-rs-relay.svg', author: 'scsiblade', dockerImage: `${R}/nostr-rs-relay:0.9.0`, repoUrl: 'https://sr.ht/~gheartsfield/nostr-rs-relay/' },
{ id: 'indeedhub', title: 'Indeehub', version: '0.1.0', description: 'Bitcoin documentary streaming with Nostr identity. Stream sovereignty content.', icon: '/assets/img/app-icons/indeedhub.png', author: 'Indeehub Team', dockerImage: 'localhost/indeedhub:latest', repoUrl: 'https://github.com/indeedhub/indeedhub' },
{ id: 'dwn', title: 'Decentralized Web Node', version: '0.4.0', description: 'Own your data with DID-based access control. Sync across devices, sovereign.', icon: '/assets/img/app-icons/dwn.svg', author: 'TBD', dockerImage: `${R}/dwn-server:main`, repoUrl: 'https://github.com/TBD54566975/dwn-server' },
{ id: 'nostr-vpn', title: 'Nostr VPN', version: '0.3.4', category: 'networking', description: 'Tailscale-style mesh VPN with Nostr control plane. Peer discovery and key exchange over relays, WireGuard tunnels.', icon: '/assets/img/app-icons/nostr-vpn.svg', author: 'Martti Malmi', dockerImage: `${R}/nostr-vpn:v0.3.4`, repoUrl: 'https://github.com/mmalmi/nostr-vpn' },
{ id: 'fips', title: 'FIPS', version: '0.1.0', category: 'networking', description: 'Free Internetworking Peering System. Self-organizing encrypted mesh network with Nostr identity.', icon: '/assets/img/app-icons/fips.svg', author: 'Jim Corgan', dockerImage: `${R}/fips:v0.1.0`, repoUrl: 'https://github.com/jmcorgan/fips' },
{ id: 'routstr', title: 'Routstr', version: '0.4.3', category: 'community', description: 'Decentralized AI inference proxy. Pay-per-request with Cashu ecash, provider discovery via Nostr.', icon: '/assets/img/app-icons/routstr.svg', author: 'Routstr', dockerImage: `${R}/routstr:v0.4.3`, repoUrl: 'https://github.com/routstr/routstr-core' },
{ id: 'nostrudel', title: 'noStrudel', version: '0.40.0', category: 'nostr', description: 'Feature-rich Nostr web client. Browse feeds, post notes, manage relays with NIP-07.', icon: '/assets/img/app-icons/nostrudel.svg', author: 'hzrd149', dockerImage: '', repoUrl: 'https://github.com/hzrd149/nostrudel', webUrl: 'https://nostrudel.ninja' },
{ id: 'botfights', title: 'BotFights', version: '1.0.0', description: 'AI bot arena — build, train, and battle autonomous agents in strategy tournaments.', icon: '/assets/img/app-icons/botfights.svg', author: 'BotFights', dockerImage: '', repoUrl: 'https://botfights.net', webUrl: 'https://botfights.net' },
{ id: 'nwnn', title: 'Next Web News Network', version: '1.0.0', category: 'l484', description: 'Decentralized news aggregator. Community-curated Bitcoin and sovereignty content.', icon: '/assets/img/app-icons/nwnn.png', author: 'L484', dockerImage: '', repoUrl: 'https://nwnn.l484.com', webUrl: 'https://nwnn.l484.com' },
@@ -58,6 +61,9 @@ export const INSTALLED_ALIASES: Record<string, string[]> = {
filebrowser: ['filebrowser'],
tailscale: ['tailscale'],
ollama: ['ollama'],
'nostr-vpn': ['nostr-vpn'],
fips: ['fips'],
routstr: ['routstr'],
}
export const FEATURED_DEFINITIONS = [

View File

@@ -54,6 +54,9 @@ export const INSTALLED_ALIASES: Record<string, string[]> = {
filebrowser: ['filebrowser'],
tailscale: ['tailscale'],
ollama: ['ollama'],
'nostr-vpn': ['nostr-vpn'],
fips: ['fips'],
routstr: ['routstr'],
}
/** Get app tier classification (matches backend get_app_tier) */
@@ -402,6 +405,42 @@ export function getCuratedAppList(): MarketplaceApp[] {
manifestUrl: undefined,
repoUrl: 'https://github.com/TBD54566975/dwn-server'
},
{
id: 'nostr-vpn',
title: 'Nostr VPN',
version: '0.3.4',
category: 'networking',
description: 'Tailscale-style mesh VPN with Nostr control plane. Peer discovery and key exchange over relays, WireGuard tunnels.',
icon: '/assets/img/app-icons/nostr-vpn.svg',
author: 'Martti Malmi',
dockerImage: `${REGISTRY}/nostr-vpn:v0.3.4`,
manifestUrl: undefined,
repoUrl: 'https://github.com/mmalmi/nostr-vpn'
},
{
id: 'fips',
title: 'FIPS',
version: '0.1.0',
category: 'networking',
description: 'Free Internetworking Peering System. Self-organizing encrypted mesh network with Nostr identity.',
icon: '/assets/img/app-icons/fips.svg',
author: 'Jim Corgan',
dockerImage: `${REGISTRY}/fips:v0.1.0`,
manifestUrl: undefined,
repoUrl: 'https://github.com/jmcorgan/fips'
},
{
id: 'routstr',
title: 'Routstr',
version: '0.4.3',
category: 'community',
description: 'Decentralized AI inference proxy. Pay-per-request with Cashu ecash, provider discovery via Nostr.',
icon: '/assets/img/app-icons/routstr.svg',
author: 'Routstr',
dockerImage: `${REGISTRY}/routstr:v0.4.3`,
manifestUrl: undefined,
repoUrl: 'https://github.com/routstr/routstr-core'
},
{
id: 'nostrudel',
title: 'noStrudel',

View File

@@ -400,10 +400,8 @@ if ! $DOCKER ps --format '{{.Names}}' 2>/dev/null | grep -qE 'bitcoin-knots|arch
-p 8332:8332 -p 8333:8333 -p 28332:28332 -p 28333:28333 \
-v /var/lib/archipelago/bitcoin:/home/bitcoin/.bitcoin \
"${BITCOIN_KNOTS_IMAGE}" \
-server=1 $BTC_EXTRA_ARGS \
-rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0:8332 \
-proxy=host.containers.internal:9050 -listen=1 -bind=0.0.0.0:8333 \
-dbcache=$BTC_DBCACHE 2>>"$LOG"; then
$BTC_EXTRA_ARGS \
-printtoconsole=1 -dbcache=$BTC_DBCACHE 2>>"$LOG"; then
log "Bitcoin Knots started"
else
log "Bitcoin Knots failed (may already exist)"

View File

@@ -63,6 +63,11 @@ VALKEY_IMAGE="$ARCHY_REGISTRY/valkey:8.1.6"
# Nostr
NOSTR_RS_RELAY_IMAGE="$ARCHY_REGISTRY/nostr-rs-relay:0.9.0"
STRFRY_IMAGE="$ARCHY_REGISTRY/strfry:1.0.4"
NOSTR_VPN_IMAGE="$ARCHY_REGISTRY/nostr-vpn:v0.3.4"
FIPS_IMAGE="$ARCHY_REGISTRY/fips:v0.1.0"
# AI / Routing
ROUTSTR_IMAGE="$ARCHY_REGISTRY/routstr:v0.4.3"
# IndeedHub stack (local builds use :local tag, not :latest)
MINIO_IMAGE="$ARCHY_REGISTRY/minio:RELEASE.2024-11-07T00-52-20Z"