Skip to main content

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

RequirementMinimumRecommended
CPU2 cores4+ cores
RAM4 GB8+ GB
Disk20 GB SSD50+ GB SSD
OSUbuntu 22.04, Ubuntu 24.04, Debian 12Ubuntu 24.04
Architecturex86_64 (amd64), aarch64 (arm64)x86_64

DNS Requirements

Before installing, point your domain to the server:

  1. A recordpanel.example.com → your server IP
  2. 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.

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

PortDirectionPurpose
80InboundHTTP → auto-redirects to HTTPS
443InboundHTTPS (Traefik terminates SSL)
22InboundSSH access

No other services should be running on ports 80/443.

Automated Install

curl -fsSL https://get.aiadminpanel.com | bash

The installer prompts for your domain. To skip prompts, set environment variables:

export PANEL_DOMAIN="panel.example.com"
export ACME_EMAIL="admin@example.com"
curl -fsSL https://get.aiadminpanel.com | bash

Installer Options

FlagDescription
--dry-runPreview all actions without executing
--verboseEnable debug output
--unattendedNon-interactive mode (requires PANEL_DOMAIN env var)

Environment Variables

VariableRequiredDescription
PANEL_DOMAINYesBase domain (e.g., panel.example.com)
ACME_EMAILNoEmail for Let's Encrypt (default: admin@example.com)
CF_DNS_API_TOKENNoCloudflare API token for wildcard certs and auto-DNS
PANEL_VERSIONNoVersion to install (default: latest)
GOMEMLIMITNoGo 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:

ContainerImagePurpose
aiadminpanel_traefiktraefik:v3Reverse proxy, auto-SSL
aiadminpanel_postgresqlpostgres:16-alpinePrimary database
aiadminpanel_valkeyvalkey/valkey:8-alpineCache and pub/sub
aiadminpanel_keycloakkeycloak:26.0OIDC identity provider
aiadminpanel_panelghcr.io/aiadminpanel/panelThe panel itself
aiadminpanel_ollamaollama/ollamaLocal LLM inference
aiadminpanel_litellmghcr.io/berriai/litellmAI 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

ServiceURLUsernamePassword
Keycloak Adminhttps://auth.{domain}/admin/adminContents of /run/secrets/keycloak_admin_password
Panelhttps://{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