Installation
AI Admin Panel installs on a fresh Linux server and sets up everything: Docker, PostgreSQL, Valkey, Traefik (auto-SSL), Keycloak (OIDC auth), and the panel itself.
Prerequisites
Server Requirements
| Requirement | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 4 GB | 8+ GB |
| Disk | 20 GB SSD | 50+ GB SSD |
| OS | Ubuntu 22.04, Ubuntu 24.04, Debian 12 | Ubuntu 24.04 |
| Architecture | x86_64 (amd64), aarch64 (arm64) | x86_64 |
DNS Requirements
Before installing, point your domain to the server:
- A record —
panel.example.com→ your server IP - Wildcard A record —
*.panel.example.com→ same server IP
The wildcard record is essential — every deployed service gets a subdomain like myapp.panel.example.com.
Tip: Cloudflare Users — Disable the orange proxy cloud during installation so Let's Encrypt can issue certificates via HTTP challenge. Re-enable it after setup if desired.
Network Requirements
| Port | Direction | Purpose |
|---|---|---|
| 80 | Inbound | HTTP → auto-redirects to HTTPS |
| 443 | Inbound | HTTPS (Traefik terminates SSL) |
| 22 | Inbound | SSH access |
No other services should be running on ports 80/443.
Automated Install
curl -fsSL https://get.aiadminpanel.com -o install.sh && bash install.sh
The installer will ask for your domain, then handle everything else automatically. At the end it prints your admin URL, email, and password.
To skip the prompt (CI/automation), set environment variables:
PANEL_DOMAIN="panel.example.com" ACME_EMAIL="admin@example.com" \ curl -fsSL https://get.aiadminpanel.com | bash
Installer Options
| Flag | Description |
|---|---|
--dry-run | Preview all actions without executing |
--verbose | Enable debug output |
--unattended | Non-interactive mode (requires PANEL_DOMAIN env var) |
Environment Variables
| Variable | Required | Description |
|---|---|---|
PANEL_DOMAIN | Yes | Base domain (e.g., panel.example.com) |
ACME_EMAIL | No | Email for Let's Encrypt (default: admin@example.com) |
CF_DNS_API_TOKEN | No | Cloudflare API token for wildcard certs and auto-DNS |
PANEL_VERSION | No | Version to install (default: latest) |
GOMEMLIMIT | No | Go memory limit (default: 0 = unlimited) |
Manual Install
If you prefer full control, follow these steps:
1. Install Docker
curl -fsSL https://get.docker.com | sh systemctl enable --now docker
Verify Docker 24+:
docker --version docker compose version
2. Create Directories and Secrets
# Create directories mkdir -p /opt/aiadminpanel /etc/aiadminpanel /var/log/aiadminpanel /run/secrets # Generate secrets dd if=/dev/urandom bs=32 count=1 2>/dev/null | xxd -p -c 64 > /run/secrets/master_key dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 -w0 | tr '+/' '-_' > /run/secrets/db_password dd if=/dev/urandom bs=32 count=1 2>/dev/null | base64 -w0 | tr '+/' '-_' > /run/secrets/keycloak_admin_password chmod 600 /run/secrets/*
3. Download and Configure
Clone the repository or download the release files:
cd /opt/aiadminpanel # Download docker-compose.yml and realm export curl -fsSL https://raw.githubusercontent.com/iskraecommerce/ai-admin-panel/main/docker-compose.yml -o docker-compose.yml curl -fsSL https://raw.githubusercontent.com/iskraecommerce/ai-admin-panel/main/keycloak-realm-export.json -o keycloak-realm-export.json
Create the .env file:
cat > /opt/aiadminpanel/.env <<EOF PANEL_DOMAIN=panel.example.com ACME_EMAIL=admin@example.com PANEL_VERSION=latest GOMEMLIMIT=0 # Keycloak OIDC OIDC_DISCOVERY_URL=http://keycloak:8180/realms/aiadminpanel/.well-known/openid-configuration OIDC_CLIENT_ID=panel-backend KEYCLOAK_URL=http://keycloak:8180 KEYCLOAK_REALM=aiadminpanel KEYCLOAK_ADMIN_USER=admin KEYCLOAK_HOSTNAME=auth.panel.example.com OIDC_REDIRECT_URI=https://panel.example.com/auth/callback PANEL_INTERNAL_URL=http://panel:8080 # Optional: Cloudflare DNS # CF_DNS_API_TOKEN=your-token-here EOF chmod 600 /opt/aiadminpanel/.env
4. Start the Stack
cd /opt/aiadminpanel docker compose up -d
This starts all services: PostgreSQL, Valkey, Traefik, Keycloak, Ollama, LiteLLM, and the panel.
5. Create the Keycloak Database
Keycloak needs its own database:
docker exec aiadminpanel_postgresql psql -U aiadminpanel -c "CREATE DATABASE keycloak;" 2>/dev/null || true
6. Wait for Services
# Wait for Keycloak (up to 2 minutes)
echo "Waiting for Keycloak..."
for i in $(seq 1 120); do
health=$(docker inspect --format='{{.State.Health.Status}}' aiadminpanel_keycloak 2>/dev/null || echo "unknown")
[ "$health" = "healthy" ] && echo "Keycloak is ready" && break
sleep 1
done
# Wait for panel
echo "Waiting for panel..."
for i in $(seq 1 60); do
curl -sf http://localhost:8080/healthz > /dev/null 2>&1 && echo "Panel is ready" && break
sleep 1
done
7. Verify
# Health check
curl -s https://panel.example.com/healthz | jq .
# Expected: { "status": "ok" }
# Check all containers
docker compose ps
Open https://panel.example.com in your browser. You'll be redirected to the Keycloak login page.
What the Installer Creates
/opt/aiadminpanel/
├── .env # Environment configuration
├── docker-compose.yml # Production compose file
├── keycloak-realm-export.json # Keycloak realm with panel clients
├── litellm-config.yaml # LiteLLM AI gateway config
└── letsencrypt/
├── acme.json # Let's Encrypt certificates
└── acme-dns.json # Wildcard certificates (if Cloudflare)
/etc/aiadminpanel/
└── config.yaml # Panel configuration
/run/secrets/
├── master_key # Panel encryption key
├── db_password # PostgreSQL password
└── keycloak_admin_password # Keycloak admin password
/var/log/aiadminpanel/
└── install.log # Installation log
What Gets Deployed
The install creates these Docker containers:
| Container | Image | Purpose |
|---|---|---|
aiadminpanel_traefik | traefik:v3 | Reverse proxy, auto-SSL |
aiadminpanel_postgresql | postgres:16-alpine | Primary database |
aiadminpanel_valkey | valkey/valkey:8-alpine | Cache and pub/sub |
aiadminpanel_keycloak | keycloak:26.0 | OIDC identity provider |
aiadminpanel_panel | ghcr.io/iskraecommerce/ai-admin-panel | The panel itself |
aiadminpanel_ollama | ollama/ollama | Local LLM inference |
aiadminpanel_litellm | ghcr.io/berriai/litellm | AI gateway |
Post-Install Verification
# Check panel health
curl -s https://panel.example.com/healthz | jq .
# Check Keycloak is accessible
curl -s -o /dev/null -w "%{http_code}" https://auth.panel.example.com
# Check template catalog loaded
curl -s https://panel.example.com/api/v1/templates/catalog | jq '.templates | length'
# Expected: 45
# Check all containers running
docker compose -f /opt/aiadminpanel/docker-compose.yml ps
Then open https://panel.example.com and log in. The first time, create an admin user through Keycloak at https://auth.panel.example.com/admin/.
Default Credentials
| Service | URL | Username | Password |
|---|---|---|---|
| Keycloak Admin | https://auth.{domain}/admin/ | admin | Contents of /run/secrets/keycloak_admin_password |
| Panel | https://{domain} | Created via Keycloak | — |
Troubleshooting
Port 80/443 already in use
Stop any existing web server:
systemctl stop nginx apache2 2>/dev/null systemctl disable nginx apache2 2>/dev/null
DNS not resolving
dig +short panel.example.com dig +short test.panel.example.com
Both should return your server IP. If not, wait for DNS propagation (up to 48 hours for some providers).
Let's Encrypt rate limits
For testing, use the staging CA:
# In docker-compose.yml, change the ACME server to: # --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory
Production rate limit: 50 certificates per registered domain per week.
Keycloak not starting
Keycloak needs its own database. If it fails to start:
# Check logs docker logs aiadminpanel_keycloak # Common fix: create the database docker exec aiadminpanel_postgresql psql -U aiadminpanel -c "CREATE DATABASE keycloak;" docker compose restart keycloak
Checking logs
docker logs --tail 100 aiadminpanel_panel # Panel docker logs --tail 100 aiadminpanel_traefik # Traefik docker logs --tail 100 aiadminpanel_keycloak # Keycloak docker logs --tail 100 aiadminpanel_postgresql # PostgreSQL
Dry run
Test the installer without making changes:
bash install.sh --dry-run --verbose