airlinklabs/panel

Airlink, Open-source game server management that actually works -_-

TypeScript

68

940 commits

updated Sep 30, 2026

See the code

See what people are saying

SourceMessageScoreDate

Airlink, an open-source game server panel I'm building as a Pterodactyl alternative (r/selfhosted)

I've been building an open-source game server management panel called **Airlink**. The goal isn't to clone Pterodactyl feature-for-feature. I want to build a panel that is easier to understand, easier to extend, and gives both administrators and users a clean interface for managing game servers.…

1

Sep 30, 2026

README

[!CAUTION]

⚠️ THIS SOFTWARE IS HIGHLY UNSTABLE — DO NOT USE IN PRODUCTION ⚠️

Airlink Panel is in early BETA. Expect breaking changes, data loss, security vulnerabilities, and incomplete features with every update. APIs, database schemas, configuration formats, and stored data may change without notice between releases.

This is a development preview only. We are not responsible for any data loss, security incidents, or damages resulting from use of this software. If you need a stable game server panel today, this is not it.

AIRLINK

Airlink Panel (Katharos) BETA v2.5.191

Open-source game server management panel

TypeScript Prisma Node.js Docker Tailwind CSS PostgreSQL Redis

License Discord GitHub Stars GitHub Forks GitHub Issues GitHub Pull Requests GitHub last commit CI

Website · Documentation · Discord · Report a Bug · Request a Feature


Airlink Panel is a web-based control panel for deploying, monitoring, and managing game servers across multiple machines. It communicates with daemons on each node to handle Docker containers, files, and SFTP.

Core features:

  • Web UI for admins and users (EJS templates, Tailwind CSS, Alpine.js, HTMX)
  • Node-based architecture: one panel controlling many daemons
  • Addon system for extending functionality without touching core files
  • REST API (v2) with scoped API keys and HMAC-signed daemon communication
  • Real-time console, file manager, backups, and SFTP
  • Server creation, power controls, and resource management
  • User management with 2FA and WebAuthn passkey support
  • Analytics and player stats
  • Multi-language support (i18n) — 10 languages
  • Redis-backed sessions with user-index revocation
  • Node.js cluster mode (auto-forks per CPU core)
  • CSP headers with per-request nonces (configurable)
  • TLS direct HTTPS support
  • Configurable rate limiting

Documentation: airlinklabs.xyz/docs/quick-start/


Prerequisites

  • Node.js v22 or later
  • pnpm v11 or later (npm install -g pnpm)
  • Git
  • Docker
  • Redis (default: 127.0.0.1:6379)
  • PostgreSQL (default: 127.0.0.1:5432)

[!NOTE] MariaDB/MySQL is no longer supported. The database engine was migrated to PostgreSQL.


Installation

Option 1: Installer script

