diff --git a/stacks/dashboard/config/www/.env b/stacks/dashboard/config/www/.env new file mode 100644 index 0000000..1f6b0b6 --- /dev/null +++ b/stacks/dashboard/config/www/.env @@ -0,0 +1,69 @@ +APP_NAME=Heimdall +APP_ENV=local +APP_KEY=base64:iovIUyf+fbX/1gbhrxHIr/58SLI1F3u/GGVd60r4WpQ= +APP_DEBUG=false +APP_URL=http://localhost + +APP_LOCALE=en +APP_FALLBACK_LOCALE=en +APP_FAKER_LOCALE=en_US +APP_MAINTENANCE_DRIVER=file +APP_MAINTENANCE_STORE=database +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=daily +LOG_STACK=single + +DB_CONNECTION=sqlite +DB_DATABASE=app.sqlite + +#DB_CONNECTION= +#DB_HOST= +#DB_PORT= +#DB_DATABASE= +#DB_USERNAME= +#DB_PASSWORD= + +BROADCAST_CONNECTION=log +CACHE_STORE=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null +QUEUE_DRIVER=database + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=smtp.mailtrap.io +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=null +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_APP_CLUSTER=mt1 + +MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +AUTH_ROLES_ENABLE=false +AUTH_ROLES_HEADER="remote-groups" +AUTH_ROLES_HTTP_HEADER="HTTP_REMOTE_GROUPS" +AUTH_ROLES_ADMIN="admin" +AUTH_ROLES_DELIMITER="," + +ALLOW_INTERNAL_REQUESTS=false \ No newline at end of file diff --git a/stacks/dashboard/config/www/SupportedApps/Bookstack/Bookstack.php b/stacks/dashboard/config/www/SupportedApps/Bookstack/Bookstack.php new file mode 100644 index 0000000..5ff07e1 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Bookstack/Bookstack.php @@ -0,0 +1,83 @@ +jar = new \GuzzleHttp\Cookie\CookieJar; // Uncomment if cookies need to be set + } + + public function getHeaders() + { + $api_token = $this->config->api_token . ":" . $this->config->api_secret; + + $attrs["headers"] = ["Authorization" => "Token " . $api_token]; + return $attrs; + } + + public function test() + { + $test = parent::appTest( + $this->url("api/shelves?count=0"), + $this->getHeaders() + ); + echo $test->status; + } + + public function livestats() + { + $status = "inactive"; + + $attrs = $this->getHeaders(); + + $data = ["visiblestats" => []]; + + foreach ($this->config->availablestats as $stat) { + if (!isset(self::getAvailableStats()[$stat])) { + continue; + } + + $res = parent::execute( + $this->url("api/" . $stat . "?count=0"), + $attrs + ); + $details = json_decode($res->getBody()); + + $newstat = new \stdClass(); + $newstat->title = self::getAvailableStats()[$stat]; + $newstat->value = isset($details->total) + ? number_format($details->total) + : "N/A"; + + $data["visiblestats"][] = $newstat; + } + + return parent::getLiveStats($status, $data); + } + + public function url($endpoint) + { + $api_url = + rtrim(parent::normaliseurl($this->config->url), "/") . + "/" . + ltrim($endpoint, "/"); + return $api_url; + } + + public static function getAvailableStats() + { + return [ + "shelves" => "Shelves", + "books" => "Books", + "chapters" => "Chapters", + "pages" => "Pages", + ]; + } +} diff --git a/stacks/dashboard/config/www/SupportedApps/Bookstack/app.json b/stacks/dashboard/config/www/SupportedApps/Bookstack/app.json new file mode 100644 index 0000000..605b92d --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Bookstack/app.json @@ -0,0 +1,10 @@ +{ + "appid": "348c49dd03dddd418929316668d2e67bf2d9ae88", + "name": "Bookstack", + "website": "https://www.bookstackapp.com", + "license": "MIT License", + "description": "BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information.", + "enhanced": true, + "tile_background": "dark", + "icon": "bookstack.svg" +} diff --git a/stacks/dashboard/config/www/SupportedApps/Bookstack/config.blade.php b/stacks/dashboard/config/www/SupportedApps/Bookstack/config.blade.php new file mode 100644 index 0000000..fcb8b6c --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Bookstack/config.blade.php @@ -0,0 +1,22 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')

