PanelInstallation
Docker
Deploy the Struxa Panel using Docker Compose.
This guide covers a manual Docker installation. For a fully automated setup that handles Docker, nginx, SSL, and secrets generation in one command, see the automated installer section in the Introduction guide (coming soon).
Prerequisites
- Linux VPS - Ubuntu 22.04+ or Debian 12+ recommended
- Root access
- A domain name pointed at your server
curlandopensslavailable
System Requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU | 2 vCPU |
| RAM | 512 MB | 1 GB |
| Disk | 5 GB | 20 GB |
| OS | Ubuntu 22.04 / Debian 12 | Ubuntu 22.04 LTS |
Step 1: Install Docker
curl -fsSL https://get.docker.com | sh
systemctl enable --now dockerVerify:
docker --version
docker compose versionStep 2: Create Directory
mkdir -p /opt/struxaStep 3: Fetch Compose File
curl -fsSL https://raw.githubusercontent.com/struxadotcloud/struxa/main/docker-compose.prod.yml \
-o /opt/struxa/docker-compose.prod.ymlStep 4: Generate Secrets
MYSQL_ROOT_PASSWORD=$(openssl rand -hex 32)
MYSQL_PASSWORD=$(openssl rand -hex 32)
BETTER_AUTH_SECRET=$(openssl rand -hex 32)
DATABASE_ENCRYPTION_KEY=$(openssl rand -hex 32)
# RSA key pair for Wings authentication
openssl genrsa -out /tmp/priv.pem 2048
openssl rsa -in /tmp/priv.pem -pubout -out /tmp/pub.pem
JWT_PRIVATE_KEY=$(base64 -w0 < /tmp/priv.pem)
JWT_PUBLIC_KEY=$(base64 -w0 < /tmp/pub.pem)
rm /tmp/priv.pem /tmp/pub.pemStep 5: Write .env.prod
Replace panel.example.com with your actual domain.
cat > /opt/struxa/.env.prod << EOF
GITHUB_REPOSITORY_OWNER=struxadotcloud
IMAGE_TAG=latest
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE=struxa
MYSQL_USER=struxa
MYSQL_PASSWORD=${MYSQL_PASSWORD}
DATABASE_URL=mysql://struxa:${MYSQL_PASSWORD}@mysql:3306/struxa
BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
BETTER_AUTH_URL=https://panel.example.com
CORS_ORIGIN=https://panel.example.com
APP_URL=https://panel.example.com
JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY}
JWT_PUBLIC_KEY=${JWT_PUBLIC_KEY}
DATABASE_ENCRYPTION_KEY=${DATABASE_ENCRYPTION_KEY}
EOF
chmod 600 /opt/struxa/.env.prod.env.prod contains all secrets for your installation. Keep it secure - never commit it to version control.
Step 6: Configure nginx
server {
listen 443 ssl;
server_name panel.example.com;
ssl_certificate /etc/letsencrypt/live/panel.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 86400;
}
}
server {
listen 80;
server_name panel.example.com;
return 301 https://$host$request_uri;
}Obtain an SSL certificate:
certbot --nginx -d panel.example.com --non-interactive --agree-tos \
-m you@example.com --redirectStep 7: Start Services
cd /opt/struxa
docker compose -f docker-compose.prod.yml --env-file .env.prod pull
docker compose -f docker-compose.prod.yml --env-file .env.prod up -dStep 8: Verify
docker compose -f docker-compose.prod.yml psBoth the web and mysql containers should show status Up.
Docker Compose Services
| Service | Image | Internal Port |
|---|---|---|
web | ghcr.io/struxadotcloud/struxa:latest | 3001 |
mysql | mysql:8.0 | 3306 (internal only) |