I Built a Free Alternative to cPanel - Here's What I Learned
Source: Dev.to

The Problem
Last year I was managing a handful of WordPress sites and a few Python apps for clients. My options were:
- cPanel – $45/month per server. For 3 servers, that’s $1,620 /year just for a control panel.
- Coolify – Great for Docker but felt like overkill for WordPress sites. I don’t need Kubernetes.
- CloudPanel – Nice and lightweight but no Docker support. I need both.
- HestiaCP – Free and feature‑rich but the UI looks like it’s from 2008.
I wanted something in between: the simplicity of traditional hosting panels with the power of modern deployment tools. So I built ServerKit.
What is ServerKit?
ServerKit is an open‑source server management panel that lets you:
- Deploy WordPress, Flask, Django, and Node.js apps
- Manage Docker containers alongside traditional apps
- Automatic HTTPS via Let’s Encrypt
- Real‑time monitoring with alerts to Discord/Slack/Telegram
- Visual firewall and cron‑job management
- 2FA security with ClamAV malware scanning

The Tech Stack
Backend
- Python 3.11 with Flask
- SQLAlchemy ORM
- Flask‑SocketIO for real‑time updates
- Gunicorn for production
Frontend
- React 18 with Vite
- WebSocket connection for live metrics
- LESS for styling
Infrastructure
- Nginx reverse proxy
- Let’s Encrypt via Certbot
- Docker & Docker Compose
- MySQL/PostgreSQL support
Architecture Decisions
Why Flask over FastAPI?
FastAPI is great for pure APIs, but ServerKit needs:
- WebSocket support (Flask‑SocketIO is mature)
- Template rendering for some pages
- Simpler debugging during development
Real‑Time Metrics
Every second, the backend collects:
metrics = {
'cpu': psutil.cpu_percent(),
'memory': psutil.virtual_memory().percent,
'disk': psutil.disk_usage('/').percent,
'network': get_network_stats()
}
socketio.emit('metrics', metrics, broadcast=True)
The React frontend subscribes and updates the dashboard live—no polling, no page refreshes.
Dynamic Nginx Configuration
Each app type has a Jinja2 template, e.g. for a PHP app:
# PHP app nginx config
server {
listen 80;
server_name {{ app.domain }};
root {{ app.path }}/public;
location ~ \.php$ {
fastcgi_pass unix:/run/php/php{{ app.php_version }}-fpm.sock;
# ...
}
}
When you create an app, ServerKit generates the config, symlinks it, and reloads Nginx.
What I Learned
-
Start with the UI – I built the backend first and regretted it. Users see the interface, not the API. Begin with mockups, validate the UX, then build the backend to support it.
-
Security is non‑negotiable – Server management panels are high‑value targets. From day one:
- JWT with short expiration
- TOTP 2FA with backup codes
- All secrets encrypted at rest
- No shell commands built from user input
-
Real‑time feels premium – Static dashboards feel dead. Adding WebSocket‑based live metrics made the app feel 10× more polished with relatively little code.
-
Don’t reinvent everything – I use:
- Certbot for SSL (don’t roll your own ACME)
- ClamAV for malware (don’t write an antivirus)
- systemd for service management (it works)
Focus on the glue, not the components.
Try It
One‑line install
curl -fsSL https://raw.githubusercontent.com/jhd3197/ServerKit/main/install.sh | bash
Or with Docker
git clone https://github.com/jhd3197/ServerKit.git
cd ServerKit
docker compose up -d
GitHub:
MIT licensed, no telemetry, no cloud dependency.
What features would make this useful for you? Drop a comment – I read everything.