{"id":50724830,"url":"https://github.com/glyndor/panel","last_synced_at":"2026-06-10T03:02:51.715Z","repository":{"id":357475859,"uuid":"1236899680","full_name":"Glyndor/panel","owner":"Glyndor","description":"Self-hosted VPS \u0026 container manager — cPanel/Plesk/Coolify alternative. Podman, nftables, WireGuard. Rust + Next.js.","archived":false,"fork":false,"pushed_at":"2026-06-04T22:44:34.000Z","size":7069,"stargazers_count":1,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T00:08:56.679Z","etag":null,"topics":["caprover-alternative","container-management","coolify-alternative","cpanel-alternative","devops","docker-alternative","dokploy-alternative","firewall","nextjs","nftables","paas","plesk-alternative","podman","postgresql","rust","self-hosted","vps","wireguard"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Glyndor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["Jaro-c"]}},"created_at":"2026-05-12T17:20:28.000Z","updated_at":"2026-06-04T21:42:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/Glyndor/panel","commit_stats":null,"previous_names":["jaro-c/lynx","glyndor/panel"],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/Glyndor/panel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glyndor%2Fpanel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glyndor%2Fpanel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glyndor%2Fpanel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glyndor%2Fpanel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Glyndor","download_url":"https://codeload.github.com/Glyndor/panel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Glyndor%2Fpanel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34134634,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caprover-alternative","container-management","coolify-alternative","cpanel-alternative","devops","docker-alternative","dokploy-alternative","firewall","nextjs","nftables","paas","plesk-alternative","podman","postgresql","rust","self-hosted","vps","wireguard"],"created_at":"2026-06-10T03:02:49.917Z","updated_at":"2026-06-10T03:02:51.699Z","avatar_url":"https://github.com/Glyndor.png","language":"Rust","funding_links":["https://github.com/sponsors/Jaro-c"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"lynx/dashboard/ui/public/logo.webp\" alt=\"Lynx\" width=\"140\" /\u003e\u003cbr /\u003e\u003cbr /\u003e\n\n  # Lynx\n\n  **Self-hosted VPS \u0026 container manager.**\u003cbr /\u003e\n  Containers · Firewall · VPN — from one dashboard, across any number of servers.\n\n  \u003cbr /\u003e\n\n  [![CI — Dashboard](https://github.com/Glyndor/panel/actions/workflows/dashboard-server.yml/badge.svg)](https://github.com/Glyndor/panel/actions/workflows/dashboard-server.yml)\n  ![Rust](https://img.shields.io/badge/Agent-Rust-orange?logo=rust)\n  ![Next.js](https://img.shields.io/badge/Dashboard-Next.js-black?logo=next.js)\n\n  \u003cbr /\u003e\n\n  [Install](#-install) · [Architecture](#-architecture) · [vs Alternatives](#-vs-alternatives) · [Security](#-security)\n\n\u003c/div\u003e\n\n---\n\n\u003e **The cPanel/Plesk/Coolify alternative built for people who care about security.**  \n\u003e One binary per VPS. All traffic encrypted over WireGuard. No SaaS. No cloud lock-in. No Docker daemon.\n\n---\n\n## ✨ Features\n\n**📦 Containers** — Podman rootless, per-organization isolation, survive VPS reboots without Lynx running  \n**🔥 Firewall** — Full nftables control from the dashboard, three-layer hierarchy, atomic apply, auto-restore on any tampering  \n**🔒 Networking** — All dashboard → agent traffic over WireGuard + mTLS. Cross-VPS scaling via direct agent tunnels — no relay through dashboard  \n**🔑 Encryption** — PostgreSQL AES-256 at rest (pg_tde) + per-user envelope encryption (KEK/DEK)  \n**📁 Single binary** — No runtime dependencies on the server. No Node.js, no Bun, no Docker Engine. Install one binary, uninstall one binary  \n**🔄 Auto-update** — Hourly GitHub Releases check, Ed25519 signature verification before any swap, automatic rollback if the new binary fails to start\n\n---\n\n## 🏗 Architecture\n\n```\nDashboard VPS\n├── Frontend ── Next.js (compiled binary, no runtime)\n├── Backend  ── Rust\n│    ├── WireGuard ──► Agent (local, same VPS)\n│    ├── WireGuard ──► Agent (remote VPS #1)\n│    └── WireGuard ──► Agent (remote VPS #2)\n│\n└── Each agent: Podman + nftables + WireGuard\n```\n\nEach agent connects to the dashboard over a **1:1 WireGuard tunnel** with its own PSK. Agents never talk to each other through the dashboard — cross-VPS scaling uses direct agent-to-agent tunnels.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eFirewall hierarchy (nftables)\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n```\ntable inet lynx-agent {\n    chain lynx-base    ← Lynx invariants. Never editable. Auto-restored instantly on any change.\n    chain lynx-global  ← Rules pushed to ALL agents simultaneously\n    chain lynx-local   ← Per-VPS rules for this agent only\n}\n```\n\n- **`lynx-base`** — default deny, WireGuard allowlist, inter-org isolation, anti-spoofing\n- **`lynx-global`** — IP blocklists, protocol restrictions — propagated to all agents in parallel; agents offline receive pending rules on reconnect\n- **`lynx-local`** — per-VPS port rules, IP allowlists\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eHorizontal scaling — cross-VPS\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n```\nInternet → 80/443\n    ↓\nlynx-nginx (Agent-1, entry point)\n    ├── replica:1  (Agent-1, local Podman network)\n    └── WireGuard ──► Agent-2\n                          ├── replica:2\n                          └── replica:3\n```\n\nAgent-2 never exposes public ports for the project. All traffic enters through Agent-1 via WireGuard.\n\n\u003c/details\u003e\n\n---\n\n## ⚡ Install\n\n### Dashboard\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/Glyndor/panel/main/install.sh | sudo bash\n```\n\nThe installer handles everything:\n1. Detects and removes incompatible software (Docker, firewalld, ufw, iptables)\n2. Installs Podman, WireGuard, nftables\n3. Generates all secrets — never written to disk in plaintext\n4. Starts PostgreSQL → Redis → Backend → Frontend\n5. Prints a one-time setup URL:\n   ```\n   https://YOUR-IP:19443/register?setup_token=\u003ctoken\u003e\n   ```\n\n### Agent (additional VPS)\n\n1. Dashboard → **Connect new VPS** → copy the displayed keypair + PSK\n2. On the new VPS, run the same installer and paste the dashboard data when prompted\n3. Done — the tunnel is up and the agent appears online in the dashboard\n\n### Requirements\n\n| | |\n|---|---|\n| **OS** | Ubuntu 22.04+, Debian 12+, Fedora 39+, CentOS/RHEL 9+, Rocky/AlmaLinux 9+ |\n| **SSH port** | Auto-detected — any port works |\n| **Fixed ports** | `19443/TCP` (dashboard) · `51820/UDP` (WireGuard) — opened automatically. Must be free and allowed by your VPS provider's external firewall if applicable. |\n| **Root access** | Required for install |\n\n---\n\n## 🆚 vs Alternatives\n\n| | **Lynx** | Coolify | Dokploy | cPanel / Plesk |\n|---|---|---|---|---|\n| Container runtime | Podman (rootless) | Docker | Docker | varies |\n| Firewall management | ✅ Full nftables | ❌ | ❌ | Partial |\n| VPN between servers | ✅ WireGuard | ❌ | ❌ | ❌ |\n| Encryption at rest | ✅ AES-256 (pg_tde) | ❌ | ❌ | ❌ |\n| Per-user encryption | ✅ KEK/DEK | ❌ | ❌ | ❌ |\n| Signed binary updates | ✅ Ed25519 | ❌ | ❌ | ❌ |\n| Runtime dependencies | None | Docker Engine | Docker Engine | Heavy |\n| Pricing | Free / self-hosted | Free tier + paid | Free / self-hosted | Paid license |\n| SaaS / cloud | Never | Optional | Optional | Optional |\n\n---\n\n## 🔐 Security\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eTransport \u0026amp; cryptography\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n- **WireGuard + mTLS** — double-layer encryption on all dashboard ↔ agent traffic\n- **TLS 1.3 minimum** — no TLS 1.0/1.1/1.2 accepted anywhere\n- **Ed25519** — JWT signing, agent command signing, and binary update verification\n- **Per-agent PSK** — each tunnel has its own unique preshared key, rotated automatically\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSigned commands \u0026amp; immutable audit log\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\nEvery command the dashboard sends to an agent is Ed25519-signed. The agent verifies signature, nonce (replay prevention), and timestamp (\u003c 30s window) before executing anything.\n\nAll executed and rejected commands are stored in a **hash-chained append-only audit log** on the agent, synced to dashboard PostgreSQL in real time. Tampering with any entry is mathematically detectable.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eReporting a vulnerability\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\nSee the [security policy](https://github.com/Glyndor/panel/security/policy) and\nthe [security architecture](docs/security-architecture.md) for threat modeling.\n\n\u003c/details\u003e\n\n---\n\n## 🛠 Development\n\nContribution model, branch flow and code style live in the\n[organization contributing guide](https://github.com/Glyndor/.github/blob/main/CONTRIBUTING.md).\nRepo-specific setup:\n\n**Dashboard backend (Rust):**\n\n```bash\ncd lynx\nSQLX_OFFLINE=true cargo build -p lynx-dashboard-server\nSQLX_OFFLINE=true cargo test -p lynx-dashboard-server\n```\n\n`sqlx` compile-time checks use the committed `.sqlx` cache. To run against a\nreal database, see `lynx/dashboard/server/.env` and start PostgreSQL locally.\n\n**Dashboard frontend (Next.js):**\n\n```bash\ncd lynx/dashboard/ui\nbun install\nbun dev\n```\n\n**Shell lint:** `bash scripts/lint.sh` (shellcheck on all `.sh` files).\n\nThe agent and the compose translator live in\n[panel-agent](https://github.com/Glyndor/panel-agent) and\n[podup](https://github.com/Glyndor/podup).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eVM test matrix\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\nSome features cannot be tested in CI (nftables, WireGuard, Podman, systemd).\nChanges in these areas require local VMs — note in your PR which scenarios you ran:\n\n| Area | Environment |\n|------|-------------|\n| nftables rules, divergence detection | VM local |\n| WireGuard tunnel setup, PSK rotation | VM local (CAP_NET_ADMIN) |\n| Podman containers, org isolation | VM local |\n| Auto-update binary swap | VM local |\n| Installation + incompatible software | VM local |\n| Dashboard ↔ agent connectivity | 2 VMs |\n| Migration (dashboard or agent) | 2–3 VMs |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eOut of scope — do not contribute\u003c/strong\u003e\u003c/summary\u003e\n\u003cbr /\u003e\n\n- Docker support — incompatible by design (nftables/network isolation conflict)\n- Rollback / downgrade mechanisms — hotfix + auto-update is the model\n- Metrics persistence — metrics are real-time WebSocket only\n- SMTP integration — not planned\n- Changes that break backwards compatibility of migrations (additive-only)\n\n\u003c/details\u003e\n\n---\n\n## 📄 License\n\n[Apache-2.0](LICENSE) — © 2026 [Glyndor](https://github.com/Glyndor)\n\n\u003cdiv align=\"center\"\u003e\n  \u003cbr /\u003e\n  \u003csub\u003eMade with ❤️ by \u003ca href=\"https://github.com/Jaro-c\"\u003eJaroc\u003c/a\u003e\u003c/sub\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglyndor%2Fpanel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fglyndor%2Fpanel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fglyndor%2Fpanel/lists"}