+
+
+ + {!! Form::text('config[override_url]', isset($item) ? $item->getConfig()->override_url ?? null : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!} +
+
+ + {!! Form::text('config[api_token]', isset($item) ? $item->getconfig()->api_token : null, ['placeholder' => 'Token ID', 'data-config' => 'api_token', 'class' => 'form-control config-item']) !!} +
+
+ + {!! Form::text('config[api_secret]', isset($item) ? $item->getconfig()->api_secret : null, ['placeholder' => 'Token Secret', 'data-config' => 'api_secret', 'class' => 'form-control config-item']) !!} +
+
+ + {!! Form::select('config[availablestats][]', App\SupportedApps\Bookstack\Bookstack::getAvailableStats(), isset($item) ? $item->getConfig()->availablestats ?? null : null, ['multiple' => 'multiple']) !!} +
+
+ +
+
diff --git a/stacks/dashboard/config/www/SupportedApps/Bookstack/livestats.blade.php b/stacks/dashboard/config/www/SupportedApps/Bookstack/livestats.blade.php new file mode 100644 index 0000000..cb9431a --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Bookstack/livestats.blade.php @@ -0,0 +1,8 @@ +
    + @foreach ($visiblestats as $stat) +
  • + {!! $stat->title !!} + {!! $stat->value !!} +
  • + @endforeach +
diff --git a/stacks/dashboard/config/www/SupportedApps/Dockge/Dockge.php b/stacks/dashboard/config/www/SupportedApps/Dockge/Dockge.php new file mode 100644 index 0000000..6d931b7 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Dockge/Dockge.php @@ -0,0 +1,7 @@ +jar = new \GuzzleHttp\Cookie\CookieJar; // Uncomment if cookies need to be set + } + + private function getToken() + { + $username = $this->config->username; + $password = $this->config->password; + $authHeader = $this->config->authHeader; + + $attrs = [ + "headers" => [ + "Content-Type" => "application/json" + ], + "body" => json_encode([ + "username" => $username, + "password" => $password + ]) + ]; + if ($authHeader !== null) { + $attrs["headers"][$authHeader] = $username; + } + + $res = parent::execute($this->url("api/login"), $attrs, null, "POST"); + + switch ($res->getStatusCode()) { + case 200: + return $res->getBody()->getContents(); + case 403: + throw new \Exception("Invalid username/password"); + default: + throw new \Exception("Could not connect to FileBrowser"); + } + } + + private function formatBytes($bytes, $precision = 2) { + $units = array('B', 'KB', 'MB', 'GB', 'TB'); + $bytes = max($bytes, 0); + $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + + $bytes /= pow(1024, $pow); + + $value = round($bytes, $precision); + $unit = $units[$pow]; + + return [ + "value" => $value, + "unit" => $unit + ]; + } + + public function test() + { + try { + $token = $this->getToken(); + echo "Successfully communicated with the API"; + } catch (Exception $err) { + echo $err->getMessage(); + } + } + + public function livestats() + { + $status = "inactive"; + + $token = $this->getToken(); + $attrs = [ + "headers" => [ + "X-AUTH" => $token + ], + ]; + $res = parent::execute($this->url("api/usage"), $attrs); + $details = json_decode($res->getBody()); + + if ($details != null) { + $data["used"] = $this->formatBytes($details->used); + $data["total"] = $this->formatBytes($details->total); + } + return parent::getLiveStats($status, $data); + } + + public function url($endpoint) + { + $api_url = parent::normaliseurl($this->config->url) . $endpoint; + + return $api_url; + } +} diff --git a/stacks/dashboard/config/www/SupportedApps/FileBrowser/app.json b/stacks/dashboard/config/www/SupportedApps/FileBrowser/app.json new file mode 100644 index 0000000..0e412a6 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/FileBrowser/app.json @@ -0,0 +1,10 @@ +{ + "appid": "ba05dd8e070851895ee6184eb9778cfa0753a490", + "name": "FileBrowser", + "website": "https://github.com/filebrowser/filebrowser", + "license": "Apache License 2.0", + "description": "filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app or as a middleware.", + "enhanced": true, + "tile_background": "dark", + "icon": "filebrowser.svg" +} diff --git a/stacks/dashboard/config/www/SupportedApps/FileBrowser/config.blade.php b/stacks/dashboard/config/www/SupportedApps/FileBrowser/config.blade.php new file mode 100644 index 0000000..6436ca8 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/FileBrowser/config.blade.php @@ -0,0 +1,29 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')

+
+
+
+ + {!! Form::text('config[override_url]', isset($item) ? $item->getconfig()->override_url : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!} +
+
+
+
+ + {!! Form::text('config[username]', isset($item) ? $item->getconfig()->username : null, ['placeholder' => __('app.apps.username'), 'data-config' => 'username', 'class' => 'form-control config-item']) !!} +
+
+ + {!! Form::input('password', 'config[password]', '', ['placeholder' => __('app.apps.password'), 'data-config' => 'password', 'class' => 'form-control config-item']) !!} +
+
+
+
+ + {!! Form::text('config[authHeader]', isset($item) ? $item->getconfig()->authHeader : null, ['placeholder' => 'X-My-Header', 'data-config' => 'authHeader', 'class' => 'form-control config-item']) !!} + Also fill {{ __('app.apps.username') }} +
+
+
+ +
+
diff --git a/stacks/dashboard/config/www/SupportedApps/FileBrowser/livestats.blade.php b/stacks/dashboard/config/www/SupportedApps/FileBrowser/livestats.blade.php new file mode 100644 index 0000000..93f35f6 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/FileBrowser/livestats.blade.php @@ -0,0 +1,10 @@ +
    +
  • + Used + {!! $used["value"] !!}{!! $used["unit"] !!} +
  • +
  • + Total + {!! $total["value"] !!}{!! $total["unit"] !!} +
  • +
diff --git a/stacks/dashboard/config/www/SupportedApps/ITTools/ITTools.php b/stacks/dashboard/config/www/SupportedApps/ITTools/ITTools.php new file mode 100644 index 0000000..5836b43 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/ITTools/ITTools.php @@ -0,0 +1,7 @@ +url("System/Info"), + $this->getAttrs() + ); + echo $test->status; + } + + public function livestats() + { + $status = "inactive"; + $res = parent::execute($this->url("Items/Counts"), $this->getAttrs()); + $result = json_decode($res->getBody()); + $details = ["visiblestats" => []]; + foreach ($this->config->availablestats as $stat) { + $newstat = new \stdClass(); + $newstat->title = self::getAvailableStats()[$stat]; + $newstat->value = $result->{$stat}; + $details["visiblestats"][] = $newstat; + } + return parent::getLiveStats($status, $details); + } + public function url($endpoint) + { + $api_url = parent::normaliseurl($this->config->url) . $endpoint; + return $api_url; + } + + private function getAttrs() + { + $authorizationHeader = "MediaBrowser " . + "Token=\"" . urlencode($this->config->password) . "\", " . + "Client=\"Heimdall\""; + return [ + "headers" => [ + "Authorization" => $authorizationHeader, + ], + ]; + } + + public static function getAvailableStats() + { + return [ + "MovieCount" => "Movies", + "SeriesCount" => "Series", + "EpisodeCount" => "Episodes", + "ArtistCount" => "Artists", + "ProgramCount" => "Programs", + "TrailerCount" => "Trailers", + "SongCount" => "Songs", + "AlbumCount" => "Albums", + "MusicVideoCount" => "MusicVideos", + "BoxSetCount" => "BoxSets", + "BookCount" => "Books", + "ItemCount" => "Items", + ]; + } +} diff --git a/stacks/dashboard/config/www/SupportedApps/Jellyfin/app.json b/stacks/dashboard/config/www/SupportedApps/Jellyfin/app.json new file mode 100644 index 0000000..2460041 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Jellyfin/app.json @@ -0,0 +1,10 @@ +{ + "appid": "3e0a7f109bd760b9474c78cb652e8c3e82669226", + "name": "Jellyfin", + "website": "https://jellyfin.github.io", + "license": "GNU General Public License v2.0 only", + "description": "Jellyfin is the Free Software Media System that puts you in control of managing and streaming your media. There are no strings attached, no premium licenses or features, and no hidden agendas.", + "enhanced": true, + "tile_background": "dark", + "icon": "jellyfin.svg" +} diff --git a/stacks/dashboard/config/www/SupportedApps/Jellyfin/config.blade.php b/stacks/dashboard/config/www/SupportedApps/Jellyfin/config.blade.php new file mode 100644 index 0000000..faa3632 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Jellyfin/config.blade.php @@ -0,0 +1,18 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')

