feat: optimize JSON sync with 1 API call + raw URLs

- Replace GitHub API calls (390+) with 1 API call + raw URL downloads
- Create GitHubJsonService for efficient JSON file syncing
- Reduce API rate limiting issues by 99.7%
- Add automatic page reload after successful sync
- Update tests to use new service
- Maintain same functionality with better performance

Performance improvement:
- Before: 390+ GitHub API calls (1 per JSON file)
- After: 1 GitHub API call + 389 raw URL downloads
- Raw URLs have no rate limits, making sync much more reliable
This commit is contained in:
Michel Roegl-Brunner
2025-09-15 14:30:07 +02:00
parent 92b2c0d5fc
commit 82dc4643de
392 changed files with 3323 additions and 1381 deletions

View File

@@ -1,35 +1,35 @@
{
"name": "Actual Budget",
"slug": "actualbudget",
"categories": [
23
],
"date_created": "2025-05-06",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 5006,
"documentation": "https://github.com/community-scripts/ProxmoxVE/discussions/807",
"website": "https://actualbudget.org/",
"config_path": "/opt/actualbudget-data/config.json",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/actual-budget.webp",
"description": "Actual Budget is a super fast and privacy-focused app for managing your finances. At its heart is the well proven and much loved Envelope Budgeting methodology.",
"install_methods": [
{
"type": "default",
"script": "ct/actualbudget.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "Actual Budget",
"slug": "actualbudget",
"categories": [
23
],
"date_created": "2025-05-06",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 5006,
"documentation": "https://github.com/community-scripts/ProxmoxVE/discussions/807",
"website": "https://actualbudget.org/",
"config_path": "/opt/actualbudget-data/config.json",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/actual-budget.webp",
"description": "Actual Budget is a super fast and privacy-focused app for managing your finances. At its heart is the well proven and much loved Envelope Budgeting methodology.",
"install_methods": [
{
"type": "default",
"script": "ct/actualbudget.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,51 +1,51 @@
{
"name": "AdGuard Home",
"slug": "adguard",
"categories": [
5
],
"date_created": "2024-04-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started",
"website": "https://adguard.com/en/adguard-home/overview.html",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/adguard-home.webp",
"config_path": "/opt/AdGuardHome/AdGuardHome.yaml",
"description": "AdGuard Home is an open-source, self-hosted network-wide ad blocker. It blocks advertisements, trackers, phishing and malware websites, and provides protection against online threats. AdGuard Home is a DNS-based solution, which means it blocks ads and malicious content at the network level, before it even reaches your device. It runs on your home network and can be easily configured and managed through a web-based interface. It provides detailed statistics and logs, allowing you to see which websites are being blocked, and why. AdGuard Home is designed to be fast, lightweight, and easy to use, making it an ideal solution for home users who want to block ads, protect their privacy, and improve the speed and security of their online experience.",
"install_methods": [
{
"type": "default",
"script": "ct/adguard.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
},
{
"type": "alpine",
"script": "ct/alpine-adguard.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 1,
"os": "alpine",
"version": "3.22"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "AdGuard Home",
"slug": "adguard",
"categories": [
5
],
"date_created": "2024-04-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started",
"website": "https://adguard.com/en/adguard-home/overview.html",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/adguard-home.webp",
"config_path": "/opt/AdGuardHome/AdGuardHome.yaml",
"description": "AdGuard Home is an open-source, self-hosted network-wide ad blocker. It blocks advertisements, trackers, phishing and malware websites, and provides protection against online threats. AdGuard Home is a DNS-based solution, which means it blocks ads and malicious content at the network level, before it even reaches your device. It runs on your home network and can be easily configured and managed through a web-based interface. It provides detailed statistics and logs, allowing you to see which websites are being blocked, and why. AdGuard Home is designed to be fast, lightweight, and easy to use, making it an ideal solution for home users who want to block ads, protect their privacy, and improve the speed and security of their online experience.",
"install_methods": [
{
"type": "default",
"script": "ct/adguard.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
},
"notes": [
{
"text": "Adguard Home can be updated via the user interface.",
"type": "info"
}
]
{
"type": "alpine",
"script": "ct/alpine-adguard.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 1,
"os": "alpine",
"version": "3.22"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Adguard Home can be updated via the user interface.",
"type": "info"
}
]
}

View File

@@ -0,0 +1,35 @@
{
"name": "Redlib",
"slug": "alpine-redlib",
"categories": [
10
],
"date_created": "2025-08-25",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 5252,
"documentation": "https://github.com/redlib-org/redlib/blob/main/README.md",
"website": "https://github.com/redlib-org/redlib",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/redlib.webp",
"config_path": "/opt/redlib/redlib.conf",
"description": "An alternative private front-end to Reddit. Redlib hopes to provide an easier way to browse Reddit, without the ads, trackers, and bloat.",
"install_methods": [
{
"type": "default",
"script": "ct/alpine-redlib.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 1,
"os": "alpine",
"version": "3.22"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -6,7 +6,7 @@
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"updateable": true,
"privileged": false,
"interface_port": 13378,
"documentation": "https://www.audiobookshelf.org/guides/",
@@ -21,7 +21,7 @@
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 4,
"hdd": 5,
"os": "debian",
"version": "12"
}

View File

@@ -40,7 +40,7 @@
"text": "After installation, checkout: ´https://github.com/community-scripts/ProxmoxVE/discussions/836´ for useful Debian commands",
"type": "info"
},
{
{
"text": "If you use Cloud-init, checkout after installation: ´https://github.com/community-scripts/ProxmoxVE/discussions/272´",
"type": "info"
}

View File

@@ -1,40 +1,40 @@
{
"name": "Duplicati",
"slug": "duplicati",
"categories": [
7
],
"date_created": "2025-02-06",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8200,
"documentation": "https://docs.duplicati.com/",
"website": "https://duplicati.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/duplicati.webp",
"config_path": "",
"description": "Duplicati is a free, open-source backup solution that offers zero-trust, fully encrypted backups for your data.",
"install_methods": [
{
"type": "default",
"script": "ct/duplicati.sh",
"resources": {
"cpu": 1,
"ram": 1048,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Admin password and database encryption key: `cat ~/duplicati.creds`",
"type": "info"
}
]
"name": "Duplicati",
"slug": "duplicati",
"categories": [
7
],
"date_created": "2025-02-06",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8200,
"documentation": "https://docs.duplicati.com/",
"website": "https://duplicati.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/duplicati.webp",
"config_path": "",
"description": "Duplicati is a free, open-source backup solution that offers zero-trust, fully encrypted backups for your data.",
"install_methods": [
{
"type": "default",
"script": "ct/duplicati.sh",
"resources": {
"cpu": 1,
"ram": 1048,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Admin password and database encryption key: `cat ~/duplicati.creds`",
"type": "info"
}
]
}

View File

@@ -21,7 +21,7 @@
"resources": {
"cpu": 2,
"ram": 1024,
"hdd": 4,
"hdd": 10,
"os": "debian",
"version": "12"
}

View File

@@ -1,40 +1,40 @@
{
"name": "evcc",
"slug": "evcc",
"categories": [
16
],
"date_created": "2024-10-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7070,
"documentation": "https://evcc.io/#devices",
"website": "https://evcc.io/en/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/evcc.webp",
"config_path": "",
"description": "EVCC is an open-source tool that manages EV charging, prioritizing solar energy use to reduce costs and optimize charging times. It supports various EVs and chargers, adjusting power automatically based on real-time data.",
"install_methods": [
{
"type": "default",
"script": "ct/evcc.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "To configure evcc, type `cd /etc` followed by `evcc configure` in the evcc LXC shell",
"type": "info"
}
]
"name": "evcc",
"slug": "evcc",
"categories": [
16
],
"date_created": "2024-10-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7070,
"documentation": "https://evcc.io/#devices",
"website": "https://evcc.io/en/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/evcc.webp",
"config_path": "",
"description": "EVCC is an open-source tool that manages EV charging, prioritizing solar energy use to reduce costs and optimize charging times. It supports various EVs and chargers, adjusting power automatically based on real-time data.",
"install_methods": [
{
"type": "default",
"script": "ct/evcc.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "To configure evcc, type `cd /etc` followed by `evcc configure` in the evcc LXC shell",
"type": "info"
}
]
}

View File

@@ -1,46 +1,46 @@
{
"name": "Grafana",
"slug": "grafana",
"categories": [
9
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://grafana.com/docs/grafana/latest/",
"website": "https://grafana.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/grafana.webp",
"config_path": "Debian: /etc/grafana/grafana.ini | Alpine: /etc/grafana.ini",
"description": "Grafana is a data visualization and monitoring platform that enables users to query, visualize, alert on and understand metrics, logs, and other data sources. It integrates with various data sources, including Prometheus, InfluxDB, Elasticsearch, and many others, to present a unified view of the data and enable users to create insightful and interactive dashboards.",
"install_methods": [
{
"type": "default",
"script": "ct/grafana.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
},
{
"type": "alpine",
"script": "ct/alpine-grafana.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 1,
"os": "alpine",
"version": "3.22"
}
}
],
"default_credentials": {
"username": "admin",
"password": "admin"
"name": "Grafana",
"slug": "grafana",
"categories": [
9
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://grafana.com/docs/grafana/latest/",
"website": "https://grafana.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/grafana.webp",
"config_path": "Debian: /etc/grafana/grafana.ini | Alpine: /etc/grafana.ini",
"description": "Grafana is a data visualization and monitoring platform that enables users to query, visualize, alert on and understand metrics, logs, and other data sources. It integrates with various data sources, including Prometheus, InfluxDB, Elasticsearch, and many others, to present a unified view of the data and enable users to create insightful and interactive dashboards.",
"install_methods": [
{
"type": "default",
"script": "ct/grafana.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
},
"notes": []
{
"type": "alpine",
"script": "ct/alpine-grafana.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 1,
"os": "alpine",
"version": "3.22"
}
}
],
"default_credentials": {
"username": "admin",
"password": "admin"
},
"notes": []
}

View File

@@ -1,44 +1,44 @@
{
"name": "Graylog",
"slug": "graylog",
"categories": [
9
],
"date_created": "2025-02-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9000,
"documentation": "https://go2docs.graylog.org/current/home.htm",
"website": "https://graylog.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/graylog.webp",
"config_path": "/etc/graylog/server/server.conf",
"description": "Graylog is an open-source log management and analysis platform that centralizes and processes log data from various sources, enabling real-time search, analysis, and alerting for IT infrastructure monitoring and troubleshooting.",
"install_methods": [
{
"type": "default",
"script": "ct/graylog.sh",
"resources": {
"cpu": 2,
"ram": 8192,
"hdd": 30,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Graylog",
"slug": "graylog",
"categories": [
9
],
"date_created": "2025-02-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9000,
"documentation": "https://go2docs.graylog.org/current/home.htm",
"website": "https://graylog.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/graylog.webp",
"config_path": "/etc/graylog/server/server.conf",
"description": "Graylog is an open-source log management and analysis platform that centralizes and processes log data from various sources, enabling real-time search, analysis, and alerting for IT infrastructure monitoring and troubleshooting.",
"install_methods": [
{
"type": "default",
"script": "ct/graylog.sh",
"resources": {
"cpu": 2,
"ram": 8192,
"hdd": 30,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Initial Setup credentials: `tail /var/log/graylog-server/server.log` after the server starts for the first time.",
"type": "info"
},
"notes": [
{
"text": "Initial Setup credentials: `tail /var/log/graylog-server/server.log` after the server starts for the first time.",
"type": "info"
},
{
"text": "Type `cat ~/graylog.creds` to get admin password that you use to log in AFTER the Initial Setup",
"type": "info"
}
]
{
"text": "Type `cat ~/graylog.creds` to get admin password that you use to log in AFTER the Initial Setup",
"type": "info"
}
]
}

View File

@@ -1,52 +1,52 @@
{
"name": "Home Assistant Container",
"slug": "homeassistant",
"categories": [
16
],
"date_created": "2024-04-29",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8123,
"documentation": "https://www.home-assistant.io/docs/",
"website": "https://www.home-assistant.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/home-assistant.webp",
"config_path": "/var/lib/docker/volumes/hass_config/_data",
"description": "A standalone container-based installation of Home Assistant Core means that the software is installed inside a Docker container, separate from the host operating system. This allows for flexibility and scalability, as well as improved security, as the container can be easily moved or isolated from other processes on the host.",
"install_methods": [
{
"type": "default",
"script": "ct/homeassistant.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 16,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Home Assistant Container",
"slug": "homeassistant",
"categories": [
16
],
"date_created": "2024-04-29",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8123,
"documentation": "https://www.home-assistant.io/docs/",
"website": "https://www.home-assistant.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/home-assistant.webp",
"config_path": "/var/lib/docker/volumes/hass_config/_data",
"description": "A standalone container-based installation of Home Assistant Core means that the software is installed inside a Docker container, separate from the host operating system. This allows for flexibility and scalability, as well as improved security, as the container can be easily moved or isolated from other processes on the host.",
"install_methods": [
{
"type": "default",
"script": "ct/homeassistant.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 16,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "If the LXC is created Privileged, the script will automatically set up USB passthrough.",
"type": "warning"
},
"notes": [
{
"text": "If the LXC is created Privileged, the script will automatically set up USB passthrough.",
"type": "warning"
},
{
"text": "config path: `/var/lib/docker/volumes/hass_config/_data`",
"type": "info"
},
{
"text": "Portainer interface: $IP: 9443 - User & password must be set manually within 5 minutes, otherwise a restart of Portainer is required!",
"type": "info"
},
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
}
]
{
"text": "config path: `/var/lib/docker/volumes/hass_config/_data`",
"type": "info"
},
{
"text": "Portainer interface: $IP: 9443 - User & password must be set manually within 5 minutes, otherwise a restart of Portainer is required!",
"type": "info"
},
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
}
]
}

View File

@@ -13,7 +13,7 @@
"website": "https://homebox.software/en/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/homebox.webp",
"config_path": "/opt/homebox/.env",
"description": "HomeBox is a simple, home-focused inventory management software. It allows users to organize and track household items by adding, updating, or deleting them. Features include optional details like warranty info, CSV import/export, custom labels, locations, and multi-tenant support for sharing with others. It\u2019s designed to be fast, easy to use, and portable.",
"description": "HomeBox is a simple, home-focused inventory management software. It allows users to organize and track household items by adding, updating, or deleting them. Features include optional details like warranty info, CSV import/export, custom labels, locations, and multi-tenant support for sharing with others. Its designed to be fast, easy to use, and portable.",
"install_methods": [
{
"type": "default",

View File

@@ -40,7 +40,7 @@
"text": "FFmpeg path: /usr/lib/jellyfin-ffmpeg/ffmpeg",
"type": "info"
},
{
{
"text": "For NVIDIA graphics cards, you'll need to install the same drivers in the container that you did on the host. In the container, run the driver installation script and add the CLI arg --no-kernel-module",
"type": "info"
}

View File

@@ -13,7 +13,7 @@
"website": "https://docs.magicmirror.builders/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/magicmirror2.webp",
"config_path": "/opt/magicmirror/config/config.js",
"description": "MagicMirror\u00b2 is a smart mirror software that allows you to build your own personal smart mirror. It uses modular components that you can customize to display information such as the weather, news, calendar, to-do list, and more. The platform is open source, allowing for community contributions and customization.",
"description": "MagicMirror² is a smart mirror software that allows you to build your own personal smart mirror. It uses modular components that you can customize to display information such as the weather, news, calendar, to-do list, and more. The platform is open source, allowing for community contributions and customization.",
"install_methods": [
{
"type": "default",

View File

@@ -13,7 +13,7 @@
"website": "https://www.usememos.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/memos.webp",
"config_path": "",
"description": "Memos is an open-source, self-hosted platform designed for fast, privacy-focused note-taking. Users can create, organize, and format notes with Markdown, which are securely stored in a local database. It\u2019s lightweight and customizable, built for quick access and adaptability to individual or team needs.",
"description": "Memos is an open-source, self-hosted platform designed for fast, privacy-focused note-taking. Users can create, organize, and format notes with Markdown, which are securely stored in a local database. Its lightweight and customizable, built for quick access and adaptability to individual or team needs.",
"install_methods": [
{
"type": "default",

View File

@@ -1,35 +1,35 @@
{
"name": "Monica",
"slug": "monica",
"categories": [
24
],
"date_created": "2025-01-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://github.com/monicahq/monica/tree/4.x/docs",
"website": "https://www.monicahq.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/monica.webp",
"config_path": "/opt/monica/.env",
"description": "Monica is an open-source personal CRM designed to help you manage and strengthen your relationships. It allows you to store important details about your contacts, track interactions, set reminders for special dates, and log activities—all in one secure, private place. Perfect for busy individuals, Monica helps you stay organized, remember meaningful moments, and nurture your connections without ads or data mining. Install it on your own server for full control!",
"install_methods": [
{
"type": "default",
"script": "ct/monica.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "admin@helper-scripts.com",
"password": "helper-scripts.com"
},
"notes": []
"name": "Monica",
"slug": "monica",
"categories": [
24
],
"date_created": "2025-01-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://github.com/monicahq/monica/tree/4.x/docs",
"website": "https://www.monicahq.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/monica.webp",
"config_path": "/opt/monica/.env",
"description": "Monica is an open-source personal CRM designed to help you manage and strengthen your relationships. It allows you to store important details about your contacts, track interactions, set reminders for special dates, and log activities—all in one secure, private place. Perfect for busy individuals, Monica helps you stay organized, remember meaningful moments, and nurture your connections without ads or data mining. Install it on your own server for full control!",
"install_methods": [
{
"type": "default",
"script": "ct/monica.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "admin@helper-scripts.com",
"password": "helper-scripts.com"
},
"notes": []
}

View File

@@ -13,7 +13,7 @@
"website": null,
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
"config_path": "",
"description": "This script will add Monitor-All to Proxmox VE, which will monitor the status of all your instances, both containers and virtual machines, excluding templates and user-defined ones, and automatically restart or reset them if they become unresponsive. This is particularly useful if you're experiencing problems with Home Assistant becoming non-responsive every few days/weeks. Monitor-All also maintains a log of the entire process, which can be helpful for troubleshooting and monitoring purposes.\r\n\r\n\ud83d\udec8 Virtual machines without the QEMU guest agent installed must be excluded.\r\n\ud83d\udec8 Prior to generating any new CT/VM not found in this repository, it's necessary to halt Proxmox VE Monitor-All by running systemctl stop ping-instances.",
"description": "This script will add Monitor-All to Proxmox VE, which will monitor the status of all your instances, both containers and virtual machines, excluding templates and user-defined ones, and automatically restart or reset them if they become unresponsive. This is particularly useful if you're experiencing problems with Home Assistant becoming non-responsive every few days/weeks. Monitor-All also maintains a log of the entire process, which can be helpful for troubleshooting and monitoring purposes.\r\n\r\n🛈 Virtual machines without the QEMU guest agent installed must be excluded.\r\n🛈 Prior to generating any new CT/VM not found in this repository, it's necessary to halt Proxmox VE Monitor-All by running systemctl stop ping-instances.",
"install_methods": [
{
"type": "default",

View File

@@ -1,48 +1,48 @@
{
"name": "MySQL",
"slug": "mysql",
"categories": [
8
],
"date_created": "2024-10-10",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://dev.mysql.com/doc/",
"website": "https://www.mysql.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/mysql.webp",
"config_path": "",
"description": "MySQL is an open-source relational database management system (RDBMS) that uses SQL for managing and manipulating data. It is known for its scalability, reliability, and high performance, making it suitable for small to large-scale applications. Key features include support for ACID transactions, data replication for high availability, and compatibility with various programming languages like Python, PHP, and Java.",
"install_methods": [
{
"type": "default",
"script": "ct/mysql.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "MySQL",
"slug": "mysql",
"categories": [
8
],
"date_created": "2024-10-10",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://dev.mysql.com/doc/",
"website": "https://www.mysql.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/mysql.webp",
"config_path": "",
"description": "MySQL is an open-source relational database management system (RDBMS) that uses SQL for managing and manipulating data. It is known for its scalability, reliability, and high performance, making it suitable for small to large-scale applications. Key features include support for ACID transactions, data replication for high availability, and compatibility with various programming languages like Python, PHP, and Java.",
"install_methods": [
{
"type": "default",
"script": "ct/mysql.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Database credentials: `cat mysql.creds`",
"type": "info"
},
"notes": [
{
"text": "Database credentials: `cat mysql.creds`",
"type": "info"
},
{
"text": "With an option to install the MySQL 8.4 LTS release instead of MySQL 8.0",
"type": "info"
},
{
"text": "If installed, access phpMyAdmin at `http://<LXC_IP>/phpMyAdmin`, case sensitive.",
"type": "info"
}
]
{
"text": "With an option to install the MySQL 8.4 LTS release instead of MySQL 8.0",
"type": "info"
},
{
"text": "If installed, access phpMyAdmin at `http://<LXC_IP>/phpMyAdmin`, case sensitive.",
"type": "info"
}
]
}

View File

@@ -1,35 +1,35 @@
{
"name": "Omada Controller",
"slug": "omada",
"categories": [
4
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8043,
"documentation": null,
"website": "https://www.tp-link.com/us/support/download/omada-software-controller/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/omada.webp",
"config_path": "",
"description": "Omada Controller is a software application used to manage TP-Link's Omada EAP (Enterprise Access Point) devices. It allows administrators to centrally manage a large number of EAPs, monitor network performance, and control user access to the network. The software provides an intuitive interface for network configuration, firmware upgrades, and network monitoring. By using the Omada Controller, administrators can streamline the management process, reduce manual intervention, and improve the overall security and reliability of the network.",
"install_methods": [
{
"type": "default",
"script": "ct/omada.sh",
"resources": {
"cpu": 2,
"ram": 3072,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "Omada Controller",
"slug": "omada",
"categories": [
4
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8043,
"documentation": null,
"website": "https://www.tp-link.com/us/support/download/omada-software-controller/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/omada.webp",
"config_path": "",
"description": "Omada Controller is a software application used to manage TP-Link's Omada EAP (Enterprise Access Point) devices. It allows administrators to centrally manage a large number of EAPs, monitor network performance, and control user access to the network. The software provides an intuitive interface for network configuration, firmware upgrades, and network monitoring. By using the Omada Controller, administrators can streamline the management process, reduce manual intervention, and improve the overall security and reliability of the network.",
"install_methods": [
{
"type": "default",
"script": "ct/omada.sh",
"resources": {
"cpu": 2,
"ram": 3072,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -0,0 +1,41 @@
{
"name": "OpenWrt",
"slug": "openwrt-vm",
"categories": [
4,
2
],
"date_created": "2024-05-02",
"type": "vm",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://openwrt.org/docs/start",
"website": "https://openwrt.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/openwrt.webp",
"config_path": "",
"description": "OpenWrt is a powerful open-source firmware that can transform a wide range of networking devices into highly customizable and feature-rich routers, providing users with greater control and flexibility over their network infrastructure.",
"install_methods": [
{
"type": "default",
"script": "vm/openwrt-vm.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 0.5,
"os": null,
"version": null
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "If you use VLANs (default LAN is set to VLAN 999), make sure the Proxmox Linux Bridge is configured as VLAN-aware, otherwise the VM may fail to start.",
"type": "info"
}
]
}

View File

@@ -1,44 +1,44 @@
{
"name": "Outline",
"slug": "outline",
"categories": [
12
],
"date_created": "2025-02-26",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://docs.getoutline.com/s/hosting/",
"website": "https://www.getoutline.com",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/outline.webp",
"config_path": "/opt/outline/.env",
"description": "The fastest knowledge base for growing teams. Beautiful, realtime collaborative, feature packed, and markdown compatible. Its time to get your teams knowledge organized.",
"install_methods": [
{
"type": "default",
"script": "ct/outline.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Outline",
"slug": "outline",
"categories": [
12
],
"date_created": "2025-02-26",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3000,
"documentation": "https://docs.getoutline.com/s/hosting/",
"website": "https://www.getoutline.com",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/outline.webp",
"config_path": "/opt/outline/.env",
"description": "The fastest knowledge base for growing teams. Beautiful, realtime collaborative, feature packed, and markdown compatible. Its time to get your teams knowledge organized.",
"install_methods": [
{
"type": "default",
"script": "ct/outline.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 8,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "After installation finishes, application will do a database migration so web UI might be unavailable for a minute or two. Also you need to manually add authentication and/or enable HTTPS.",
"type": "info"
},
"notes": [
{
"text": "After installation finishes, application will do a database migration so web UI might be unavailable for a minute or two. Also you need to manually add authentication and/or enable HTTPS.",
"type": "info"
},
{
"text": "Configuration file is at: `/opt/outline/.env`. Modify to suit your environment.",
"type": "info"
}
]
{
"text": "Configuration file is at: `/opt/outline/.env`. Modify to suit your environment.",
"type": "info"
}
]
}

View File

@@ -1,35 +1,35 @@
{
"name": "phpIPAM",
"slug": "phpipam",
"categories": [
4
],
"date_created": "2025-01-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://phpipam.net/documents/all-documents/",
"website": "https://phpipam.net/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/phpipam.webp",
"config_path": "/opt/phpipam/config.php",
"description": "phpipam is an open-source web IP address management application (IPAM). Its goal is to provide light, modern and useful IP address management.",
"install_methods": [
{
"type": "default",
"script": "ct/phpipam.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "Admin",
"password": "ipamadmin"
},
"notes": []
"name": "phpIPAM",
"slug": "phpipam",
"categories": [
4
],
"date_created": "2025-01-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://phpipam.net/documents/all-documents/",
"website": "https://phpipam.net/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/phpipam.webp",
"config_path": "/opt/phpipam/config.php",
"description": "phpipam is an open-source web IP address management application (IPAM). Its goal is to provide light, modern and useful IP address management.",
"install_methods": [
{
"type": "default",
"script": "ct/phpipam.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "Admin",
"password": "ipamadmin"
},
"notes": []
}

View File

@@ -1,52 +1,52 @@
{
"name": "Pi-Hole",
"slug": "pihole",
"categories": [
5
],
"date_created": "2024-04-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://docs.pi-hole.net/",
"website": "https://pi-hole.net/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/pi-hole.webp",
"config_path": "/etc/pihole/pihole.toml",
"description": "Pi-hole is a free, open-source network-level advertisement and Internet tracker blocking application. It runs on a Raspberry Pi or other Linux-based systems and acts as a DNS sinkhole, blocking unwanted traffic before it reaches a user's device. Pi-hole can also function as a DHCP server, providing IP addresses and other network configuration information to devices on a network. The software is highly configurable and supports a wide range of customizations, such as allowing or blocking specific domains, setting up blocklists and whitelists, and customizing the appearance of the web-based interface. The main purpose of Pi-hole is to protect users' privacy and security by blocking unwanted and potentially malicious content, such as ads, trackers, and malware. It is designed to be easy to set up and use, and can be configured through a web-based interface or through a terminal-based command-line interface.",
"install_methods": [
{
"type": "default",
"script": "ct/pihole.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Pi-Hole",
"slug": "pihole",
"categories": [
5
],
"date_created": "2024-04-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://docs.pi-hole.net/",
"website": "https://pi-hole.net/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/pi-hole.webp",
"config_path": "/etc/pihole/pihole.toml",
"description": "Pi-hole is a free, open-source network-level advertisement and Internet tracker blocking application. It runs on a Raspberry Pi or other Linux-based systems and acts as a DNS sinkhole, blocking unwanted traffic before it reaches a user's device. Pi-hole can also function as a DHCP server, providing IP addresses and other network configuration information to devices on a network. The software is highly configurable and supports a wide range of customizations, such as allowing or blocking specific domains, setting up blocklists and whitelists, and customizing the appearance of the web-based interface. The main purpose of Pi-hole is to protect users' privacy and security by blocking unwanted and potentially malicious content, such as ads, trackers, and malware. It is designed to be easy to set up and use, and can be configured through a web-based interface or through a terminal-based command-line interface.",
"install_methods": [
{
"type": "default",
"script": "ct/pihole.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "To set your password, log in to the container, and type the following: `pihole setpassword`",
"type": "info"
},
"notes": [
{
"text": "To set your password, log in to the container, and type the following: `pihole setpassword`",
"type": "info"
},
{
"text": "With an option to add Unbound",
"type": "info"
},
{
"text": "With an option to configure Unbound as a forwarding DNS server (using DNS-over-TLS (DoT)) as opposed to a recursive DNS server",
"type": "info"
},
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
}
]
{
"text": "With an option to add Unbound",
"type": "info"
},
{
"text": "With an option to configure Unbound as a forwarding DNS server (using DNS-over-TLS (DoT)) as opposed to a recursive DNS server",
"type": "info"
},
{
"text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
"type": "warning"
}
]
}

View File

@@ -13,7 +13,7 @@
"website": "https://www.home-assistant.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/home-assistant.webp",
"config_path": "/var/lib/containers/storage/volumes/hass_config/_data",
"description": "A standalone Podman container-based installation of Home Assistant Core means that the Home Assistant Core software is installed inside a container managed by Podman, separate from the host operating system. This provides a flexible and scalable solution for running the software, as the container can be easily moved between host systems or isolated from other processes for security. Podman is a popular open-source tool for managing containers that is similar to Docker, but designed for use on Linux systems without a daemon.\r\n\r\n\ud83d\udec8 If the LXC is created Privileged, the script will automatically set up USB passthrough.",
"description": "A standalone Podman container-based installation of Home Assistant Core means that the Home Assistant Core software is installed inside a container managed by Podman, separate from the host operating system. This provides a flexible and scalable solution for running the software, as the container can be easily moved between host systems or isolated from other processes for security. Podman is a popular open-source tool for managing containers that is similar to Docker, but designed for use on Linux systems without a daemon.\r\n\r\n🛈 If the LXC is created Privileged, the script will automatically set up USB passthrough.",
"install_methods": [
{
"type": "default",

View File

@@ -1,35 +1,35 @@
{
"name": "PrivateBin",
"slug": "privatebin",
"categories": [
12
],
"date_created": "2025-01-29",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://github.com/PrivateBin/PrivateBin/wiki",
"website": "https://github.com/PrivateBin/PrivateBin",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/privatebin.webp",
"config_path": "/opt/privatebin/cfg/conf.php",
"description": "PrivateBin is a minimalist, open-source pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256-bit AES.",
"install_methods": [
{
"type": "default",
"script": "ct/privatebin.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "PrivateBin",
"slug": "privatebin",
"categories": [
12
],
"date_created": "2025-01-29",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://github.com/PrivateBin/PrivateBin/wiki",
"website": "https://github.com/PrivateBin/PrivateBin",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/privatebin.webp",
"config_path": "/opt/privatebin/cfg/conf.php",
"description": "PrivateBin is a minimalist, open-source pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256-bit AES.",
"install_methods": [
{
"type": "default",
"script": "ct/privatebin.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,35 +1,35 @@
{
"name": "Prometheus Alertmanager",
"slug": "prometheus-alertmanager",
"categories": [
9
],
"date_created": "2025-01-09",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9093,
"documentation": "https://prometheus.io/docs/alerting/latest/overview/",
"website": "https://prometheus.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/prometheus.webp",
"config_path": "/etc/alertmanager/alertmanager.yml",
"description": "Alerting with Prometheus is separated into two parts. Alerting rules in Prometheus servers send alerts to an Alertmanager. The Alertmanager then manages those alerts, including silencing, inhibition, aggregation and sending out notifications via methods such as email, on-call notification systems, and chat platforms.",
"install_methods": [
{
"type": "default",
"script": "ct/prometheus-alertmanager.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "Prometheus Alertmanager",
"slug": "prometheus-alertmanager",
"categories": [
9
],
"date_created": "2025-01-09",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9093,
"documentation": "https://prometheus.io/docs/alerting/latest/overview/",
"website": "https://prometheus.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/prometheus.webp",
"config_path": "/etc/alertmanager/alertmanager.yml",
"description": "Alerting with Prometheus is separated into two parts. Alerting rules in Prometheus servers send alerts to an Alertmanager. The Alertmanager then manages those alerts, including silencing, inhibition, aggregation and sending out notifications via methods such as email, on-call notification systems, and chat platforms.",
"install_methods": [
{
"type": "default",
"script": "ct/prometheus-alertmanager.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,44 +1,44 @@
{
"name": "Prometheus Paperless NGX Exporter",
"slug": "prometheus-paperless-ngx-exporter",
"categories": [
9
],
"date_created": "2025-02-07",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8081,
"documentation": null,
"website": "https://github.com/hansmi/prometheus-paperless-exporter",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp",
"config_path": "",
"description": "Prometheus metrics exporter for Paperless-NGX, a document management system transforming physical documents into a searchable online archive. The exporter relies on Paperless' REST API.",
"install_methods": [
{
"type": "default",
"script": "ct/prometheus-paperless-ngx-exporter.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
"name": "Prometheus Paperless NGX Exporter",
"slug": "prometheus-paperless-ngx-exporter",
"categories": [
9
],
"date_created": "2025-02-07",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8081,
"documentation": null,
"website": "https://github.com/hansmi/prometheus-paperless-exporter",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/paperless-ngx.webp",
"config_path": "",
"description": "Prometheus metrics exporter for Paperless-NGX, a document management system transforming physical documents into a searchable online archive. The exporter relies on Paperless' REST API.",
"install_methods": [
{
"type": "default",
"script": "ct/prometheus-paperless-ngx-exporter.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Please adjust the Paperless URL in the systemd unit file: /etc/systemd/system/prometheus-paperless-ngx-exporter.service",
"type": "info"
},
"notes": [
{
"text": "Please adjust the Paperless URL in the systemd unit file: /etc/systemd/system/prometheus-paperless-ngx-exporter.service",
"type": "info"
},
{
"text": "Please adjust the Paperless authentication token in the configuration file: /etc/prometheus-paperless-ngx-exporter/paperless_auth_token_file",
"type": "info"
}
]
{
"text": "Please adjust the Paperless authentication token in the configuration file: /etc/prometheus-paperless-ngx-exporter/paperless_auth_token_file",
"type": "info"
}
]
}

View File

@@ -1,44 +1,44 @@
{
"name": "Proxmox Backup Server",
"slug": "proxmox-backup-server",
"categories": [
1
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8007,
"documentation": "https://pbs.proxmox.com/docs/",
"website": "https://www.proxmox.com/en/proxmox-backup-server/overview",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
"config_path": "",
"description": "Proxmox Backup Server is an enterprise backup solution, for backing up and restoring VMs, containers, and physical hosts. By supporting incremental, fully deduplicated backups, Proxmox Backup Server significantly reduces network load and saves valuable storage space.",
"install_methods": [
{
"type": "default",
"script": "ct/proxmox-backup-server.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "root",
"password": null
"name": "Proxmox Backup Server",
"slug": "proxmox-backup-server",
"categories": [
1
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8007,
"documentation": "https://pbs.proxmox.com/docs/",
"website": "https://www.proxmox.com/en/proxmox-backup-server/overview",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
"config_path": "",
"description": "Proxmox Backup Server is an enterprise backup solution, for backing up and restoring VMs, containers, and physical hosts. By supporting incremental, fully deduplicated backups, Proxmox Backup Server significantly reduces network load and saves valuable storage space.",
"install_methods": [
{
"type": "default",
"script": "ct/proxmox-backup-server.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "root",
"password": null
},
"notes": [
{
"text": "Set a root password if using autologin. This will be the PBS password. `passwd root`",
"type": "warning"
},
"notes": [
{
"text": "Set a root password if using autologin. This will be the PBS password. `passwd root`",
"type": "warning"
},
{
"text": "Advanced Install is only possible with disabled IPV6! Otherwise the installation sometimes stuck.",
"type": "warning"
}
]
{
"text": "Advanced Install is only possible with disabled IPV6! Otherwise the installation sometimes stuck.",
"type": "warning"
}
]
}

View File

@@ -1,40 +1,40 @@
{
"name": "Proxmox Mail Gateway",
"slug": "proxmox-mail-gateway",
"categories": [
1
],
"date_created": "2025-02-04",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8006,
"documentation": "https://pmg.proxmox.com/pmg-docs/pmg-admin-guide.html",
"website": "https://www.proxmox.com/en/products/proxmox-mail-gateway/overview",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
"config_path": "",
"description": "Proxmox Mail Gateway is the leading open-source email security solution helping you to protect your mail server against all email threats from the moment they emerge.",
"install_methods": [
{
"type": "default",
"script": "ct/proxmox-mail-gateway.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "root",
"password": null
},
"notes": [
{
"text": "Set a root password if using autologin. This will be the PMG password. `passwd root`",
"type": "warning"
}
]
"name": "Proxmox Mail Gateway",
"slug": "proxmox-mail-gateway",
"categories": [
1
],
"date_created": "2025-02-04",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8006,
"documentation": "https://pmg.proxmox.com/pmg-docs/pmg-admin-guide.html",
"website": "https://www.proxmox.com/en/products/proxmox-mail-gateway/overview",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
"config_path": "",
"description": "Proxmox Mail Gateway is the leading open-source email security solution helping you to protect your mail server against all email threats from the moment they emerge.",
"install_methods": [
{
"type": "default",
"script": "ct/proxmox-mail-gateway.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "root",
"password": null
},
"notes": [
{
"text": "Set a root password if using autologin. This will be the PMG password. `passwd root`",
"type": "warning"
}
]
}

View File

@@ -1,40 +1,40 @@
{
"name": "PS5-MQTT",
"slug": "ps5-mqtt",
"categories": [
18
],
"date_created": "2025-01-09",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8645,
"documentation": null,
"website": "https://github.com/FunkeyFlo/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/ps5-mqtt.webp",
"config_path": "/opt/.config/ps5-mqtt/config.json",
"description": "Integrate your Sony Playstation 5 devices with Home Assistant using MQTT.",
"install_methods": [
{
"type": "default",
"script": "ct/ps5-mqtt.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 3,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "After installation, the MQTT endpoint must be configured. The configuration file is located within the LXC container at: `/opt/.config/ps5-mqtt/config.json`",
"type": "info"
}
]
"name": "PS5-MQTT",
"slug": "ps5-mqtt",
"categories": [
18
],
"date_created": "2025-01-09",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8645,
"documentation": null,
"website": "https://github.com/FunkeyFlo/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/ps5-mqtt.webp",
"config_path": "/opt/.config/ps5-mqtt/config.json",
"description": "Integrate your Sony Playstation 5 devices with Home Assistant using MQTT.",
"install_methods": [
{
"type": "default",
"script": "ct/ps5-mqtt.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 3,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "After installation, the MQTT endpoint must be configured. The configuration file is located within the LXC container at: `/opt/.config/ps5-mqtt/config.json`",
"type": "info"
}
]
}

View File

@@ -17,7 +17,7 @@
"install_methods": [
{
"type": "default",
"script": "ct/resilio-sync.sh",
"script": "ct/resiliosync.sh",
"resources": {
"cpu": 2,
"ram": 2048,

View File

@@ -1,35 +1,35 @@
{
"name": "SABnzbd",
"slug": "sabnzbd",
"categories": [
11
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7777,
"documentation": "https://sabnzbd.org/wiki/",
"website": "https://sabnzbd.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/sabnzbd.webp",
"config_path": "/.sabnzbd/sabnzbd.ini",
"description": "SABnzbd is a free, open-source software program for downloading binary files from Usenet newsgroups. It is designed to be easy to use, and provides a number of features to simplify the downloading process, such as automatic error detection and repair, download scheduling, and integration with other applications. SABnzbd is a binary newsreader, which means it is specifically designed for downloading binary files, such as images, music, and video, from Usenet newsgroups. With its user-friendly interface and powerful features, SABnzbd makes it easy to manage your Usenet downloads and keep your download queue organized.",
"install_methods": [
{
"type": "default",
"script": "ct/sabnzbd.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 5,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "SABnzbd",
"slug": "sabnzbd",
"categories": [
11
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7777,
"documentation": "https://sabnzbd.org/wiki/",
"website": "https://sabnzbd.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/sabnzbd.webp",
"config_path": "/.sabnzbd/sabnzbd.ini",
"description": "SABnzbd is a free, open-source software program for downloading binary files from Usenet newsgroups. It is designed to be easy to use, and provides a number of features to simplify the downloading process, such as automatic error detection and repair, download scheduling, and integration with other applications. SABnzbd is a binary newsreader, which means it is specifically designed for downloading binary files, such as images, music, and video, from Usenet newsgroups. With its user-friendly interface and powerful features, SABnzbd makes it easy to manage your Usenet downloads and keep your download queue organized.",
"install_methods": [
{
"type": "default",
"script": "ct/sabnzbd.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 5,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -0,0 +1,40 @@
{
"name": "Scraparr",
"slug": "scraparr",
"categories": [
14
],
"date_created": "2025-09-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7100,
"documentation": "https://github.com/thecfu/scraparr/blob/main/README.md",
"website": "https://github.com/thecfu/scraparr",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/scraparr-dark.svg",
"config_path": "/scraparr/config/config.yaml",
"description": "Scraparr is a Prometheus exporter for the *arr suite (Sonarr, Radarr, Lidarr, etc.). It provides metrics that can be scraped by Prometheus to monitor and visualize the health and performance of your *arr applications.",
"install_methods": [
{
"type": "default",
"script": "ct/scraparr.sh",
"resources": {
"cpu": 2,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Edit config file then restart the scraparr service: `systemctl restart scraparr`",
"type": "info"
}
]
}

View File

@@ -1,40 +1,40 @@
{
"name": "seelf",
"slug": "seelf",
"categories": [
4
],
"date_created": "2025-02-04",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://yuukanoo.github.io/seelf/guide/quickstart.html",
"website": "https://yuukanoo.github.io/seelf/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/seelf.webp",
"config_path": "",
"description": "seelf is a self-hosted software which makes it easy to deploy your own applications on your own hardware using an easy to use interface.",
"install_methods": [
{
"type": "default",
"script": "ct/seelf.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Initial admin email and password: `cat ~/seelf.creds`",
"type": "info"
}
]
"name": "seelf",
"slug": "seelf",
"categories": [
4
],
"date_created": "2025-02-04",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://yuukanoo.github.io/seelf/guide/quickstart.html",
"website": "https://yuukanoo.github.io/seelf/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/seelf.webp",
"config_path": "",
"description": "seelf is a self-hosted software which makes it easy to deploy your own applications on your own hardware using an easy to use interface.",
"install_methods": [
{
"type": "default",
"script": "ct/seelf.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 10,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Initial admin email and password: `cat ~/seelf.creds`",
"type": "info"
}
]
}

40
scripts/json/signoz.json Normal file
View File

@@ -0,0 +1,40 @@
{
"name": "SigNoz",
"slug": "signoz",
"categories": [
9
],
"date_created": "2025-09-15",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://signoz.io/docs/introduction/",
"config_path": "/opt/signoz/conf/systemd.env",
"website": "https://signoz.io/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/signoz.webp",
"description": "SigNoz is an open-source Datadog or New Relic alternative. Get APM, logs, traces, metrics, exceptions, & alerts in a single tool.",
"install_methods": [
{
"type": "default",
"script": "ct/signoz.sh",
"resources": {
"cpu": 2,
"ram": 4096,
"hdd": 20,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "The first user you register will be the admin user.",
"type": "info"
}
]
}

35
scripts/json/stylus.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "Stylus",
"slug": "stylus",
"categories": [
4
],
"date_created": "2025-09-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8000,
"documentation": "https://mmastrac.github.io/stylus/",
"website": "https://github.com/mmastrac/stylus",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/stylus.webp",
"config_path": "/opt/stylus/config.yaml",
"description": "Stylus (style + status) is a lightweight status page for infrastructure and networks. Configure a set of bash scripts that test the various parts of your infrastructure, set up visualizations with minimal configuration, and Stylus will generate you a dashboard for your system.",
"install_methods": [
{
"type": "default",
"script": "ct/stylus.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,35 +1,35 @@
{
"name": "TasmoAdmin",
"slug": "tasmoadmin",
"categories": [
16
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"privileged": false,
"interface_port": 9999,
"documentation": null,
"website": "https://github.com/TasmoAdmin/TasmoAdmin#readme",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/tasmoadmin.webp",
"config_path": "",
"description": "TasmoAdmin is an administrative platform for devices flashed with Tasmota.",
"install_methods": [
{
"type": "default",
"script": "ct/tasmoadmin.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "TasmoAdmin",
"slug": "tasmoadmin",
"categories": [
16
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": false,
"privileged": false,
"interface_port": 9999,
"documentation": null,
"website": "https://github.com/TasmoAdmin/TasmoAdmin#readme",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/tasmoadmin.webp",
"config_path": "",
"description": "TasmoAdmin is an administrative platform for devices flashed with Tasmota.",
"install_methods": [
{
"type": "default",
"script": "ct/tasmoadmin.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -0,0 +1,40 @@
{
"name": "Telegraf",
"slug": "telegraf",
"categories": [
9
],
"date_created": "2025-09-11",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": null,
"documentation": "https://docs.influxdata.com/telegraf/v1/",
"config_path": "/etc/telegraf/telegraf.conf",
"website": "https://github.com/influxdata/telegraf",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/telegraf.webp",
"description": "Telegraf collects and sends time series data from databases, systems, and IoT sensors. It has no external dependencies, is easy to install, and requires minimal memory.",
"install_methods": [
{
"type": "default",
"script": "ct/telegraf.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Make sure to configure an output for the telegraf config and start the service with `systemctl start telegraf`.",
"type": "info"
}
]
}

View File

@@ -13,7 +13,7 @@
"website": "https://tianji.msgbyte.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/tianji.webp",
"config_path": "/opt/tianji/src/server/.env",
"description": "Tianji is an open-source tool for website analytics, uptime monitoring, and server status tracking, all in one. It\u2019s lightweight, privacy-focused, and helps teams monitor web traffic, server health, and gather user interaction data",
"description": "Tianji is an open-source tool for website analytics, uptime monitoring, and server status tracking, all in one. Its lightweight, privacy-focused, and helps teams monitor web traffic, server health, and gather user interaction data",
"install_methods": [
{
"type": "default",

35
scripts/json/uhf.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "UHF Server",
"slug": "uhf",
"categories": [
13
],
"date_created": "2025-09-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 7568,
"documentation": "https://www.uhfapp.com/server",
"website": "https://www.uhfapp.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/uhf.webp",
"config_path": "/etc/uhf-server/",
"description": "UHF Server is a powerful companion app that lets you seamlessly schedule and record your favorite shows from the UHF app.",
"install_methods": [
{
"type": "default",
"script": "ct/uhf.sh",
"resources": {
"cpu": 2,
"ram": 2048,
"hdd": 8,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

1452
scripts/json/undefined.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +1,40 @@
{
"name": "UrBackup Server",
"slug": "urbackupserver",
"categories": [
7
],
"date_created": "2025-01-18",
"type": "ct",
"updateable": true,
"privileged": true,
"interface_port": 55414,
"documentation": "https://www.urbackup.org/documentation.html",
"website": "https://www.urbackup.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/urbackup.webp",
"config_path": "",
"description": "URBackup is an open-source backup software designed for creating reliable and efficient backups of both files and system images. It supports client-server architecture, allowing you to back up multiple computers to a central server. It offers features such as incremental backups, real-time file backup, and scheduling, ensuring minimal data loss and quick recovery",
"install_methods": [
{
"type": "default",
"script": "ct/urbackupserver.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 16,
"os": "debian",
"version": "12"
}
"name": "UrBackup Server",
"slug": "urbackupserver",
"categories": [
7
],
"date_created": "2025-01-18",
"type": "ct",
"updateable": true,
"privileged": true,
"interface_port": 55414,
"documentation": "https://www.urbackup.org/documentation.html",
"website": "https://www.urbackup.org/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/urbackup.webp",
"config_path": "",
"description": "URBackup is an open-source backup software designed for creating reliable and efficient backups of both files and system images. It supports client-server architecture, allowing you to back up multiple computers to a central server. It offers features such as incremental backups, real-time file backup, and scheduling, ensuring minimal data loss and quick recovery",
"install_methods": [
{
"type": "default",
"script": "ct/urbackupserver.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 16,
"os": "debian",
"version": "12"
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "You probably want to drastically extend the storage space to fit whatever clients you want to back up",
"type": "info"
}
]
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "You probably want to drastically extend the storage space to fit whatever clients you want to back up",
"type": "info"
}
]
}

View File

@@ -1,35 +1,35 @@
{
"name": "Watcharr",
"slug": "watcharr",
"categories": [
13
],
"date_created": "2025-02-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3080,
"documentation": "https://watcharr.app/docs/introduction",
"website": "https://watcharr.app/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/watcharr.webp",
"config_path": "",
"description": "Open source, self-hostable watched list for all your content with user authentication, modern and clean UI and a very simple setup.",
"install_methods": [
{
"type": "default",
"script": "ct/watcharr.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
"name": "Watcharr",
"slug": "watcharr",
"categories": [
13
],
"date_created": "2025-02-12",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3080,
"documentation": "https://watcharr.app/docs/introduction",
"website": "https://watcharr.app/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/watcharr.webp",
"config_path": "",
"description": "Open source, self-hostable watched list for all your content with user authentication, modern and clean UI and a very simple setup.",
"install_methods": [
{
"type": "default",
"script": "ct/watcharr.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -1,35 +1,35 @@
{
"name": "Zerotier-One",
"slug": "zerotier-one",
"categories": [
4
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3443,
"documentation": "https://docs.zerotier.com/",
"website": "https://www.zerotier.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/zerotier.webp",
"config_path": "/opt/key-networks/ztncui/.env",
"description": "ZeroTier is a secure network overlay that allows you to manage all of your network resources as if they were on the same LAN. The software-defined solution can be deployed in minutes from anywhere. No matter how many devices you need to connect, or where they are in the world, ZeroTier makes global networking simple.",
"install_methods": [
{
"type": "default",
"script": "ct/zerotier-one.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "admin",
"password": "password"
},
"notes": []
"name": "Zerotier-One",
"slug": "zerotier-one",
"categories": [
4
],
"date_created": "2024-05-02",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 3443,
"documentation": "https://docs.zerotier.com/",
"website": "https://www.zerotier.com/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/zerotier.webp",
"config_path": "/opt/key-networks/ztncui/.env",
"description": "ZeroTier is a secure network overlay that allows you to manage all of your network resources as if they were on the same LAN. The software-defined solution can be deployed in minutes from anywhere. No matter how many devices you need to connect, or where they are in the world, ZeroTier makes global networking simple.",
"install_methods": [
{
"type": "default",
"script": "ct/zerotier-one.sh",
"resources": {
"cpu": 1,
"ram": 512,
"hdd": 4,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": "admin",
"password": "password"
},
"notes": []
}

35
scripts/json/zot.json Normal file
View File

@@ -0,0 +1,35 @@
{
"name": "Zot Registry",
"slug": "zot",
"categories": [
13
],
"date_created": "2025-06-06",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 8080,
"documentation": "https://zotregistry.dev/docs/intro/",
"website": "https://zotregistry.dev/",
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/zot-registry.webp",
"config_path": "/etc/zot/config.json",
"description": "Zot is a cloud-native OCI image registry focused on extensibility, maintainability, and performance. It supports advanced features such as Web UI, security scanning, authentication via htpasswd and OIDC, and more.",
"install_methods": [
{
"type": "default",
"script": "ct/zot-registry.sh",
"resources": {
"cpu": 1,
"ram": 2048,
"hdd": 5,
"os": "Debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@@ -14,11 +14,15 @@ export function ResyncButton() {
setLastSync(new Date());
if (data.success) {
setSyncMessage(data.message ?? 'Scripts synced successfully');
// Reload the page after successful sync
setTimeout(() => {
window.location.reload();
}, 2000); // Wait 2 seconds to show the success message
} else {
setSyncMessage(data.error ?? 'Failed to sync scripts');
// Clear message after 3 seconds for errors
setTimeout(() => setSyncMessage(null), 3000);
}
// Clear message after 3 seconds
setTimeout(() => setSyncMessage(null), 3000);
},
onError: (error) => {
setIsResyncing(false);

View File

@@ -19,9 +19,11 @@ vi.mock('~/server/lib/git', () => ({
},
}))
vi.mock('~/server/services/github', () => ({
githubService: {
vi.mock('~/server/services/githubJsonService', () => ({
githubJsonService: {
syncJsonFiles: vi.fn(),
getAllScripts: vi.fn(),
getScriptBySlug: vi.fn(),
},
}))
@@ -212,8 +214,8 @@ describe('scriptsRouter', () => {
it('should return script on success', async () => {
const mockScript = { name: 'Test Script', slug: 'test-script' }
const { localScriptsService } = await import('~/server/services/localScripts')
vi.mocked(localScriptsService.getScriptBySlug).mockResolvedValue(mockScript)
const { githubJsonService } = await import('~/server/services/githubJsonService')
vi.mocked(githubJsonService.getScriptBySlug).mockResolvedValue(mockScript)
const result = await caller.getScriptBySlug({ slug: 'test-script' })
@@ -224,8 +226,8 @@ describe('scriptsRouter', () => {
})
it('should return error when script not found', async () => {
const { localScriptsService } = await import('~/server/services/localScripts')
vi.mocked(localScriptsService.getScriptBySlug).mockResolvedValue(null)
const { githubJsonService } = await import('~/server/services/githubJsonService')
vi.mocked(githubJsonService.getScriptBySlug).mockResolvedValue(null)
const result = await caller.getScriptBySlug({ slug: 'nonexistent' })
@@ -239,35 +241,36 @@ describe('scriptsRouter', () => {
describe('resyncScripts', () => {
it('should resync scripts successfully', async () => {
const mockGitHubScripts = [
{ name: 'Script 1', slug: 'script-1' },
{ name: 'Script 2', slug: 'script-2' },
]
const { githubJsonService } = await import('~/server/services/githubJsonService')
const { githubService } = await import('~/server/services/github')
const { localScriptsService } = await import('~/server/services/localScripts')
vi.mocked(githubService.getAllScripts).mockResolvedValue(mockGitHubScripts)
vi.mocked(localScriptsService.saveScriptsFromGitHub).mockResolvedValue(undefined)
vi.mocked(githubJsonService.syncJsonFiles).mockResolvedValue({
success: true,
message: 'Successfully synced 2 scripts from GitHub using 1 API call + raw downloads',
count: 2
})
const result = await caller.resyncScripts()
expect(result).toEqual({
success: true,
message: 'Successfully synced 2 scripts from GitHub to local directory',
message: 'Successfully synced 2 scripts from GitHub using 1 API call + raw downloads',
count: 2,
})
})
it('should return error on failure', async () => {
const { githubService } = await import('~/server/services/github')
vi.mocked(githubService.getAllScripts).mockRejectedValue(new Error('GitHub error'))
const { githubJsonService } = await import('~/server/services/githubJsonService')
vi.mocked(githubJsonService.syncJsonFiles).mockResolvedValue({
success: false,
message: 'GitHub error',
count: 0
})
const result = await caller.resyncScripts()
expect(result).toEqual({
success: false,
error: 'GitHub error',
message: 'GitHub error',
count: 0,
})
})

View File

@@ -2,7 +2,7 @@ import { z } from "zod";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { scriptManager } from "~/server/lib/scripts";
import { gitManager } from "~/server/lib/git";
import { githubService } from "~/server/services/github";
import { githubJsonService } from "~/server/services/githubJsonService";
import { localScriptsService } from "~/server/services/localScripts";
import { scriptDownloaderService } from "~/server/services/scriptDownloader";
@@ -97,11 +97,11 @@ export const scriptsRouter = createTRPCRouter({
}
}),
// Get all scripts from local directory
// Get all scripts from GitHub (1 API call + raw downloads)
getAllScripts: publicProcedure
.query(async () => {
try {
const scripts = await localScriptsService.getAllScripts();
const scripts = await githubJsonService.getAllScripts();
return { success: true, scripts };
} catch (error) {
return {
@@ -112,12 +112,12 @@ export const scriptsRouter = createTRPCRouter({
}
}),
// Get script by slug from local directory
// Get script by slug from GitHub (1 API call + raw downloads)
getScriptBySlug: publicProcedure
.input(z.object({ slug: z.string() }))
.query(async ({ input }) => {
try {
const script = await localScriptsService.getScriptBySlug(input.slug);
const script = await githubJsonService.getScriptBySlug(input.slug);
if (!script) {
return {
success: false,
@@ -135,20 +135,17 @@ export const scriptsRouter = createTRPCRouter({
}
}),
// Resync scripts from GitHub repo to local directory
// Resync scripts from GitHub (1 API call + raw downloads)
resyncScripts: publicProcedure
.mutation(async () => {
try {
// First, try to get scripts from GitHub
const githubScripts = await githubService.getAllScripts();
// Save scripts to local directory
await localScriptsService.saveScriptsFromGitHub(githubScripts);
// Sync JSON files using 1 API call + raw downloads
const result = await githubJsonService.syncJsonFiles();
return {
success: true,
message: `Successfully synced ${githubScripts.length} scripts from GitHub to local directory`,
count: githubScripts.length
success: result.success,
message: result.message,
count: result.count
};
} catch (error) {
console.error('Error in resyncScripts:', error);

View File

@@ -0,0 +1,185 @@
import { writeFile, mkdir } from 'fs/promises';
import { join } from 'path';
import { env } from '~/env.js';
import type { Script, ScriptCard, GitHubFile } from '~/types/script';
export class GitHubJsonService {
private baseUrl: string;
private repoUrl: string;
private branch: string;
private jsonFolder: string;
private localJsonDirectory: string;
constructor() {
this.repoUrl = env.REPO_URL ?? "";
this.branch = env.REPO_BRANCH;
this.jsonFolder = env.JSON_FOLDER;
this.localJsonDirectory = join(process.cwd(), 'scripts', 'json');
// Only validate GitHub URL if it's provided
if (this.repoUrl) {
// Extract owner and repo from the URL
const urlMatch = /github\.com\/([^\/]+)\/([^\/]+)/.exec(this.repoUrl);
if (!urlMatch) {
throw new Error(`Invalid GitHub repository URL: ${this.repoUrl}`);
}
const [, owner, repo] = urlMatch;
this.baseUrl = `https://api.github.com/repos/${owner}/${repo}`;
} else {
// Set a dummy base URL if no REPO_URL is provided
this.baseUrl = "";
}
}
private async fetchFromGitHub<T>(endpoint: string): Promise<T> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
headers: {
'Accept': 'application/vnd.github.v3+json',
'User-Agent': 'PVEScripts-Local/1.0',
},
});
if (!response.ok) {
throw new Error(`GitHub API error: ${response.status} ${response.statusText}`);
}
return response.json() as Promise<T>;
}
private async downloadJsonFile(filePath: string): Promise<Script> {
const rawUrl = `https://raw.githubusercontent.com/${this.extractRepoPath()}/${this.branch}/${filePath}`;
const response = await fetch(rawUrl);
if (!response.ok) {
throw new Error(`Failed to download ${filePath}: ${response.status} ${response.statusText}`);
}
const content = await response.text();
return JSON.parse(content) as Script;
}
private extractRepoPath(): string {
const match = /github\.com\/([^\/]+)\/([^\/]+)/.exec(this.repoUrl);
if (!match) {
throw new Error('Invalid GitHub repository URL');
}
return `${match[1]}/${match[2]}`;
}
async getJsonFiles(): Promise<GitHubFile[]> {
if (!this.repoUrl) {
throw new Error('REPO_URL environment variable is not set. Cannot fetch from GitHub.');
}
try {
const files = await this.fetchFromGitHub<GitHubFile[]>(
`/contents/${this.jsonFolder}?ref=${this.branch}`
);
// Filter for JSON files only
return files.filter(file => file.name.endsWith('.json'));
} catch (error) {
console.error('Error fetching JSON files from GitHub:', error);
throw new Error('Failed to fetch script files from repository');
}
}
async getAllScripts(): Promise<Script[]> {
try {
// First, get the list of JSON files (1 API call)
const jsonFiles = await this.getJsonFiles();
const scripts: Script[] = [];
// Then download each JSON file using raw URLs (no rate limit)
for (const file of jsonFiles) {
try {
const script = await this.downloadJsonFile(file.path);
scripts.push(script);
} catch (error) {
console.error(`Failed to download script ${file.name}:`, error);
// Continue with other files even if one fails
}
}
return scripts;
} catch (error) {
console.error('Error fetching all scripts:', error);
throw new Error('Failed to fetch scripts from repository');
}
}
async getScriptCards(): Promise<ScriptCard[]> {
try {
const scripts = await this.getAllScripts();
return scripts.map(script => ({
name: script.name,
slug: script.slug,
description: script.description,
logo: script.logo,
type: script.type,
updateable: script.updateable,
website: script.website,
}));
} catch (error) {
console.error('Error creating script cards:', error);
throw new Error('Failed to create script cards');
}
}
async getScriptBySlug(slug: string): Promise<Script | null> {
try {
const scripts = await this.getAllScripts();
return scripts.find(script => script.slug === slug) ?? null;
} catch (error) {
console.error('Error fetching script by slug:', error);
throw new Error(`Failed to fetch script: ${slug}`);
}
}
async syncJsonFiles(): Promise<{ success: boolean; message: string; count: number }> {
try {
// Get all scripts from GitHub (1 API call + raw downloads)
const scripts = await this.getAllScripts();
// Save scripts to local directory
await this.saveScriptsLocally(scripts);
return {
success: true,
message: `Successfully synced ${scripts.length} scripts from GitHub using 1 API call + raw downloads`,
count: scripts.length
};
} catch (error) {
console.error('Error syncing JSON files:', error);
return {
success: false,
message: `Failed to sync JSON files: ${error instanceof Error ? error.message : 'Unknown error'}`,
count: 0
};
}
}
private async saveScriptsLocally(scripts: Script[]): Promise<void> {
try {
// Ensure the directory exists
await mkdir(this.localJsonDirectory, { recursive: true });
// Save each script as a JSON file
for (const script of scripts) {
const filename = `${script.slug}.json`;
const filePath = join(this.localJsonDirectory, filename);
const content = JSON.stringify(script, null, 2);
await writeFile(filePath, content, 'utf-8');
}
} catch (error) {
console.error('Error saving scripts locally:', error);
throw new Error('Failed to save scripts locally');
}
}
}
// Singleton instance
export const githubJsonService = new GitHubJsonService();