Skip to content

Commit

Permalink
Merge pull request #34 from lllllllillllllillll/dev
Browse files Browse the repository at this point in the history
v0.08
  • Loading branch information
lllllllillllllillll authored Dec 15, 2023
2 parents 7f6370c + d4211f7 commit bc10e26
Show file tree
Hide file tree
Showing 30 changed files with 360 additions and 178 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
## v0.08 (Dec 15th 2023)
* Updates to compose file and instructions from [steveiliop56](https://github.com/steveiliop56)
* Added SECRET field to compose file as a basic security measure.
* Visibility button to hide containers or reset view.
* Container link now uses server IP address.
* More compact container card, with style options planned.
* Improved log view.
* Removed VPN, Firewall, and VNC buttons.
* Updated dependencies (Sequelize 6.35.2)
* Fixed web pages not using the "public" static folder.
* Small tweaks to router.
* Replaced the default icon shown for missing icons (docker.png).

## v0.07 (Dec 8th 2023)
* View container logs.
* Removed Redis.
Expand Down
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

FROM node:21-alpine

ENV NODE_ENV production

WORKDIR /app

Expand Down
Binary file removed DweebUI.png
Binary file not shown.
97 changes: 61 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# DweebUI
DweebUI is a simple Docker web interface created with javascript and node.js
DweebUI is a simple Docker web interface created using Javascript, Node.JS, and Express.

Pre-Pre-Pre-Pre-Pre Alpha v0.07 ( :fire: Experimental. Don't install on any servers you care about :fire: )
Pre-Pre-Pre-Pre-Pre Alpha v0.08 ( :fire: Experimental. Don't install on any servers you care about :fire: )

[![GitHub Stars](https://img.shields.io/github/stars/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll)
[![GitHub License](https://img.shields.io/github/license/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll/DweebUI/blob/main/LICENSE)
[![GitHub Activity](https://img.shields.io/github/commit-activity/y/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll)
[![Docker Pulls](https://img.shields.io/docker/pulls/lllllllillllllillll/dweebui)](https://hub.docker.com/repository/docker/lllllllillllllillll/dweebui)
[![GitHub License](https://img.shields.io/github/license/lllllllillllllillll/DweebUI)](https://github.com/lllllllillllllillll/DweebUI/blob/main/LICENSE)


* I haven't used Github very much and I'm still new to javascript.
* This is the first project I've ever released and I'm sure it's full of plenty of bugs and mistakes.
* This is a personal project that I decided to share. I'm sure it has plenty of bugs and mistakes.
* I haven't used Github very much and I'm still new to Javascript.
* I probably should have waited a lot longer to share this :|

<a href="https://raw.githubusercontent.com//lllllllillllllillll/DweebUI/main/screenshots/dashboard.png"><img src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI/main/screenshots/dashboard.png" width="50%"/></a>
Expand All @@ -17,49 +19,71 @@ Pre-Pre-Pre-Pre-Pre Alpha v0.07 ( :fire: Experimental. Don't install on any serv


## Features
* [x] Dashboard provides server metrics (cpu, ram, network, disk) and container controls on a single page.
* [x] Dashboard provides server metrics, container metrics, and container controls, on a single page.
* [x] View container logs.
* [ ] Update containers (planned).
* [ ] Manage your Docker networks, images, and volumes (planned).
* [x] Light/Dark Mode.
* [x] Easy to install app templates.
* [x] Automatically persists data in docker volumes if bind mount isn't used.
* [x] Proxy manager for Caddy. (Optional)
* [x] Partial Portainer Template Support (Network Mode, Ports, Volumes, Enviroment Variables, Labels, Commands, Restart Policy, Nvidia Hardware Acceleration).
* [x] Proxy manager for Caddy (Optional).
* [x] Multi-User built-in.
* [ ] User pages: Shortcuts, Requests, Support. (planned)
* [ ] User pages (planned).
* [x] Support for Windows, Linux, and MacOS.
* [ ] Import compose files. (planned)
* [x] Javascript, Node.js, and Express.
* [ ] Docker compose support (planned).
* [x] Templates.json maintains compatability with Portainer, allowing you to use the template without needing to use DweebUI.
* [ ] Manage your Docker networks, images, and volumes. (planned)
* [ ] Preset variables. (planned)
* [ ] VPN, VPS, and Firewall Toggles. (planned)
* [ ] Offline Mode. (planned)
* [x] Automatically persists data in docker volumes if bind mount isn't used.
* [ ] Preset variables (planned).
* [ ] Offline/Local Icons (planned).


## Setup

* Docker compose.yaml:
Docker Compose:
```
version: "3.9"
services:
  dweebui:
    container_name: DweebUI
    image: lllllllillllllillll/dweebui:v0.07
    environment:
      NODE_ENV: production
      PORT: 8000
      # Proxy_Manager: enabled
    restart: unless-stopped
    ports:
      - 8000:8000
    volumes:
      - dweebui:/app
      - caddyfiles:/app/caddyfiles
      - /var/run/docker.sock:/var/run/docker.sock
dweebui:
container_name: dweebui
image: lllllllillllllillll/dweebui:v0.08
# build:
# context: .
environment:
NODE_ENV: production
PORT: 8000
SECRET: MrWiskers
#Proxy_Manager: enabled
restart: unless-stopped
ports:
- 8000:8000
volumes:
- dweebui:/app
- caddyfiles:/app/caddyfiles
- /var/run/docker.sock:/var/run/docker.sock
#- ./custom-templates.json:/app/custom-templates.json
#- ./composefiles:/app/composefiles
networks:
- dweeb_network
volumes:
  dweebui:
  caddyfiles:
dweebui:
caddyfiles:
networks:
dweeb_network:
driver: bridge
```

* Using setup.sh:
Compose setup:

* Paste the above content into a file named ```docker-compose.yml``` then place it in a folder named ```dweebui```.
* Open a terminal in the ```dweebui``` folder, then enter ```docker compose up -d```.
* You may need to use ```docker-compose up -d``` or execute the command as root with either ```sudo docker compose up -d``` or ```sudo docker-compose up -d```.


Using setup.sh:
```
Extract DweebUI.zip and navigate to /DweebUI
cd DweebUI
Expand All @@ -68,8 +92,9 @@ sudo ./setup.sh
```


## Credit
## Credits

* Dockerode and dockerode-compose by Apocas: https://github.com/apocas/dockerode
* UI was built using HTML and CSS elements from https://tabler.io/
* Apps template based on Portainer template provided by Lissy93: https://github.com/Lissy93/portainer-templates
* Icons from Walkxcode with some renames and additions: https://github.com/walkxcode/dashboard-icons
* Icons from Walkxcode with some renames and additions: https://github.com/walkxcode/dashboard-icons
35 changes: 33 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ const PORT = process.env.PORT || 8000;
const routes = require("./routes");

// Functions and variables
const { serverStats, containerList, containerStats, containerAction, containerLogs } = require('./functions/system');
const { serverStats, containerList, containerStats, containerAction, containerLogs, hiddenContainers } = require('./functions/system');
let sentList, clicked;
app.locals.site_list = '';

const Containers = require('./database/ContainerSettings');


// Configure Session
const sessionMiddleware = session({
secret: "keyboard cat",
Expand All @@ -36,7 +39,7 @@ app.use([

// Start Express server
const server = app.listen(PORT, async () => {
console.log(`App listening on port ${PORT}`);
console.log(`App listening on port ${PORT}`);
});

// Start Socket.io
Expand Down Expand Up @@ -90,11 +93,39 @@ io.on('connection', (socket) => {
clicked = false;
});


socket.on('hide', async (data) => {
console.log(`Hide ${data.container}`);

let containerExists = await Containers.findOne({ where: {name:data.container}});

if(!containerExists){
const container = await Containers.create({
name: data.container,
visibility: false
});
hiddenContainers();
console.log(`[Created] Container ${data.container} hidden`)
} else {
containerExists.update({ visibility: false });
console.log(`[Updated] Container ${data.container} hidden`)
hiddenContainers();
}
});

socket.on('reset', (data) => {
// set visibility to true for all containers
Containers.update({ visibility: true }, { where: {} });
console.log('All containers visible');
hiddenContainers();
});


// Container logs
socket.on('logs', (data) => {
containerLogs(data.container)
.then(logs => {
console.log(`Refreshed logs for ${data.container}`)
socket.emit('logString', logs);
})
.catch(err => {
Expand Down
46 changes: 34 additions & 12 deletions components/dashCard.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
module.exports.dashCard = function dashCard(data) {

let { name, service, id, state, image, external_port, internal_port, ports, volumes, environment_variables, labels } = data;

let { name, service, id, state, image, external_port, internal_port, ports, volumes, environment_variables, labels, IPv4, style } = data;

let margin, iconSize, fontSize = '';

if (style == "Large") {
iconSize = 'width="150px"'
} else if ((style == "Compact") || (style == undefined)) {
iconSize = 'width="100px"'
margin = 'style="margin-bottom: 0;"'
} else if (style == "Row") {
iconSize = 'width="50px"'
margin = 'style="margin-bottom: 0;"'
}


//disable controls for a docker container depending on its name
let enabled = "";
if (name.startsWith('Dweeb')) {
enabled = 'disabled=""';
let actions = "";
if (name.startsWith('dweebui')) {
actions = 'disabled=""';
}

if ( external_port == undefined ) { external_port = 0; }
Expand Down Expand Up @@ -115,23 +128,23 @@ module.exports.dashCard = function dashCard(data) {
<div class="card">
<div class="card-body">
<div class="card-stamp card-stamp-sm">
<img heigh="150px" width="150px" src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI-Icons/main/${service}.png" onerror="this.onerror=null;this.src='https://raw.githubusercontent.com/lllllllillllllillll/DweebUI-Icons/main/dweebui.png';"></img>
<img ${iconSize} src="https://raw.githubusercontent.com/lllllllillllllillll/DweebUI-Icons/main/${service}.png" onerror="this.onerror=null;this.src='https://raw.githubusercontent.com/lllllllillllllillll/DweebUI-Icons/main/docker.png';"></img>
</div>
<div class="d-flex align-items-center">
<div class="subheader text-yellow">${external_port}:${internal_port}</div>
<div class="ms-auto lh-1">
<div class="card-actions btn-actions">
<div class="card-actions btn-actions">
<button onclick="buttonAction(this)" name="${name}" value="start" id="${state}" class="btn-action" title="Start" ${enabled}><!-- player-play -->
<button onclick="buttonAction(this)" name="${name}" value="start" id="${state}" class="btn-action" title="Start" ${actions}><!-- player-play -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-player-play" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7 4v16l13 -8z"></path></svg>
</button>
<button onclick="buttonAction(this)" name="${name}" value="stop" id="${state}" class="btn-action" title="Stop" ${enabled}><!-- player-stop -->
<button onclick="buttonAction(this)" name="${name}" value="stop" id="${state}" class="btn-action" title="Stop" ${actions}><!-- player-stop -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-player-stop" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M5 5m0 2a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v10a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2z"></path></svg>
</button>
<button onclick="buttonAction(this)" name="${name}" value="pause" id="${state}" class="btn-action" title="Pause" ${enabled}><!-- player-pause -->
<button onclick="buttonAction(this)" name="${name}" value="pause" id="${state}" class="btn-action" title="Pause" ${actions}><!-- player-pause -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-player-pause" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M6 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path><path d="M14 5m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v12a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path></svg>
</button>
<button onclick="buttonAction(this)" name="${name}" value="restart" id="${state}" class="btn-action" title="Restart" ${enabled}><!-- reload -->
<button onclick="buttonAction(this)" name="${name}" value="restart" id="${state}" class="btn-action" title="Restart" ${actions}><!-- reload -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-reload" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M19.933 13.041a8 8 0 1 1 -9.925 -8.788c3.899 -1 7.935 1.007 9.425 4.747"></path><path d="M20 4v5h-5"></path></svg>
</button>
<div class="dropdown">
Expand All @@ -146,13 +159,22 @@ module.exports.dashCard = function dashCard(data) {
<a class="dropdown-item text-danger" data-bs-toggle="modal" data-bs-target="#${name}_modal-danger" href="#">Remove</a>
</div>
</div>
<div class="dropdown">
<a href="#" class="btn-action dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><!-- Download SVG icon from http://tabler-icons.io/i/dots-vertical -->
<svg xmlns="http://www.w3.org/2000/svg" class="icon-tabler icon-tabler-eye" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"/> <path d="M10 12a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /> <path d="M21 12c-2.4 4 -5.4 6 -9 6c-3.6 0 -6.6 -2 -9 -6c2.4 -4 5.4 -6 9 -6c3.6 0 6.6 2 9 6" /> </svg>
</a>
<div class="dropdown-menu dropdown-menu-end">
<a class="dropdown-item" onclick="hideContainer(this)" name="${name}" href="#">Hide</a>
<a class="dropdown-item" onclick="resetView()" name="${name}" href="#">Reset View</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="d-flex align-items-baseline">
<div class="h1 me-2" title="${name}">
<a href="http://localhost:${external_port}" target="_blank">
<div class="h1 me-2" title="${name}" ${margin}>
<a href="http://${IPv4}:${external_port}" target="_blank">
${shortened_name}
</a>
</div>
Expand Down
19 changes: 0 additions & 19 deletions compose.yaml

This file was deleted.

14 changes: 6 additions & 8 deletions controllers/apps.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
const User = require('../database/UserModel');
const { appCard } = require('../components/appCard')
const { dashCard } = require('../components/dashCard');

const { install, uninstall } = require('../functions/package_manager');

// import { install, uninstall } from '../functions/package_manager';

const templates_json = require('../templates.json');
let templates = templates_json.templates;

Expand All @@ -18,23 +15,24 @@ templates = templates.sort((a, b) => {


exports.Apps = async function(req, res) {

if (req.session.role == "admin") {

// Get the user.
let user = await User.findOne({ where: { UUID: req.session.UUID }});

let page = Number(req.query.page) || 1;
let page = Number(req.params.page) || 1;
let list_start = (page - 1) * 28;
let list_end = (page * 28);
let last_page = Math.ceil(templates.length / 28);

let prev = '/apps?page=' + (page - 1);
let next = '/apps?page=' + (page + 1);
let prev = '/apps/' + (page - 1);
let next = '/apps/' + (page + 1);
if (page == 1) {
prev = '/apps?page=' + (page);
prev = '/apps/' + (page);
}
if (page == last_page) {
next = '/apps?page=' + (page);
next = '/apps/' + (page);
}

let apps_list = '';
Expand Down
4 changes: 2 additions & 2 deletions controllers/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ exports.Register = function(req,res){
exports.processRegister = async function(req,res){

// Get the data.
let { first_name, last_name, username, email, password, avatar, tos } = req.body;
let { first_name, last_name, username, email, password, avatar, tos, secret } = req.body;
let role = "user";

// Check the data.
if(first_name && last_name && email && password && username && tos){
if((first_name && last_name && email && password && username && tos) && (secret == process.env.SECRET)){

// Check if there is an existing user with that username.
let existingUser = await User.findOne({ where: {username:username}});
Expand Down
2 changes: 2 additions & 0 deletions controllers/dashboard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const User = require('../database/UserModel');
const Containers = require('../database/ContainerSettings');

const { readFileSync, writeFileSync, appendFileSync, readdirSync } = require('fs');
const { execSync } = require("child_process");
const { siteCard } = require('../components/siteCard');
Expand Down
Loading

0 comments on commit bc10e26

Please sign in to comment.