+
+
+ + {!! Form::text('config[override_url]', isset($item) ? $item->getconfig()->override_url : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!} +
+
+ + {!! Form::input('password', 'config[password]', '', ['placeholder' => __('app.apps.password'), 'data-config' => 'password', 'class' => 'form-control config-item']) !!} +
+
+ + {!! Form::select('config[availablestats][]', App\SupportedApps\Jellyfin\Jellyfin::getAvailableStats(), isset($item) ? $item->getConfig()->availablestats ?? null : null, ['multiple' => 'multiple']) !!} +
+
+ +
+
diff --git a/stacks/dashboard/config/www/SupportedApps/Jellyfin/livestats.blade.php b/stacks/dashboard/config/www/SupportedApps/Jellyfin/livestats.blade.php new file mode 100644 index 0000000..cb9431a --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Jellyfin/livestats.blade.php @@ -0,0 +1,8 @@ +
    + @foreach ($visiblestats as $stat) +
  • + {!! $stat->title !!} + {!! $stat->value !!} +
  • + @endforeach +
diff --git a/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/NginxProxyManager.php b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/NginxProxyManager.php new file mode 100644 index 0000000..026e30b --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/NginxProxyManager.php @@ -0,0 +1,61 @@ +jar = new \GuzzleHttp\Cookie\CookieJar; // Uncomment if cookies need to be set + } + + public function test() + { + $test = parent::appTest($this->url("api")); + echo $test->status; + } + + public function livestats() + { + $status = "inactive"; + $auth_attrs = [ + "headers" => [ + "Accept" => "application/json", + "Content-Type" => "application/json", + ], + "body" => json_encode([ + "identity" => $this->config->email, + "secret" => $this->config->password, + ]), + ]; + $auth_res = parent::execute( + $this->url("api/tokens"), + $auth_attrs, + null, + "POST" + ); + $auth_data = json_decode($auth_res->getBody(), true); + $token = $auth_data["token"]; + + $attrs = [ + "headers" => [ + "Accept" => "application/json", + "Authorization" => "Bearer " . $token, + ], + ]; + $res = parent::execute($this->url("api/reports/hosts"), $attrs); + $data = json_decode($res->getBody(), true); + + return parent::getLiveStats($status, $data); + } + public function url($endpoint) + { + $api_url = parent::normaliseurl($this->config->url) . $endpoint; + return $api_url; + } +} diff --git a/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/app.json b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/app.json new file mode 100644 index 0000000..87e8c44 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/app.json @@ -0,0 +1,10 @@ +{ + "appid": "cbfad988a16a9fbcc1812bc206afcc1f73dd36de", + "name": "Nginx Proxy Manager", + "website": "https://nginxproxymanager.jc21.com", + "license": "MIT License", + "description": "This project comes as a pre-built docker image that enables you to easily forward to your websites running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.", + "enhanced": true, + "tile_background": "light", + "icon": "nginxproxymanager.png" +} diff --git a/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/config.blade.php b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/config.blade.php new file mode 100644 index 0000000..0173dbc --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/config.blade.php @@ -0,0 +1,18 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')

+
+
+ + {!! Form::text('config[override_url]', isset($item) ? $item->getconfig()->override_url : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!} +
+
+ + {!! Form::text('config[email]', isset($item) ? $item->getconfig()->email : null, ['placeholder' => __('Email address'), 'data-config' => 'email', 'class' => 'form-control config-item']) !!} +
+
+ + {!! Form::input('password', 'config[password]', '', ['placeholder' => __('app.apps.password'), 'data-config' => 'password', 'class' => 'form-control config-item']) !!} +
+
+ +
+
diff --git a/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/livestats.blade.php b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/livestats.blade.php new file mode 100644 index 0000000..8536006 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/NginxProxyManager/livestats.blade.php @@ -0,0 +1,10 @@ +
    +
  • + Proxy Hosts + {!! $proxy !!} +
  • +
  • + Redirection Hosts + {!! $redirection !!} +
  • +
diff --git a/stacks/dashboard/config/www/SupportedApps/OnlyOffice/OnlyOffice.php b/stacks/dashboard/config/www/SupportedApps/OnlyOffice/OnlyOffice.php new file mode 100644 index 0000000..b9c6f39 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/OnlyOffice/OnlyOffice.php @@ -0,0 +1,7 @@ +jar = new \GuzzleHttp\Cookie\CookieJar(); // Uncomment if cookies need to be set + } + + public function test() + { + $version = $this->config->version; + + if ($version == 5) { + $test = parent::appTest($this->url("api.php?summaryRaw")); + echo $test->status; + } + if ($version == 6) { + $test = $this->getInfo(); + if ($test["valid"]) { + echo "Successfully communicated with the API"; + } else { + echo "Error while communicating with the API: " . $test["message"]; + } + } + } + public function livestats() + { + $data = []; + $status = "inactive"; + $version = $this->config->version; + + if ($version == 5) { + $res = parent::execute($this->url("api.php?summaryRaw")); + $details = json_decode($res->getBody()); + if ($details) { + $data["ads_blocked"] = number_format( + $details->ads_blocked_today + ); + $data["ads_percentage"] = number_format( + $details->ads_percentage_today, + 1 + ); + + $status = "active"; + } + } + + if ($version == 6) { + $results = $this->getInfo(); + + if ($results["valid"]) { + $data["ads_blocked"] = $results["queries"]; + $data["ads_percentage"] = $results["percent"]; + + $status = "active"; + } + } + return parent::getLiveStats($status, $data); + } + + public function url($endpoint) + { + $version = $this->config->version; + if ($version == 5) { + $apikey = $this->config->apikey; + $api_url = parent::normaliseurl($this->config->url) . $endpoint; + + if ($apikey) { + $api_url .= "&auth=" . $apikey; + } + } + if ($version == 6) { + $api_url = parent::normaliseurl($this->config->url) . $endpoint; + } + return $api_url; + } + + public function getInfo() + { + $ignoreTls = $this->getConfigValue("ignore_tls", false); + if ($ignoreTls) { + $attrs = [ + "body" => json_encode(['password' => $this->config->apikey]), + "cookies" => $this->jar, + "verify" => false, + "headers" => [ + "Content-Type" => "application/json", + "Accept" => "application/json", + ], + ]; + $attrsid["verify"] = false; + } else { + $attrs = [ + "body" => json_encode(['password' => $this->config->apikey]), + "cookies" => $this->jar, + "headers" => [ + "Content-Type" => "application/json", + "Accept" => "application/json", + ], + ]; + } + + // Create session and retrieve data + $response = parent::execute($this->url("api/auth"), $attrs, null, "POST"); + $auth = json_decode($response->getBody()); + + if (!$auth->session->valid) { + $data = [ + 'valid' => false, + 'validity' => -1, + 'message' => $auth->session->message, + 'queries' => 0, + 'percent' => 0 + ]; + return $data; + } + + if ($ignoreTls) { + $attrsid = [ + "body" => json_encode(['sid' => $auth->session->sid]), + "cookies" => $this->jar, + "verify" => false, + "headers" => [ + "Content-Type" => "application/json", + "Accept" => "application/json", + ], + ]; + } else { + $attrsid = [ + "body" => json_encode(['sid' => $auth->session->sid]), + "cookies" => $this->jar, + "headers" => [ + "Content-Type" => "application/json", + "Accept" => "application/json", + ], + ]; + } + + // Get queries data + $responsesummary = parent::execute($this->url("api/stats/summary"), $attrsid, null, "GET"); + $datasummary = json_decode($responsesummary->getBody()); + + // After retrieving the data the session is closed to declutter + parent::execute($this->url("api/auth"), $attrsid, null, "DELETE"); + + // Extract data from the response + $valid = $auth->session->valid; + $validity = $auth->session->validity; + $message = $auth->session->message; + + if (!$auth->session->valid) { + $queriesblocked = 0; + $percentblocked = 0; + } else { + $queriesblocked = $datasummary->queries->blocked; + $percentblocked = round($datasummary->queries->percent_blocked, 2); + } + + $data = [ + 'valid' => $valid, + 'validity' => $validity, + 'message' => $message, + 'queries' => $queriesblocked, + 'percent' => $percentblocked + ]; + return $data; + } + public function getConfigValue($key, $default = null) + { + return isset($this->config) && isset($this->config->$key) + ? $this->config->$key + : $default; + } +} diff --git a/stacks/dashboard/config/www/SupportedApps/Pihole/app.json b/stacks/dashboard/config/www/SupportedApps/Pihole/app.json new file mode 100644 index 0000000..5490455 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Pihole/app.json @@ -0,0 +1,10 @@ +{ + "appid": "b89920409bdce40e08ba1023480b0546061cd577", + "name": "Pi-hole", + "website": "https://pi-hole.net", + "license": "European Union Public License 1.2", + "description": "Pi-hole is a Linux network-level advertisement and internet tracker blocking application which acts as a DNS sinkhole, intended for use on a private network.", + "enhanced": true, + "tile_background": "dark", + "icon": "pihole.svg" +} diff --git a/stacks/dashboard/config/www/SupportedApps/Pihole/config.blade.php b/stacks/dashboard/config/www/SupportedApps/Pihole/config.blade.php new file mode 100644 index 0000000..3d8eff4 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Pihole/config.blade.php @@ -0,0 +1,43 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')

+
+ +
+ + {!! Form::text('config[override_url]', isset($item) ? $item->getconfig()->override_url : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!} +
+
+ + {!! Form::text('config[apikey]', isset($item) && property_exists($item->getconfig(), 'apikey') ? $item->getconfig()->apikey : null, ['placeholder' => __('app.apps.apikey'), 'data-config' => 'apikey', 'class' => 'form-control config-item']) !!} +
+
+
+ + {!! Form::select( + 'config[version]', + ['5' => 'v5', '6' => 'v6'], + isset($item) ? $item->getconfig()->version : null, + ['data-config' => 'version', 'class' => 'form-control config-item'], + ) !!} +
+
+
+ +
+ {!! Form::hidden('config[ignore_tls]', 0, ['class' => 'config-item', 'data-config' => 'ignore_tls']) !!} + +
+
+
+ +
+
diff --git a/stacks/dashboard/config/www/SupportedApps/Pihole/livestats.blade.php b/stacks/dashboard/config/www/SupportedApps/Pihole/livestats.blade.php new file mode 100644 index 0000000..d905f0b --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Pihole/livestats.blade.php @@ -0,0 +1,10 @@ +
    +
  • + Queries
    Blocked
    + {!! $ads_blocked !!} +
  • +
  • + Percent
    Blocked
    + {!! $ads_percentage !!} +
  • +
diff --git a/stacks/dashboard/config/www/SupportedApps/UptimeKuma/UptimeKuma.php b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/UptimeKuma.php new file mode 100644 index 0000000..6e35524 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/UptimeKuma.php @@ -0,0 +1,95 @@ + "down", + 1 => "up", + 2 => "pending", + 3 => "maintenance", + ]; + + public function __construct() + { + } + + private function getAttrs() + { + if (empty($this->config->apikey)) { + return []; + } + + $basicAuthValue = base64_encode(":" . $this->config->apikey); + + return [ + "headers" => [ + "Authorization" => "Basic " . $basicAuthValue, + ] + ]; + } + + public function test() + { + + $test = parent::appTest($this->url("metrics"), $this->getAttrs()); + echo $test->status; + } + + public function livestats() + { + $status = "inactive"; + + $response = parent::execute($this->url("metrics"), $this->getAttrs()); + $body = $response->getBody(); + + $lines = explode("\n", $body); + + $data = [ + "up" => 0, + "down" => 0, + "pending" => 0, + "maintenance" => 0, + "unknown" => 0, + ]; + + foreach ($lines as $line) { + if (strlen($line) === 0 || strpos($line, '#') === 0) { + // If the line is empty or is a comment we can skip it + continue; + } + + if (strpos($line, 'monitor_status') !== 0) { + // If the line is a metric but not a monitor we can ignore it + continue; + } + + // We only really care about the state, which is the integer at the end + // of the line. + // + // This can be 0 (Down), 1 (Up), 2 (Pending), 3 (Maintenance) + // + // We only care about the down or up but let's translate all of them. + $state = intval(substr($line, strrpos($line, ' '))); + + $data[$this->mapping[$state] ?? 'unknown']++; + } + + if ($data["down"] > 0) { + $status = "active"; + } + + return parent::getLiveStats($status, $data); + } + + public function url($endpoint) + { + $api_url = parent::normaliseurl($this->config->url) . + $endpoint; + + return $api_url; + } +} diff --git a/stacks/dashboard/config/www/SupportedApps/UptimeKuma/app.json b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/app.json new file mode 100644 index 0000000..2ebffba --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/app.json @@ -0,0 +1,10 @@ +{ + "appid": "366c6646eedab83cc4b349f198424d2291cbfa76", + "name": "Uptime Kuma", + "website": "https://uptime.kuma.pet", + "license": "MIT License", + "description": "It is a self-hosted monitoring tool like \"Uptime Robot\".", + "enhanced": true, + "tile_background": "dark", + "icon": "uptimekuma.svg" +} diff --git a/stacks/dashboard/config/www/SupportedApps/UptimeKuma/config.blade.php b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/config.blade.php new file mode 100644 index 0000000..aa383f0 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/config.blade.php @@ -0,0 +1,32 @@ +

{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')

+
+ +
+ + {!! Form::text('config[override_url]', isset($item) ? $item->getconfig()->override_url : null, ['placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control']) !!} +
+
+ + {!! Form::text('config[apikey]', isset($item) ? ($item->getconfig()->apikey ?? null) : null, ['placeholder' => __('app.apps.apikey'), 'data-config' => 'apikey', 'class' => 'form-control config-item']) !!} +
+
+ +
+ {!! Form::hidden('config[ignore_tls]', 0, ['class' => 'config-item', 'data-config' => 'ignore_tls']) !!} + +
+
+
+ +
+
diff --git a/stacks/dashboard/config/www/SupportedApps/UptimeKuma/livestats.blade.php b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/livestats.blade.php new file mode 100644 index 0000000..109206a --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/UptimeKuma/livestats.blade.php @@ -0,0 +1,10 @@ +
    +
  • + Up + {!! $up ?? 0 !!} +
  • +
  • + Down + {!! $down ?? 0 !!} +
  • +
diff --git a/stacks/dashboard/config/www/SupportedApps/Vaultwarden/Vaultwarden.php b/stacks/dashboard/config/www/SupportedApps/Vaultwarden/Vaultwarden.php new file mode 100644 index 0000000..ffb7a58 --- /dev/null +++ b/stacks/dashboard/config/www/SupportedApps/Vaultwarden/Vaultwarden.php @@ -0,0 +1,7 @@ + + + + + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/dockge.svg b/stacks/dashboard/config/www/icons/dockge.svg new file mode 100644 index 0000000..c3d6be2 --- /dev/null +++ b/stacks/dashboard/config/www/icons/dockge.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/dozzle.svg b/stacks/dashboard/config/www/icons/dozzle.svg new file mode 100644 index 0000000..7712588 --- /dev/null +++ b/stacks/dashboard/config/www/icons/dozzle.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/filebrowser.svg b/stacks/dashboard/config/www/icons/filebrowser.svg new file mode 100644 index 0000000..95b6ac3 --- /dev/null +++ b/stacks/dashboard/config/www/icons/filebrowser.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/ittools.png b/stacks/dashboard/config/www/icons/ittools.png new file mode 100644 index 0000000..465b7c4 Binary files /dev/null and b/stacks/dashboard/config/www/icons/ittools.png differ diff --git a/stacks/dashboard/config/www/icons/jellyfin.svg b/stacks/dashboard/config/www/icons/jellyfin.svg new file mode 100644 index 0000000..6c8cbfa --- /dev/null +++ b/stacks/dashboard/config/www/icons/jellyfin.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/nginxproxymanager.png b/stacks/dashboard/config/www/icons/nginxproxymanager.png new file mode 100644 index 0000000..7c5b28a Binary files /dev/null and b/stacks/dashboard/config/www/icons/nginxproxymanager.png differ diff --git a/stacks/dashboard/config/www/icons/onlyoffice.png b/stacks/dashboard/config/www/icons/onlyoffice.png new file mode 100644 index 0000000..685cb6c Binary files /dev/null and b/stacks/dashboard/config/www/icons/onlyoffice.png differ diff --git a/stacks/dashboard/config/www/icons/owncloud.png b/stacks/dashboard/config/www/icons/owncloud.png new file mode 100644 index 0000000..a780061 Binary files /dev/null and b/stacks/dashboard/config/www/icons/owncloud.png differ diff --git a/stacks/dashboard/config/www/icons/pihole.svg b/stacks/dashboard/config/www/icons/pihole.svg new file mode 100644 index 0000000..5495ad1 --- /dev/null +++ b/stacks/dashboard/config/www/icons/pihole.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/uptimekuma.svg b/stacks/dashboard/config/www/icons/uptimekuma.svg new file mode 100644 index 0000000..eaf0f3f --- /dev/null +++ b/stacks/dashboard/config/www/icons/uptimekuma.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/stacks/dashboard/config/www/icons/vaultwarden.png b/stacks/dashboard/config/www/icons/vaultwarden.png new file mode 100644 index 0000000..2e4becf Binary files /dev/null and b/stacks/dashboard/config/www/icons/vaultwarden.png differ diff --git a/stacks/dashboard/config/www/icons/wireguard.png b/stacks/dashboard/config/www/icons/wireguard.png new file mode 100644 index 0000000..d257aa4 Binary files /dev/null and b/stacks/dashboard/config/www/icons/wireguard.png differ diff --git a/stacks/dashboard/config/www/index.html b/stacks/dashboard/config/www/index.html new file mode 100644 index 0000000..8351def --- /dev/null +++ b/stacks/dashboard/config/www/index.html @@ -0,0 +1,34 @@ + + + Welcome to our server + + + +
+

Welcome to our server

+

The website is currently being setup under this address.

+

For help and support, please contact: me@example.com

+
+ + diff --git a/stacks/dashboard/config/www/logs/laravel-2026-03-05.log b/stacks/dashboard/config/www/logs/laravel-2026-03-05.log new file mode 100644 index 0000000..2df875e --- /dev/null +++ b/stacks/dashboard/config/www/logs/laravel-2026-03-05.log @@ -0,0 +1,307 @@ +[2026-03-05 02:13:25] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:13:25] local.DEBUG: Process Apps dispatched +[2026-03-05 02:13:25] local.DEBUG: Process Apps dispatched +[2026-03-05 02:52:38] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:52:38] local.DEBUG: Process Apps dispatched +[2026-03-05 02:52:40] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:52:40] local.DEBUG: Process Apps dispatched +[2026-03-05 02:52:42] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:52:42] local.DEBUG: Process Apps dispatched +[2026-03-05 02:52:46] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:52:46] local.DEBUG: Process Apps dispatched +[2026-03-05 02:52:46] local.DEBUG: Get app triggered for: ba05dd8e070851895ee6184eb9778cfa0753a490 +[2026-03-05 02:52:46] local.DEBUG: Download triggered for stdClass Object +( + [appid] => ba05dd8e070851895ee6184eb9778cfa0753a490 + [name] => FileBrowser + [website] => https://github.com/filebrowser/filebrowser + [license] => Apache License 2.0 + [description] => filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app or as a middleware. + [enhanced] => 1 + [tile_background] => dark + [icon] => filebrowser.svg + [sha] => b92328bdd28ebaf4103fa1a7ba22da49e3c263e7 + [class] => App\SupportedApps\FileBrowser\FileBrowser +) + +[2026-03-05 02:52:47] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:52:56] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:52:57] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:02] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:03] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:09] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:09] local.DEBUG: Get app triggered for: 668b5fcda851fe516fef14e82973beffe32f385a +[2026-03-05 02:53:09] local.DEBUG: Download triggered for stdClass Object +( + [appid] => 668b5fcda851fe516fef14e82973beffe32f385a + [name] => ownCloud + [website] => https://owncloud.org + [license] => GNU Affero General Public License v3.0 or later + [description] => ownCloud is a free and open source file hosting service. It also supports extensions for online document editing, calendar and contact synchronization. It's a safe home for all your data. + [enhanced] => + [tile_background] => dark + [icon] => owncloud.png + [sha] => fa9bc697bec8367d9f4d4e98e9a34ea9c61d4710 + [class] => App\SupportedApps\ownCloud\ownCloud +) + +[2026-03-05 02:53:17] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:17] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:20] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:22] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:51] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:51] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:53] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:53:54] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:00] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:00] local.DEBUG: Get app triggered for: b89920409bdce40e08ba1023480b0546061cd577 +[2026-03-05 02:54:00] local.DEBUG: Download triggered for stdClass Object +( + [appid] => b89920409bdce40e08ba1023480b0546061cd577 + [name] => Pi-hole + [website] => https://pi-hole.net + [license] => European Union Public License 1.2 + [description] => Pi-hole is a Linux network-level advertisement and internet tracker blocking application which acts as a DNS sinkhole, intended for use on a private network. + [enhanced] => 1 + [tile_background] => dark + [icon] => pihole.svg + [sha] => 945fe7045036e17eff1d0c46be6280f207cef77a + [class] => App\SupportedApps\Pihole\Pihole +) + +[2026-03-05 02:54:00] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:11] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:11] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:13] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:14] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:18] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:18] local.DEBUG: Get app triggered for: 0bafb882c9d2c034ca5333367f8ccc90f4ae85e4 +[2026-03-05 02:54:18] local.DEBUG: Download triggered for stdClass Object +( + [appid] => 0bafb882c9d2c034ca5333367f8ccc90f4ae85e4 + [name] => Dockge + [website] => https://github.com/louislam/dockge + [license] => MIT License + [description] => A fancy, easy-to-use and reactive self-hosted docker compose.yaml stack-oriented manager. + [enhanced] => + [tile_background] => dark + [icon] => dockge.svg + [sha] => f4e77826a682041f4ab5e3276d3a7c1886d8095d + [class] => App\SupportedApps\Dockge\Dockge +) + +[2026-03-05 02:54:27] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:27] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:29] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:31] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:34] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:34] local.DEBUG: Get app triggered for: 348c49dd03dddd418929316668d2e67bf2d9ae88 +[2026-03-05 02:54:34] local.DEBUG: Download triggered for stdClass Object +( + [appid] => 348c49dd03dddd418929316668d2e67bf2d9ae88 + [name] => Bookstack + [website] => https://www.bookstackapp.com + [license] => MIT License + [description] => BookStack is a simple, self-hosted, easy-to-use platform for organising and storing information. + [enhanced] => 1 + [tile_background] => dark + [icon] => bookstack.svg + [sha] => fd57e5a47f09f6227b62b74428765dbce7f5813d + [class] => App\SupportedApps\Bookstack\Bookstack +) + +[2026-03-05 02:54:34] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:42] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:42] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:47] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:49] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:53] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:54:53] local.DEBUG: Get app triggered for: af7b37e2841d9150f6abd5a936b32a1f681d6bda +[2026-03-05 02:54:53] local.DEBUG: Download triggered for stdClass Object +( + [appid] => af7b37e2841d9150f6abd5a936b32a1f681d6bda + [name] => JDownloader + [website] => http://jdownloader.org + [license] => Creative Commons Attribution Non Commercial Share Alike 2.0 Generic + [description] => JDownloader is a free, open-source download management tool with a huge community of developers that makes downloading as easy and fast as it should be. + [enhanced] => + [tile_background] => dark + [icon] => jdownloader.png + [sha] => 32303a80935e2fbbecb1132e2358498ba876060b + [class] => App\SupportedApps\JDownloader\JDownloader +) + +[2026-03-05 02:55:00] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:17] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:17] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:20] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:22] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:24] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:24] local.DEBUG: Get app triggered for: 176d99d897dbd7c02b1a1db4142054f74a76aa47 +[2026-03-05 02:55:24] local.DEBUG: Download triggered for stdClass Object +( + [appid] => 176d99d897dbd7c02b1a1db4142054f74a76aa47 + [name] => Dozzle + [website] => https://dozzle.dev + [license] => MIT License + [description] => Dozzle is a real-time log viewer for docker containers. + [enhanced] => + [tile_background] => dark + [icon] => dozzle.svg + [sha] => 46ca9ab4e1428db7e545d09261f487b08220d28d + [class] => App\SupportedApps\Dozzle\Dozzle +) + +[2026-03-05 02:55:32] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:32] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:36] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:37] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:42] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:42] local.DEBUG: Get app triggered for: fc4e407d69510b855b678aa4fba6083fbbfc5383 +[2026-03-05 02:55:42] local.DEBUG: Download triggered for stdClass Object +( + [appid] => fc4e407d69510b855b678aa4fba6083fbbfc5383 + [name] => OnlyOffice + [website] => https://www.onlyoffice.com + [license] => GNU Affero General Public License v3.0 or later + [description] => ONLYOFFICE online editors for text documents, spreadsheets, and presentations with access to pro features and connect them to the platform of your choice with ready-to-use connectors: https://www.onlyoffice.com/download.aspx#connectors + [enhanced] => + [tile_background] => light + [icon] => onlyoffice.png + [sha] => 4b8aa18f29760fab9ce5cd94976e86e464772a85 + [class] => App\SupportedApps\OnlyOffice\OnlyOffice +) + +[2026-03-05 02:55:42] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:48] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:48] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:51] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:52] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:55] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:55] local.DEBUG: Get app triggered for: cbfad988a16a9fbcc1812bc206afcc1f73dd36de +[2026-03-05 02:55:55] local.DEBUG: Download triggered for stdClass Object +( + [appid] => cbfad988a16a9fbcc1812bc206afcc1f73dd36de + [name] => Nginx Proxy Manager + [website] => https://nginxproxymanager.jc21.com + [license] => MIT License + [description] => This project comes as a pre-built docker image that enables you to easily forward to your websites running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt. + [enhanced] => 1 + [tile_background] => light + [icon] => nginxproxymanager.png + [sha] => 0b8e03a7f9a833c0e644f401ee85926b8ba86c73 + [class] => App\SupportedApps\NginxProxyManager\NginxProxyManager +) + +[2026-03-05 02:55:55] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:55:55] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:02] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:02] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:06] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:07] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:10] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:10] local.DEBUG: Get app triggered for: 366c6646eedab83cc4b349f198424d2291cbfa76 +[2026-03-05 02:56:10] local.DEBUG: Download triggered for stdClass Object +( + [appid] => 366c6646eedab83cc4b349f198424d2291cbfa76 + [name] => Uptime Kuma + [website] => https://uptime.kuma.pet + [license] => MIT License + [description] => It is a self-hosted monitoring tool like "Uptime Robot". + [enhanced] => 1 + [tile_background] => dark + [icon] => uptimekuma.svg + [sha] => 5179586b1259c3eba3fbf0c4712436110adb1885 + [class] => App\SupportedApps\UptimeKuma\UptimeKuma +) + +[2026-03-05 02:56:10] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:18] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:19] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:29] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:33] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:41] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:41] local.DEBUG: Get app triggered for: b5f16344632fdfe68391a2dc3816ee0edbb1813c +[2026-03-05 02:56:41] local.DEBUG: Download triggered for stdClass Object +( + [appid] => b5f16344632fdfe68391a2dc3816ee0edbb1813c + [name] => IT-Tools + [website] => https://it-tools.tech/ + [license] => GNU General Public License v3.0 only + [description] => Useful tools for developer and people working in IT. + [enhanced] => + [tile_background] => light + [icon] => ittools.png + [sha] => c42fe8dccaae8c320230a00f24771745edc8dc2d + [class] => App\SupportedApps\ITTools\ITTools +) + +[2026-03-05 02:56:41] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:47] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:48] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:50] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:51] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:56] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:56:56] local.DEBUG: Get app triggered for: ddf4f264320af1347ef54d424c60fae3b4fcc448 +[2026-03-05 02:56:56] local.DEBUG: Download triggered for stdClass Object +( + [appid] => ddf4f264320af1347ef54d424c60fae3b4fcc448 + [name] => Vaultwarden + [website] => https://github.com/dani-garcia/vaultwarden + [license] => GNU Affero General Public License v3.0 + [description] => Alternative implementation of the Bitwarden server API written in Rust and compatible with upstream Bitwarden clients*, perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. + [enhanced] => + [tile_background] => light + [icon] => vaultwarden.png + [sha] => fbc0ce92000160c6576cf4dc54b3859098f9faa8 + [class] => App\SupportedApps\Vaultwarden\Vaultwarden +) + +[2026-03-05 02:56:57] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:03] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:03] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:05] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:06] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:10] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:10] local.DEBUG: Get app triggered for: 3e0a7f109bd760b9474c78cb652e8c3e82669226 +[2026-03-05 02:57:10] local.DEBUG: Download triggered for stdClass Object +( + [appid] => 3e0a7f109bd760b9474c78cb652e8c3e82669226 + [name] => Jellyfin + [website] => https://jellyfin.github.io + [license] => GNU General Public License v2.0 only + [description] => Jellyfin is the Free Software Media System that puts you in control of managing and streaming your media. There are no strings attached, no premium licenses or features, and no hidden agendas. + [enhanced] => 1 + [tile_background] => dark + [icon] => jellyfin.svg + [sha] => 0261afdcd2000d2ed0fddf978d364b8ffcae961d + [class] => App\SupportedApps\Jellyfin\Jellyfin +) + +[2026-03-05 02:57:11] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:18] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:19] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:20] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:21] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:25] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:25] local.DEBUG: Get app triggered for: afef2217e82ee20638490bb102605f6e09789093 +[2026-03-05 02:57:25] local.DEBUG: Download triggered for stdClass Object +( + [appid] => afef2217e82ee20638490bb102605f6e09789093 + [name] => WireGuard + [website] => https://www.wireguard.com + [license] => CNRI Python Open Source GPL Compatible License Agreement + [description] => WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. Initially released for the Linux kernel, it is now cross-platform (Windows, macOS, BSD, iOS, Android) and widely deployable. It is currently under heavy development, but already it might be regarded as the most secure, easiest to use, and simplest VPN solution in the industry. + [enhanced] => + [tile_background] => dark + [icon] => wireguard.png + [sha] => 5c05f64749725c3179f109d21977d086101b3ee7 + [class] => App\SupportedApps\WireGuard\WireGuard +) + +[2026-03-05 02:57:31] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:32] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:34] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:35] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:49] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite +[2026-03-05 02:57:49] local.DEBUG: SQLite Database Path: /app/www/database/app.sqlite diff --git a/stacks/dashboard/config/www/searchproviders.yaml b/stacks/dashboard/config/www/searchproviders.yaml new file mode 100644 index 0000000..bbb13d6 --- /dev/null +++ b/stacks/dashboard/config/www/searchproviders.yaml @@ -0,0 +1,44 @@ +tiles: + id: tiles + name: Tiles + target: _blank + +baidu: + id: baidu + url: https://www.baidu.com/s + name: Baidu + method: get + target: _blank + query: wd + +bing: + id: bing + url: https://www.bing.com/search + name: Bing + method: get + target: _blank + query: q + +ddg: + id: ddg + url: https://duckduckgo.com/ + name: DuckDuckGo + method: get + target: _blank + query: q + +google: + id: google + url: https://www.google.com/search + name: Google + method: get + target: _blank + query: q + +startpage: + id: startpage + url: https://www.startpage.com/do/dsearch + name: Startpage + method: get + target: _blank + query: query