diff --git a/.gitignore b/.gitignore
index 67d0346..3751439 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,5 @@ yarn-error.log*
# production
/build/
/data/
-/confs/
\ No newline at end of file
+/confs/
+/private/
\ No newline at end of file
diff --git a/components/layout.tsx b/components/layout.tsx
index 6a2f966..9205de4 100644
--- a/components/layout.tsx
+++ b/components/layout.tsx
@@ -48,24 +48,6 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
defer src='https://static.cloudflareinsights.com/beacon.min.js'
data-cf-beacon='{"token": "826fc083aa86417890c0ceb3e0a597fa"}'>
-
diff --git a/interfaces/CardTypes.ts b/interfaces/CardTypes.ts
index aabe411..bae386c 100644
--- a/interfaces/CardTypes.ts
+++ b/interfaces/CardTypes.ts
@@ -32,6 +32,7 @@ export enum Status {
export enum ServiceLocation {
brr7_4800u = "brr7-4800u",
+ tower_0 = "tower-0",
other = ""
}
diff --git a/interfaces/DockerStatus.ts b/interfaces/DockerStatus.ts
new file mode 100644
index 0000000..910f222
--- /dev/null
+++ b/interfaces/DockerStatus.ts
@@ -0,0 +1,11 @@
+import { ServiceLocation } from './CardTypes';
+export interface DockerInfo {
+ name: string,
+ status: DockerStatus,
+ id: string
+ location: ServiceLocation,
+}
+
+export enum DockerStatus {
+ running = "running",
+}
diff --git a/pages/api/containers.tsx b/pages/api/containers.tsx
index 6f75e6e..7f6a6d2 100644
--- a/pages/api/containers.tsx
+++ b/pages/api/containers.tsx
@@ -1,13 +1,29 @@
import Docker from 'dockerode'
+import ApiSecret from '../../private/portainer_api_secret.json'
+import { DockerInfo } from '../../interfaces/DockerStatus';
+import { ServiceLocation } from '../../interfaces/CardTypes';
export default async function ContainersAPI(req: any, res: any) {
+ const token = JSON.parse(JSON.stringify(ApiSecret.token));
+
try {
- const options = {
- socketPath: '/var/run/docker.sock',
- path: '/v1.41/containers/json'
- };
- var docker = new Docker({ socketPath: options.socketPath });
- const list = await docker.listContainers({ all: true })
+ const res1 = await fetch('https://portainer.neshweb.net/api/endpoints/2/docker/containers/json', {
+ method: "GET",
+ headers: {"X-API-Key": token}
+ });
+
+ const unparsed = await res1.json();
+ let list: DockerInfo[] = [];
+
+ unparsed.forEach((entry: any) => {
+ let newEntry = {} as DockerInfo;
+
+ newEntry.name = entry.Names[0].substring(1);
+ newEntry.status = entry.State;
+ newEntry.id = entry.Id;
+ newEntry.location = ServiceLocation.tower_0;
+ list.push(newEntry);
+ });
res.status(200).json(list);
}
diff --git a/pages/servers.tsx b/pages/servers.tsx
index 1acfe95..c193a49 100644
--- a/pages/servers.tsx
+++ b/pages/servers.tsx
@@ -1,7 +1,7 @@
import Head from 'next/head'
import { Game } from '../interfaces/CardTypes';
import { PageContentBox, PageDescription, PageTitle, CardContentGame } from '../components/styles/content'
-import GameList from '../public/pages.json';
+import GameList from '../public/data/pages.json';
function Servers() {
// TODO: unuggly this shit
diff --git a/pages/services.tsx b/pages/services.tsx
index a42efab..fce23f6 100644
--- a/pages/services.tsx
+++ b/pages/services.tsx
@@ -5,6 +5,7 @@ import { ReactElement } from 'react'
import useSWR from 'swr';
import { CardContentService, PageContentBox, PageDescription, PageTitle } from '../components/styles/content';
import ServiceList from '../public/data/pages.json';
+import { DockerInfo } from '../interfaces/DockerStatus';
const fetcher = (url: string) => fetch(url).then((res) => res.json())
@@ -56,82 +57,12 @@ function Services() {
)
}
-async function getStatus(entry: Service, containers: Dockerode.ContainerInfo[]) {
+async function getStatus(entry: Service, containers: DockerInfo[]) {
// Currently the only location supporting different fetching depending on type is brr7-4800u
// Others to follow but low prio as this is currently the only location used
- // Location BRR7-4800U
- if (entry.location === ServiceLocation.brr7_4800u) {
- // Type APP
- if (entry.type === ServiceType.app) {
- await fetch(entry.href)
- .then((response) => {
- if (response.ok) {
- switch (response.status) {
- case 200:
- case 301:
- case 302:
- entry.status = Status.online;
- break;
- default:
- entry.status = Status.offline;
- }
- }
- else {
- entry.status = Status.offline;
- }
- })
- .catch((error) => {
- console.error("Error pinging Website: ", error);
- entry.status = Status.error;
- })
- }
- // Type Docker
- else if (entry.type === ServiceType.docker) {
- if (entry.name !== null) {
- let found = false;
- for (let i = 0; i < containers.length; i++) {
- const container = containers[i];
- // Docker API returns container names with / prepended
- if (containers[i].Names.includes("/" + entry.docker_container_name)) {
- // so far only "running" is properly implemented, mroe cases to follow as needed
- switch (container.State) {
- case "running":
- entry.status = Status.online;
- break;
- default:
- console.log("Container Status " + container.State + " has no case implemented");
- entry.status = Status.offline;
- }
- found = true;
- // cancel the for
- break;
- }
- // If container name is not missing the container is set to offline
- else {
- entry.status = Status.offline;
- }
- }
- if (!found) {
- console.warn("Container for " + entry.name + " could not be found");
- }
- }
- // if name is null do not enter for loop
- else {
- console.error("Container Name not specified");
- entry.status = Status.error;
- }
- }
- // If no Type matches
- else {
- console.warn("Service Type for Service " + entry.name + " not specified or invalid");
- entry.status = Status.error;
- }
- }
- // Location Other
- // TODO: implement docker type for other locations
- else if (entry.location === ServiceLocation.other) {
- // Currently uses the same handling as app type for the other location
+ // Type APP
+ if (entry.type === ServiceType.app) {
await fetch(entry.href)
.then((response) => {
if (response.ok) {
@@ -154,15 +85,54 @@ async function getStatus(entry: Service, containers: Dockerode.ContainerInfo[])
entry.status = Status.error;
})
}
- // If no Location matches
+ // Type Docker
+ else if (entry.type === ServiceType.docker) {
+ if (entry.name !== null) {
+ let found = false;
+ for (let i = 0; i < containers.length; i++) {
+ const container = containers[i];
+ // Docker API returns container names with / prepended
+ if (container.name === entry.docker_container_name) {
+
+ if (container.location === entry.location) {
+ // so far only "running" is properly implemented, mroe cases to follow as needed
+ switch (container.status) {
+ case "running":
+ entry.status = Status.online;
+ break;
+ default:
+ console.log("Container Status " + container.status + " has no case implemented");
+ entry.status = Status.offline;
+ }
+ found = true;
+ // cancel the for
+ break;
+ }
+ }
+ // If container name is not missing the container is set to offline
+ else {
+ entry.status = Status.offline;
+ }
+ }
+ if (!found) {
+ console.warn("Container for " + entry.name + " could not be found");
+ }
+ }
+ // if name is null do not enter for loop
+ else {
+ console.error("Container Name not specified");
+ entry.status = Status.error;
+ }
+ }
+ // If no Type matches
else {
- console.warn("Service Location for Service " + entry.name + " not specified");
+ console.warn("Service Type for Service " + entry.name + " not specified or invalid");
entry.status = Status.error;
}
return entry;
}
-const fetchFullDataArray = (containerData: Dockerode.ContainerInfo[], dataSet: Service[]) => {
+const fetchFullDataArray = (containerData: DockerInfo[], dataSet: Service[]) => {
const fetchStatus = (entry: Service) => getStatus(entry, containerData);
return Promise.all(dataSet.map(fetchStatus));
}
diff --git a/public/data/pages.json b/public/data/pages.json
index 57aff98..32e48a2 100644
--- a/public/data/pages.json
+++ b/public/data/pages.json
@@ -8,7 +8,7 @@
"warn": "Note: Registration requires approval",
"type": "docker",
"docker_container_name": "nextcloud",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Kavita",
@@ -18,17 +18,7 @@
"warn": "Registration via Admin invite",
"type": "docker",
"docker_container_name": "kavita",
- "location": "brr7-4800u"
- },
- {
- "name": "Komga",
- "icon": "/icons/komga-logo.png",
- "href": "https://komga.neshweb.net",
- "desc": "Self-hosted Comic Library",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "komga",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Calibre Web",
@@ -36,8 +26,9 @@
"href": "https://calibre.neshweb.net/",
"desc": "Self-hosted Ebook Library Service",
"warn": "Note: Registration only via Admin",
- "type": "app",
- "location": "brr7-4800u"
+ "type": "docker",
+ "docker_container_name": "calibre-web",
+ "location": "tower-0"
},
{
"name": "PeerTube",
@@ -47,7 +38,7 @@
"warn": "Note: Registration only via Admin",
"type": "docker",
"docker_container_name": "peertube",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Mastodon",
@@ -57,7 +48,7 @@
"warn": "Note: Registration requires approval",
"type": "docker",
"docker_container_name": "mastodon-web",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
@@ -68,7 +59,7 @@
"warn": "Note: Invite only",
"type": "docker",
"docker_container_name": "vaultwarden",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "File Browser",
@@ -77,7 +68,7 @@
"warn": "Note: Registration only via Admin",
"type": "docker",
"docker_container_name": "filebrowser",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Jellyfin",
@@ -87,7 +78,7 @@
"warn": "Note: Registration only via Admin",
"type": "docker",
"docker_container_name": "jellyfin",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Navidrome",
@@ -97,7 +88,7 @@
"warn": "Note: Registration only via Admin",
"type": "docker",
"docker_container_name": "navidrome",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Picard",
@@ -106,7 +97,7 @@
"warn": "Note: Access only via Admin",
"type": "docker",
"docker_container_name": "picard",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Gitlab",
@@ -116,7 +107,7 @@
"warn": "Note: Registration only via Admin",
"type": "docker",
"docker_container_name": "gitlab",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Portainer",
@@ -126,7 +117,7 @@
"warn": "Note: Admin Only",
"type": "docker",
"docker_container_name": "portainer",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
"name": "Nginx Proxy Manager",
@@ -136,26 +127,16 @@
"warn": "Note: Admin Only",
"type": "docker",
"docker_container_name": "nginx-prox",
- "location": "brr7-4800u"
+ "location": "tower-0"
},
{
- "name": "Grafana",
- "icon": "/icons/grafana-logo.svg",
- "href": "https://monitoring.neshweb.net/",
- "desc": "Server Monitoring Utility",
+ "name": "Proxmox",
+ "icon": "/icons/proxmox-logo.png",
+ "href": "https://proxmox.neshweb.net/",
+ "desc": "Hypervisor Webinterface",
"warn": "Note: Admin Only",
- "type": "docker",
- "docker_container_name": "grafana",
- "location": "brr7-4800u"
- },
- {
- "name": "Matomo",
- "href": "https://tracking.neshweb.net/",
- "desc": "Traffic Tracking Utility",
- "warn": "Note: Admin Only",
- "type": "docker",
- "docker_container_name": "matomo-web",
- "location": "brr7-4800u"
+ "type": "app",
+ "location": ""
}
],
"games": {
diff --git a/public/pages.json b/public/pages.json
deleted file mode 100644
index f7378c9..0000000
--- a/public/pages.json
+++ /dev/null
@@ -1,160 +0,0 @@
-{
- "services": [
- {
- "name": "Nextcloud",
- "icon": "/icons/nextcloud-logo.svg",
- "href": "https://nextcloud.neshweb.net/",
- "desc": "Self-hosted Cloud Storage Service",
- "warn": "Note: Registration requires approval",
- "type": "docker",
- "docker_container_name": "nextcloud",
- "location": "brr7-4800u"
- },
- {
- "name": "Komga",
- "icon": "/icons/komga-logo.png",
- "href": "https://komga.neshweb.net/",
- "desc": "Self-hosted Comic Library",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "komga",
- "location": "brr7-4800u"
- },
- {
- "name": "Calibre Web",
- "icon": "/icons/calibre-logo.ico",
- "href": "https://calibre.neshweb.net/",
- "desc": "Self-hosted Ebook Library Service",
- "warn": "Note: Registration only via Admin",
- "type": "app",
- "location": "brr7-4800u"
- },
- {
- "name": "PeerTube",
- "icon": "/icons/peertube-logo.svg",
- "href": "https://tube.neshweb.net/",
- "desc": "Self-hosted PeerTube Instance",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "peertube",
- "location": "brr7-4800u"
- },
- {
- "name": "Mastodon",
- "icon": "/icons/mastodon-logo.svg",
- "href": "https://mastodon.neshweb.net/",
- "desc": "Self-hosted Mastodon Instance",
- "warn": "Note: Registration requires approval",
- "type": "docker",
- "docker_container_name": "mastodon-web",
- "location": "brr7-4800u"
- },
- {
- "name": "File Browser",
- "href": "https://files.neshweb.net/",
- "desc": "Server File Browser",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "filebrowser",
- "location": "brr7-4800u"
- },
- {
- "name": "Jellyfin",
- "icon": "/icons/jellyfin-logo.svg",
- "href": "https://jellyfin.neshweb.net/",
- "desc": "Open-Source, Self-Hosted Media Platform",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "jellyfin",
- "location": "brr7-4800u"
- },
- {
- "name": "Navidrome",
- "icon": "/icons/navidrome-logo.png",
- "href": "https://navidrome.neshweb.net/",
- "desc": "Open-Source, Self-Hosted Music Streaming Platform",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "navidrome",
- "location": "brr7-4800u"
- },
- {
- "name": "Picard",
- "href": "https://picard.neshweb.net/",
- "desc": "MP3 Tagger",
- "warn": "Note: Access only via Admin",
- "type": "docker",
- "docker_container_name": "picard",
- "location": "brr7-4800u"
- },
- {
- "name": "Gitlab",
- "icon": "/icons/gitlab-logo.svg",
- "href": "https://gitlab.neshweb.net/",
- "desc": "Self-hosted Git Service",
- "warn": "Note: Registration only via Admin",
- "type": "docker",
- "docker_container_name": "gitlab",
- "location": "brr7-4800u"
- },
- {
- "name": "Portainer",
- "icon": "/icons/portainer-logo.png",
- "href": "https://portainer.neshweb.net/",
- "desc": "Docker Container Manager",
- "warn": "Note: Admin Only",
- "type": "docker",
- "docker_container_name": "portainer",
- "location": "brr7-4800u"
- },
- {
- "name": "Nginx Proxy Manager",
- "icon": "/icons/npm-logo.png",
- "href": "https://nginx.neshweb.net/",
- "desc": "Web-based Nginx Proxy Manager",
- "warn": "Note: Admin Only",
- "type": "docker",
- "docker_container_name": "nginx-prox",
- "location": "brr7-4800u"
- },
- {
- "name": "Grafana",
- "icon": "/icons/grafana-logo.svg",
- "href": "https://monitoring.neshweb.net/",
- "desc": "Server Monitoring Utility",
- "warn": "Note: Admin Only",
- "type": "docker",
- "docker_container_name": "grafana",
- "location": "brr7-4800u"
- },
- {
- "name": "Matomo",
- "href": "https://tracking.neshweb.net/",
- "desc": "Traffic Tracking Utility",
- "warn": "Note: Admin Only",
- "type": "docker",
- "docker_container_name": "matomo-web",
- "location": "brr7-4800u"
- }
- ],
- "games": {
- "minecraft": {
- "name": "Minecraft",
- "icon": "/icons/minecraft-logo.png",
- "href": "https://minecraft.neshweb.net/",
- "desc": "View all currently available Minecraft Servers and their mods"
- },
- "ready_or_not": {
- "name": "Ready or Not",
- "icon": "/icons/ron-logo.png",
- "href": "https://readyornot.neshweb.net/",
- "desc": "Collection of Floor Plans for the Game 'Ready or Not'"
- },
- "zomboid": {
- "name": "Zomboid",
- "icon": "/icons/zomboid-logo.png",
- "ip": "91.13.248.30",
- "status": "Online"
- }
- }
-}