2497 lines
67 KiB
JavaScript
2497 lines
67 KiB
JavaScript
// SAMI-CLOUD App Templates Database
|
|
// Pre-configured Docker applications for one-click deployment
|
|
|
|
const APP_TEMPLATES = {
|
|
// === MEDIA & ENTERTAINMENT ===
|
|
'plex': {
|
|
name: 'Plex',
|
|
description: 'Stream your personal media collection anywhere',
|
|
icon: '🎬',
|
|
logo: '/assets/plex.png',
|
|
category: 'Media',
|
|
popularity: 95,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'plexinc/pms-docker:latest',
|
|
ports: ['{{PORT}}:32400'],
|
|
volumes: [
|
|
'/opt/plex/config:/config',
|
|
'/opt/plex/transcode:/transcode',
|
|
'{{MEDIA_PATH}}:/data',
|
|
],
|
|
environment: {
|
|
'PLEX_CLAIM': '',
|
|
'ADVERTISE_IP': 'http://{{HOST_IP}}:{{PORT}}/',
|
|
'PLEX_UID': '1000',
|
|
'PLEX_GID': '1000',
|
|
},
|
|
},
|
|
subdomain: 'plex',
|
|
defaultPort: 32400,
|
|
healthCheck: '/web/index.html',
|
|
subpathSupport: 'none',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/data',
|
|
label: 'Media Library',
|
|
description: 'Folder containing your movies, TV shows, music, etc.',
|
|
defaultPath: '/media',
|
|
},
|
|
claimToken: {
|
|
envVar: 'PLEX_CLAIM',
|
|
label: 'Plex Claim Token',
|
|
description: 'Get from https://plex.tv/claim - expires in 4 minutes!',
|
|
placeholder: 'claim-xxxxxxxxxxxxxxxxxxxx',
|
|
helpUrl: 'https://plex.tv/claim',
|
|
},
|
|
setupInstructions: [
|
|
'Get your claim token from https://plex.tv/claim',
|
|
'Add your media libraries in the web interface',
|
|
'Configure remote access settings',
|
|
],
|
|
requiredVolumes: ['config', 'media'],
|
|
optionalVolumes: ['transcode'],
|
|
},
|
|
|
|
'jellyfin': {
|
|
name: 'Jellyfin',
|
|
description: 'Free software media system - alternative to Plex',
|
|
icon: '🍿',
|
|
logo: '/assets/jellyfin.png',
|
|
category: 'Media',
|
|
popularity: 88,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'jellyfin/jellyfin:latest',
|
|
ports: ['{{PORT}}:8096'],
|
|
volumes: [
|
|
'/opt/jellyfin/config:/config',
|
|
'/opt/jellyfin/cache:/cache',
|
|
'{{MEDIA_PATH}}:/media',
|
|
],
|
|
environment: {
|
|
'JELLYFIN_PublishedServerUrl': 'https://{{SUBDOMAIN}}.sami',
|
|
},
|
|
},
|
|
subdomain: 'jellyfin',
|
|
defaultPort: 8096,
|
|
healthCheck: '/health',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'JELLYFIN_BaseUrl',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/media',
|
|
label: 'Media Library',
|
|
description: 'Folder containing your movies, TV shows, music, etc.',
|
|
defaultPath: '/media',
|
|
},
|
|
setupInstructions: [
|
|
'Complete the initial setup wizard',
|
|
'Add your media libraries',
|
|
'Configure user accounts and permissions',
|
|
],
|
|
},
|
|
|
|
'emby': {
|
|
name: 'Emby',
|
|
description: 'Personal media server with apps for all devices',
|
|
icon: '🎥',
|
|
logo: '/assets/emby.png',
|
|
category: 'Media',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'emby/embyserver:latest',
|
|
ports: ['{{PORT}}:8096'],
|
|
volumes: [
|
|
'/opt/emby/config:/config',
|
|
'/opt/emby/cache:/cache',
|
|
'{{MEDIA_PATH}}:/media',
|
|
],
|
|
environment: {
|
|
'UID': '1000',
|
|
'GID': '1000',
|
|
},
|
|
},
|
|
subdomain: 'emby',
|
|
defaultPort: 8096,
|
|
healthCheck: '/emby/web/',
|
|
subpathSupport: 'none',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/media',
|
|
label: 'Media Library',
|
|
description: 'Folder containing your movies, TV shows, music, etc.',
|
|
defaultPath: '/media',
|
|
},
|
|
setupInstructions: [
|
|
'Complete the initial setup wizard at the web interface',
|
|
'Add your media libraries (Movies, TV Shows, Music)',
|
|
'Configure user accounts and permissions',
|
|
'Install Emby apps on your devices for remote access',
|
|
],
|
|
},
|
|
|
|
'sonarr': {
|
|
name: 'Sonarr',
|
|
description: 'Smart PVR for newsgroup and bittorrent users',
|
|
icon: '📺',
|
|
category: 'Media Management',
|
|
popularity: 82,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/sonarr:latest',
|
|
ports: ['{{PORT}}:8989'],
|
|
volumes: [
|
|
'/opt/sonarr/config:/config',
|
|
'/downloads:/downloads',
|
|
'/tv:/tv',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'sonarr',
|
|
defaultPort: 8989,
|
|
healthCheck: '/api/v3/system/status',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'URL_BASE',
|
|
setupInstructions: [
|
|
'Configure download clients (qBittorrent, etc.)',
|
|
'Add indexers for content discovery',
|
|
'Set up root folders for TV shows',
|
|
],
|
|
},
|
|
|
|
'radarr': {
|
|
name: 'Radarr',
|
|
description: 'Movie collection manager for Usenet and BitTorrent',
|
|
icon: '🎭',
|
|
category: 'Media Management',
|
|
popularity: 80,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/radarr:latest',
|
|
ports: ['{{PORT}}:7878'],
|
|
volumes: [
|
|
'/opt/radarr/config:/config',
|
|
'/downloads:/downloads',
|
|
'/movies:/movies',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'radarr',
|
|
defaultPort: 7878,
|
|
healthCheck: '/api/v3/system/status',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'URL_BASE',
|
|
},
|
|
|
|
'prowlarr': {
|
|
name: 'Prowlarr',
|
|
description: 'Indexer manager/proxy for *arr applications',
|
|
icon: '🔍',
|
|
category: 'Media Management',
|
|
popularity: 75,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'linuxserver/prowlarr:latest',
|
|
ports: ['{{PORT}}:9696'],
|
|
volumes: ['/opt/prowlarr/config:/config'],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'prowlarr',
|
|
defaultPort: 9696,
|
|
healthCheck: '/api/v1/system/status',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'URL_BASE',
|
|
},
|
|
|
|
'qbittorrent': {
|
|
name: 'qBittorrent',
|
|
description: 'Lightweight BitTorrent client with web UI',
|
|
icon: '⬇️',
|
|
category: 'Downloads',
|
|
popularity: 90,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'linuxserver/qbittorrent:latest',
|
|
ports: ['{{PORT}}:8080', '6881:6881', '6881:6881/udp'],
|
|
volumes: [
|
|
'/opt/qbittorrent/config:/config',
|
|
'/downloads:/downloads',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
'WEBUI_PORT': '8080',
|
|
},
|
|
},
|
|
subdomain: 'torrent',
|
|
defaultPort: 8080,
|
|
healthCheck: '/',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'WEBUI_BASE_PATH',
|
|
setupInstructions: [
|
|
'Default login: admin/adminadmin',
|
|
'Change default password immediately',
|
|
'Configure download paths',
|
|
],
|
|
},
|
|
|
|
// === PRODUCTIVITY & TOOLS ===
|
|
'nextcloud': {
|
|
name: 'Nextcloud',
|
|
description: 'Self-hosted productivity platform and file sync',
|
|
icon: '☁️',
|
|
category: 'Productivity',
|
|
popularity: 92,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'nextcloud:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [
|
|
'/opt/nextcloud/html:/var/www/html',
|
|
'/opt/nextcloud/data:/var/www/html/data',
|
|
],
|
|
environment: {
|
|
'NEXTCLOUD_ADMIN_USER': 'admin',
|
|
'NEXTCLOUD_ADMIN_PASSWORD': '{{NEXTCLOUD_ADMIN_PASSWORD}}',
|
|
'NEXTCLOUD_TRUSTED_DOMAINS': '{{SUBDOMAIN}}.sami',
|
|
},
|
|
},
|
|
subdomain: 'cloud',
|
|
defaultPort: 8080,
|
|
healthCheck: '/status.php',
|
|
subpathSupport: 'none',
|
|
setupInstructions: [
|
|
'Change the default admin password',
|
|
'Configure trusted domains',
|
|
'Install recommended apps',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'NEXTCLOUD_ADMIN_PASSWORD',
|
|
label: 'Admin Password',
|
|
description: 'Secure password for Nextcloud admin account',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'vscode-server': {
|
|
name: 'VS Code Server',
|
|
description: 'Visual Studio Code in your browser',
|
|
icon: '💻',
|
|
category: 'Development',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'codercom/code-server:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/opt/vscode/config:/home/coder/.config',
|
|
'/opt/vscode/projects:/home/coder/projects',
|
|
],
|
|
environment: {
|
|
'PASSWORD': '{{VSCODE_PASSWORD}}',
|
|
},
|
|
},
|
|
subdomain: 'code',
|
|
defaultPort: 8443,
|
|
healthCheck: '/healthz',
|
|
subpathSupport: 'strip',
|
|
secrets: [
|
|
{
|
|
envVar: 'VSCODE_PASSWORD',
|
|
label: 'Access Password',
|
|
description: 'Password to access VS Code Server web interface',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 24,
|
|
},
|
|
],
|
|
},
|
|
|
|
// === MONITORING & ADMIN ===
|
|
'portainer': {
|
|
name: 'Portainer',
|
|
description: 'Docker container management UI',
|
|
icon: '🐳',
|
|
category: 'Management',
|
|
popularity: 88,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'portainer/portainer-ce:latest',
|
|
ports: ['{{PORT}}:9000'],
|
|
volumes: [
|
|
'/var/run/docker.sock:/var/run/docker.sock',
|
|
'/opt/portainer/data:/data',
|
|
],
|
|
},
|
|
subdomain: 'portainer',
|
|
defaultPort: 9000,
|
|
healthCheck: '/api/status',
|
|
subpathSupport: 'strip',
|
|
},
|
|
|
|
'grafana': {
|
|
name: 'Grafana',
|
|
description: 'Analytics and interactive visualization platform',
|
|
icon: '📊',
|
|
category: 'Monitoring',
|
|
popularity: 78,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'grafana/grafana:latest',
|
|
ports: ['{{PORT}}:3000'],
|
|
volumes: ['/opt/grafana/data:/var/lib/grafana'],
|
|
environment: {
|
|
'GF_SECURITY_ADMIN_PASSWORD': '{{GRAFANA_ADMIN_PASSWORD}}',
|
|
},
|
|
},
|
|
subdomain: 'grafana',
|
|
defaultPort: 3000,
|
|
healthCheck: '/api/health',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'GF_SERVER_ROOT_URL',
|
|
secrets: [
|
|
{
|
|
envVar: 'GRAFANA_ADMIN_PASSWORD',
|
|
label: 'Admin Password',
|
|
description: 'Password for Grafana admin user',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'uptime-kuma': {
|
|
name: 'Uptime Kuma',
|
|
description: 'Self-hosted monitoring tool like Uptime Robot',
|
|
icon: '📈',
|
|
category: 'Monitoring',
|
|
popularity: 82,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'louislam/uptime-kuma:latest',
|
|
ports: ['{{PORT}}:3001'],
|
|
volumes: ['/opt/uptime-kuma:/app/data'],
|
|
},
|
|
subdomain: 'uptime',
|
|
defaultPort: 3002,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
},
|
|
|
|
// === NETWORKING & SECURITY ===
|
|
'pihole': {
|
|
name: 'Pi-hole',
|
|
description: 'Network-wide ad blocker and DNS sinkhole',
|
|
icon: '🛡️',
|
|
category: 'Networking',
|
|
popularity: 90,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'pihole/pihole:latest',
|
|
ports: ['{{PORT}}:80', '53:53', '53:53/udp'],
|
|
volumes: [
|
|
'/opt/pihole/etc:/etc/pihole',
|
|
'/opt/pihole/dnsmasq:/etc/dnsmasq.d',
|
|
],
|
|
environment: {
|
|
'WEBPASSWORD': '{{PIHOLE_WEB_PASSWORD}}',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'pihole',
|
|
defaultPort: 80,
|
|
healthCheck: '/admin/',
|
|
subpathSupport: 'strip',
|
|
secrets: [
|
|
{
|
|
envVar: 'PIHOLE_WEB_PASSWORD',
|
|
label: 'Web Interface Password',
|
|
description: 'Password for Pi-hole admin web interface',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 24,
|
|
},
|
|
],
|
|
},
|
|
|
|
'wireguard': {
|
|
name: 'WireGuard VPN',
|
|
description: 'Fast, modern, secure VPN tunnel',
|
|
icon: '🔒',
|
|
category: 'Networking',
|
|
popularity: 75,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'linuxserver/wireguard:latest',
|
|
ports: ['{{PORT}}:51820/udp'],
|
|
volumes: ['/opt/wireguard/config:/config'],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
'SERVERURL': '{{HOST_IP}}',
|
|
'SERVERPORT': '{{PORT}}',
|
|
'PEERS': '1',
|
|
},
|
|
capabilities: ['NET_ADMIN', 'SYS_MODULE'],
|
|
},
|
|
subdomain: 'vpn',
|
|
defaultPort: 51820,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure your external IP/domain',
|
|
'Set up port forwarding on router',
|
|
'Download client configs from /config/peer1/',
|
|
],
|
|
},
|
|
|
|
// === DNS SERVERS ===
|
|
'technitium': {
|
|
name: 'Technitium DNS Server',
|
|
description: 'Modern DNS server with web UI for managing private zones',
|
|
icon: '🌐',
|
|
category: 'DNS',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
features: [
|
|
'Web-based management interface',
|
|
'Private zone management for .sami domain',
|
|
'DHCP server integration',
|
|
'DNS-over-HTTPS and DNS-over-TLS support',
|
|
'Built-in DNSSEC support',
|
|
],
|
|
docker: {
|
|
image: 'technitium/dns-server:latest',
|
|
ports: ['{{PORT}}:5380', '53:53', '53:53/udp'],
|
|
volumes: ['/opt/technitium/config:/etc/dns'],
|
|
environment: {
|
|
'DNS_SERVER_DOMAIN': 'dns1.sami',
|
|
'DNS_SERVER_ADMIN_PASSWORD': '{{DNS_ADMIN_PASSWORD}}',
|
|
},
|
|
},
|
|
subdomain: 'dns1',
|
|
defaultPort: 5380,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Access web interface at https://dns1.sami',
|
|
'Login with admin credentials',
|
|
"Create a primary zone for 'sami' domain",
|
|
'Add A records for your services (e.g., plex.sami -> 192.168.1.100)',
|
|
'Configure your devices to use this DNS server',
|
|
],
|
|
requiredVolumes: ['config'],
|
|
optionalVolumes: [],
|
|
secrets: [
|
|
{
|
|
envVar: 'DNS_ADMIN_PASSWORD',
|
|
label: 'Admin Password',
|
|
description: 'Password for Technitium DNS admin account',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'bind9': {
|
|
name: 'BIND9 DNS Server',
|
|
description: 'Industry-standard DNS server - powerful and flexible',
|
|
icon: '🔧',
|
|
category: 'DNS',
|
|
popularity: 80,
|
|
difficulty: 'Advanced',
|
|
features: [
|
|
'Industry standard DNS server',
|
|
'Full RFC compliance',
|
|
'Advanced zone management',
|
|
'DNSSEC support',
|
|
'High performance and reliability',
|
|
],
|
|
docker: {
|
|
image: 'ubuntu/bind9:latest',
|
|
ports: ['53:53', '53:53/udp', '{{PORT}}:953'],
|
|
volumes: [
|
|
'/opt/bind9/config:/etc/bind',
|
|
'/opt/bind9/cache:/var/cache/bind',
|
|
'/opt/bind9/records:/var/lib/bind',
|
|
],
|
|
environment: {
|
|
'BIND9_USER': 'root',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'dns2',
|
|
defaultPort: 953,
|
|
healthCheck: null,
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure zone files in /opt/bind9/config/',
|
|
'Create named.conf.local for your .sami zone',
|
|
'Add zone file: /opt/bind9/records/db.sami',
|
|
'Restart container to apply changes',
|
|
'Test with: dig @localhost sami',
|
|
],
|
|
requiredVolumes: ['config', 'records'],
|
|
optionalVolumes: ['cache'],
|
|
},
|
|
|
|
'powerdns': {
|
|
name: 'PowerDNS',
|
|
description: 'High-performance DNS server with SQL backend',
|
|
icon: '⚡',
|
|
category: 'DNS',
|
|
popularity: 75,
|
|
difficulty: 'Intermediate',
|
|
features: [
|
|
'SQL database backend (MySQL/PostgreSQL)',
|
|
'RESTful API for automation',
|
|
'PowerDNS Admin web interface available',
|
|
'Geographic load balancing',
|
|
'DNSSEC support',
|
|
],
|
|
docker: {
|
|
image: 'pschiffe/pdns-mysql:latest',
|
|
ports: ['53:53', '53:53/udp', '{{PORT}}:8081'],
|
|
volumes: ['/opt/powerdns/data:/var/lib/mysql'],
|
|
environment: {
|
|
'PDNS_api': 'yes',
|
|
'PDNS_api_key': '{{POWERDNS_API_KEY}}',
|
|
'PDNS_webserver': 'yes',
|
|
'PDNS_webserver_address': '0.0.0.0',
|
|
'PDNS_webserver_allow_from': '0.0.0.0/0',
|
|
'MYSQL_ROOT_PASSWORD': '{{MYSQL_ROOT_PASSWORD}}',
|
|
},
|
|
},
|
|
subdomain: 'dns3',
|
|
defaultPort: 8081,
|
|
healthCheck: '/api/v1/servers',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Access API at https://dns3.sami:8081',
|
|
'Use API key for authentication',
|
|
'Create zone via API or PowerDNS Admin',
|
|
'Add records for your .sami domain',
|
|
'Configure devices to use DNS server',
|
|
],
|
|
requiredVolumes: ['data'],
|
|
optionalVolumes: [],
|
|
secrets: [
|
|
{
|
|
envVar: 'POWERDNS_API_KEY',
|
|
label: 'API Key',
|
|
description: 'API key for PowerDNS webserver authentication',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
{
|
|
envVar: 'MYSQL_ROOT_PASSWORD',
|
|
label: 'MySQL Root Password',
|
|
description: 'Root password for embedded MySQL database',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'coredns': {
|
|
name: 'CoreDNS',
|
|
description: 'Cloud-native DNS server - lightweight and flexible',
|
|
icon: '☁️',
|
|
category: 'DNS',
|
|
popularity: 70,
|
|
difficulty: 'Intermediate',
|
|
features: [
|
|
'Plugin-based architecture',
|
|
'Kubernetes-native (used in K8s)',
|
|
'Lightweight and fast',
|
|
'Prometheus metrics',
|
|
'Easy configuration via Corefile',
|
|
],
|
|
docker: {
|
|
image: 'coredns/coredns:latest',
|
|
ports: ['53:53', '53:53/udp'],
|
|
volumes: ['/opt/coredns/config:/etc/coredns'],
|
|
environment: {},
|
|
command: ['-conf', '/etc/coredns/Corefile'],
|
|
},
|
|
subdomain: 'dns4',
|
|
defaultPort: 53,
|
|
healthCheck: null,
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Create Corefile in /opt/coredns/config/',
|
|
'Define .sami zone with file plugin',
|
|
'Create zone file with your records',
|
|
'Restart container to load config',
|
|
'Test with: dig @localhost test.sami',
|
|
],
|
|
requiredVolumes: ['config'],
|
|
optionalVolumes: [],
|
|
},
|
|
|
|
// === FILE MANAGEMENT ===
|
|
'filebrowser': {
|
|
name: 'FileBrowser',
|
|
description: 'Web-based file manager with sharing capabilities',
|
|
icon: '📁',
|
|
category: 'Files',
|
|
popularity: 88,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'filebrowser/filebrowser:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [
|
|
'/opt/filebrowser/data:/srv',
|
|
'/opt/filebrowser/database:/database',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'files',
|
|
defaultPort: 8085,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Default login: admin/admin',
|
|
'Change default password immediately',
|
|
'Configure user permissions and shares',
|
|
],
|
|
},
|
|
|
|
'syncthing': {
|
|
name: 'Syncthing',
|
|
description: 'Continuous file synchronization between devices',
|
|
icon: '🔄',
|
|
category: 'Files',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'linuxserver/syncthing:latest',
|
|
ports: ['{{PORT}}:8384', '22000:22000', '21027:21027/udp'],
|
|
volumes: [
|
|
'/opt/syncthing/config:/config',
|
|
'/opt/syncthing/data:/data',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'sync',
|
|
defaultPort: 8384,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Add devices using their Device IDs',
|
|
'Configure shared folders',
|
|
'Set up folder synchronization',
|
|
],
|
|
},
|
|
|
|
// === COMMUNICATION & EMAIL ===
|
|
'mailserver': {
|
|
name: 'Docker Mailserver',
|
|
description: 'Full-featured email server with SMTP, IMAP, spam filtering',
|
|
icon: '📧',
|
|
category: 'Communication',
|
|
popularity: 70,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'mailserver/docker-mailserver:latest',
|
|
ports: ['{{PORT}}:25', '143:143', '587:587', '993:993'],
|
|
volumes: [
|
|
'/opt/mailserver/data:/var/mail',
|
|
'/opt/mailserver/state:/var/mail-state',
|
|
'/opt/mailserver/logs:/var/log/mail',
|
|
'/opt/mailserver/config:/tmp/docker-mailserver',
|
|
],
|
|
environment: {
|
|
'ENABLE_SPAMASSASSIN': '1',
|
|
'ENABLE_CLAMAV': '1',
|
|
'ENABLE_FAIL2BAN': '1',
|
|
'ONE_DIR': '1',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'mail',
|
|
defaultPort: 25,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure DNS records (MX, SPF, DKIM, DMARC)',
|
|
'Create email accounts using setup.sh',
|
|
'Set up SSL certificates for secure connections',
|
|
],
|
|
},
|
|
|
|
'roundcube': {
|
|
name: 'Roundcube',
|
|
description: 'Modern webmail client with rich features',
|
|
icon: '💌',
|
|
category: 'Communication',
|
|
popularity: 72,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'roundcube/roundcubemail:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [
|
|
'/opt/roundcube/config:/var/roundcube/config',
|
|
'/opt/roundcube/db:/var/roundcube/db',
|
|
],
|
|
environment: {
|
|
'ROUNDCUBEMAIL_DEFAULT_HOST': 'mail.{{SUBDOMAIN}}.sami',
|
|
'ROUNDCUBEMAIL_SMTP_SERVER': 'mail.{{SUBDOMAIN}}.sami',
|
|
},
|
|
},
|
|
subdomain: 'webmail',
|
|
defaultPort: 8086,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure IMAP/SMTP server settings',
|
|
'Set up database connection',
|
|
'Customize appearance and plugins',
|
|
],
|
|
},
|
|
|
|
'matrix': {
|
|
name: 'Matrix Synapse',
|
|
description: 'Decentralized, secure messaging and collaboration',
|
|
icon: '💬',
|
|
category: 'Communication',
|
|
popularity: 75,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'matrixdotorg/synapse:latest',
|
|
ports: ['{{PORT}}:8008'],
|
|
volumes: ['/opt/matrix/data:/data'],
|
|
environment: {
|
|
'SYNAPSE_SERVER_NAME': '{{SUBDOMAIN}}.sami',
|
|
'SYNAPSE_REPORT_STATS': 'no',
|
|
},
|
|
},
|
|
subdomain: 'matrix',
|
|
defaultPort: 8008,
|
|
healthCheck: '/_matrix/client/versions',
|
|
subpathSupport: 'none',
|
|
setupInstructions: [
|
|
'Generate initial config with --generate',
|
|
'Configure homeserver.yaml',
|
|
'Set up federation if needed',
|
|
],
|
|
},
|
|
|
|
'rocketchat': {
|
|
name: 'Rocket.Chat',
|
|
description: 'Team collaboration platform like Slack',
|
|
icon: '🚀',
|
|
category: 'Communication',
|
|
popularity: 78,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'rocket.chat:latest',
|
|
ports: ['{{PORT}}:3000'],
|
|
volumes: ['/opt/rocketchat/uploads:/app/uploads'],
|
|
environment: {
|
|
'ROOT_URL': 'https://{{SUBDOMAIN}}.sami',
|
|
'MONGO_URL': 'mongodb://mongo:27017/rocketchat',
|
|
},
|
|
},
|
|
subdomain: 'chat',
|
|
defaultPort: 3004,
|
|
healthCheck: '/api/info',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Requires MongoDB - deploy mongo container first',
|
|
'Complete admin setup wizard',
|
|
'Configure OAuth and integrations',
|
|
],
|
|
},
|
|
|
|
// === HOME AUTOMATION ===
|
|
'homeassistant': {
|
|
name: 'Home Assistant',
|
|
description: 'Open source home automation platform',
|
|
icon: '🏠',
|
|
category: 'Home Automation',
|
|
popularity: 92,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'homeassistant/home-assistant:stable',
|
|
ports: ['{{PORT}}:8123'],
|
|
volumes: [
|
|
'/opt/homeassistant/config:/config',
|
|
'/etc/localtime:/etc/localtime:ro',
|
|
],
|
|
environment: {
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'home',
|
|
defaultPort: 8123,
|
|
healthCheck: '/api/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Complete onboarding wizard',
|
|
'Add integrations for your smart devices',
|
|
'Create automations and dashboards',
|
|
],
|
|
},
|
|
|
|
'nodered': {
|
|
name: 'Node-RED',
|
|
description: 'Flow-based programming for IoT and automation',
|
|
icon: '🔴',
|
|
category: 'Home Automation',
|
|
popularity: 80,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'nodered/node-red:latest',
|
|
ports: ['{{PORT}}:1880'],
|
|
volumes: ['/opt/nodered/data:/data'],
|
|
environment: {
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'nodered',
|
|
defaultPort: 1880,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Install additional nodes from palette',
|
|
'Create flows for automation',
|
|
'Connect to Home Assistant or MQTT',
|
|
],
|
|
},
|
|
|
|
// === DATABASES ===
|
|
'postgres': {
|
|
name: 'PostgreSQL',
|
|
description: 'Advanced open-source relational database',
|
|
icon: '🐘',
|
|
category: 'Database',
|
|
popularity: 85,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'postgres:16-alpine',
|
|
ports: ['{{PORT}}:5432'],
|
|
volumes: ['/opt/postgres/data:/var/lib/postgresql/data'],
|
|
environment: {
|
|
'POSTGRES_USER': 'admin',
|
|
'POSTGRES_PASSWORD': '{{POSTGRES_PASSWORD}}',
|
|
'POSTGRES_DB': 'default',
|
|
},
|
|
},
|
|
subdomain: 'postgres',
|
|
defaultPort: 5432,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Change default password immediately',
|
|
'Create databases and users as needed',
|
|
'Configure pg_hba.conf for remote access',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'POSTGRES_PASSWORD',
|
|
label: 'Admin Password',
|
|
description: 'Password for PostgreSQL admin user',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'redis': {
|
|
name: 'Redis',
|
|
description: 'In-memory data structure store and cache',
|
|
icon: '🔴',
|
|
category: 'Database',
|
|
popularity: 82,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'redis:alpine',
|
|
ports: ['{{PORT}}:6379'],
|
|
volumes: ['/opt/redis/data:/data'],
|
|
environment: {},
|
|
},
|
|
subdomain: 'redis',
|
|
defaultPort: 6379,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure redis.conf for persistence',
|
|
'Set up authentication if needed',
|
|
'Configure maxmemory policy',
|
|
],
|
|
},
|
|
|
|
'mongodb': {
|
|
name: 'MongoDB',
|
|
description: 'Document-oriented NoSQL database',
|
|
icon: '🍃',
|
|
category: 'Database',
|
|
popularity: 80,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'mongo:latest',
|
|
ports: ['{{PORT}}:27017'],
|
|
volumes: ['/opt/mongodb/data:/data/db'],
|
|
environment: {
|
|
'MONGO_INITDB_ROOT_USERNAME': 'admin',
|
|
'MONGO_INITDB_ROOT_PASSWORD': '{{MONGO_ROOT_PASSWORD}}',
|
|
},
|
|
},
|
|
subdomain: 'mongo',
|
|
defaultPort: 27017,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Change default admin password',
|
|
'Create application databases and users',
|
|
'Configure replica set if needed',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'MONGO_ROOT_PASSWORD',
|
|
label: 'Root Password',
|
|
description: 'Root password for MongoDB admin user',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'adminer': {
|
|
name: 'Adminer',
|
|
description: 'Lightweight database management in single PHP file',
|
|
icon: '🗄️',
|
|
category: 'Database',
|
|
popularity: 75,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'adminer:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [],
|
|
environment: {
|
|
'ADMINER_DEFAULT_SERVER': 'postgres',
|
|
},
|
|
},
|
|
subdomain: 'adminer',
|
|
defaultPort: 8087,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Connect to your database servers',
|
|
'Supports MySQL, PostgreSQL, SQLite, etc.',
|
|
],
|
|
},
|
|
|
|
// === SECURITY & AUTH ===
|
|
'vaultwarden': {
|
|
name: 'Vaultwarden',
|
|
description: 'Lightweight Bitwarden-compatible password manager',
|
|
icon: '🔑',
|
|
category: 'Security',
|
|
popularity: 90,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'vaultwarden/server:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: ['/opt/vaultwarden/data:/data'],
|
|
environment: {
|
|
'DOMAIN': 'https://{{SUBDOMAIN}}.sami',
|
|
'ADMIN_TOKEN': '{{VAULTWARDEN_ADMIN_TOKEN}}',
|
|
},
|
|
},
|
|
subdomain: 'vault',
|
|
defaultPort: 8088,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Change admin token immediately',
|
|
'Create your account',
|
|
'Install browser extensions and mobile apps',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'VAULTWARDEN_ADMIN_TOKEN',
|
|
label: 'Admin Token',
|
|
description: 'Admin panel access token for Vaultwarden',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 48,
|
|
},
|
|
],
|
|
},
|
|
|
|
'dashca': {
|
|
name: 'DashCA',
|
|
description: 'One-click root CA certificate installer for your network',
|
|
icon: '🔐',
|
|
logo: '/assets/certificate-icon.png',
|
|
category: 'Security',
|
|
popularity: 95,
|
|
difficulty: 'Easy',
|
|
isStaticSite: true, // Special flag for non-Docker deployments
|
|
subdomain: 'ca',
|
|
defaultPort: null, // Static site, no port needed
|
|
healthCheck: null,
|
|
subpathSupport: 'strip',
|
|
features: [
|
|
'Automatic OS detection',
|
|
'One-click installation',
|
|
'Supports Windows, macOS, Linux, iOS, Android',
|
|
'Apple mobileconfig for easy iOS/macOS setup',
|
|
'QR code for mobile access',
|
|
'Certificate expiration monitoring',
|
|
],
|
|
setupInstructions: [
|
|
'New devices: visit http://ca.sami (HTTP, no certificate needed)',
|
|
"Click the 'Install Certificate' button for your platform",
|
|
'Follow platform-specific instructions',
|
|
'Verify all *.sami domains now show secure connections',
|
|
],
|
|
tags: ['security', 'certificates', 'ssl', 'tls', 'infrastructure'],
|
|
},
|
|
|
|
'weather': {
|
|
name: 'Weather',
|
|
description: 'Live weather widget with temperature, conditions, and wind',
|
|
icon: '🌤️',
|
|
category: 'Utilities',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
isDashboardWidget: true,
|
|
widgetSelector: '.weather-widget-container',
|
|
subdomain: null,
|
|
defaultPort: null,
|
|
healthCheck: null,
|
|
subpathSupport: 'strip',
|
|
features: [
|
|
'Current temperature and conditions',
|
|
'Wind speed and direction',
|
|
'Weather icon with emoji fallback',
|
|
'Configurable ZIP code',
|
|
'Auto-refreshes periodically',
|
|
],
|
|
setupInstructions: [
|
|
'Click the gear icon on the widget to set your ZIP code',
|
|
'Weather appears in the top bar next to the logo',
|
|
],
|
|
tags: ['weather', 'widget', 'dashboard', 'utility'],
|
|
},
|
|
|
|
'digital-clock': {
|
|
name: 'Digital Clock',
|
|
description: 'Live digital clock with time, date, and day of week',
|
|
icon: '🕐',
|
|
category: 'Utilities',
|
|
popularity: 80,
|
|
difficulty: 'Easy',
|
|
isDashboardWidget: true,
|
|
widgetSelector: '.clock-widget-container',
|
|
subdomain: null,
|
|
defaultPort: null,
|
|
healthCheck: null,
|
|
subpathSupport: 'strip',
|
|
features: [
|
|
'12-hour format with AM/PM',
|
|
'Live seconds display',
|
|
'Full date with day of week',
|
|
'Responsive sizing across all devices',
|
|
'Matches dashboard theme automatically',
|
|
],
|
|
setupInstructions: [
|
|
'Clock appears in the top bar to the right of the weather widget',
|
|
'No configuration needed — runs automatically',
|
|
],
|
|
tags: ['clock', 'time', 'widget', 'dashboard', 'utility'],
|
|
},
|
|
|
|
// === MEDIA MANAGEMENT (Additional) ===
|
|
'lidarr': {
|
|
name: 'Lidarr',
|
|
description: 'Music collection manager for Usenet and BitTorrent',
|
|
icon: '🎵',
|
|
category: 'Media Management',
|
|
popularity: 70,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/lidarr:latest',
|
|
ports: ['{{PORT}}:8686'],
|
|
volumes: [
|
|
'/opt/lidarr/config:/config',
|
|
'/downloads:/downloads',
|
|
'/music:/music',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'lidarr',
|
|
defaultPort: 8686,
|
|
healthCheck: '/api/v1/system/status',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'URL_BASE',
|
|
setupInstructions: [
|
|
'Configure download clients',
|
|
'Add indexers',
|
|
'Set up root folders for music',
|
|
],
|
|
},
|
|
|
|
'readarr': {
|
|
name: 'Readarr',
|
|
description: 'Book and audiobook collection manager',
|
|
icon: '📚',
|
|
category: 'Media Management',
|
|
popularity: 65,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/readarr:develop',
|
|
ports: ['{{PORT}}:8787'],
|
|
volumes: [
|
|
'/opt/readarr/config:/config',
|
|
'/downloads:/downloads',
|
|
'/books:/books',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'readarr',
|
|
defaultPort: 8787,
|
|
healthCheck: '/api/v1/system/status',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'URL_BASE',
|
|
setupInstructions: [
|
|
'Configure download clients',
|
|
'Add indexers for books',
|
|
'Set up root folders',
|
|
],
|
|
},
|
|
|
|
'bazarr': {
|
|
name: 'Bazarr',
|
|
description: 'Automatic subtitle downloader for Sonarr and Radarr',
|
|
icon: '💬',
|
|
category: 'Media Management',
|
|
popularity: 72,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'linuxserver/bazarr:latest',
|
|
ports: ['{{PORT}}:6767'],
|
|
volumes: [
|
|
'/opt/bazarr/config:/config',
|
|
'/movies:/movies',
|
|
'/tv:/tv',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'bazarr',
|
|
defaultPort: 6767,
|
|
healthCheck: '/',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'BASE_URL',
|
|
setupInstructions: [
|
|
'Connect to Sonarr and Radarr',
|
|
'Configure subtitle providers',
|
|
'Set language preferences',
|
|
],
|
|
},
|
|
|
|
'seerr': {
|
|
name: 'Seerr',
|
|
description: 'Media request and discovery manager for Plex, Jellyfin, and Emby',
|
|
icon: '🎫',
|
|
category: 'Media Management',
|
|
popularity: 82,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/seerr-team/seerr:latest',
|
|
ports: ['{{PORT}}:5055'],
|
|
volumes: ['/opt/seerr/config:/app/config'],
|
|
environment: {
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
init: true,
|
|
},
|
|
subdomain: 'requests',
|
|
defaultPort: 5055,
|
|
healthCheck: '/api/v1/status',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'BASE_PATH',
|
|
setupInstructions: [
|
|
'Connect to Plex, Jellyfin, or Emby server',
|
|
'Link Sonarr and Radarr',
|
|
'Configure user permissions',
|
|
],
|
|
},
|
|
|
|
'tautulli': {
|
|
name: 'Tautulli',
|
|
description: 'Plex media server monitoring and statistics',
|
|
icon: '📊',
|
|
category: 'Media Management',
|
|
popularity: 78,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'linuxserver/tautulli:latest',
|
|
ports: ['{{PORT}}:8181'],
|
|
volumes: ['/opt/tautulli/config:/config'],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'tautulli',
|
|
defaultPort: 8181,
|
|
healthCheck: '/',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'TAUTULLI_HTTP_ROOT',
|
|
setupInstructions: [
|
|
'Connect to Plex server',
|
|
'Configure notifications',
|
|
'Set up newsletters',
|
|
],
|
|
},
|
|
|
|
// === DEVELOPMENT TOOLS ===
|
|
'gitea': {
|
|
name: 'Gitea',
|
|
description: 'Lightweight self-hosted Git service',
|
|
icon: '🦊',
|
|
category: 'Development',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'gitea/gitea:latest',
|
|
ports: ['{{PORT}}:3000', '2222:22'],
|
|
volumes: [
|
|
'/opt/gitea/data:/data',
|
|
'/etc/timezone:/etc/timezone:ro',
|
|
'/etc/localtime:/etc/localtime:ro',
|
|
],
|
|
environment: {
|
|
'USER_UID': '1000',
|
|
'USER_GID': '1000',
|
|
},
|
|
},
|
|
subdomain: 'gitea',
|
|
defaultPort: 3005,
|
|
healthCheck: '/',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'GITEA__server__ROOT_URL',
|
|
setupInstructions: [
|
|
'Complete initial setup wizard',
|
|
'Create admin account',
|
|
'Configure SSH access',
|
|
],
|
|
},
|
|
|
|
'jenkins': {
|
|
name: 'Jenkins',
|
|
description: 'Automation server for CI/CD pipelines',
|
|
icon: '🔧',
|
|
category: 'Development',
|
|
popularity: 75,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'jenkins/jenkins:lts',
|
|
ports: ['{{PORT}}:8080', '50000:50000'],
|
|
volumes: ['/opt/jenkins/data:/var/jenkins_home'],
|
|
environment: {},
|
|
},
|
|
subdomain: 'jenkins',
|
|
defaultPort: 8089,
|
|
healthCheck: '/login',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Get initial admin password from logs',
|
|
'Install suggested plugins',
|
|
'Create admin user',
|
|
],
|
|
},
|
|
|
|
'drone': {
|
|
name: 'Drone CI',
|
|
description: 'Container-native continuous delivery platform',
|
|
icon: '🐝',
|
|
category: 'Development',
|
|
popularity: 70,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'drone/drone:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: ['/opt/drone/data:/data'],
|
|
environment: {
|
|
'DRONE_GITEA_SERVER': 'https://git.sami',
|
|
'DRONE_RPC_SECRET': '{{DRONE_RPC_SECRET}}',
|
|
'DRONE_SERVER_HOST': '{{SUBDOMAIN}}.sami',
|
|
'DRONE_SERVER_PROTO': 'https',
|
|
},
|
|
},
|
|
subdomain: 'drone',
|
|
defaultPort: 8090,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure Git provider integration',
|
|
'Set up shared secret',
|
|
'Deploy Drone runners',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'DRONE_RPC_SECRET',
|
|
label: 'RPC Secret',
|
|
description: 'Shared secret for Drone server and runner communication',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 64,
|
|
},
|
|
],
|
|
},
|
|
|
|
// === NOTES & WIKI ===
|
|
'bookstack': {
|
|
name: 'BookStack',
|
|
description: 'Simple wiki and documentation platform',
|
|
icon: '📖',
|
|
category: 'Productivity',
|
|
popularity: 80,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/bookstack:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: ['/opt/bookstack/config:/config'],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'APP_URL': 'https://{{SUBDOMAIN}}.sami',
|
|
'DB_HOST': 'mariadb',
|
|
'DB_DATABASE': 'bookstack',
|
|
'DB_USERNAME': 'bookstack',
|
|
'DB_PASSWORD': '{{BOOKSTACK_DB_PASSWORD}}',
|
|
},
|
|
},
|
|
subdomain: 'wiki',
|
|
defaultPort: 8091,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Requires MariaDB/MySQL database',
|
|
'Default login: admin@admin.com / password',
|
|
'Change default credentials',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'BOOKSTACK_DB_PASSWORD',
|
|
label: 'Database Password',
|
|
description: 'Password for BookStack database user',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'outline': {
|
|
name: 'Outline',
|
|
description: 'Modern team knowledge base and wiki',
|
|
icon: '📝',
|
|
category: 'Productivity',
|
|
popularity: 75,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'outlinewiki/outline:latest',
|
|
ports: ['{{PORT}}:3000'],
|
|
volumes: ['/opt/outline/data:/var/lib/outline/data'],
|
|
environment: {
|
|
'URL': 'https://{{SUBDOMAIN}}.sami',
|
|
'SECRET_KEY': '{{OUTLINE_SECRET_KEY}}',
|
|
'DATABASE_URL': 'postgres://outline:{{OUTLINE_DB_PASSWORD}}@postgres:5432/outline',
|
|
},
|
|
},
|
|
subdomain: 'outline',
|
|
defaultPort: 3006,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Requires PostgreSQL and Redis',
|
|
'Configure OAuth provider',
|
|
'Set up S3-compatible storage',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'OUTLINE_SECRET_KEY',
|
|
label: 'Secret Key',
|
|
description: 'Secret key for encrypting session data',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 64,
|
|
},
|
|
{
|
|
envVar: 'OUTLINE_DB_PASSWORD',
|
|
label: 'Database Password',
|
|
description: 'Password for Outline PostgreSQL database user',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'standardnotes': {
|
|
name: 'Standard Notes',
|
|
description: 'End-to-end encrypted notes app',
|
|
icon: '🔒',
|
|
category: 'Productivity',
|
|
popularity: 72,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'standardnotes/server:latest',
|
|
ports: ['{{PORT}}:3000'],
|
|
volumes: ['/opt/standardnotes/data:/var/lib/server'],
|
|
environment: {
|
|
'RAILS_ENV': 'production',
|
|
},
|
|
},
|
|
subdomain: 'notes',
|
|
defaultPort: 3007,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure environment variables',
|
|
'Set up database connection',
|
|
'Install Standard Notes apps',
|
|
],
|
|
},
|
|
|
|
// === PHOTOS & GALLERIES ===
|
|
'immich': {
|
|
name: 'Immich',
|
|
description: 'Self-hosted Google Photos alternative',
|
|
icon: '📸',
|
|
category: 'Photos',
|
|
popularity: 90,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'ghcr.io/immich-app/immich-server:latest',
|
|
ports: ['{{PORT}}:2283'],
|
|
volumes: [
|
|
'/opt/immich/upload:/usr/src/app/upload',
|
|
'/opt/immich/library:/usr/src/app/library',
|
|
],
|
|
environment: {
|
|
'DB_HOSTNAME': 'postgres',
|
|
'DB_USERNAME': 'immich',
|
|
'DB_PASSWORD': '{{IMMICH_DB_PASSWORD}}',
|
|
'DB_DATABASE_NAME': 'immich',
|
|
'REDIS_HOSTNAME': 'redis',
|
|
},
|
|
},
|
|
subdomain: 'photos',
|
|
defaultPort: 2283,
|
|
healthCheck: '/api/server-info/ping',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Requires PostgreSQL and Redis',
|
|
'Install mobile apps for backup',
|
|
'Configure machine learning for face detection',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'IMMICH_DB_PASSWORD',
|
|
label: 'Database Password',
|
|
description: 'Password for Immich PostgreSQL database user',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
'photoprism': {
|
|
name: 'PhotoPrism',
|
|
description: 'AI-powered photo management',
|
|
icon: '🖼️',
|
|
category: 'Photos',
|
|
popularity: 85,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'photoprism/photoprism:latest',
|
|
ports: ['{{PORT}}:2342'],
|
|
volumes: [
|
|
'/opt/photoprism/storage:/photoprism/storage',
|
|
'/opt/photoprism/originals:/photoprism/originals',
|
|
],
|
|
environment: {
|
|
'PHOTOPRISM_ADMIN_PASSWORD': '{{PHOTOPRISM_ADMIN_PASSWORD}}',
|
|
'PHOTOPRISM_SITE_URL': 'https://{{SUBDOMAIN}}.sami/',
|
|
'PHOTOPRISM_DATABASE_DRIVER': 'sqlite',
|
|
},
|
|
},
|
|
subdomain: 'gallery',
|
|
defaultPort: 2342,
|
|
healthCheck: '/api/v1/status',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Change admin password',
|
|
'Import your photos',
|
|
'Run indexing for AI features',
|
|
],
|
|
secrets: [
|
|
{
|
|
envVar: 'PHOTOPRISM_ADMIN_PASSWORD',
|
|
label: 'Admin Password',
|
|
description: 'Password for PhotoPrism admin account',
|
|
type: 'password',
|
|
required: true,
|
|
generate: 'alphanumeric',
|
|
length: 32,
|
|
},
|
|
],
|
|
},
|
|
|
|
// === DOWNLOAD MANAGERS ===
|
|
'sabnzbd': {
|
|
name: 'SABnzbd',
|
|
description: 'Binary newsreader for Usenet downloads',
|
|
icon: '📰',
|
|
category: 'Downloads',
|
|
popularity: 75,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/sabnzbd:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/opt/sabnzbd/config:/config',
|
|
'/downloads:/downloads',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'sabnzbd',
|
|
defaultPort: 8092,
|
|
healthCheck: '/',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'SABNZBD_URL_BASE',
|
|
setupInstructions: [
|
|
'Configure Usenet server credentials',
|
|
'Set up download categories',
|
|
'Configure post-processing scripts',
|
|
],
|
|
},
|
|
|
|
'nzbget': {
|
|
name: 'NZBGet',
|
|
description: 'Efficient Usenet downloader',
|
|
icon: '📥',
|
|
category: 'Downloads',
|
|
popularity: 70,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'linuxserver/nzbget:latest',
|
|
ports: ['{{PORT}}:6789'],
|
|
volumes: [
|
|
'/opt/nzbget/config:/config',
|
|
'/downloads:/downloads',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'nzbget',
|
|
defaultPort: 6789,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Default login: nzbget/tegbzn6789',
|
|
'Configure news servers',
|
|
'Set up categories and paths',
|
|
],
|
|
},
|
|
|
|
'transmission': {
|
|
name: 'Transmission',
|
|
description: 'Lightweight BitTorrent client',
|
|
icon: '🌊',
|
|
category: 'Downloads',
|
|
popularity: 80,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'linuxserver/transmission:latest',
|
|
ports: ['{{PORT}}:9091', '51413:51413', '51413:51413/udp'],
|
|
volumes: [
|
|
'/opt/transmission/config:/config',
|
|
'/downloads:/downloads',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'transmission',
|
|
defaultPort: 9092,
|
|
healthCheck: '/transmission/web/',
|
|
subpathSupport: 'native',
|
|
urlBaseEnv: 'TRANSMISSION_WEB_HOME',
|
|
setupInstructions: [
|
|
'Configure download paths',
|
|
'Set bandwidth limits',
|
|
'Configure blocklists if needed',
|
|
],
|
|
},
|
|
|
|
'jdownloader': {
|
|
name: 'JDownloader 2',
|
|
description: 'Download manager for file hosting sites',
|
|
icon: '⬇️',
|
|
category: 'Downloads',
|
|
popularity: 72,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'jlesage/jdownloader-2:latest',
|
|
ports: ['{{PORT}}:5800'],
|
|
volumes: [
|
|
'/opt/jdownloader/config:/config',
|
|
'/downloads:/output',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'jdownloader',
|
|
defaultPort: 5800,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Access web interface to configure',
|
|
'Link to MyJDownloader account',
|
|
'Configure download paths',
|
|
],
|
|
},
|
|
|
|
// === STREAMING & MEDIA ===
|
|
'navidrome': {
|
|
name: 'Navidrome',
|
|
description: 'Modern music server and streamer',
|
|
icon: '🎶',
|
|
category: 'Media',
|
|
popularity: 80,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'deluan/navidrome:latest',
|
|
ports: ['{{PORT}}:4533'],
|
|
volumes: [
|
|
'/opt/navidrome/data:/data',
|
|
'/music:/music:ro',
|
|
],
|
|
environment: {
|
|
'ND_SCANSCHEDULE': '1h',
|
|
'ND_LOGLEVEL': 'info',
|
|
},
|
|
},
|
|
subdomain: 'music',
|
|
defaultPort: 4533,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Point to your music library',
|
|
'Create user accounts',
|
|
'Install Subsonic-compatible apps',
|
|
],
|
|
},
|
|
|
|
'airsonic': {
|
|
name: 'Airsonic Advanced',
|
|
description: 'Free web-based media streamer',
|
|
icon: '🎧',
|
|
category: 'Media',
|
|
popularity: 68,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'linuxserver/airsonic-advanced:latest',
|
|
ports: ['{{PORT}}:4040'],
|
|
volumes: [
|
|
'/opt/airsonic/config:/config',
|
|
'/music:/music',
|
|
'/podcasts:/podcasts',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'airsonic',
|
|
defaultPort: 4040,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Default login: admin/admin',
|
|
'Configure media folders',
|
|
'Set up transcoding',
|
|
],
|
|
},
|
|
|
|
// === MISC UTILITIES ===
|
|
'homepage': {
|
|
name: 'Homepage',
|
|
description: 'Highly customizable application dashboard',
|
|
icon: '🏡',
|
|
category: 'Utilities',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/gethomepage/homepage:latest',
|
|
ports: ['{{PORT}}:3000'],
|
|
volumes: [
|
|
'/opt/homepage/config:/app/config',
|
|
'/var/run/docker.sock:/var/run/docker.sock:ro',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'dashboard',
|
|
defaultPort: 3008,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Edit config files to add services',
|
|
'Configure widgets',
|
|
'Customize appearance',
|
|
],
|
|
},
|
|
|
|
'homarr': {
|
|
name: 'Homarr',
|
|
description: 'Sleek dashboard for all your services',
|
|
icon: '🎯',
|
|
category: 'Utilities',
|
|
popularity: 82,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/ajnart/homarr:latest',
|
|
ports: ['{{PORT}}:7575'],
|
|
volumes: [
|
|
'/opt/homarr/configs:/app/data/configs',
|
|
'/opt/homarr/icons:/app/public/icons',
|
|
'/var/run/docker.sock:/var/run/docker.sock:ro',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'homarr',
|
|
defaultPort: 7575,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Add your services via UI',
|
|
'Configure integrations',
|
|
'Customize layout and appearance',
|
|
],
|
|
},
|
|
|
|
'changedetection': {
|
|
name: 'Change Detection',
|
|
description: 'Monitor websites for changes',
|
|
icon: '👁️',
|
|
category: 'Utilities',
|
|
popularity: 70,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/dgtlmoon/changedetection.io:latest',
|
|
ports: ['{{PORT}}:5000'],
|
|
volumes: ['/opt/changedetection/data:/datastore'],
|
|
environment: {},
|
|
},
|
|
subdomain: 'watch',
|
|
defaultPort: 5001,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Add URLs to monitor',
|
|
'Configure check frequency',
|
|
'Set up notifications',
|
|
],
|
|
},
|
|
|
|
'speedtest': {
|
|
name: 'Speedtest Tracker',
|
|
description: 'Internet speed monitoring over time',
|
|
icon: '⚡',
|
|
category: 'Monitoring',
|
|
popularity: 75,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/alexjustesen/speedtest-tracker:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: ['/opt/speedtest/config:/config'],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'DB_CONNECTION': 'sqlite',
|
|
},
|
|
},
|
|
subdomain: 'speedtest',
|
|
defaultPort: 8093,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Configure test schedule',
|
|
'View historical data',
|
|
'Set up notifications for slow speeds',
|
|
],
|
|
},
|
|
|
|
'whoami': {
|
|
name: 'Whoami',
|
|
description: 'Simple HTTP request debugging service',
|
|
icon: '🔍',
|
|
category: 'Utilities',
|
|
popularity: 60,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'traefik/whoami:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [],
|
|
environment: {},
|
|
},
|
|
subdomain: 'whoami',
|
|
defaultPort: 8094,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Useful for testing reverse proxy setup',
|
|
'Shows request headers and info',
|
|
],
|
|
},
|
|
|
|
// === NEW APPS ===
|
|
|
|
'stirling-pdf': {
|
|
name: 'Stirling PDF',
|
|
description: 'Self-hosted PDF manipulation tool - merge, split, convert, and more',
|
|
icon: '\uD83D\uDCC4',
|
|
logo: '/assets/stirling-pdf.png',
|
|
category: 'Utilities',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'frooodle/s-pdf:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/opt/stirling-pdf/data:/usr/share/tessdata',
|
|
'/opt/stirling-pdf/config:/configs',
|
|
],
|
|
environment: {
|
|
'DOCKER_ENABLE_SECURITY': 'false',
|
|
},
|
|
},
|
|
subdomain: 'pdf',
|
|
defaultPort: 8084,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Access the web interface to start manipulating PDFs',
|
|
'Supports merge, split, rotate, convert, compress, and more',
|
|
'Optional OCR support via Tesseract',
|
|
],
|
|
},
|
|
|
|
'actual-budget': {
|
|
name: 'Actual Budget',
|
|
description: 'Privacy-focused budgeting app with envelope budgeting',
|
|
icon: '\uD83D\uDCB0',
|
|
logo: '/assets/actual-budget.png',
|
|
category: 'Productivity',
|
|
popularity: 78,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'actualbudget/actual-server:latest',
|
|
ports: ['{{PORT}}:5006'],
|
|
volumes: [
|
|
'/opt/actual-budget/data:/data',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'budget',
|
|
defaultPort: 5006,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Create your first budget in the web interface',
|
|
'Import transactions from your bank (OFX, QFX, CSV)',
|
|
'Set up envelope categories for spending control',
|
|
],
|
|
},
|
|
|
|
'mealie': {
|
|
name: 'Mealie',
|
|
description: 'Recipe manager and meal planner with grocery lists',
|
|
icon: '\uD83C\uDF73',
|
|
logo: '/assets/mealie.png',
|
|
category: 'Productivity',
|
|
popularity: 76,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/mealie-recipes/mealie:latest',
|
|
ports: ['{{PORT}}:9000'],
|
|
volumes: [
|
|
'/opt/mealie/data:/app/data',
|
|
],
|
|
environment: {
|
|
'ALLOW_SIGNUP': 'true',
|
|
'MAX_WORKERS': '1',
|
|
'WEB_CONCURRENCY': '1',
|
|
'BASE_URL': 'https://{{SUBDOMAIN}}.sami',
|
|
},
|
|
},
|
|
subdomain: 'mealie',
|
|
defaultPort: 9925,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Default login: changeme@example.com / MyPassword',
|
|
'Import recipes from URLs or add them manually',
|
|
'Create meal plans and generate shopping lists',
|
|
],
|
|
},
|
|
|
|
'paperless-ngx': {
|
|
name: 'Paperless-ngx',
|
|
description: 'Document management system - scan, organize, and search documents',
|
|
icon: '\uD83D\uDCDA',
|
|
logo: '/assets/paperless-ngx.png',
|
|
category: 'Productivity',
|
|
popularity: 82,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'ghcr.io/paperless-ngx/paperless-ngx:latest',
|
|
ports: ['{{PORT}}:8000'],
|
|
volumes: [
|
|
'/opt/paperless/data:/usr/src/paperless/data',
|
|
'/opt/paperless/media:/usr/src/paperless/media',
|
|
'/opt/paperless/consume:/usr/src/paperless/consume',
|
|
],
|
|
environment: {
|
|
'PAPERLESS_URL': 'https://{{SUBDOMAIN}}.sami',
|
|
'USERMAP_UID': '1000',
|
|
'USERMAP_GID': '1000',
|
|
'PAPERLESS_TIME_ZONE': '{{TIMEZONE}}',
|
|
'PAPERLESS_OCR_LANGUAGE': 'eng',
|
|
'PAPERLESS_SECRET_KEY': '{{GENERATED_SECRET}}',
|
|
},
|
|
},
|
|
subdomain: 'paperless',
|
|
defaultPort: 8095,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Create admin account via: docker exec -it <container> python3 manage.py createsuperuser',
|
|
'Drop documents into the consume folder for automatic import',
|
|
'Configure tags and correspondents for organization',
|
|
],
|
|
},
|
|
|
|
'audiobookshelf': {
|
|
name: 'Audiobookshelf',
|
|
description: 'Self-hosted audiobook and podcast server',
|
|
icon: '\uD83C\uDFA7',
|
|
logo: '/assets/audiobookshelf.png',
|
|
category: 'Media',
|
|
popularity: 80,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'ghcr.io/advplyr/audiobookshelf:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [
|
|
'/opt/audiobookshelf/config:/config',
|
|
'/opt/audiobookshelf/metadata:/metadata',
|
|
'{{MEDIA_PATH}}:/audiobooks',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'audiobooks',
|
|
defaultPort: 13378,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/audiobooks',
|
|
label: 'Audiobook Library',
|
|
description: 'Folder containing your audiobooks and podcasts',
|
|
defaultPath: '/media/audiobooks',
|
|
},
|
|
setupInstructions: [
|
|
'Create your account on first access',
|
|
'Add your audiobook library folders',
|
|
'Download the mobile app for offline listening',
|
|
],
|
|
},
|
|
|
|
'calibre-web': {
|
|
name: 'Calibre-Web',
|
|
description: 'Web-based ebook manager and reader',
|
|
icon: '\uD83D\uDCD6',
|
|
logo: '/assets/calibre-web.png',
|
|
category: 'Media',
|
|
popularity: 74,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'lscr.io/linuxserver/calibre-web:latest',
|
|
ports: ['{{PORT}}:8083'],
|
|
volumes: [
|
|
'/opt/calibre-web/config:/config',
|
|
'{{MEDIA_PATH}}:/books',
|
|
],
|
|
environment: {
|
|
'PUID': '1000',
|
|
'PGID': '1000',
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'books',
|
|
defaultPort: 8083,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/books',
|
|
label: 'Ebook Library',
|
|
description: 'Folder containing your Calibre library (with metadata.db)',
|
|
defaultPath: '/media/books',
|
|
},
|
|
setupInstructions: [
|
|
'Default login: admin / admin123',
|
|
'Point to your Calibre database location on first setup',
|
|
'Supports EPUB, PDF, MOBI, and more formats',
|
|
],
|
|
},
|
|
|
|
'komga': {
|
|
name: 'Komga',
|
|
description: 'Comic and manga media server with web reader',
|
|
icon: '\uD83D\uDCDA',
|
|
logo: '/assets/komga.png',
|
|
category: 'Media',
|
|
popularity: 70,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'gotson/komga:latest',
|
|
ports: ['{{PORT}}:25600'],
|
|
volumes: [
|
|
'/opt/komga/config:/config',
|
|
'{{MEDIA_PATH}}:/data',
|
|
],
|
|
environment: {
|
|
'TZ': '{{TIMEZONE}}',
|
|
},
|
|
},
|
|
subdomain: 'komga',
|
|
defaultPort: 25600,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/data',
|
|
label: 'Comics Library',
|
|
description: 'Folder containing your comics and manga',
|
|
defaultPath: '/media/comics',
|
|
},
|
|
setupInstructions: [
|
|
'Create admin account on first access',
|
|
'Add your comic libraries (CBZ, CBR, PDF supported)',
|
|
'Use OPDS for third-party reader apps',
|
|
],
|
|
},
|
|
|
|
'kavita': {
|
|
name: 'Kavita',
|
|
description: 'Digital reading platform for manga, comics, and books',
|
|
icon: '\uD83D\uDCD6',
|
|
logo: '/assets/kavita.png',
|
|
category: 'Media',
|
|
popularity: 72,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'jvmilazz0/kavita:latest',
|
|
ports: ['{{PORT}}:5000'],
|
|
volumes: [
|
|
'/opt/kavita/config:/kavita/config',
|
|
'{{MEDIA_PATH}}:/data',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'kavita',
|
|
defaultPort: 5004,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
mediaMount: {
|
|
required: true,
|
|
containerPath: '/data',
|
|
label: 'Reading Library',
|
|
description: 'Folder containing your manga, comics, and ebooks',
|
|
defaultPath: '/media/reading',
|
|
},
|
|
setupInstructions: [
|
|
'Create admin account on first access',
|
|
'Add library folders for manga, comics, or books',
|
|
'Supports EPUB, PDF, CBZ, CBR formats',
|
|
],
|
|
},
|
|
|
|
'trilium': {
|
|
name: 'Trilium Notes',
|
|
description: 'Hierarchical knowledge base and note-taking app',
|
|
icon: '\uD83D\uDDD2\uFE0F',
|
|
logo: '/assets/trilium.png',
|
|
category: 'Productivity',
|
|
popularity: 75,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'zadam/trilium:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/opt/trilium/data:/home/node/trilium-data',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'notes',
|
|
defaultPort: 8085,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Set your password on first access',
|
|
'Organize notes in a tree hierarchy',
|
|
'Supports rich text, code blocks, math equations, and diagrams',
|
|
],
|
|
},
|
|
|
|
'excalidraw': {
|
|
name: 'Excalidraw',
|
|
description: 'Collaborative virtual whiteboard for sketching and diagrams',
|
|
icon: '\uD83C\uDFA8',
|
|
logo: '/assets/excalidraw.png',
|
|
category: 'Productivity',
|
|
popularity: 73,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'excalidraw/excalidraw:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [],
|
|
environment: {},
|
|
},
|
|
subdomain: 'draw',
|
|
defaultPort: 8086,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Start drawing immediately - no account needed',
|
|
'Share drawings via link for real-time collaboration',
|
|
'Export as PNG, SVG, or Excalidraw file',
|
|
],
|
|
},
|
|
|
|
'it-tools': {
|
|
name: 'IT Tools',
|
|
description: 'Collection of handy developer and IT tools in one place',
|
|
icon: '\uD83E\uDDF0',
|
|
logo: '/assets/it-tools.png',
|
|
category: 'Utilities',
|
|
popularity: 79,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'corentinth/it-tools:latest',
|
|
ports: ['{{PORT}}:80'],
|
|
volumes: [],
|
|
environment: {},
|
|
},
|
|
subdomain: 'tools',
|
|
defaultPort: 8087,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Access the web interface for instant tools access',
|
|
'Includes: hash generators, UUID, JWT decoder, base64, regex tester, and 70+ more',
|
|
'No configuration needed',
|
|
],
|
|
},
|
|
|
|
'dozzle': {
|
|
name: 'Dozzle',
|
|
description: 'Real-time Docker container log viewer',
|
|
icon: '\uD83D\uDCDC',
|
|
logo: '/assets/dozzle.png',
|
|
category: 'Monitoring',
|
|
popularity: 77,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'amir20/dozzle:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/var/run/docker.sock:/var/run/docker.sock:ro',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'logs',
|
|
defaultPort: 8088,
|
|
healthCheck: '/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'View real-time logs from all running containers',
|
|
'Filter and search across container logs',
|
|
'No configuration needed - auto-discovers containers',
|
|
],
|
|
},
|
|
|
|
'watchtower': {
|
|
name: 'Watchtower',
|
|
description: 'Automatic Docker container image updates',
|
|
icon: '\uD83D\uDC53',
|
|
logo: '/assets/watchtower.png',
|
|
category: 'Management',
|
|
popularity: 81,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'containrrr/watchtower:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/var/run/docker.sock:/var/run/docker.sock',
|
|
],
|
|
environment: {
|
|
'WATCHTOWER_CLEANUP': 'true',
|
|
'WATCHTOWER_SCHEDULE': '0 0 4 * * *',
|
|
'WATCHTOWER_HTTP_API_METRICS': 'true',
|
|
'WATCHTOWER_HTTP_API_TOKEN': '{{GENERATED_SECRET}}',
|
|
},
|
|
},
|
|
subdomain: 'watchtower',
|
|
defaultPort: 8089,
|
|
healthCheck: '/v1/update',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Watchtower checks for image updates daily at 4 AM by default',
|
|
'Customize schedule via WATCHTOWER_SCHEDULE (cron format)',
|
|
'Add labels to exclude specific containers from updates',
|
|
],
|
|
},
|
|
|
|
'authentik': {
|
|
name: 'Authentik',
|
|
description: 'Identity provider and single sign-on platform',
|
|
icon: '\uD83D\uDD10',
|
|
logo: '/assets/authentik.png',
|
|
category: 'Security',
|
|
popularity: 80,
|
|
difficulty: 'Advanced',
|
|
docker: {
|
|
image: 'ghcr.io/goauthentik/server:latest',
|
|
ports: ['{{PORT}}:9000'],
|
|
volumes: [
|
|
'/opt/authentik/media:/media',
|
|
'/opt/authentik/templates:/templates',
|
|
],
|
|
environment: {
|
|
'AUTHENTIK_SECRET_KEY': '{{GENERATED_SECRET}}',
|
|
'AUTHENTIK_ERROR_REPORTING__ENABLED': 'false',
|
|
},
|
|
},
|
|
subdomain: 'auth',
|
|
defaultPort: 9010,
|
|
healthCheck: '/-/health/live/',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Requires a PostgreSQL database and Redis instance',
|
|
'Consider deploying via the Dev Environment recipe for full stack',
|
|
'Set up flows for authentication, enrollment, and recovery',
|
|
'Configure OAuth2/OIDC providers for SSO with other apps',
|
|
],
|
|
},
|
|
|
|
'crowdsec': {
|
|
name: 'CrowdSec',
|
|
description: 'Collaborative intrusion prevention system',
|
|
icon: '\uD83D\uDEE1\uFE0F',
|
|
logo: '/assets/crowdsec.png',
|
|
category: 'Security',
|
|
popularity: 74,
|
|
difficulty: 'Intermediate',
|
|
docker: {
|
|
image: 'crowdsecurity/crowdsec:latest',
|
|
ports: ['{{PORT}}:8080'],
|
|
volumes: [
|
|
'/opt/crowdsec/config:/etc/crowdsec',
|
|
'/opt/crowdsec/data:/var/lib/crowdsec/data',
|
|
'/var/log:/var/log:ro',
|
|
],
|
|
environment: {},
|
|
},
|
|
subdomain: 'crowdsec',
|
|
defaultPort: 8091,
|
|
healthCheck: '/health',
|
|
subpathSupport: 'strip',
|
|
setupInstructions: [
|
|
'Register at app.crowdsec.net for community threat intelligence',
|
|
'Install bouncers on your reverse proxy for active blocking',
|
|
'CrowdSec analyzes logs and shares threat data with the community',
|
|
],
|
|
},
|
|
|
|
'minecraft': {
|
|
name: 'Minecraft Server',
|
|
description: 'Minecraft Java Edition dedicated server',
|
|
icon: '\u26CF\uFE0F',
|
|
logo: '/assets/minecraft.png',
|
|
category: 'Gaming',
|
|
popularity: 85,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'itzg/minecraft-server:latest',
|
|
ports: ['{{PORT}}:25565'],
|
|
volumes: [
|
|
'/opt/minecraft/data:/data',
|
|
],
|
|
environment: {
|
|
'EULA': 'TRUE',
|
|
'TYPE': 'VANILLA',
|
|
'VERSION': 'LATEST',
|
|
'MEMORY': '2G',
|
|
'MAX_PLAYERS': '20',
|
|
'MOTD': 'DashCaddy Minecraft Server',
|
|
},
|
|
},
|
|
subdomain: 'mc',
|
|
defaultPort: 25565,
|
|
healthCheck: null,
|
|
subpathSupport: 'none',
|
|
setupInstructions: [
|
|
'Server accepts the Minecraft EULA automatically',
|
|
'Connect with your Minecraft client to the server IP:port',
|
|
'Configure server.properties in the data volume for customization',
|
|
'Supports Vanilla, Paper, Forge, Fabric via TYPE environment variable',
|
|
],
|
|
},
|
|
|
|
'valheim': {
|
|
name: 'Valheim Server',
|
|
description: 'Valheim dedicated server for multiplayer Viking adventures',
|
|
icon: '\u2694\uFE0F',
|
|
logo: '/assets/valheim.png',
|
|
category: 'Gaming',
|
|
popularity: 72,
|
|
difficulty: 'Easy',
|
|
docker: {
|
|
image: 'lloesche/valheim-server:latest',
|
|
ports: ['{{PORT}}:2456/udp', '2457:2457/udp', '2458:2458/udp'],
|
|
volumes: [
|
|
'/opt/valheim/config:/config',
|
|
'/opt/valheim/data:/opt/valheim',
|
|
],
|
|
environment: {
|
|
'SERVER_NAME': 'DashCaddy Valheim',
|
|
'WORLD_NAME': 'DashCaddyWorld',
|
|
'SERVER_PASS': '{{GENERATED_SECRET}}',
|
|
'SERVER_PUBLIC': 'false',
|
|
},
|
|
},
|
|
subdomain: 'valheim',
|
|
defaultPort: 2456,
|
|
healthCheck: null,
|
|
subpathSupport: 'none',
|
|
setupInstructions: [
|
|
'Connect via Steam: Add Server > IP:2456',
|
|
'Default server password is auto-generated (check environment variables)',
|
|
'World data is persisted in the data volume',
|
|
'Requires at least 4GB RAM for smooth operation',
|
|
],
|
|
},
|
|
};
|
|
|
|
// Template categories for organization
|
|
const TEMPLATE_CATEGORIES = {
|
|
'Media': { icon: '🎬', color: '#e74c3c' },
|
|
'Media Management': { icon: '📋', color: '#3498db' },
|
|
'Downloads': { icon: '⬇️', color: '#2ecc71' },
|
|
'Productivity': { icon: '📝', color: '#f39c12' },
|
|
'Development': { icon: '💻', color: '#9b59b6' },
|
|
'Management': { icon: '⚙️', color: '#34495e' },
|
|
'Monitoring': { icon: '📊', color: '#1abc9c' },
|
|
'Networking': { icon: '🌐', color: '#e67e22' },
|
|
'DNS': { icon: '🌐', color: '#3498db' },
|
|
'Files': { icon: '📁', color: '#3498db' },
|
|
'Communication': { icon: '💬', color: '#9b59b6' },
|
|
'Home Automation': { icon: '🏠', color: '#27ae60' },
|
|
'Database': { icon: '🗄️', color: '#8e44ad' },
|
|
'Security': { icon: '🔐', color: '#c0392b' },
|
|
'Photos': { icon: '📸', color: '#16a085' },
|
|
'Utilities': { icon: '\uD83D\uDEE0\uFE0F', color: '#7f8c8d' },
|
|
'Gaming': { icon: '\uD83C\uDFAE', color: '#e91e63' },
|
|
};
|
|
|
|
// Difficulty levels
|
|
const DIFFICULTY_LEVELS = {
|
|
'Easy': { color: '#2ecc71', description: 'Quick setup, minimal configuration' },
|
|
'Intermediate': { color: '#f39c12', description: 'Some configuration required' },
|
|
'Advanced': { color: '#e74c3c', description: 'Complex setup, technical knowledge needed' },
|
|
};
|
|
|
|
module.exports = {
|
|
APP_TEMPLATES,
|
|
TEMPLATE_CATEGORIES,
|
|
DIFFICULTY_LEVELS,
|
|
}; |