Requirements, setup, server configuration, and security checklist
| Component | Minimum | Recommended |
|---|---|---|
| PHP | 8.1 | 8.3+ |
| PostgreSQL | 14 | 16+ (or Supabase) |
| Web server | Apache 2.4 / Nginx 1.18 | Either |
| PHP extensions | pdo_pgsql, curl, json, openssl | Same |
| HTTPS | Required (Let's Encrypt is free) | â |
| Browser | Any modern browser with ES modules support | â |
EcomCentral stores connections, encrypted credentials, settings, and audit logs in PostgreSQL.
-- Run as postgres superuser
CREATE DATABASE ecomcentral;
CREATE USER ecomcentral_user WITH PASSWORD 'your-strong-password';
GRANT ALL PRIVILEGES ON DATABASE ecomcentral TO ecomcentral_user;
Apply the schema SQL file from the files/ directory:
psql -U ecomcentral_user -d ecomcentral -f files/shop_api_credentials_schema.sql
psql -U ecomcentral_user -d ecomcentral -f files/shop_channel_types_seed_extended.sql
psql -U ecomcentral_user -d ecomcentral -f files/shop_channel_types_seed_extended_2.sql
shop_channel_types with all 45+ supported marketplaces and their API credential schemas, logos, and OAuth flags.
# From the project root
php -S localhost:8080
Then open http://localhost:8080 in your browser.
Place the project in your tool's webroot and point the document root to the project folder.
Create api/config.local.php (it is already gitignored):
<?php
return [
'db' => [
'host' => 'localhost',
'port' => '5432',
'dbname' => 'ecomcentral',
'user' => 'ecomcentral_user',
'pass' => 'your-strong-password',
],
'encryption_key' => 'your-32-byte-key-here-exactly!!',
'default_id_mandant' => 1,
];
Generate a 32-character encryption key:
openssl rand -hex 16
# or
php -r "echo bin2hex(random_bytes(16));"
<VirtualHost *:443>
ServerName ecomcentral.example.com
DocumentRoot /var/www/ecomcentral
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/ecomcentral.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/ecomcentral.example.com/privkey.pem
<Directory /var/www/ecomcentral>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
# Deny direct access to internal PHP helpers
<FilesMatch "^_">
Require all denied
</FilesMatch>
# Deny access to config.local.php
<Files "config.local.php">
Require all denied
</Files>
</VirtualHost>
# Redirect HTTP â HTTPS
<VirtualHost *:80>
ServerName ecomcentral.example.com
Redirect permanent / https://ecomcentral.example.com/
</VirtualHost>
a2enmod ssl rewrite headers
systemctl restart apache2
Options -Indexes
<FilesMatch "^_.*\.php$">
Require all denied
</FilesMatch>
server {
listen 443 ssl http2;
server_name ecomcentral.example.com;
root /var/www/ecomcentral;
index index.html index.php;
ssl_certificate /etc/letsencrypt/live/ecomcentral.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ecomcentral.example.com/privkey.pem;
# Block directory listings
autoindex off;
# Block internal PHP helpers and config.local
location ~ /api/(_.*\.php|config\.local\.php) {
deny all;
return 404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name ecomcentral.example.com;
return 301 https://$host$request_uri;
}
For container/cloud deployments (Docker, Kubernetes, Heroku, Railway, Render, etc.), set secrets as environment variables instead of using config.local.php.
| Variable | Required | Description |
|---|---|---|
| DB_PASS | â Yes | PostgreSQL password |
| ECOM_ENCRYPT_KEY | â Yes | 32-character AES encryption key for credentials |
| DB_HOST | No | DB host (default: aws-1-eu-central-1.pooler.supabase.com) |
| DB_PORT | No | DB port (default: 5432) |
| DB_NAME | No | Database name (default: postgres) |
| DB_USER | No | Database user (default: configured Supabase user) |
| DEFAULT_ID_MANDANT | No | Default tenant ID (default: 1) |
docker run -d \
-e DB_HOST=your-db-host \
-e DB_PASS=your-db-password \
-e ECOM_ENCRYPT_KEY=your32charencryptionkeyhere!! \
-p 80:80 \
your-ecomcentral-image
services:
app:
build: .
ports: ["80:80"]
environment:
DB_HOST: db
DB_PASS: ${DB_PASS}
ECOM_ENCRYPT_KEY: ${ECOM_ENCRYPT_KEY}
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ecomcentral
For single-server deployments where you don't use environment variables, create api/config.local.php. This file is in .gitignore and takes priority over env vars.
<?php
// api/config.local.php â NEVER commit this file
return [
'db' => [
'host' => 'your-db-host',
'port' => '5432',
'dbname' => 'ecomcentral',
'user' => 'ecomcentral_user',
'pass' => 'your-db-password',
],
'encryption_key' => 'your32charencryptionkeyhere!!',
'default_id_mandant' => 1,
];
git status before any push.
config.local.php is blocked by web server (not directly accessible via URL)api/_*.php helpers are blocked by web server (not publicly accessible)Options -Indexes / autoindex off)api/_csrf.php)api/_cors.phpdisplay_errors is Off in production (php.ini)credential_rotated or connection_deleted eventsEcomCentral is pre-configured to work with Supabase, a managed PostgreSQL service with a generous free tier.
postgresql://postgres.abcdefgh:[YOUR-PASSWORD]@aws-1-eu-central-1.pooler.supabase.com:5432/postgres
files/shop_api_credentials_schema.sql to create the schemaDB_PASS to the Supabase project password and update DB_HOST, DB_USER accordingly