sudo su
bash <(curl -s https://raw.githubusercontent.com/airlinklabs/panel/refs/heads/main/installer.sh)

The installer handles Node.js, Docker, PostgreSQL, Redis, database setup, build, and systemd service registration.

cd /var/www/
git clone https://github.com/AirlinkLabs/panel.git
cd panel
node public/scripts/setup.mjs
pnpm run start

Setup flags:

FlagDescription
--yes, -yNon-interactive mode (accepts all defaults)
--skip-servicesDon't install or start Redis / PostgreSQL
--skip-buildDon't run package install, tsc, or tailwindcss
--db-host HOSTPostgreSQL host (default: 127.0.0.1)
--db-port PORTPostgreSQL port (default: 5432)
--db-name NAMEDatabase name (default: airlink)
--db-user USERDatabase username (default: airlink)
--redis-url URLRedis URL (default: redis://127.0.0.1:6379)
--url URLPanel public URL (default: http://localhost:3000)
--trust-proxyEnable X-Forwarded-* headers
--cookie-domain DOMAINCookie domain for cross-subdomain sessions
--asset-base-url URLBase URL for static assets (CDN)
--csp-enabledForce Content Security Policy on
--rate-limit MAXRequest rate limit per IP (default: 500)
--log-level LEVELLog level (default: info)
--smtp-host HOSTSMTP server host
--smtp-port PORTSMTP server port (default: 587)
--smtp-user USERSMTP username
--smtp-pass PASSSMTP password

Examples:

node public/scripts/setup.mjs                          # Interactive
node public/scripts/setup.mjs --yes                    # CI / unattended
node public/scripts/setup.mjs --skip-services --db-host=db.internal --yes

Option 3: Manual

cd /var/www/
git clone https://github.com/AirlinkLabs/panel.git
cd panel

cp example.env .env
# Edit .env with your values (see Configuration below)

pnpm install
npx prisma generate
npx prisma db push
pnpm run build
pnpm run start

Running with systemd

systemctl start airlink-panel
systemctl stop airlink-panel
systemctl restart airlink-panel
journalctl -u airlink-panel -f

Running with pm2

npm install -g pm2
pm2 start "pnpm run start" --name airlink-panel
pm2 save
pm2 startup

Configuration

Copy example.env to .env and configure the values for your environment.

Core

VariableRequiredDefaultDescription
URLYeshttp://localhost:3000Full URL the panel is accessible from
PORTNo3000Port to listen on
NAMENoAirlinkPanel display name
NODE_ENVNodevelopmentSet to production for live deployments
SESSION_SECRETYes—Random secret for session signing. Generate with openssl rand -hex 32
STORAGE_DIRNo./storageBase directory for all panel data

Database (PostgreSQL)

VariableRequiredDefaultDescription
DATABASE_URLYes—PostgreSQL connection string
PGHOSTNo127.0.0.1PostgreSQL host
PGPORTNo5432PostgreSQL port
PGUSERNoairlinkPostgreSQL username
PGPASSWORDNo—PostgreSQL password

[!IMPORTANT] DATABASE_URL must use the postgresql:// scheme. MariaDB/MySQL is no longer supported.

Redis

VariableRequiredDefaultDescription
REDIS_URLNoredis://127.0.0.1:6379Redis connection string

Proxy & Security

VariableRequiredDefaultDescription
TRUST_PROXYNofalseEnable X-Forwarded-* headers (required behind reverse proxies)
COOKIE_DOMAINNo—Cookie domain for cross-subdomain sessions
ALLOWED_ORIGINSNo—Comma-separated list of allowed CORS origins
CSP_ENABLEDNofalseForce Content Security Policy headers on

TLS (Direct HTTPS)

VariableRequiredDefaultDescription
TLS_CERT_PATHNo—Path to TLS certificate file
TLS_KEY_PATHNo—Path to TLS private key file

When both are set, the panel starts an HTTPS server directly (with HTTP fallback). Otherwise, use a reverse proxy.

Rate Limiting

VariableRequiredDefaultDescription
RATE_LIMIT_MAXNo500Max requests per window per IP
RATE_LIMIT_WINDOW_MSNo60000Rate limit window in milliseconds

SMTP (Email)

VariableRequiredDefaultDescription
SMTP_HOSTNo—SMTP server hostname
SMTP_PORTNo587SMTP server port
SMTP_USERNo—SMTP username
SMTP_PASSNo—SMTP password

Logging

VariableRequiredDefaultDescription
LOG_LEVELNoinfoLog level (debug, info, warn, error)

[!IMPORTANT] Set URL to the actual IP or hostname the panel is accessible from. Using http://localhost will block external access and cause CSP errors.


Architecture

Stack

LayerTechnology
RuntimeNode.js 22+ (cluster mode)
LanguageTypeScript (CommonJS output)
FrameworkExpress 5
TemplatingEJS + Alpine.js + HTMX
StylingTailwind CSS v4
ORMPrisma 7
DatabasePostgreSQL
Cache / SessionsRedis
Container runtimeDocker (via node-docker-api)

Redis Usage

  • Sessions: Stored in Redis (airlink:sess:*) with a user index (airlink:usr:{id}) for admin revocation
  • Node health cache: checkNodeStatus results cached 15s per node
  • Search cache: /api/search results cached 30s per user+query
  • Realtime events: Pub/sub for live console output and server status updates

Directory Structure

panel/
├── src/                  # TypeScript source
│   ├── config/           # Configuration (mime, auth, limits, etc.)
│   ├── handlers/         # Middleware, utilities, realtime
│   ├── modules/          # Route handlers (admin, api, auth, user)
│   ├── services/         # Business logic (backup, daemon, file, i18n)
│   ├── types/            # TypeScript type definitions
│   └── utils/            # Shared utilities
├── views/                # EJS templates
│   ├── admin/            # Admin panel views
│   ├── auth/             # Login, register, 2FA
│   ├── components/       # Shared UI components
│   └── user/             # User dashboard, server management
├── public/               # Static assets
│   ├── javascript/       # Client-side JS + vendor bundles
│   ├── styles/           # CSS (Tailwind input)
│   └── scripts/          # Setup / install scripts
├── storage/              # Runtime data
│   ├── prisma/           # Schema + migrations
│   ├── lang/             # i18n translation files (10 languages)
│   └── addons/           # Addon storage
├── tests/                # Vitest unit tests + Docker test infra
│   └── docker/           # Dockerfile, entrypoint.sh, docker-compose.test.yml
├── docs/                 # API spec and documentation
└── .github/workflows/    # CI pipeline (10 jobs)

Scripts

CommandDescription
pnpm run devStart with auto-restart on file changes
pnpm run buildProduction build (tsc + tailwindcss)
pnpm run startStart the panel (node --env-file=.env dist/app.js)
pnpm run typecheckType checking
pnpm run lintESLint
pnpm run testRun unit tests (Vitest)
pnpm run test:watchRun tests in watch mode
pnpm run test:coverageRun tests with coverage
pnpm run test:e2eRun Playwright e2e tests
pnpm run test:dockerRun tests in Docker (PostgreSQL + Redis)
pnpm run test:allRun unit + e2e tests
pnpm run db:generateGenerate Prisma client
pnpm run db:pushPush schema to database
pnpm run db:migrateCreate and apply a migration
pnpm run db:migrate:deployApply pending migrations
pnpm run db:resetReset database and reapply migrations
pnpm run db:studioOpen Prisma Studio
pnpm run db:statusShow migration status
pnpm run db:seedSeed initial data

API Reference

The panel exposes a REST API with 138 HTTP routes and 4 WebSocket endpoints. See docs/specsheet.md for the full route catalog, request/response formats, authentication details, and notes on daemon communication.


Addon System

Addons let you extend the panel without modifying core files. They live under storage/addons/ and can be managed from the /admin/addons page.

See storage/addons/README.md for the structure and API reference.


Testing

Unit tests use Vitest. E2e tests use Playwright.

pnpm run test              # Run all unit tests
pnpm run test:e2e          # Run e2e tests (requires Chromium)
pnpm run test:docker       # Run full test suite in Docker

Tests mock Redis and database connections where needed. The CI pipeline runs all checks across 10 jobs: SAST, Dependency Review, Audit, Lint, Typecheck, Unit Tests, Build, and more.


Development

pnpm install
pnpm run dev        # Start with auto-restart on file changes
pnpm run typecheck  # Type checking
pnpm run lint       # Linting
pnpm run build      # Production build

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Commit your changes: git commit -m 'feat: describe your change'
  4. Push and open a pull request against main

Please run pnpm run lint and pnpm run typecheck before submitting.


Star History

Star History Chart


Project Leads

AvatarHandleRole
thavanishMaintainer
privt00Project Lead
achul123Core Developer

Contributors

Contributions of all sizes are welcome. Take a look at the open issues if you're not sure where to start.

Contributors

Made with contrib.rocks



License

MIT. See LICENSE for details.

Made by the Airlink community
airlink
alternative
client
daemon
docker
game-panel
panel
pterodactyl
tailwindcss
typescript

airlinklabs/panel

Airlink, Open-source game server management that actually works -_-

TypeScript

68

940 commits

updated Sep 30, 2026

See the code

See what people are saying

SourceMessageScoreDate

Airlink, an open-source game server panel I'm building as a Pterodactyl alternative (r/selfhosted)

I've been building an open-source game server management panel called **Airlink**. The goal isn't to clone Pterodactyl feature-for-feature. I want to build a panel that is easier to understand, easier to extend, and gives both administrators and users a clean interface for managing game servers.…

1

Sep 30, 2026

README

[!CAUTION]

⚠️ THIS SOFTWARE IS HIGHLY UNSTABLE — DO NOT USE IN PRODUCTION ⚠️

Airlink Panel is in early BETA. Expect breaking changes, data loss, security vulnerabilities, and incomplete features with every update. APIs, database schemas, configuration formats, and stored data may change without notice between releases.

This is a development preview only. We are not responsible for any data loss, security incidents, or damages resulting from use of this software. If you need a stable game server panel today, this is not it.

AIRLINK

Airlink Panel (Katharos) BETA v2.5.191

Open-source game server management panel

TypeScript Prisma Node.js Docker Tailwind CSS PostgreSQL Redis

License Discord GitHub Stars GitHub Forks GitHub Issues GitHub Pull Requests GitHub last commit CI

Website · Documentation · Discord · Report a Bug · Request a Feature


Airlink Panel is a web-based control panel for deploying, monitoring, and managing game servers across multiple machines. It communicates with daemons on each node to handle Docker containers, files, and SFTP.

Core features:

  • Web UI for admins and users (EJS templates, Tailwind CSS, Alpine.js, HTMX)
  • Node-based architecture: one panel controlling many daemons
  • Addon system for extending functionality without touching core files
  • REST API (v2) with scoped API keys and HMAC-signed daemon communication
  • Real-time console, file manager, backups, and SFTP
  • Server creation, power controls, and resource management
  • User management with 2FA and WebAuthn passkey support
  • Analytics and player stats
  • Multi-language support (i18n) — 10 languages
  • Redis-backed sessions with user-index revocation
  • Node.js cluster mode (auto-forks per CPU core)
  • CSP headers with per-request nonces (configurable)
  • TLS direct HTTPS support
  • Configurable rate limiting

Documentation: airlinklabs.xyz/docs/quick-start/


Prerequisites

  • Node.js v22 or later
  • pnpm v11 or later (npm install -g pnpm)
  • Git
  • Docker
  • Redis (default: 127.0.0.1:6379)
  • PostgreSQL (default: 127.0.0.1:5432)

[!NOTE] MariaDB/MySQL is no longer supported. The database engine was migrated to PostgreSQL.


Installation

Option 1: Installer script

sudo su
bash <(curl -s https://raw.githubusercontent.com/airlinklabs/panel/refs/heads/main/installer.sh)

The installer handles Node.js, Docker, PostgreSQL, Redis, database setup, build, and systemd service registration.

cd /var/www/
git clone https://github.com/AirlinkLabs/panel.git
cd panel
node public/scripts/setup.mjs
pnpm run start

Setup flags:

FlagDescription
--yes, -yNon-interactive mode (accepts all defaults)
--skip-servicesDon't install or start Redis / PostgreSQL
--skip-buildDon't run package install, tsc, or tailwindcss
--db-host HOSTPostgreSQL host (default: 127.0.0.1)
--db-port PORTPostgreSQL port (default: 5432)
--db-name NAMEDatabase name (default: airlink)
--db-user USERDatabase username (default: airlink)
--redis-url URLRedis URL (default: redis://127.0.0.1:6379)
--url URLPanel public URL (default: http://localhost:3000)
--trust-proxyEnable X-Forwarded-* headers
--cookie-domain DOMAINCookie domain for cross-subdomain sessions
--asset-base-url URLBase URL for static assets (CDN)
--csp-enabledForce Content Security Policy on
--rate-limit MAXRequest rate limit per IP (default: 500)
--log-level LEVELLog level (default: info)
--smtp-host HOSTSMTP server host
--smtp-port PORTSMTP server port (default: 587)
--smtp-user USERSMTP username
--smtp-pass PASSSMTP password

Examples:

node public/scripts/setup.mjs                          # Interactive
node public/scripts/setup.mjs --yes                    # CI / unattended
node public/scripts/setup.mjs --skip-services --db-host=db.internal --yes

Option 3: Manual

cd /var/www/
git clone https://github.com/AirlinkLabs/panel.git
cd panel

cp example.env .env
# Edit .env with your values (see Configuration below)

pnpm install
npx prisma generate
npx prisma db push
pnpm run build
pnpm run start

Running with systemd

systemctl start airlink-panel
systemctl stop airlink-panel
systemctl restart airlink-panel
journalctl -u airlink-panel -f

Running with pm2

npm install -g pm2
pm2 start "pnpm run start" --name airlink-panel
pm2 save
pm2 startup

Configuration

Copy example.env to .env and configure the values for your environment.

Core

VariableRequiredDefaultDescription
URLYeshttp://localhost:3000Full URL the panel is accessible from
PORTNo3000Port to listen on
NAMENoAirlinkPanel display name
NODE_ENVNodevelopmentSet to production for live deployments
SESSION_SECRETYes—Random secret for session signing. Generate with openssl rand -hex 32
STORAGE_DIRNo./storageBase directory for all panel data

Database (PostgreSQL)

VariableRequiredDefaultDescription
DATABASE_URLYes—PostgreSQL connection string
PGHOSTNo127.0.0.1PostgreSQL host
PGPORTNo5432PostgreSQL port
PGUSERNoairlinkPostgreSQL username
PGPASSWORDNo—PostgreSQL password

[!IMPORTANT] DATABASE_URL must use the postgresql:// scheme. MariaDB/MySQL is no longer supported.

Redis

VariableRequiredDefaultDescription
REDIS_URLNoredis://127.0.0.1:6379Redis connection string

Proxy & Security

VariableRequiredDefaultDescription
TRUST_PROXYNofalseEnable X-Forwarded-* headers (required behind reverse proxies)
COOKIE_DOMAINNo—Cookie domain for cross-subdomain sessions
ALLOWED_ORIGINSNo—Comma-separated list of allowed CORS origins
CSP_ENABLEDNofalseForce Content Security Policy headers on

TLS (Direct HTTPS)

VariableRequiredDefaultDescription
TLS_CERT_PATHNo—Path to TLS certificate file
TLS_KEY_PATHNo—Path to TLS private key file

When both are set, the panel starts an HTTPS server directly (with HTTP fallback). Otherwise, use a reverse proxy.

Rate Limiting

VariableRequiredDefaultDescription
RATE_LIMIT_MAXNo500Max requests per window per IP
RATE_LIMIT_WINDOW_MSNo60000Rate limit window in milliseconds

SMTP (Email)

VariableRequiredDefaultDescription
SMTP_HOSTNo—SMTP server hostname
SMTP_PORTNo587SMTP server port
SMTP_USERNo—SMTP username
SMTP_PASSNo—SMTP password

Logging

VariableRequiredDefaultDescription
LOG_LEVELNoinfoLog level (debug, info, warn, error)

[!IMPORTANT] Set URL to the actual IP or hostname the panel is accessible from. Using http://localhost will block external access and cause CSP errors.


Architecture

Stack

LayerTechnology
RuntimeNode.js 22+ (cluster mode)
LanguageTypeScript (CommonJS output)
FrameworkExpress 5
TemplatingEJS + Alpine.js + HTMX
StylingTailwind CSS v4
ORMPrisma 7
DatabasePostgreSQL
Cache / SessionsRedis
Container runtimeDocker (via node-docker-api)

Redis Usage

  • Sessions: Stored in Redis (airlink:sess:*) with a user index (airlink:usr:{id}) for admin revocation
  • Node health cache: checkNodeStatus results cached 15s per node
  • Search cache: /api/search results cached 30s per user+query
  • Realtime events: Pub/sub for live console output and server status updates

Directory Structure

panel/
├── src/                  # TypeScript source
│   ├── config/           # Configuration (mime, auth, limits, etc.)
│   ├── handlers/         # Middleware, utilities, realtime
│   ├── modules/          # Route handlers (admin, api, auth, user)
│   ├── services/         # Business logic (backup, daemon, file, i18n)
│   ├── types/            # TypeScript type definitions
│   └── utils/            # Shared utilities
├── views/                # EJS templates
│   ├── admin/            # Admin panel views
│   ├── auth/             # Login, register, 2FA
│   ├── components/       # Shared UI components
│   └── user/             # User dashboard, server management
├── public/               # Static assets
│   ├── javascript/       # Client-side JS + vendor bundles
│   ├── styles/           # CSS (Tailwind input)
│   └── scripts/          # Setup / install scripts
├── storage/              # Runtime data
│   ├── prisma/           # Schema + migrations
│   ├── lang/             # i18n translation files (10 languages)
│   └── addons/           # Addon storage
├── tests/                # Vitest unit tests + Docker test infra
│   └── docker/           # Dockerfile, entrypoint.sh, docker-compose.test.yml
├── docs/                 # API spec and documentation
└── .github/workflows/    # CI pipeline (10 jobs)

Scripts

CommandDescription
pnpm run devStart with auto-restart on file changes
pnpm run buildProduction build (tsc + tailwindcss)
pnpm run startStart the panel (node --env-file=.env dist/app.js)
pnpm run typecheckType checking
pnpm run lintESLint
pnpm run testRun unit tests (Vitest)
pnpm run test:watchRun tests in watch mode
pnpm run test:coverageRun tests with coverage
pnpm run test:e2eRun Playwright e2e tests
pnpm run test:dockerRun tests in Docker (PostgreSQL + Redis)
pnpm run test:allRun unit + e2e tests
pnpm run db:generateGenerate Prisma client
pnpm run db:pushPush schema to database
pnpm run db:migrateCreate and apply a migration
pnpm run db:migrate:deployApply pending migrations
pnpm run db:resetReset database and reapply migrations
pnpm run db:studioOpen Prisma Studio
pnpm run db:statusShow migration status
pnpm run db:seedSeed initial data

API Reference

The panel exposes a REST API with 138 HTTP routes and 4 WebSocket endpoints. See docs/specsheet.md for the full route catalog, request/response formats, authentication details, and notes on daemon communication.


Addon System

Addons let you extend the panel without modifying core files. They live under storage/addons/ and can be managed from the /admin/addons page.

See storage/addons/README.md for the structure and API reference.


Testing

Unit tests use Vitest. E2e tests use Playwright.

pnpm run test              # Run all unit tests
pnpm run test:e2e          # Run e2e tests (requires Chromium)
pnpm run test:docker       # Run full test suite in Docker

Tests mock Redis and database connections where needed. The CI pipeline runs all checks across 10 jobs: SAST, Dependency Review, Audit, Lint, Typecheck, Unit Tests, Build, and more.


Development

pnpm install
pnpm run dev        # Start with auto-restart on file changes
pnpm run typecheck  # Type checking
pnpm run lint       # Linting
pnpm run build      # Production build

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Commit your changes: git commit -m 'feat: describe your change'
  4. Push and open a pull request against main

Please run pnpm run lint and pnpm run typecheck before submitting.


Star History

Star History Chart


Project Leads

AvatarHandleRole
thavanishMaintainer
privt00Project Lead
achul123Core Developer

Contributors

Contributions of all sizes are welcome. Take a look at the open issues if you're not sure where to start.

Contributors

Made with contrib.rocks



License

MIT. See LICENSE for details.

Made by the Airlink community
airlink
alternative
client
daemon
docker
game-panel
panel
pterodactyl
tailwindcss
typescript

Languages

TypeScript

72.8%

EJS

18.9%

JavaScript

4.5%

CSS

2.9%