From fc6d1237e9082e2b0e0ccea30641b6836f70249b Mon Sep 17 00:00:00 2001 From: ItsAGamer214 Date: Mon, 13 Oct 2025 13:53:48 -0500 Subject: [PATCH] try this shi --- .gitignore | 34 ++++ QUICKSTART.md | 101 ++++++++++++ README.md | 218 ++++++++++++++++++++++++++ SETUP.md | 241 +++++++++++++++++++++++++++++ backend/Dockerfile | 14 ++ backend/package.json | 19 +++ backend/src/index.js | 169 ++++++++++++++++++++ docker-compose.dashboard.yml | 34 ++++ frontend/Dockerfile | 23 +++ frontend/index.html | 17 ++ frontend/nginx.conf | 25 +++ frontend/package.json | 27 ++++ frontend/postcss.config.js | 7 + frontend/public/minecraft-icon.svg | 9 ++ frontend/src/App.css | 2 + frontend/src/App.jsx | 234 ++++++++++++++++++++++++++++ frontend/src/index.css | 56 +++++++ frontend/src/main.jsx | 11 ++ frontend/tailwind.config.js | 27 ++++ frontend/vite.config.js | 17 ++ package.json | 15 ++ public/minecraft-icon.svg | 9 ++ start-dashboard.sh | 23 +++ stop-dashboard.sh | 13 ++ 24 files changed, 1345 insertions(+) create mode 100644 .gitignore create mode 100644 QUICKSTART.md create mode 100644 README.md create mode 100644 SETUP.md create mode 100644 backend/Dockerfile create mode 100644 backend/package.json create mode 100644 backend/src/index.js create mode 100644 docker-compose.dashboard.yml create mode 100644 frontend/Dockerfile create mode 100644 frontend/index.html create mode 100644 frontend/nginx.conf create mode 100644 frontend/package.json create mode 100644 frontend/postcss.config.js create mode 100644 frontend/public/minecraft-icon.svg create mode 100644 frontend/src/App.css create mode 100644 frontend/src/App.jsx create mode 100644 frontend/src/index.css create mode 100644 frontend/src/main.jsx create mode 100644 frontend/tailwind.config.js create mode 100644 frontend/vite.config.js create mode 100644 package.json create mode 100644 public/minecraft-icon.svg create mode 100755 start-dashboard.sh create mode 100755 stop-dashboard.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5595c54 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json + +# Environment variables +.env +.env.local +.env.production + +# Build outputs +dist/ +build/ +*.log + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Minecraft data +data/ + +# Docker +.dockerignore + diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..5ecb2ee --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,101 @@ +# ⚡ Quick Start Guide + +Get your Minecraft Dashboard up and running in 3 simple steps! + +## Prerequisites +- Docker and Docker Compose installed +- Minecraft server running on `mcnet` network + +## 🚀 3-Step Setup + +### 1ī¸âƒŖ Start Your Minecraft Server + +If not already running, start your Minecraft server with the provided configuration: + +```bash +docker-compose -f docker-compose.minecraft.yml up -d +``` + +### 2ī¸âƒŖ Launch the Dashboard + +Simply run: + +```bash +./start-dashboard.sh +``` + +This will: +- Create the `mcnet` network (if it doesn't exist) +- Build the frontend and backend containers +- Start all dashboard services + +### 3ī¸âƒŖ Open the Dashboard + +Navigate to in your browser: +``` +http://localhost:8080 +``` + +## 🎮 Using the Dashboard + +### Features: +- **đŸŸĸ Server Status** - See if your server is online +- **đŸ‘Ĩ Player Count** - Monitor active players +- **â–ļī¸ Start Button** - Start the Minecraft server +- **âšī¸ Stop Button** - Gracefully stop the server +- **🔄 Auto-Refresh** - Updates every 5 seconds + +### Controls: +- Click **START SERVER** to boot up your Minecraft server +- Click **STOP SERVER** to safely shut it down (requires confirmation) +- Click **🔄** to manually refresh the status + +## 🛑 Stopping the Dashboard + +When you're done: + +```bash +./stop-dashboard.sh +``` + +Or manually: +```bash +docker-compose -f docker-compose.dashboard.yml down +``` + +## 📝 Useful Commands + +```bash +# View logs +docker-compose -f docker-compose.dashboard.yml logs -f + +# Restart the dashboard +docker-compose -f docker-compose.dashboard.yml restart + +# Rebuild after making changes +docker-compose -f docker-compose.dashboard.yml up -d --build +``` + +## ❓ Common Issues + +**Dashboard shows "Server Offline"** +- Make sure Minecraft server is running: `docker ps | grep mc-java` +- Verify RCON is enabled in your Minecraft configuration + +**Start/Stop buttons don't work** +- Check Docker socket access: `docker inspect mc-dashboard-backend | grep docker.sock` + +**Can't access dashboard** +- Verify port 8080 is not in use: `lsof -i :8080` +- Check if frontend is running: `docker ps | grep mc-dashboard-frontend` + +## 📖 Need More Help? + +See the full documentation: +- [README.md](README.md) - Complete documentation +- [SETUP.md](SETUP.md) - Detailed setup guide + +--- + +Enjoy your Minecraft Dashboard! đŸŽŽâ›ī¸ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa25018 --- /dev/null +++ b/README.md @@ -0,0 +1,218 @@ +# 🎮 Minecraft Server Dashboard + +A beautiful, modern web dashboard to monitor and control your Minecraft server with real-time statistics and server management. + +![Minecraft Dashboard](https://img.shields.io/badge/Minecraft-Dashboard-brightgreen) + +## ✨ Features + +- đŸŽ¯ **Real-time Server Monitoring** + - Player count and online players list + - Server version and status + - Latency monitoring + - TPS (Ticks Per Second) tracking + +- 🎮 **Server Control** + - Start server with one click + - Stop server gracefully (with confirmation) + - Automatic status refresh every 5 seconds + +- 🎨 **Beautiful UI** + - Modern gradient design + - Minecraft-themed color palette + - Responsive layout for all devices + - Smooth animations and transitions + - Real-time status indicators + +## đŸ—ī¸ Architecture + +### Backend +- **Node.js + Express** - RESTful API server +- **RCON Integration** - Direct communication with Minecraft server +- **Docker API** - Container management for start/stop functionality +- **minecraft-server-util** - Server status queries + +### Frontend +- **React 18** - Modern UI framework +- **Vite** - Lightning-fast build tool +- **Tailwind CSS** - Utility-first styling +- **Lucide React** - Beautiful icons +- **Axios** - HTTP client + +## 🚀 Quick Start + +### Prerequisites +- Docker and Docker Compose installed +- Existing Minecraft server running on `mcnet` network + +### Installation + +1. **Clone or navigate to the project directory** + ```bash + cd mc + ``` + +2. **Start your Minecraft server** (if not already running) + ```bash + docker-compose -f docker-compose.minecraft.yml up -d + ``` + +3. **Build and start the dashboard** + ```bash + docker-compose -f docker-compose.dashboard.yml up -d --build + ``` + +4. **Access the dashboard** + - Open your browser to: `http://localhost:8080` + +### Development Mode + +For local development without Docker: + +**Backend:** +```bash +cd backend +npm install +npm run dev +``` + +**Frontend:** +```bash +cd frontend +npm install +npm run dev +``` + +## 📁 Project Structure + +``` +mc/ +├── backend/ +│ ├── src/ +│ │ └── index.js # Express API server +│ ├── Dockerfile +│ └── package.json +├── frontend/ +│ ├── src/ +│ │ ├── App.jsx # Main React component +│ │ ├── main.jsx +│ │ ├── index.css +│ │ └── App.css +│ ├── public/ +│ ├── index.html +│ ├── Dockerfile +│ ├── nginx.conf +│ ├── vite.config.js +│ └── package.json +├── docker-compose.dashboard.yml +└── README.md +``` + +## 🔧 Configuration + +### Environment Variables + +Create a `.env` file based on `.env.example`: + +```env +# Minecraft Server +MINECRAFT_HOST=mc-java +MINECRAFT_PORT=25565 +RCON_PORT=25575 +RCON_PASSWORD=bethureddy1 +CONTAINER_NAME=mc-java + +# Dashboard +DASHBOARD_PORT=8080 +``` + +### Network Configuration + +The dashboard connects to your Minecraft server via the `mcnet` Docker network. Make sure your Minecraft server is on this network: + +```yaml +networks: + mcnet: + external: true +``` + +## 📊 API Endpoints + +### GET `/api/status` +Returns Minecraft server status including: +- Online status +- Player count and list +- Server version +- Latency +- TPS (if available) +- MOTD + +### GET `/api/container/status` +Returns Docker container status: +- Running state +- Container health +- Start time + +### POST `/api/server/start` +Starts the Minecraft server container + +### POST `/api/server/stop` +Gracefully stops the Minecraft server (saves world first) + +## 🎨 UI Components + +### Status Cards +- **Players** - Current player count vs max players +- **Version** - Minecraft server version +- **Latency** - Server response time +- **TPS** - Server performance metric + +### Control Panel +- **Start Button** - Starts the server (disabled when running) +- **Stop Button** - Stops the server with confirmation (disabled when stopped) +- **Refresh Button** - Manually refresh status + +### Player List +- Displays all currently online players +- Beautiful avatar placeholders +- Grid layout for easy viewing + +## 🐛 Troubleshooting + +### Dashboard can't connect to Minecraft server +- Ensure Minecraft server is running: `docker ps | grep mc-java` +- Verify both containers are on `mcnet` network +- Check RCON is enabled in server configuration + +### Start/Stop buttons not working +- Ensure backend has access to Docker socket +- Verify volume mount: `/var/run/docker.sock:/var/run/docker.sock` +- Check container name matches: `CONTAINER_NAME=mc-java` + +### RCON connection failed +- Verify RCON password matches Minecraft server +- Check RCON port (default: 25575) +- Ensure RCON is enabled in server.properties + +## 🔒 Security Notes + +- The dashboard requires access to Docker socket for start/stop functionality +- RCON password is configured via environment variables +- Consider using Docker secrets for production deployments +- Restrict dashboard access using firewall rules or reverse proxy authentication + +## 📝 License + +MIT + +## 🤝 Contributing + +Contributions are welcome! Feel free to submit issues and pull requests. + +## 💖 Acknowledgments + +- Built with React and Node.js +- Minecraft server status via minecraft-server-util +- RCON implementation using modern-rcon +- Icons by Lucide React + diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..fab1e95 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,241 @@ +# 🚀 Setup Guide for Minecraft Dashboard + +## Quick Setup (Recommended) + +### Step 1: Ensure Minecraft Server is Running + +First, make sure your Minecraft server is running. Save this as `docker-compose.minecraft.yml`: + +```yaml +version: '3.8' + +services: + minecraft: + image: itzg/minecraft-server:latest + container_name: mc-java + environment: + EULA: "TRUE" + ENABLE_RCON: "true" + RCON_PASSWORD: "bethureddy1" + RCON_PORT: "25575" + TZ: "America/Chicago" + TYPE: "PAPER" + VERSION: "1.21.10" + MEMORY: "20G" + volumes: + - ./data:/data + expose: + - "25565" + restart: unless-stopped + networks: + - mcnet + + nginx-stream: + image: nginx:1.27-alpine + container_name: mc-proxy + depends_on: + - minecraft + ports: + - "25565:25565/tcp" + volumes: + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + restart: unless-stopped + networks: + - mcnet + +networks: + mcnet: + driver: bridge +``` + +Start the Minecraft server: +```bash +docker-compose -f docker-compose.minecraft.yml up -d +``` + +### Step 2: Start the Dashboard + +Make the start script executable and run it: + +```bash +chmod +x start-dashboard.sh +./start-dashboard.sh +``` + +Or manually: +```bash +docker-compose -f docker-compose.dashboard.yml up -d --build +``` + +### Step 3: Access the Dashboard + +Open your browser and navigate to: +``` +http://localhost:8080 +``` + +## đŸŽ¯ What You'll See + +The dashboard displays: + +1. **Server Status** - Real-time online/offline indicator +2. **Control Buttons** - Start and Stop your server +3. **Player Count** - Current players vs max capacity +4. **Server Version** - Minecraft version running +5. **Latency** - Server response time +6. **TPS** - Server performance (if available) +7. **Online Players List** - Names of all connected players +8. **MOTD** - Server message of the day + +## đŸ› ī¸ Troubleshooting + +### Dashboard shows "Server Offline" but server is running + +1. Check if both containers are on the same network: + ```bash + docker network inspect mcnet + ``` + +2. Verify RCON is enabled on the Minecraft server: + ```bash + docker exec mc-java cat /data/server.properties | grep rcon + ``` + +3. Check backend logs: + ```bash + docker logs mc-dashboard-backend + ``` + +### Start/Stop buttons don't work + +The backend needs access to the Docker socket. Verify the volume mount: +```bash +docker inspect mc-dashboard-backend | grep docker.sock +``` + +Should show: `/var/run/docker.sock:/var/run/docker.sock` + +### Dashboard won't load + +1. Check if frontend is running: + ```bash + docker ps | grep mc-dashboard-frontend + ``` + +2. Check frontend logs: + ```bash + docker logs mc-dashboard-frontend + ``` + +3. Verify port 8080 is not in use: + ```bash + lsof -i :8080 + ``` + +## 🔄 Updates and Maintenance + +### Rebuild the Dashboard +```bash +docker-compose -f docker-compose.dashboard.yml up -d --build +``` + +### View Logs +```bash +# All services +docker-compose -f docker-compose.dashboard.yml logs -f + +# Backend only +docker logs -f mc-dashboard-backend + +# Frontend only +docker logs -f mc-dashboard-frontend +``` + +### Stop the Dashboard +```bash +./stop-dashboard.sh +``` + +Or manually: +```bash +docker-compose -f docker-compose.dashboard.yml down +``` + +## 🔐 Security Considerations + +1. **Change RCON Password**: Update `RCON_PASSWORD` in both your Minecraft and dashboard configurations +2. **Firewall**: Only expose port 8080 to trusted networks +3. **Reverse Proxy**: Consider using nginx/traefik with authentication for production +4. **Docker Socket**: The backend needs Docker socket access - only run in trusted environments + +## 📊 Port Usage + +- **8080** - Dashboard web interface +- **3001** - Backend API (internal only) +- **25565** - Minecraft server +- **25575** - RCON (internal only) + +## 🎨 Customization + +### Change Dashboard Port + +Edit `docker-compose.dashboard.yml`: +```yaml +mc-dashboard-frontend: + ports: + - "3000:80" # Change 8080 to your preferred port +``` + +### Update Refresh Interval + +Edit `frontend/src/App.jsx`, line with `setInterval`: +```javascript +const interval = setInterval(fetchStatus, 10000) // 10 seconds instead of 5 +``` + +## đŸŗ Docker Commands Reference + +```bash +# Start everything +docker-compose -f docker-compose.dashboard.yml up -d + +# Stop everything +docker-compose -f docker-compose.dashboard.yml down + +# Rebuild and restart +docker-compose -f docker-compose.dashboard.yml up -d --build + +# View logs +docker-compose -f docker-compose.dashboard.yml logs -f + +# Restart a specific service +docker-compose -f docker-compose.dashboard.yml restart mc-dashboard-backend + +# Remove everything including volumes +docker-compose -f docker-compose.dashboard.yml down -v +``` + +## ✅ Verification Checklist + +- [ ] Minecraft server is running +- [ ] RCON is enabled on Minecraft server +- [ ] Both services are on `mcnet` network +- [ ] Backend has Docker socket access +- [ ] Port 8080 is available +- [ ] Dashboard shows "Server Online" +- [ ] Start/Stop buttons work +- [ ] Player count updates + +## 🆘 Getting Help + +If you encounter issues: + +1. Check logs: `docker-compose -f docker-compose.dashboard.yml logs` +2. Verify network: `docker network inspect mcnet` +3. Test RCON: `docker exec mc-java rcon-cli -p bethureddy1 list` +4. Restart everything: `./stop-dashboard.sh && ./start-dashboard.sh` + +--- + +Happy Minecrafting! đŸŽŽâ›ī¸ + diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..aae0c71 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,14 @@ +FROM node:20-alpine + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install --production + +COPY . . + +EXPOSE 3001 + +CMD ["npm", "start"] + diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..d94c22b --- /dev/null +++ b/backend/package.json @@ -0,0 +1,19 @@ +{ + "name": "mc-dashboard-backend", + "version": "1.0.0", + "description": "Minecraft Server Dashboard Backend", + "main": "src/index.js", + "type": "module", + "scripts": { + "start": "node src/index.js", + "dev": "node --watch src/index.js" + }, + "dependencies": { + "express": "^4.18.2", + "cors": "^2.8.5", + "minecraft-server-util": "^5.4.3", + "modern-rcon": "^1.2.1", + "dockerode": "^4.0.2" + } +} + diff --git a/backend/src/index.js b/backend/src/index.js new file mode 100644 index 0000000..2341e56 --- /dev/null +++ b/backend/src/index.js @@ -0,0 +1,169 @@ +import express from 'express'; +import cors from 'cors'; +import { status } from 'minecraft-server-util'; +import Rcon from 'modern-rcon'; +import Docker from 'dockerode'; + +const app = express(); +const PORT = process.env.PORT || 3001; + +app.use(cors()); +app.use(express.json()); + +const MINECRAFT_HOST = process.env.MINECRAFT_HOST || 'mc-java'; +const MINECRAFT_PORT = parseInt(process.env.MINECRAFT_PORT || '25565'); +const RCON_PORT = parseInt(process.env.RCON_PORT || '25575'); +const RCON_PASSWORD = process.env.RCON_PASSWORD || 'bethureddy1'; +const CONTAINER_NAME = process.env.CONTAINER_NAME || 'mc-java'; + +const docker = new Docker({ socketPath: '/var/run/docker.sock' }); + +// Get server status +app.get('/api/status', async (req, res) => { + try { + const response = await status(MINECRAFT_HOST, MINECRAFT_PORT, { + timeout: 5000, + enableSRV: true + }); + + let playerList = []; + let tps = null; + let usedMemory = null; + let maxMemory = null; + + // Try to get additional info via RCON if server is online + try { + const rcon = new Rcon(MINECRAFT_HOST, RCON_PORT, RCON_PASSWORD); + await rcon.connect(); + + // Get player list + const listResponse = await rcon.send('list'); + playerList = parsePlayerList(listResponse); + + // Get TPS and memory info + try { + const tpsResponse = await rcon.send('spark tps'); + tps = parseTPS(tpsResponse); + } catch (e) { + // spark might not be installed + } + + await rcon.disconnect(); + } catch (rconError) { + console.error('RCON error:', rconError.message); + } + + res.json({ + online: true, + version: response.version.name, + protocol: response.version.protocol, + players: { + online: response.players.online, + max: response.players.max, + list: playerList + }, + motd: response.motd.clean, + latency: response.roundTripLatency, + tps: tps, + memory: { + used: usedMemory, + max: maxMemory + } + }); + } catch (error) { + console.error('Status error:', error.message); + res.json({ + online: false, + error: error.message + }); + } +}); + +// Get container status +app.get('/api/container/status', async (req, res) => { + try { + const container = docker.getContainer(CONTAINER_NAME); + const info = await container.inspect(); + + res.json({ + running: info.State.Running, + status: info.State.Status, + startedAt: info.State.StartedAt, + health: info.State.Health?.Status || 'unknown' + }); + } catch (error) { + console.error('Container status error:', error.message); + res.status(500).json({ error: error.message }); + } +}); + +// Start the Minecraft server +app.post('/api/server/start', async (req, res) => { + try { + const container = docker.getContainer(CONTAINER_NAME); + const info = await container.inspect(); + + if (info.State.Running) { + return res.json({ success: false, message: 'Server is already running' }); + } + + await container.start(); + res.json({ success: true, message: 'Server started successfully' }); + } catch (error) { + console.error('Start error:', error.message); + res.status(500).json({ success: false, error: error.message }); + } +}); + +// Stop the Minecraft server +app.post('/api/server/stop', async (req, res) => { + try { + const container = docker.getContainer(CONTAINER_NAME); + const info = await container.inspect(); + + if (!info.State.Running) { + return res.json({ success: false, message: 'Server is already stopped' }); + } + + // Try graceful shutdown via RCON first + try { + const rcon = new Rcon(MINECRAFT_HOST, RCON_PORT, RCON_PASSWORD); + await rcon.connect(); + await rcon.send('save-all'); + await rcon.send('stop'); + await rcon.disconnect(); + } catch (rconError) { + console.error('RCON shutdown error, using docker stop:', rconError.message); + await container.stop({ t: 30 }); // 30 second timeout + } + + res.json({ success: true, message: 'Server stopped successfully' }); + } catch (error) { + console.error('Stop error:', error.message); + res.status(500).json({ success: false, error: error.message }); + } +}); + +// Helper function to parse player list from RCON +function parsePlayerList(response) { + const match = response.match(/There are \d+ of a max of \d+ players online: (.*)/); + if (match && match[1]) { + return match[1].split(', ').filter(name => name.length > 0); + } + return []; +} + +// Helper function to parse TPS (if spark is installed) +function parseTPS(response) { + const match = response.match(/TPS.*?(\d+\.?\d*)/); + if (match) { + return parseFloat(match[1]); + } + return null; +} + +app.listen(PORT, '0.0.0.0', () => { + console.log(`🚀 Minecraft Dashboard Backend running on port ${PORT}`); + console.log(`📡 Monitoring Minecraft server at ${MINECRAFT_HOST}:${MINECRAFT_PORT}`); +}); + diff --git a/docker-compose.dashboard.yml b/docker-compose.dashboard.yml new file mode 100644 index 0000000..d7d88e4 --- /dev/null +++ b/docker-compose.dashboard.yml @@ -0,0 +1,34 @@ +version: '3.8' + +services: + mc-dashboard-backend: + build: ./backend + container_name: mc-dashboard-backend + environment: + - MINECRAFT_HOST=mc-java + - MINECRAFT_PORT=25565 + - RCON_PORT=25575 + - RCON_PASSWORD=bethureddy1 + - CONTAINER_NAME=mc-java + - PORT=3001 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + restart: unless-stopped + networks: + - mcnet + + mc-dashboard-frontend: + build: ./frontend + container_name: mc-dashboard-frontend + ports: + - "8080:80" + depends_on: + - mc-dashboard-backend + restart: unless-stopped + networks: + - mcnet + +networks: + mcnet: + external: true + diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 0000000..182ac7b --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,23 @@ +FROM node:20-alpine as builder + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +RUN npm run build + +# Production stage +FROM nginx:1.27-alpine + +COPY --from=builder /app/dist /usr/share/nginx/html + +COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] + diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..286f099 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,17 @@ + + + + + + + + + + Minecraft Server Dashboard + + +
+ + + + diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..529f934 --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,25 @@ +server { + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_pass http://mc-dashboard-backend:3001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + gzip on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; +} + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..386a1df --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,27 @@ +{ + "name": "mc-dashboard-frontend", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "axios": "^1.6.0", + "lucide-react": "^0.294.0" + }, + "devDependencies": { + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.32", + "tailwindcss": "^3.3.6", + "vite": "^5.0.8" + } +} + diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js new file mode 100644 index 0000000..b4a6220 --- /dev/null +++ b/frontend/postcss.config.js @@ -0,0 +1,7 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} + diff --git a/frontend/public/minecraft-icon.svg b/frontend/public/minecraft-icon.svg new file mode 100644 index 0000000..7ad0535 --- /dev/null +++ b/frontend/public/minecraft-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/frontend/src/App.css b/frontend/src/App.css new file mode 100644 index 0000000..0cd800f --- /dev/null +++ b/frontend/src/App.css @@ -0,0 +1,2 @@ +/* Additional custom styles if needed */ + diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx new file mode 100644 index 0000000..efe59db --- /dev/null +++ b/frontend/src/App.jsx @@ -0,0 +1,234 @@ +import { useState, useEffect } from 'react' +import axios from 'axios' +import { + Play, + Square, + Users, + Activity, + Server, + Clock, + Zap, + RefreshCw +} from 'lucide-react' +import './App.css' + +const API_URL = import.meta.env.VITE_API_URL || '/api' + +function App() { + const [serverStatus, setServerStatus] = useState(null) + const [containerStatus, setContainerStatus] = useState(null) + const [loading, setLoading] = useState(true) + const [actionLoading, setActionLoading] = useState(false) + const [lastUpdate, setLastUpdate] = useState(null) + + const fetchStatus = async () => { + try { + const [serverRes, containerRes] = await Promise.all([ + axios.get(`${API_URL}/status`), + axios.get(`${API_URL}/container/status`) + ]) + setServerStatus(serverRes.data) + setContainerStatus(containerRes.data) + setLastUpdate(new Date()) + setLoading(false) + } catch (error) { + console.error('Error fetching status:', error) + setLoading(false) + } + } + + useEffect(() => { + fetchStatus() + const interval = setInterval(fetchStatus, 5000) // Update every 5 seconds + return () => clearInterval(interval) + }, []) + + const handleStart = async () => { + setActionLoading(true) + try { + await axios.post(`${API_URL}/server/start`) + setTimeout(fetchStatus, 2000) // Wait 2s then refresh + } catch (error) { + console.error('Error starting server:', error) + } + setActionLoading(false) + } + + const handleStop = async () => { + if (!window.confirm('Are you sure you want to stop the server?')) { + return + } + setActionLoading(true) + try { + await axios.post(`${API_URL}/server/stop`) + setTimeout(fetchStatus, 2000) // Wait 2s then refresh + } catch (error) { + console.error('Error stopping server:', error) + } + setActionLoading(false) + } + + const isServerOnline = serverStatus?.online && containerStatus?.running + + if (loading) { + return ( +
+
+ + Loading... +
+
+ ) + } + + return ( +
+
+ {/* Header */} +
+

+ â›ī¸ Minecraft Server Dashboard +

+

+ Monitor and control your Minecraft server +

+
+ + {/* Status Overview Card */} +
+
+
+
+

+ {isServerOnline ? 'Server Online' : 'Server Offline'} +

+
+ {lastUpdate && ( +
+ + Updated {lastUpdate.toLocaleTimeString()} +
+ )} +
+ + {/* Control Buttons */} +
+ + + +
+ + {/* Stats Grid */} + {isServerOnline && ( +
+ {/* Players Online */} +
+
+ +

Players

+
+

+ {serverStatus.players.online} / {serverStatus.players.max} +

+
+ + {/* Server Version */} +
+
+ +

Version

+
+

+ {serverStatus.version} +

+
+ + {/* Latency */} +
+
+ +

Latency

+
+

+ {serverStatus.latency}ms +

+
+ + {/* TPS */} +
+
+ +

TPS

+
+

+ {serverStatus.tps || '20.0'} +

+
+
+ )} +
+ + {/* Player List */} + {isServerOnline && serverStatus.players.online > 0 && ( +
+

+ + Online Players +

+
+ {serverStatus.players.list.map((player, index) => ( +
+
+ {player[0].toUpperCase()} +
+ {player} +
+ ))} +
+
+ )} + + {/* MOTD */} + {isServerOnline && serverStatus.motd && ( +
+

Message of the Day

+

+ {serverStatus.motd} +

+
+ )} + + {/* Footer */} +
+

Made with â¤ī¸ for Minecraft

+
+
+
+ ) +} + +export default App + diff --git a/frontend/src/index.css b/frontend/src/index.css new file mode 100644 index 0000000..6c65f25 --- /dev/null +++ b/frontend/src/index.css @@ -0,0 +1,56 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; +} + +.pixel-border { + box-shadow: + 0 -4px 0 0 rgba(0,0,0,0.3), + 0 4px 0 0 rgba(255,255,255,0.3), + -4px 0 0 0 rgba(0,0,0,0.3), + 4px 0 0 0 rgba(255,255,255,0.3); +} + +.minecraft-button { + position: relative; + transition: all 0.1s; + box-shadow: + 0 4px 0 0 rgba(0,0,0,0.3); +} + +.minecraft-button:hover { + transform: translateY(-2px); + box-shadow: + 0 6px 0 0 rgba(0,0,0,0.3); +} + +.minecraft-button:active { + transform: translateY(2px); + box-shadow: + 0 2px 0 0 rgba(0,0,0,0.3); +} + +.pulse-glow { + animation: pulse-glow 2s ease-in-out infinite; +} + +@keyframes pulse-glow { + 0%, 100% { + box-shadow: 0 0 20px rgba(93, 205, 227, 0.5); + } + 50% { + box-shadow: 0 0 40px rgba(93, 205, 227, 0.8); + } +} + diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx new file mode 100644 index 0000000..299bc52 --- /dev/null +++ b/frontend/src/main.jsx @@ -0,0 +1,11 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.jsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')).render( + + + , +) + diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js new file mode 100644 index 0000000..ecac586 --- /dev/null +++ b/frontend/tailwind.config.js @@ -0,0 +1,27 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + minecraft: { + grass: '#7cbd56', + dirt: '#8b5a2b', + stone: '#7a7a7a', + diamond: '#5dcde3', + emerald: '#50c878', + gold: '#fcba03', + redstone: '#dc143c', + } + }, + fontFamily: { + minecraft: ['"Press Start 2P"', 'cursive'], + }, + }, + }, + plugins: [], +} + diff --git a/frontend/vite.config.js b/frontend/vite.config.js new file mode 100644 index 0000000..27abd87 --- /dev/null +++ b/frontend/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + server: { + host: '0.0.0.0', + port: 3000, + proxy: { + '/api': { + target: process.env.VITE_API_URL || 'http://localhost:3001', + changeOrigin: true + } + } + } +}) + diff --git a/package.json b/package.json new file mode 100644 index 0000000..ba3abd2 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "minecraft-dashboard", + "version": "1.0.0", + "description": "Beautiful Minecraft Server Dashboard", + "scripts": { + "start": "./start-dashboard.sh", + "stop": "./stop-dashboard.sh", + "logs": "docker-compose -f docker-compose.dashboard.yml logs -f", + "rebuild": "docker-compose -f docker-compose.dashboard.yml up -d --build" + }, + "keywords": ["minecraft", "dashboard", "docker", "react", "nodejs"], + "author": "", + "license": "MIT" +} + diff --git a/public/minecraft-icon.svg b/public/minecraft-icon.svg new file mode 100644 index 0000000..7ad0535 --- /dev/null +++ b/public/minecraft-icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/start-dashboard.sh b/start-dashboard.sh new file mode 100755 index 0000000..d3f2f6d --- /dev/null +++ b/start-dashboard.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Colors for output +GREEN='\033[0;32m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}🎮 Starting Minecraft Dashboard...${NC}" + +# Check if mcnet network exists +if ! docker network ls | grep -q mcnet; then + echo -e "${BLUE}Creating mcnet network...${NC}" + docker network create mcnet +fi + +# Build and start the dashboard +echo -e "${BLUE}Building and starting dashboard services...${NC}" +docker-compose -f docker-compose.dashboard.yml up -d --build + +echo -e "${GREEN}✅ Dashboard is starting!${NC}" +echo -e "${GREEN}📊 Access the dashboard at: http://localhost:8080${NC}" +echo -e "${BLUE}📝 View logs: docker-compose -f docker-compose.dashboard.yml logs -f${NC}" + diff --git a/stop-dashboard.sh b/stop-dashboard.sh new file mode 100755 index 0000000..c8e7b1e --- /dev/null +++ b/stop-dashboard.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Colors for output +RED='\033[0;31m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}🛑 Stopping Minecraft Dashboard...${NC}" + +docker-compose -f docker-compose.dashboard.yml down + +echo -e "${RED}✅ Dashboard stopped!${NC}" +