Enhance README and RPC for package management
- Added instructions to README.md for building an ISO from source and flashing it to USB. - Introduced a new RPC method for package installation, including security checks and container management. - Updated Docker and Podman integration in build scripts to support both container runtimes. - Enhanced Nginx configuration for improved timeout settings and WebSocket support. - Added new app metadata for additional applications in the Docker package scanner.
This commit is contained in:
@@ -18,6 +18,9 @@ export class WebSocketClient {
|
||||
private reconnectTimer: ReturnType<typeof setTimeout> | null = null
|
||||
private visibilityChangeHandler: (() => void) | null = null
|
||||
private onlineHandler: (() => void) | null = null
|
||||
private heartbeatTimer: ReturnType<typeof setTimeout> | null = null
|
||||
private lastMessageTime: number = Date.now()
|
||||
private heartbeatInterval = 10000 // Check connection every 10 seconds
|
||||
|
||||
constructor(url: string = '/ws/db') {
|
||||
this.url = url
|
||||
@@ -132,8 +135,10 @@ export class WebSocketClient {
|
||||
this.ws.onopen = () => {
|
||||
clearTimeout(connectionTimeout)
|
||||
this.reconnectAttempts = 0
|
||||
this.lastMessageTime = Date.now()
|
||||
console.log('[WebSocket] Connected successfully')
|
||||
this.notifyConnectionState(true)
|
||||
this.startHeartbeat()
|
||||
resolve()
|
||||
}
|
||||
|
||||
@@ -145,6 +150,7 @@ export class WebSocketClient {
|
||||
}
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
this.lastMessageTime = Date.now()
|
||||
try {
|
||||
const update: Update = JSON.parse(event.data)
|
||||
this.callbacks.forEach((callback) => callback(update))
|
||||
@@ -155,6 +161,7 @@ export class WebSocketClient {
|
||||
|
||||
this.ws.onclose = (event) => {
|
||||
clearTimeout(connectionTimeout)
|
||||
this.stopHeartbeat()
|
||||
console.log('[WebSocket] Closed', { code: event.code, reason: event.reason, wasClean: event.wasClean })
|
||||
|
||||
// Notify connection state changed
|
||||
@@ -243,9 +250,39 @@ export class WebSocketClient {
|
||||
this.connectionStateCallbacks.forEach((callback) => callback(connected))
|
||||
}
|
||||
|
||||
private startHeartbeat(): void {
|
||||
this.stopHeartbeat()
|
||||
|
||||
this.heartbeatTimer = setInterval(() => {
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
||||
console.warn('[WebSocket] Heartbeat detected closed connection')
|
||||
this.stopHeartbeat()
|
||||
return
|
||||
}
|
||||
|
||||
// Check if we've received a message recently
|
||||
const timeSinceLastMessage = Date.now() - this.lastMessageTime
|
||||
|
||||
// If no message for more than 60 seconds, assume connection is stale
|
||||
if (timeSinceLastMessage > 60000) {
|
||||
console.warn('[WebSocket] No messages for 60s, reconnecting...')
|
||||
this.ws.close()
|
||||
return
|
||||
}
|
||||
}, this.heartbeatInterval)
|
||||
}
|
||||
|
||||
private stopHeartbeat(): void {
|
||||
if (this.heartbeatTimer) {
|
||||
clearInterval(this.heartbeatTimer)
|
||||
this.heartbeatTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(): void {
|
||||
this.shouldReconnect = false
|
||||
this.reconnectAttempts = 0
|
||||
this.stopHeartbeat()
|
||||
|
||||
// Clear reconnect timer
|
||||
if (this.reconnectTimer) {
|
||||
|
||||
@@ -335,7 +335,7 @@ export const dummyApps: Record<string, PackageDataEntry> = {
|
||||
'static-files': {
|
||||
license: 'MIT',
|
||||
instructions: 'Local AI model runner',
|
||||
icon: '/assets/img/ollama.webp'
|
||||
icon: '/assets/img/app-icons/ollama.png'
|
||||
},
|
||||
manifest: {
|
||||
id: 'ollama',
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
Already Installed
|
||||
</button>
|
||||
<button
|
||||
v-else-if="app.source === 'local' || app.manifestUrl"
|
||||
v-else-if="app.source === 'local' || app.dockerImage"
|
||||
@click.stop="app.source === 'local' ? installApp(app) : installCommunityApp(app)"
|
||||
:disabled="installing === app.id || installing !== null"
|
||||
class="flex-1 px-4 py-2 gradient-button rounded-lg text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
@@ -268,7 +268,10 @@
|
||||
<div class="flex items-center gap-3">
|
||||
<!-- Category Icon -->
|
||||
<div class="flex-shrink-0 w-10 h-10 rounded-lg bg-white/10 flex items-center justify-center">
|
||||
<svg v-if="category.id === 'community'" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg v-if="category.id === 'all'" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
|
||||
</svg>
|
||||
<svg v-else-if="category.id === 'community'" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
<svg v-else-if="category.id === 'commerce'" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -323,9 +326,10 @@ const { setCurrentApp } = useMarketplaceApp()
|
||||
const { bottomPosition } = useMobileBackButton()
|
||||
|
||||
// Category state
|
||||
const selectedCategory = ref('community')
|
||||
const selectedCategory = ref('all')
|
||||
|
||||
const categories = [
|
||||
{ id: 'all', name: 'All' },
|
||||
{ id: 'community', name: 'Community' },
|
||||
{ id: 'commerce', name: 'Commerce' },
|
||||
{ id: 'money', name: 'Money' },
|
||||
@@ -358,68 +362,33 @@ const communityApps = ref<any[]>([])
|
||||
const searchQuery = ref('')
|
||||
|
||||
// Available apps in marketplace
|
||||
const availableApps = ref([
|
||||
{
|
||||
id: 'atob',
|
||||
title: 'A to B Bitcoin',
|
||||
version: '0.1.0',
|
||||
icon: '/assets/img/atob.png',
|
||||
category: 'community',
|
||||
description: {
|
||||
short: 'Bitcoin tools and services for seamless transactions',
|
||||
long: 'A to B Bitcoin provides tools and services for Bitcoin transactions. Access the A to B platform through your Archipelago server with full privacy and control.'
|
||||
},
|
||||
s9pkUrl: '/packages/atob.s9pk'
|
||||
},
|
||||
{
|
||||
id: 'k484',
|
||||
title: 'K484',
|
||||
version: '0.1.0',
|
||||
icon: '/assets/img/k484.png',
|
||||
category: 'commerce',
|
||||
description: {
|
||||
short: 'Point of Sale and Admin system for Archipelago',
|
||||
long: 'K484 provides a complete POS and administration system for your Archipelago server. Choose between POS mode for transactions or Admin mode for management.'
|
||||
},
|
||||
s9pkUrl: '/packages/k484.s9pk'
|
||||
},
|
||||
{
|
||||
id: 'btcpay',
|
||||
title: 'BTCPay Server',
|
||||
version: '0.1.0',
|
||||
icon: '/assets/img/btcpay.png',
|
||||
category: 'commerce',
|
||||
description: {
|
||||
short: 'Self-hosted Bitcoin payment processor',
|
||||
long: 'BTCPay Server is a free, open-source cryptocurrency payment processor. Accept Bitcoin payments without intermediaries or fees. Complete merchant solution with invoicing, point of sale, and more.'
|
||||
},
|
||||
s9pkUrl: '/packages/btcpay.s9pk'
|
||||
},
|
||||
{
|
||||
id: 'nextcloud',
|
||||
title: 'Nextcloud',
|
||||
version: '0.1.0',
|
||||
icon: '/assets/img/nextcloud.png',
|
||||
category: 'data',
|
||||
description: {
|
||||
short: 'Self-hosted file sync and collaboration platform',
|
||||
long: 'Nextcloud provides file storage, sync, and sharing with calendar, contacts, mail, and office suite integration. Your own private cloud with complete control over your data.'
|
||||
},
|
||||
s9pkUrl: '/packages/nextcloud.s9pk'
|
||||
},
|
||||
{
|
||||
id: 'home-assistant',
|
||||
title: 'Home Assistant',
|
||||
version: '0.1.0',
|
||||
icon: '/assets/img/home-assistant.png',
|
||||
category: 'home',
|
||||
description: {
|
||||
short: 'Open-source home automation platform',
|
||||
long: 'Home Assistant is a powerful home automation hub that allows you to control and automate your smart home devices privately. No cloud required - everything runs locally on your Archipelago server.'
|
||||
},
|
||||
s9pkUrl: '/packages/home-assistant.s9pk'
|
||||
}
|
||||
])
|
||||
// Note: s9pk packages disabled until sideload functionality is implemented
|
||||
// const availableApps = ref([
|
||||
// {
|
||||
// id: 'atob',
|
||||
// title: 'A to B Bitcoin',
|
||||
// version: '0.1.0',
|
||||
// icon: '/assets/img/atob.png',
|
||||
// category: 'community',
|
||||
// description: {
|
||||
// short: 'Bitcoin tools and services for seamless transactions',
|
||||
// long: 'A to B Bitcoin provides tools and services for Bitcoin transactions. Access the A to B platform through your Archipelago server with full privacy and control.'
|
||||
// },
|
||||
// s9pkUrl: '/packages/atob.s9pk'
|
||||
// },
|
||||
// {
|
||||
// id: 'k484',
|
||||
// title: 'K484',
|
||||
// version: '0.1.0',
|
||||
// icon: '/assets/img/k484.png',
|
||||
// category: 'commerce',
|
||||
// description: {
|
||||
// short: 'Point of Sale and Admin system for Archipelago',
|
||||
// long: 'K484 provides a complete POS and administration system for your Archipelago server. Choose between POS mode for transactions or Admin mode for management.'
|
||||
// },
|
||||
// s9pkUrl: '/packages/k484.s9pk'
|
||||
// },
|
||||
// ])
|
||||
|
||||
const installedPackages = computed(() => {
|
||||
return store.data?.['package-data'] || {}
|
||||
@@ -486,14 +455,8 @@ function categorizeCommunityApp(app: any): string {
|
||||
|
||||
// Combine local and community apps with categories
|
||||
const allApps = computed(() => {
|
||||
// Local apps already have categories - normalize field names
|
||||
const local = availableApps.value.map(app => ({
|
||||
...app,
|
||||
source: 'local',
|
||||
// Add manifestUrl and url for consistency with community apps
|
||||
manifestUrl: app.s9pkUrl,
|
||||
url: app.s9pkUrl
|
||||
}))
|
||||
// Local apps disabled until s9pk support is implemented
|
||||
const local: any[] = []
|
||||
|
||||
// Categorize community apps intelligently
|
||||
const community = communityApps.value.map(app => {
|
||||
@@ -567,14 +530,14 @@ function getCuratedAppList() {
|
||||
return [
|
||||
{
|
||||
id: 'bitcoin',
|
||||
title: 'Bitcoin Core',
|
||||
title: 'Bitcoin Knots',
|
||||
version: '27.0.0',
|
||||
description: 'Run a full Bitcoin node. Validate and relay blocks and transactions on the Bitcoin network.',
|
||||
icon: '/assets/img/app-icons/bitcoin.svg',
|
||||
author: 'Bitcoin Core',
|
||||
dockerImage: 'lncm/bitcoind:v27.0',
|
||||
icon: '/assets/img/app-icons/bitcoin-knots.webp',
|
||||
author: 'Bitcoin Knots',
|
||||
dockerImage: 'docker.io/lncm/bitcoind:v27.0',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/bitcoin/bitcoin'
|
||||
repoUrl: 'https://github.com/bitcoinknots/bitcoin'
|
||||
},
|
||||
{
|
||||
id: 'btcpay-server',
|
||||
@@ -583,7 +546,7 @@ function getCuratedAppList() {
|
||||
description: 'Self-hosted Bitcoin payment processor. Accept Bitcoin payments without intermediaries or fees.',
|
||||
icon: '/assets/img/app-icons/btcpay-server.png',
|
||||
author: 'BTCPay Server Foundation',
|
||||
dockerImage: 'btcpayserver/btcpayserver:1.13.5',
|
||||
dockerImage: 'docker.io/btcpayserver/btcpayserver:1.13.5',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/btcpayserver/btcpayserver'
|
||||
},
|
||||
@@ -592,9 +555,9 @@ function getCuratedAppList() {
|
||||
title: 'LND',
|
||||
version: '0.17.4',
|
||||
description: 'Lightning Network Daemon. Fast and cheap Bitcoin payments through the Lightning Network.',
|
||||
icon: '/assets/img/app-icons/lightning-stack.png',
|
||||
icon: '/assets/img/app-icons/lnd.svg',
|
||||
author: 'Lightning Labs',
|
||||
dockerImage: 'lightninglabs/lnd:v0.17.4-beta',
|
||||
dockerImage: 'docker.io/lightninglabs/lnd:v0.17.4-beta',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/lightningnetwork/lnd'
|
||||
},
|
||||
@@ -603,9 +566,9 @@ function getCuratedAppList() {
|
||||
title: 'Mempool Explorer',
|
||||
version: '2.5.0',
|
||||
description: 'Self-hosted Bitcoin blockchain and mempool visualizer with beautiful explorer interface.',
|
||||
icon: '/assets/img/app-icons/mempool.png',
|
||||
icon: '/assets/img/app-icons/mempool.webp',
|
||||
author: 'Mempool',
|
||||
dockerImage: 'mempool/frontend:v2.5.0',
|
||||
dockerImage: 'docker.io/mempool/frontend:v2.5.0',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/mempool/mempool'
|
||||
},
|
||||
@@ -616,7 +579,7 @@ function getCuratedAppList() {
|
||||
description: 'Open-source home automation platform. Control and automate your smart home devices privately.',
|
||||
icon: '/assets/img/app-icons/homeassistant.png',
|
||||
author: 'Home Assistant',
|
||||
dockerImage: 'homeassistant/home-assistant:2024.1',
|
||||
dockerImage: 'docker.io/homeassistant/home-assistant:2024.1',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/home-assistant/core'
|
||||
},
|
||||
@@ -625,9 +588,9 @@ function getCuratedAppList() {
|
||||
title: 'Grafana',
|
||||
version: '10.2.0',
|
||||
description: 'Analytics and monitoring platform. Create dashboards and visualize data from multiple sources.',
|
||||
icon: '/assets/img/grafana.png',
|
||||
icon: '/assets/img/app-icons/grafana.png',
|
||||
author: 'Grafana Labs',
|
||||
dockerImage: 'grafana/grafana:10.2.0',
|
||||
dockerImage: 'docker.io/grafana/grafana:10.2.0',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/grafana/grafana'
|
||||
},
|
||||
@@ -638,7 +601,7 @@ function getCuratedAppList() {
|
||||
description: 'Privacy-respecting metasearch engine. Search without tracking or ads.',
|
||||
icon: '/assets/img/app-icons/searxng.png',
|
||||
author: 'SearXNG',
|
||||
dockerImage: 'searxng/searxng:latest',
|
||||
dockerImage: 'docker.io/searxng/searxng:latest',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/searxng/searxng'
|
||||
},
|
||||
@@ -647,9 +610,9 @@ function getCuratedAppList() {
|
||||
title: 'Ollama',
|
||||
version: '0.1.0',
|
||||
description: 'Run large language models locally. Download and run AI models like Llama, Mistral on your own hardware.',
|
||||
icon: '/assets/img/ollama.webp',
|
||||
icon: '/assets/img/app-icons/ollama.png',
|
||||
author: 'Ollama',
|
||||
dockerImage: 'ollama/ollama:latest',
|
||||
dockerImage: 'docker.io/ollama/ollama:latest',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/ollama/ollama'
|
||||
},
|
||||
@@ -658,9 +621,9 @@ function getCuratedAppList() {
|
||||
title: 'OnlyOffice',
|
||||
version: '7.5.1',
|
||||
description: 'Office suite for document collaboration. Edit docs, spreadsheets, and presentations.',
|
||||
icon: '/assets/img/onlyoffice.webp',
|
||||
icon: '/assets/img/app-icons/onlyoffice.webp',
|
||||
author: 'Ascensio System SIA',
|
||||
dockerImage: 'onlyoffice/documentserver:7.5.1',
|
||||
dockerImage: 'docker.io/onlyoffice/documentserver:7.5.1',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/ONLYOFFICE/DocumentServer'
|
||||
},
|
||||
@@ -671,7 +634,7 @@ function getCuratedAppList() {
|
||||
description: 'Open-source design and prototyping platform. Self-hosted alternative to Figma.',
|
||||
icon: '/assets/img/penpot.webp',
|
||||
author: 'Penpot',
|
||||
dockerImage: 'penpotapp/frontend:latest',
|
||||
dockerImage: 'docker.io/penpotapp/frontend:latest',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/penpot/penpot'
|
||||
},
|
||||
@@ -680,9 +643,9 @@ function getCuratedAppList() {
|
||||
title: 'Nextcloud',
|
||||
version: '28.0',
|
||||
description: 'Self-hosted cloud storage and collaboration platform. Your own private cloud.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/nextcloud.webp',
|
||||
author: 'Nextcloud',
|
||||
dockerImage: 'nextcloud:28',
|
||||
dockerImage: 'docker.io/library/nextcloud:28',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/nextcloud/server'
|
||||
},
|
||||
@@ -691,9 +654,9 @@ function getCuratedAppList() {
|
||||
title: 'Vaultwarden',
|
||||
version: '1.30.0',
|
||||
description: 'Self-hosted password manager (Bitwarden-compatible). Secure vault for passwords and secrets.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/vaultwarden.webp',
|
||||
author: 'Vaultwarden',
|
||||
dockerImage: 'vaultwarden/server:1.30.0-alpine',
|
||||
dockerImage: 'docker.io/vaultwarden/server:1.30.0-alpine',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/dani-garcia/vaultwarden'
|
||||
},
|
||||
@@ -702,9 +665,9 @@ function getCuratedAppList() {
|
||||
title: 'Jellyfin',
|
||||
version: '10.8.0',
|
||||
description: 'Free media server system. Stream your movies, music, and photos to any device.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/jellyfin.webp',
|
||||
author: 'Jellyfin',
|
||||
dockerImage: 'jellyfin/jellyfin:10.8.13',
|
||||
dockerImage: 'docker.io/jellyfin/jellyfin:10.8.13',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/jellyfin/jellyfin'
|
||||
},
|
||||
@@ -713,9 +676,9 @@ function getCuratedAppList() {
|
||||
title: 'PhotoPrism',
|
||||
version: '231128',
|
||||
description: 'AI-powered photo management. Organize and browse photos with facial recognition.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/photoprims.svg',
|
||||
author: 'PhotoPrism',
|
||||
dockerImage: 'photoprism/photoprism:latest',
|
||||
dockerImage: 'docker.io/photoprism/photoprism:latest',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/photoprism/photoprism'
|
||||
},
|
||||
@@ -724,7 +687,7 @@ function getCuratedAppList() {
|
||||
title: 'Immich',
|
||||
version: '1.90.0',
|
||||
description: 'High-performance self-hosted photo and video backup. Mobile-first with ML features.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/immich.png',
|
||||
author: 'Immich',
|
||||
dockerImage: 'ghcr.io/immich-app/immich-server:release',
|
||||
manifestUrl: null,
|
||||
@@ -735,9 +698,9 @@ function getCuratedAppList() {
|
||||
title: 'File Browser',
|
||||
version: '2.27.0',
|
||||
description: 'Web-based file manager. Browse, upload, and manage files through a web interface.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/file-browser.webp',
|
||||
author: 'File Browser',
|
||||
dockerImage: 'filebrowser/filebrowser:v2.27.0',
|
||||
dockerImage: 'docker.io/filebrowser/filebrowser:v2.27.0',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/filebrowser/filebrowser'
|
||||
},
|
||||
@@ -746,9 +709,9 @@ function getCuratedAppList() {
|
||||
title: 'Nginx Proxy Manager',
|
||||
version: '2.11.0',
|
||||
description: 'Easy proxy management with SSL. Beautiful web interface for managing reverse proxies.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/nginx.svg',
|
||||
author: 'Nginx Proxy Manager',
|
||||
dockerImage: 'jc21/nginx-proxy-manager:latest',
|
||||
dockerImage: 'docker.io/jc21/nginx-proxy-manager:latest',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/NginxProxyManager/nginx-proxy-manager'
|
||||
},
|
||||
@@ -757,9 +720,9 @@ function getCuratedAppList() {
|
||||
title: 'Portainer',
|
||||
version: '2.19.0',
|
||||
description: 'Container management UI. Manage Docker containers through a beautiful web interface.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/portainer.webp',
|
||||
author: 'Portainer',
|
||||
dockerImage: 'portainer/portainer-ce:2.19.4',
|
||||
dockerImage: 'docker.io/portainer/portainer-ce:2.19.4',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/portainer/portainer'
|
||||
},
|
||||
@@ -768,12 +731,23 @@ function getCuratedAppList() {
|
||||
title: 'Uptime Kuma',
|
||||
version: '1.23.0',
|
||||
description: 'Self-hosted monitoring tool. Monitor uptime for HTTP(s), TCP, DNS, and more.',
|
||||
icon: null,
|
||||
icon: '/assets/img/app-icons/uptime-kuma.webp',
|
||||
author: 'Uptime Kuma',
|
||||
dockerImage: 'louislam/uptime-kuma:1.23.11',
|
||||
dockerImage: 'docker.io/louislam/uptime-kuma:1.23.11',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/louislam/uptime-kuma'
|
||||
},
|
||||
{
|
||||
id: 'tailscale',
|
||||
title: 'Tailscale',
|
||||
version: '1.78.0',
|
||||
description: 'Zero-config VPN for secure remote access. Connect all your devices with WireGuard mesh network.',
|
||||
icon: '/assets/img/app-icons/tailscale.webp',
|
||||
author: 'Tailscale',
|
||||
dockerImage: 'docker.io/tailscale/tailscale:stable',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/tailscale/tailscale'
|
||||
},
|
||||
{
|
||||
id: 'fedimint',
|
||||
title: 'Fedimint',
|
||||
@@ -781,7 +755,7 @@ function getCuratedAppList() {
|
||||
description: 'Federated Bitcoin mint. Private, scalable Bitcoin through federated guardians.',
|
||||
icon: '/assets/img/icon-fedimint.jpeg',
|
||||
author: 'Fedimint',
|
||||
dockerImage: 'fedimint/fedimintd:v0.3.0',
|
||||
dockerImage: 'docker.io/fedimint/fedimintd:v0.3.0',
|
||||
manifestUrl: null,
|
||||
repoUrl: 'https://github.com/fedimint/fedimint'
|
||||
}
|
||||
@@ -863,7 +837,7 @@ async function installApp(app: any) {
|
||||
}
|
||||
|
||||
async function installCommunityApp(app: any) {
|
||||
if (installing.value || isInstalled(app.id) || !app.manifestUrl) return
|
||||
if (installing.value || isInstalled(app.id) || !app.dockerImage) return
|
||||
|
||||
installing.value = app.id
|
||||
|
||||
@@ -876,7 +850,8 @@ async function installCommunityApp(app: any) {
|
||||
id: app.id,
|
||||
dockerImage: app.dockerImage,
|
||||
version: app.version
|
||||
}
|
||||
},
|
||||
timeout: 180000 // 3 minutes for large images like Nextcloud
|
||||
})
|
||||
|
||||
// Wait for installation to complete (poll for package to appear)
|
||||
@@ -948,11 +923,6 @@ function handleImageError(event: Event) {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.marketplace-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.line-clamp-3 {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 3;
|
||||
|
||||
Reference in New Issue
Block a user