fix(apps): keep slow installs visible
This commit is contained in:
parent
75d147b69f
commit
87be717f40
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,5 +1,16 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v1.7.69-alpha (2026-05-19)
|
||||||
|
|
||||||
|
- App installs now allow up to 10 minutes for the initial `package.install` RPC to return, matching slow container image pulls and preventing apps from disappearing from My Apps while the backend is still pulling or retrying mirrors.
|
||||||
|
- Live diagnostics on `100.70.96.88` confirmed the Gitea install did not fail; the primary registry pull timed out after 300 seconds, the fallback mirror succeeded, and Gitea came up healthy on `3001` while the frontend had already timed out at 15 seconds.
|
||||||
|
- Gitea and other Docker-image app installs now stay visible during slow registry pulls instead of being marked as failed by the browser before backend install progress can complete.
|
||||||
|
- Gitea is now categorized as a known Data app in My Apps, so a running Gitea container appears with installed apps instead of being filtered into the Websites/Services split.
|
||||||
|
- NetBird `0.71.2` is now available in the app catalog and fallback marketplace data as a recommended networking app using the official `docker.io/netbirdio/netbird:0.71.2` image.
|
||||||
|
- NetBird installs get persistent state under `/var/lib/archipelago/netbird`, `NET_ADMIN`/`NET_RAW`, `/dev/net/tun`, `slirp4netns`, image-version pinning, backend metadata, and health checks through `netbird status`.
|
||||||
|
- The Archipelago terminal now includes `nano` on new disk installs and ISO builds, and self-update installs it on existing nodes if it is missing.
|
||||||
|
- Validation passed with catalog JSON checks, shell syntax checks, `npm run type-check`, `cargo fmt --all --check --manifest-path core/Cargo.toml`, and `cargo check -p archipelago --manifest-path core/Cargo.toml`.
|
||||||
|
|
||||||
## v1.7.68-alpha (2026-05-19)
|
## v1.7.68-alpha (2026-05-19)
|
||||||
|
|
||||||
- BTCPay Server now ships on the official `docker.io/btcpayserver/btcpayserver:2.3.9` image, fixing the plugin catalog crash caused by newer plugin dependency version metadata while preserving existing datadirs and Postgres databases.
|
- BTCPay Server now ships on the official `docker.io/btcpayserver/btcpayserver:2.3.9` image, fixing the plugin catalog crash caused by newer plugin dependency version metadata while preserving existing datadirs and Postgres databases.
|
||||||
|
|||||||
@ -275,6 +275,23 @@
|
|||||||
"args": ["sh", "-c", "tailscaled --tun=userspace-networking & sleep 2; tailscale web --listen 0.0.0.0:8240 & wait"]
|
"args": ["sh", "-c", "tailscaled --tun=userspace-networking & sleep 2; tailscale web --listen 0.0.0.0:8240 & wait"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "netbird",
|
||||||
|
"title": "NetBird",
|
||||||
|
"version": "0.71.2",
|
||||||
|
"description": "WireGuard mesh VPN client for secure remote access through NetBird Cloud or a self-hosted management server.",
|
||||||
|
"icon": "/assets/img/app-icons/netbird.svg",
|
||||||
|
"author": "NetBird",
|
||||||
|
"category": "networking",
|
||||||
|
"tier": "recommended",
|
||||||
|
"dockerImage": "docker.io/netbirdio/netbird:0.71.2",
|
||||||
|
"repoUrl": "https://github.com/netbirdio/netbird",
|
||||||
|
"containerConfig": {
|
||||||
|
"volumes": ["/var/lib/archipelago/netbird:/var/lib/netbird"],
|
||||||
|
"env": ["NB_SETUP_KEY=", "NB_MANAGEMENT_URL="],
|
||||||
|
"args": ["up"]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "uptime-kuma",
|
"id": "uptime-kuma",
|
||||||
"title": "Uptime Kuma",
|
"title": "Uptime Kuma",
|
||||||
|
|||||||
@ -217,9 +217,9 @@ pub(super) fn get_app_capabilities(app_id: &str) -> Vec<String> {
|
|||||||
"--cap-add=DAC_OVERRIDE".to_string(),
|
"--cap-add=DAC_OVERRIDE".to_string(),
|
||||||
"--cap-add=NET_BIND_SERVICE".to_string(),
|
"--cap-add=NET_BIND_SERVICE".to_string(),
|
||||||
],
|
],
|
||||||
// Nostr VPN and FIPS: mesh networking daemons need TUN + NET_ADMIN
|
// VPN/mesh daemons need TUN + NET_ADMIN.
|
||||||
// Note: --device=/dev/net/tun is added separately in install.rs
|
// Note: --device=/dev/net/tun is added separately in install.rs
|
||||||
"nostr-vpn" | "fips" => vec![
|
"nostr-vpn" | "fips" | "netbird" => vec![
|
||||||
"--cap-add=NET_ADMIN".to_string(),
|
"--cap-add=NET_ADMIN".to_string(),
|
||||||
"--cap-add=NET_RAW".to_string(),
|
"--cap-add=NET_RAW".to_string(),
|
||||||
],
|
],
|
||||||
@ -329,6 +329,7 @@ pub(super) fn get_health_check_args(app_id: &str, _rpc_pass: &str) -> Vec<String
|
|||||||
"3",
|
"3",
|
||||||
),
|
),
|
||||||
"nostr-vpn" => ("nvpn status || exit 1", "30s", "3"),
|
"nostr-vpn" => ("nvpn status || exit 1", "30s", "3"),
|
||||||
|
"netbird" => ("netbird status || exit 1", "30s", "3"),
|
||||||
"fips" => ("fipsctl status || exit 1", "30s", "3"),
|
"fips" => ("fipsctl status || exit 1", "30s", "3"),
|
||||||
_ => return vec![],
|
_ => return vec![],
|
||||||
};
|
};
|
||||||
@ -389,6 +390,7 @@ pub(super) fn get_memory_limit(app_id: &str) -> &'static str {
|
|||||||
"nostr-rs-relay" | "nostr-relay" => "256m",
|
"nostr-rs-relay" | "nostr-relay" => "256m",
|
||||||
"routstr" => "512m",
|
"routstr" => "512m",
|
||||||
"nostr-vpn" => "256m",
|
"nostr-vpn" => "256m",
|
||||||
|
"netbird" => "256m",
|
||||||
"fips" => "256m",
|
"fips" => "256m",
|
||||||
"nginx-proxy-manager" => "256m",
|
"nginx-proxy-manager" => "256m",
|
||||||
// Databases
|
// Databases
|
||||||
|
|||||||
@ -552,6 +552,7 @@ impl RpcHandler {
|
|||||||
"uptime-kuma"
|
"uptime-kuma"
|
||||||
| "gitea"
|
| "gitea"
|
||||||
| "tailscale"
|
| "tailscale"
|
||||||
|
| "netbird"
|
||||||
| "vaultwarden"
|
| "vaultwarden"
|
||||||
| "homeassistant"
|
| "homeassistant"
|
||||||
| "home-assistant"
|
| "home-assistant"
|
||||||
@ -626,6 +627,10 @@ impl RpcHandler {
|
|||||||
run_args.push("--tmpfs=/tmp:rw,exec,size=256m");
|
run_args.push("--tmpfs=/tmp:rw,exec,size=256m");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if package_id == "netbird" {
|
||||||
|
run_args.push("--device=/dev/net/tun:/dev/net/tun");
|
||||||
|
}
|
||||||
|
|
||||||
// Create data directories (mkdir only — chown happens AFTER config files are written)
|
// Create data directories (mkdir only — chown happens AFTER config files are written)
|
||||||
for volume in &volumes {
|
for volume in &volumes {
|
||||||
if let Some(host_path) = volume.split(':').next() {
|
if let Some(host_path) = volume.split(':').next() {
|
||||||
|
|||||||
@ -281,7 +281,7 @@ fn get_app_tier(app_id: &str) -> &'static str {
|
|||||||
"uptime-kuma" => "recommended",
|
"uptime-kuma" => "recommended",
|
||||||
"grafana" => "recommended",
|
"grafana" => "recommended",
|
||||||
"searxng" => "recommended",
|
"searxng" => "recommended",
|
||||||
"tailscale" => "recommended",
|
"tailscale" | "netbird" => "recommended",
|
||||||
"portainer" => "recommended",
|
"portainer" => "recommended",
|
||||||
// Optional: everything else
|
// Optional: everything else
|
||||||
_ => "optional",
|
_ => "optional",
|
||||||
@ -479,6 +479,13 @@ fn get_app_metadata(app_id: &str) -> AppMetadata {
|
|||||||
repo: "https://github.com/tailscale/tailscale".to_string(),
|
repo: "https://github.com/tailscale/tailscale".to_string(),
|
||||||
tier: "",
|
tier: "",
|
||||||
},
|
},
|
||||||
|
"netbird" => AppMetadata {
|
||||||
|
title: "NetBird".to_string(),
|
||||||
|
description: "WireGuard mesh VPN client for secure remote access".to_string(),
|
||||||
|
icon: "/assets/img/app-icons/netbird.svg".to_string(),
|
||||||
|
repo: "https://github.com/netbirdio/netbird".to_string(),
|
||||||
|
tier: "",
|
||||||
|
},
|
||||||
"indeedhub" | "indeehub" => AppMetadata {
|
"indeedhub" | "indeehub" => AppMetadata {
|
||||||
title: "IndeedHub".to_string(),
|
title: "IndeedHub".to_string(),
|
||||||
description: "Decentralized media streaming platform".to_string(),
|
description: "Decentralized media streaming platform".to_string(),
|
||||||
|
|||||||
@ -168,6 +168,7 @@ fn image_var_for_app(app_id: &str) -> Option<&'static str> {
|
|||||||
"nginx-proxy-manager" => Some("NPM_IMAGE"),
|
"nginx-proxy-manager" => Some("NPM_IMAGE"),
|
||||||
"portainer" => Some("PORTAINER_IMAGE"),
|
"portainer" => Some("PORTAINER_IMAGE"),
|
||||||
"tailscale" => Some("TAILSCALE_IMAGE"),
|
"tailscale" => Some("TAILSCALE_IMAGE"),
|
||||||
|
"netbird" => Some("NETBIRD_IMAGE"),
|
||||||
|
|
||||||
// Fedimint
|
// Fedimint
|
||||||
"fedimint" | "fedimintd" => Some("FEDIMINT_IMAGE"),
|
"fedimint" | "fedimintd" => Some("FEDIMINT_IMAGE"),
|
||||||
|
|||||||
@ -337,6 +337,7 @@ RUN apt-get update && apt-get -y full-upgrade && apt-get install -y --no-install
|
|||||||
curl \
|
curl \
|
||||||
git \
|
git \
|
||||||
vim-tiny \
|
vim-tiny \
|
||||||
|
nano \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
openssl \
|
openssl \
|
||||||
chrony \
|
chrony \
|
||||||
|
|||||||
@ -179,6 +179,7 @@ chroot /mnt/archipelago apt-get install -y \
|
|||||||
wget \
|
wget \
|
||||||
htop \
|
htop \
|
||||||
vim-tiny \
|
vim-tiny \
|
||||||
|
nano \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
chrony
|
chrony
|
||||||
|
|
||||||
|
|||||||
12
neode-ui/public/assets/img/app-icons/netbird.svg
Normal file
12
neode-ui/public/assets/img/app-icons/netbird.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="NetBird">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="g" x1="18" y1="14" x2="110" y2="116" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#24c8ff"/>
|
||||||
|
<stop offset="1" stop-color="#3157ff"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="128" height="128" rx="28" fill="#071422"/>
|
||||||
|
<path d="M28 72c16-30 39-46 72-50-11 13-18 26-21 40 10-1 19 1 29 5-19 4-35 13-48 27-8 8-18 12-30 12 7-7 12-14 15-22-7 0-13-4-17-12Z" fill="url(#g)"/>
|
||||||
|
<circle cx="82" cy="43" r="6" fill="#fff" opacity=".95"/>
|
||||||
|
<path d="M36 72c10 3 20 4 30 2" fill="none" stroke="#fff" stroke-width="6" stroke-linecap="round" opacity=".8"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 702 B |
@ -275,6 +275,23 @@
|
|||||||
"args": ["sh", "-c", "tailscaled --tun=userspace-networking & sleep 2; tailscale web --listen 0.0.0.0:8240 & wait"]
|
"args": ["sh", "-c", "tailscaled --tun=userspace-networking & sleep 2; tailscale web --listen 0.0.0.0:8240 & wait"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "netbird",
|
||||||
|
"title": "NetBird",
|
||||||
|
"version": "0.71.2",
|
||||||
|
"description": "WireGuard mesh VPN client for secure remote access through NetBird Cloud or a self-hosted management server.",
|
||||||
|
"icon": "/assets/img/app-icons/netbird.svg",
|
||||||
|
"author": "NetBird",
|
||||||
|
"category": "networking",
|
||||||
|
"tier": "recommended",
|
||||||
|
"dockerImage": "docker.io/netbirdio/netbird:0.71.2",
|
||||||
|
"repoUrl": "https://github.com/netbirdio/netbird",
|
||||||
|
"containerConfig": {
|
||||||
|
"volumes": ["/var/lib/archipelago/netbird:/var/lib/netbird"],
|
||||||
|
"env": ["NB_SETUP_KEY=", "NB_MANAGEMENT_URL="],
|
||||||
|
"args": ["up"]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "uptime-kuma",
|
"id": "uptime-kuma",
|
||||||
"title": "Uptime Kuma",
|
"title": "Uptime Kuma",
|
||||||
|
|||||||
@ -532,7 +532,7 @@ class RPCClient {
|
|||||||
return this.call({
|
return this.call({
|
||||||
method: 'package.install',
|
method: 'package.install',
|
||||||
params: { id, 'marketplace-url': marketplaceUrl, version },
|
params: { id, 'marketplace-url': marketplaceUrl, version },
|
||||||
timeout: 15000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -940,4 +940,3 @@ class RPCClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const rpcClient = new RPCClient()
|
export const rpcClient = new RPCClient()
|
||||||
|
|
||||||
|
|||||||
@ -464,7 +464,7 @@ async function submitSideload() {
|
|||||||
version: 'sideload',
|
version: 'sideload',
|
||||||
containerConfig,
|
containerConfig,
|
||||||
},
|
},
|
||||||
timeout: 15000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
closeSideload()
|
closeSideload()
|
||||||
sideloadForm.value = { id: '', image: '', title: '', port: '', description: '' }
|
sideloadForm.value = { id: '', image: '', title: '', port: '', description: '' }
|
||||||
|
|||||||
@ -383,7 +383,7 @@ function isStartingUp(appId: string): boolean {
|
|||||||
|
|
||||||
function getAppTier(appId: string): string {
|
function getAppTier(appId: string): string {
|
||||||
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
||||||
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'portainer']
|
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'netbird', 'portainer']
|
||||||
if (core.includes(appId)) return 'core'
|
if (core.includes(appId)) return 'core'
|
||||||
if (recommended.includes(appId)) return 'recommended'
|
if (recommended.includes(appId)) return 'recommended'
|
||||||
return 'optional'
|
return 'optional'
|
||||||
@ -487,7 +487,7 @@ async function installApp(app: MarketplaceApp) {
|
|||||||
router.push('/dashboard/apps').catch(() => {})
|
router.push('/dashboard/apps').catch(() => {})
|
||||||
try {
|
try {
|
||||||
const installUrl = app.url || app.manifestUrl || app.s9pkUrl
|
const installUrl = app.url || app.manifestUrl || app.s9pkUrl
|
||||||
await rpcClient.call({ method: 'package.install', params: { id: app.id, url: installUrl, version: app.version }, timeout: 15000 })
|
await rpcClient.call({ method: 'package.install', params: { id: app.id, url: installUrl, version: app.version }, timeout: 600000 })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (import.meta.env.DEV) console.error('Installation failed:', err)
|
if (import.meta.env.DEV) console.error('Installation failed:', err)
|
||||||
failInstall(app, err)
|
failInstall(app, err)
|
||||||
@ -504,7 +504,7 @@ async function installCommunityApp(app: MarketplaceApp) {
|
|||||||
if ((app as Record<string, unknown>).containerConfig) {
|
if ((app as Record<string, unknown>).containerConfig) {
|
||||||
installParams.containerConfig = (app as Record<string, unknown>).containerConfig
|
installParams.containerConfig = (app as Record<string, unknown>).containerConfig
|
||||||
}
|
}
|
||||||
await rpcClient.call({ method: 'package.install', params: installParams, timeout: 15000 })
|
await rpcClient.call({ method: 'package.install', params: installParams, timeout: 600000 })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (import.meta.env.DEV) console.error('[Discover] Installation failed:', err)
|
if (import.meta.env.DEV) console.error('[Discover] Installation failed:', err)
|
||||||
failInstall(app, err)
|
failInstall(app, err)
|
||||||
|
|||||||
@ -415,7 +415,7 @@ async function installApp(app: MarketplaceApp) {
|
|||||||
await rpcClient.call({
|
await rpcClient.call({
|
||||||
method: 'package.install',
|
method: 'package.install',
|
||||||
params: { id: app.id, url: installUrl, version: app.version },
|
params: { id: app.id, url: installUrl, version: app.version },
|
||||||
timeout: 15000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (import.meta.env.DEV) console.error('Installation failed:', err)
|
if (import.meta.env.DEV) console.error('Installation failed:', err)
|
||||||
@ -441,7 +441,7 @@ async function installCommunityApp(app: MarketplaceApp) {
|
|||||||
await rpcClient.call({
|
await rpcClient.call({
|
||||||
method: 'package.install',
|
method: 'package.install',
|
||||||
params: installParams,
|
params: installParams,
|
||||||
timeout: 15000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (import.meta.env.DEV) console.error('[Marketplace] Installation failed:', err)
|
if (import.meta.env.DEV) console.error('[Marketplace] Installation failed:', err)
|
||||||
|
|||||||
@ -616,7 +616,7 @@ async function installApp() {
|
|||||||
await rpcClient.call({
|
await rpcClient.call({
|
||||||
method: 'package.install',
|
method: 'package.install',
|
||||||
params: installParams,
|
params: installParams,
|
||||||
timeout: 15000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// Package-based installation
|
// Package-based installation
|
||||||
@ -628,7 +628,7 @@ async function installApp() {
|
|||||||
url: installUrl,
|
url: installUrl,
|
||||||
version: app.value.version,
|
version: app.value.version,
|
||||||
},
|
},
|
||||||
timeout: 15000,
|
timeout: 600000,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,7 @@ export const ROUTE_TO_PACKAGE_KEY: Record<string, string> = {
|
|||||||
portainer: 'portainer',
|
portainer: 'portainer',
|
||||||
'uptime-kuma': 'uptime-kuma',
|
'uptime-kuma': 'uptime-kuma',
|
||||||
tailscale: 'tailscale',
|
tailscale: 'tailscale',
|
||||||
|
netbird: 'netbird',
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Backend may register under variant container names */
|
/** Backend may register under variant container names */
|
||||||
|
|||||||
@ -266,7 +266,7 @@ const tier = computed(() => {
|
|||||||
const t = props.pkg.manifest?.tier
|
const t = props.pkg.manifest?.tier
|
||||||
if (t && t !== '') return t
|
if (t && t !== '') return t
|
||||||
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
||||||
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'portainer']
|
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'netbird', 'portainer']
|
||||||
if (core.includes(props.id)) return 'core'
|
if (core.includes(props.id)) return 'core'
|
||||||
if (recommended.includes(props.id)) return 'recommended'
|
if (recommended.includes(props.id)) return 'recommended'
|
||||||
return 'optional'
|
return 'optional'
|
||||||
|
|||||||
@ -55,9 +55,9 @@ export const APP_CATEGORY_MAP: Record<string, string> = {
|
|||||||
'indeedhub': 'media', 'jellyfin': 'media', 'photoprism': 'media', 'immich': 'media',
|
'indeedhub': 'media', 'jellyfin': 'media', 'photoprism': 'media', 'immich': 'media',
|
||||||
'nextcloud': 'data', 'vaultwarden': 'data', 'filebrowser': 'data', 'cryptpad': 'data',
|
'nextcloud': 'data', 'vaultwarden': 'data', 'filebrowser': 'data', 'cryptpad': 'data',
|
||||||
'homeassistant': 'home', 'lorabell': 'home', 'endurain': 'home',
|
'homeassistant': 'home', 'lorabell': 'home', 'endurain': 'home',
|
||||||
'searxng': 'community', 'ollama': 'community', 'grafana': 'data',
|
'searxng': 'community', 'ollama': 'community', 'grafana': 'data', 'gitea': 'data',
|
||||||
'nostrudel': 'nostr',
|
'nostrudel': 'nostr',
|
||||||
'tailscale': 'networking', 'nginx-proxy-manager': 'networking', 'portainer': 'networking',
|
'tailscale': 'networking', 'netbird': 'networking', 'nginx-proxy-manager': 'networking', 'portainer': 'networking',
|
||||||
'uptime-kuma': 'networking', 'dwn': 'data',
|
'uptime-kuma': 'networking', 'dwn': 'data',
|
||||||
'botfights': 'community', 'nwnn': 'l484', '484-kitchen': 'l484',
|
'botfights': 'community', 'nwnn': 'l484', '484-kitchen': 'l484',
|
||||||
'call-the-operator': 'l484', 'syntropy-institute': 'l484', 't-zero': 'l484',
|
'call-the-operator': 'l484', 'syntropy-institute': 'l484', 't-zero': 'l484',
|
||||||
|
|||||||
@ -96,6 +96,7 @@ export function getCuratedAppList(): MarketplaceApp[] {
|
|||||||
{ id: 'portainer', title: 'Portainer', version: '2.19.4', description: 'Container management UI. Manage your containerized services through the web.', icon: '/assets/img/app-icons/portainer.webp', author: 'Portainer', dockerImage: `${R}/portainer:latest`, repoUrl: 'https://github.com/portainer/portainer' },
|
{ id: 'portainer', title: 'Portainer', version: '2.19.4', description: 'Container management UI. Manage your containerized services through the web.', icon: '/assets/img/app-icons/portainer.webp', author: 'Portainer', dockerImage: `${R}/portainer:latest`, repoUrl: 'https://github.com/portainer/portainer' },
|
||||||
{ id: 'uptime-kuma', title: 'Uptime Kuma', version: '1.23.0', description: 'Self-hosted uptime monitoring. Track HTTP, TCP, DNS, and more.', icon: '/assets/img/app-icons/uptime-kuma.webp', author: 'Uptime Kuma', dockerImage: `${R}/uptime-kuma:1`, repoUrl: 'https://github.com/louislam/uptime-kuma' },
|
{ id: 'uptime-kuma', title: 'Uptime Kuma', version: '1.23.0', description: 'Self-hosted uptime monitoring. Track HTTP, TCP, DNS, and more.', icon: '/assets/img/app-icons/uptime-kuma.webp', author: 'Uptime Kuma', dockerImage: `${R}/uptime-kuma:1`, repoUrl: 'https://github.com/louislam/uptime-kuma' },
|
||||||
{ id: 'tailscale', title: 'Tailscale', version: '1.78.0', description: 'Zero-config VPN. Secure remote access with WireGuard mesh networking.', icon: '/assets/img/app-icons/tailscale.webp', author: 'Tailscale', dockerImage: `${R}/tailscale:stable`, repoUrl: 'https://github.com/tailscale/tailscale' },
|
{ id: 'tailscale', title: 'Tailscale', version: '1.78.0', description: 'Zero-config VPN. Secure remote access with WireGuard mesh networking.', icon: '/assets/img/app-icons/tailscale.webp', author: 'Tailscale', dockerImage: `${R}/tailscale:stable`, repoUrl: 'https://github.com/tailscale/tailscale' },
|
||||||
|
{ id: 'netbird', title: 'NetBird', version: '0.71.2', description: 'WireGuard mesh VPN client. Connect this node through NetBird Cloud or your own NetBird management server.', icon: '/assets/img/app-icons/netbird.svg', author: 'NetBird', dockerImage: 'docker.io/netbirdio/netbird:0.71.2', repoUrl: 'https://github.com/netbirdio/netbird' },
|
||||||
{ id: 'electrumx', title: 'ElectrumX', version: '1.18.0', description: 'Electrum protocol server. Index the blockchain for fast wallet lookups, privately.', icon: '/assets/img/app-icons/electrumx.png', author: 'Luke Childs', dockerImage: `${R}/electrumx:v1.18.0`, repoUrl: 'https://github.com/spesmilo/electrumx' },
|
{ id: 'electrumx', title: 'ElectrumX', version: '1.18.0', description: 'Electrum protocol server. Index the blockchain for fast wallet lookups, privately.', icon: '/assets/img/app-icons/electrumx.png', author: 'Luke Childs', dockerImage: `${R}/electrumx:v1.18.0`, repoUrl: 'https://github.com/spesmilo/electrumx' },
|
||||||
{ id: 'fedimint', title: 'Fedimint', version: '0.10.0', description: 'Federated Bitcoin mint. Private, scalable Bitcoin through federated guardians.', icon: '/assets/img/app-icons/fedimint.png', author: 'Fedimint', dockerImage: `${R}/fedimintd:v0.10.0`, repoUrl: 'https://github.com/fedimint/fedimint' },
|
{ id: 'fedimint', title: 'Fedimint', version: '0.10.0', description: 'Federated Bitcoin mint. Private, scalable Bitcoin through federated guardians.', icon: '/assets/img/app-icons/fedimint.png', author: 'Fedimint', dockerImage: `${R}/fedimintd:v0.10.0`, repoUrl: 'https://github.com/fedimint/fedimint' },
|
||||||
{ id: 'indeedhub', title: 'Indeehub', version: '1.0.0', description: 'Bitcoin documentary streaming with Nostr identity. Stream sovereignty content.', icon: '/assets/img/app-icons/indeedhub.png', author: 'Indeehub Team', dockerImage: `${R}/indeedhub:1.0.0`, repoUrl: 'https://github.com/indeedhub/indeedhub' },
|
{ id: 'indeedhub', title: 'Indeehub', version: '1.0.0', description: 'Bitcoin documentary streaming with Nostr identity. Stream sovereignty content.', icon: '/assets/img/app-icons/indeedhub.png', author: 'Indeehub Team', dockerImage: `${R}/indeedhub:1.0.0`, repoUrl: 'https://github.com/indeedhub/indeedhub' },
|
||||||
@ -132,6 +133,7 @@ export const INSTALLED_ALIASES: Record<string, string[]> = {
|
|||||||
lnd: ['lnd'],
|
lnd: ['lnd'],
|
||||||
filebrowser: ['filebrowser'],
|
filebrowser: ['filebrowser'],
|
||||||
tailscale: ['tailscale'],
|
tailscale: ['tailscale'],
|
||||||
|
netbird: ['netbird'],
|
||||||
ollama: ['ollama'],
|
ollama: ['ollama'],
|
||||||
indeedhub: ['indeedhub'],
|
indeedhub: ['indeedhub'],
|
||||||
botfights: ['botfights'],
|
botfights: ['botfights'],
|
||||||
@ -191,7 +193,7 @@ export function categorizeCommunityApp(app: MarketplaceApp): string {
|
|||||||
if (id.includes('cloud') || id.includes('nextcloud') || id.includes('storage') || id.includes('file') || id.includes('photo') || id.includes('immich') || id.includes('jellyfin') || id.includes('media') || id.includes('vault') || combined.includes('password manager')) return 'data'
|
if (id.includes('cloud') || id.includes('nextcloud') || id.includes('storage') || id.includes('file') || id.includes('photo') || id.includes('immich') || id.includes('jellyfin') || id.includes('media') || id.includes('vault') || combined.includes('password manager')) return 'data'
|
||||||
if (id.includes('home-assistant') || id.includes('homeassistant') || combined.includes('home automation')) return 'home'
|
if (id.includes('home-assistant') || id.includes('homeassistant') || combined.includes('home automation')) return 'home'
|
||||||
if (id.includes('nostr') || combined.includes('nostr relay')) return 'nostr'
|
if (id.includes('nostr') || combined.includes('nostr relay')) return 'nostr'
|
||||||
if (id.includes('vpn') || id.includes('wireguard') || id.includes('tailscale') || id.includes('proxy') || id.includes('dns') || id.includes('tor') || combined.includes('network')) return 'networking'
|
if (id.includes('vpn') || id.includes('wireguard') || id.includes('tailscale') || id.includes('netbird') || id.includes('proxy') || id.includes('dns') || id.includes('tor') || combined.includes('network')) return 'networking'
|
||||||
if (id.includes('matrix') || id.includes('mastodon') || id.includes('chat') || id.includes('social') || combined.includes('messaging')) return 'community'
|
if (id.includes('matrix') || id.includes('mastodon') || id.includes('chat') || id.includes('social') || combined.includes('messaging')) return 'community'
|
||||||
return 'other'
|
return 'other'
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,13 +60,14 @@ export const INSTALLED_ALIASES: Record<string, string[]> = {
|
|||||||
lnd: ['lnd', 'archy-lnd-ui'],
|
lnd: ['lnd', 'archy-lnd-ui'],
|
||||||
filebrowser: ['filebrowser'],
|
filebrowser: ['filebrowser'],
|
||||||
tailscale: ['tailscale'],
|
tailscale: ['tailscale'],
|
||||||
|
netbird: ['netbird'],
|
||||||
ollama: ['ollama'],
|
ollama: ['ollama'],
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get app tier classification (matches backend get_app_tier) */
|
/** Get app tier classification (matches backend get_app_tier) */
|
||||||
export function getAppTier(appId: string): string {
|
export function getAppTier(appId: string): string {
|
||||||
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
const core = ['bitcoin-knots', 'bitcoin', 'lnd', 'mempool', 'btcpay-server', 'dwn', 'filebrowser']
|
||||||
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'portainer']
|
const recommended = ['fedimint', 'thunderhub', 'vaultwarden', 'uptime-kuma', 'grafana', 'searxng', 'tailscale', 'netbird', 'portainer']
|
||||||
if (core.includes(appId)) return 'core'
|
if (core.includes(appId)) return 'core'
|
||||||
if (recommended.includes(appId)) return 'recommended'
|
if (recommended.includes(appId)) return 'recommended'
|
||||||
return 'optional'
|
return 'optional'
|
||||||
@ -113,7 +114,7 @@ export function categorizeCommunityApp(app: MarketplaceApp): string {
|
|||||||
return 'nostr'
|
return 'nostr'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.includes('vpn') || id.includes('wireguard') || id.includes('tailscale') ||
|
if (id.includes('vpn') || id.includes('wireguard') || id.includes('tailscale') || id.includes('netbird') ||
|
||||||
id.includes('proxy') || id.includes('dns') || id.includes('pihole') ||
|
id.includes('proxy') || id.includes('dns') || id.includes('pihole') ||
|
||||||
id.includes('adguard') || id.includes('nginx') || id.includes('tor') ||
|
id.includes('adguard') || id.includes('nginx') || id.includes('tor') ||
|
||||||
combined.includes('network') || combined.includes('firewall')) {
|
combined.includes('network') || combined.includes('firewall')) {
|
||||||
@ -365,6 +366,17 @@ export function getCuratedAppList(): MarketplaceApp[] {
|
|||||||
manifestUrl: undefined,
|
manifestUrl: undefined,
|
||||||
repoUrl: 'https://github.com/tailscale/tailscale'
|
repoUrl: 'https://github.com/tailscale/tailscale'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'netbird',
|
||||||
|
title: 'NetBird',
|
||||||
|
version: '0.71.2',
|
||||||
|
description: 'WireGuard mesh VPN client. Connect this node through NetBird Cloud or a self-hosted management server.',
|
||||||
|
icon: '/assets/img/app-icons/netbird.svg',
|
||||||
|
author: 'NetBird',
|
||||||
|
dockerImage: 'docker.io/netbirdio/netbird:0.71.2',
|
||||||
|
manifestUrl: undefined,
|
||||||
|
repoUrl: 'https://github.com/netbirdio/netbird'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'fedimint',
|
id: 'fedimint',
|
||||||
title: 'Fedimint',
|
title: 'Fedimint',
|
||||||
|
|||||||
@ -48,6 +48,7 @@ PORTAINER_IMAGE="$ARCHY_REGISTRY/portainer:latest"
|
|||||||
|
|
||||||
# Networking
|
# Networking
|
||||||
TAILSCALE_IMAGE="$ARCHY_REGISTRY/tailscale:stable"
|
TAILSCALE_IMAGE="$ARCHY_REGISTRY/tailscale:stable"
|
||||||
|
NETBIRD_IMAGE="docker.io/netbirdio/netbird:0.71.2"
|
||||||
ALPINE_TOR_IMAGE="$ARCHY_REGISTRY/alpine-tor:0.4.8.13"
|
ALPINE_TOR_IMAGE="$ARCHY_REGISTRY/alpine-tor:0.4.8.13"
|
||||||
ADGUARDHOME_IMAGE="$ARCHY_REGISTRY/adguardhome:v0.107.55"
|
ADGUARDHOME_IMAGE="$ARCHY_REGISTRY/adguardhome:v0.107.55"
|
||||||
|
|
||||||
|
|||||||
@ -75,6 +75,15 @@ fi
|
|||||||
|
|
||||||
cd "$REPO_DIR"
|
cd "$REPO_DIR"
|
||||||
|
|
||||||
|
if ! command -v nano >/dev/null 2>&1; then
|
||||||
|
log "Installing nano for Archipelago terminal..."
|
||||||
|
if sudo apt-get update -qq 2>>"$LOG_FILE" && sudo apt-get install -y -qq nano 2>>"$LOG_FILE"; then
|
||||||
|
ok "nano installed"
|
||||||
|
else
|
||||||
|
warn "Unable to install nano automatically; continuing update"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Fetch latest
|
# Fetch latest
|
||||||
log "Fetching from origin..."
|
log "Fetching from origin..."
|
||||||
git fetch origin main --quiet 2>>"$LOG_FILE"
|
git fetch origin main --quiet 2>>"$LOG_FILE"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user