CognitixERP Production Deployment

Production Deployment Guide

Same-origin HTTPS deploy for CognitixERP — publish API + WebApp, put nginx (or IIS) in front, then optionally automate updates with GitHub Actions. Section 4 walks through the packaged Linux VPS recipe in Source/CognitixERP/deploy/hetzner/.

Version 3.1.0 Same-origin · nginx / IIS Optional CI/CD

1. Big picture

Use one website for everything (same-origin):

https://yourcompany.com/           → Blazor WebApp
https://yourcompany.com/api/...    → Cognitix.API
https://yourcompany.com/uploads/   → logos & files
https://yourcompany.com/chat-hub   → SignalR (CRM)
On the serverWhere
API files/var/www/cognitix-erp/api
WebApp files/var/www/cognitix-erp/webapp
API processsystemd cognitix-api on 127.0.0.1:5100 (local only)
Public HTTPSnginx (or IIS) in front

Replace every placeholder in this guide with your own values:

PlaceholderMeaning
YOUR_SERVER_IPPublic IP of your VPS
YOUR_SSH_USERLinux user used for deploy (often deploy)
yourcompany.comYour public HTTPS hostname
/var/www/cognitix-erpInstall directory on the server (change if you prefer)

You will configure:

  1. VPS — folders, database, systemd, nginx, SSL
  2. GitHub (optional) — secrets + Actions workflow
  3. Setup Wizard — first admin + license after the first successful publish
Buyer package: Licensing ships as DLLs in lib/Cognitix.Licensing/. When you publish, use -p:BuyerBuild=true.

Sample files live in Source/CognitixERP/deploy/hetzner/ (nginx, systemd, PostgreSQL init, production appsettings, deploy key script). Commands below are the same walkthrough as deploy/hetzner/README.md.

2. URLs you must set

Replace yourcompany.com with your real domain. Keep all values matching — including JWT Issuer/Audience.

CORS AllowedOrigins must be the same HTTPS origin as the WebApp.

PlaceValue
Setup Wizard — Frontend URLhttps://yourcompany.com
Setup Wizard — API URLhttps://yourcompany.com (no /api)
WebApp appsettings.json"ApiBaseUrl": "https://yourcompany.com/"
API Jwt Issuer / Audiencehttps://yourcompany.com
API Cors AllowedOriginshttps://yourcompany.com
API ApiSettings:BaseUrlhttps://yourcompany.com
API AppSettings:WebAppUrlhttps://yourcompany.com
Do not put /api at the end of API URL or ApiBaseUrl. The WebApp already calls paths like api/.... Adding /api breaks logos and uploads (URLs become /api/uploads/... and get blocked).

3. Manual deploy (publish on your PC)

From Source/CognitixERP. Use this when you are not using GitHub Actions yet (or for a one-off publish).

3.1 Publish API (Linux VPS)

dotnet publish src\Cognitix.API\Cognitix.API.csproj ^
  -c Release -r linux-x64 --self-contained true ^
  -p:BuyerBuild=true ^
  -o C:\publish\Cognitix.API

3.2 Publish WebApp

dotnet workload install wasm-tools
dotnet publish apps\Cognitix.WebApp\Cognitix.WebApp.csproj ^
  -c Release -p:BuyerBuild=true ^
  -o C:\publish\Cognitix.WebApp

Before or after publish, set WebApp config:

{
  "ApiBaseUrl": "https://yourcompany.com/"
}

Copy API output to the server api/ folder. Copy WebApp wwwroot contents to webapp/.

3.3 Server secrets file

On the server only, create api/appsettings.Production.json (use sample deploy/hetzner/appsettings.Production.server.example.json). Set:

  • Database connection string
  • JWT key (32+ chars) or env COGNITIX_JWT_KEY
  • CORS + Jwt Issuer/Audience + BaseUrl/WebAppUrl (table in section 2)
  • Licensing:SkipInDevelopment=false + CognitiveCircle ApiKey / HmacSecret
Never commit this Production file to Git. CI must not overwrite it. Keep real secrets only on the server and in GitHub Secrets — never in the marketplace ZIP.

4. Linux VPS with nginx (recommended)

This is the packaged Hetzner-style recipe. It works on any Ubuntu/Debian VPS (Hetzner, DigitalOcean, AWS Lightsail, a local VM). Sample files are in Source/CognitixERP/deploy/hetzner/.

Target layout:

/var/www/cognitix-erp/
|-- api/       # Cognitix.API (systemd: cognitix-api)
`-- webapp/    # Blazor WASM (served by nginx)

Nginx routing:

  • / → WebApp
  • /api/ → http://127.0.0.1:5100 (API listens locally only)
  • /uploads/ → API static uploads (logos, favicons, files)
  • /api/uploads/ → same files (legacy URL compatibility)
  • /chat-hub → SignalR

API internal URL: http://127.0.0.1:5100 · Public site: https://yourcompany.com

4.1 SSH into the server

ssh YOUR_SSH_USER@YOUR_SERVER_IP

Create a non-root deploy user with sudo if you do not already have one. The sample systemd unit uses User=deploy — change it if your SSH user is different.

4.2 Create folders

sudo mkdir -p /var/www/cognitix-erp/{api,webapp}
sudo mkdir -p /etc/cognitix-erp
sudo chown -R YOUR_SSH_USER:www-data /var/www/cognitix-erp
sudo chmod -R u+rwX,g+rwX /var/www/cognitix-erp

4.3 Database

CognitixERP supports SQL Server, PostgreSQL, or MySQL — one engine per install. The Hetzner samples assume PostgreSQL on the same VPS. Create the database before first Setup Wizard, or let the wizard create it if the login has permission.

PostgreSQL (on the server):

sudo -u postgres psql <<'SQL'
CREATE USER cognitix WITH PASSWORD 'CHANGE_ME_DB_PASSWORD';
CREATE DATABASE cognitix_erp OWNER cognitix;
GRANT ALL PRIVILEGES ON DATABASE cognitix_erp TO cognitix;
\c cognitix_erp
GRANT ALL ON SCHEMA public TO cognitix;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO cognitix;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO cognitix;
SQL

Use the same password later in appsettings.Production.json.

Or copy the sample script from your PC:

scp deploy/hetzner/postgresql-init.sql YOUR_SSH_USER@YOUR_SERVER_IP:/tmp/
ssh YOUR_SSH_USER@YOUR_SERVER_IP "sudo -u postgres psql -f /tmp/postgresql-init.sql"

Edit the script first if you changed database or user names.

4.4 Production settings (server only)

From your PC (repo root Source/CognitixERP):

scp deploy/hetzner/appsettings.Production.server.example.json YOUR_SSH_USER@YOUR_SERVER_IP:/tmp/appsettings.Production.json

On the server:

ssh YOUR_SSH_USER@YOUR_SERVER_IP
sudo mv /tmp/appsettings.Production.json /var/www/cognitix-erp/api/appsettings.Production.json
sudo nano /var/www/cognitix-erp/api/appsettings.Production.json

Set at least:

  1. ConnectionStrings:DefaultConnection — DB host / user / password
  2. Jwt:Key — random secret, 32+ characters
  3. Cors:AllowedOrigins — https://yourcompany.com
  4. AllowedHosts — e.g. yourcompany.com;localhost;127.0.0.1 (CI health check uses Host: localhost)
  5. ApiSettings:BaseUrl — https://yourcompany.com (no trailing /api)
  6. AppSettings:WebAppUrl — https://yourcompany.com
  7. Licensing:ApiKey and Licensing:HmacSecret — from your license provider

Permissions:

sudo chown YOUR_SSH_USER:www-data /var/www/cognitix-erp/api/appsettings.Production.json
sudo chmod 640 /var/www/cognitix-erp/api/appsettings.Production.json

Optional overrides (systemd reads this file):

sudo tee /etc/cognitix-erp/api.env >/dev/null <<'EOF'
# ConnectionStrings__DefaultConnection=...
# Licensing__ApiKey=...
# Licensing__HmacSecret=...
EOF
sudo chmod 600 /etc/cognitix-erp/api.env
GitHub deploy must not overwrite appsettings.Production.json. Keep it only on the server — the sample workflow excludes it.

4.5 systemd unit

scp deploy/hetzner/cognitix-api.service YOUR_SSH_USER@YOUR_SERVER_IP:/tmp/
ssh YOUR_SSH_USER@YOUR_SERVER_IP
sudo mv /tmp/cognitix-api.service /etc/systemd/system/cognitix-api.service
sudo systemctl daemon-reload
sudo systemctl enable cognitix-api

Edit User= and paths in the unit if your SSH user or install path differs. The sample starts Cognitix.API --urls http://127.0.0.1:5100 with ASPNETCORE_ENVIRONMENT=Production.

systemctl start may fail until the first successful publish — that is expected.

4.6 DNS + nginx + SSL

DNS — point your hostname at the VPS:

TypeNameValue
Ayour host / @ / subdomainYOUR_SERVER_IP

nginx

  1. Copy deploy/hetzner/nginx-site.conf.example.
  2. Replace every hostname inside with yourcompany.com.
  3. Ensure these locations exist: /api/, /uploads/, /api/uploads/, /, /chat-hub.
scp deploy/hetzner/nginx-site.conf.example YOUR_SSH_USER@YOUR_SERVER_IP:/tmp/yourcompany.com.conf
ssh YOUR_SSH_USER@YOUR_SERVER_IP
sudo mv /tmp/yourcompany.com.conf /etc/nginx/sites-available/yourcompany.com
sudo ln -sf /etc/nginx/sites-available/yourcompany.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

TLS

sudo certbot --nginx -d yourcompany.com
sudo nginx -t && sudo systemctl reload nginx
Logo blank after go-live? Confirm the /uploads/ and /api/uploads/ proxy blocks (they are already in the sample nginx file). See Troubleshooting.

4.7 Passwordless restart for CI

Needed only if GitHub Actions will restart the API after each deploy.

sudo visudo -f /etc/sudoers.d/cognitix-erp-deploy

One line (use your SSH user):

YOUR_SSH_USER ALL=(ALL) NOPASSWD: /bin/systemctl restart cognitix-api

Test:

sudo -n systemctl restart cognitix-api

5. GitHub Actions CI/CD

Optional, but best for updates. Matches deploy/hetzner/README.md Part B.

5.1 What you need

  • Your code in a GitHub repo (buyer package root = Source/CognitixERP)
  • Workflow file: .github/workflows/deploy.yml (sample: deploy/hetzner/github-workflows/deploy.yml)
  • Four GitHub Secrets (no secrets inside the YAML file)
  • Licensing DLLs committed: lib/Cognitix.Licensing/*.dll
  • GitHub Environment named production

5.2 Create deploy SSH key (on your PC)

bash deploy/hetzner/generate-deploy-key.sh

Creates:

  • deploy/hetzner/deploy-keys/cognitix_erp_deploy — private (GitHub Secret only)
  • deploy/hetzner/deploy-keys/cognitix_erp_deploy.pub — public (server authorized_keys)
Never commit the private key to the repo or the CodeCanyon ZIP.

Install the public key on the server:

# Windows PowerShell
type deploy\hetzner\deploy-keys\cognitix_erp_deploy.pub | ssh YOUR_SSH_USER@YOUR_SERVER_IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# Linux / macOS
cat deploy/hetzner/deploy-keys/cognitix_erp_deploy.pub | ssh YOUR_SSH_USER@YOUR_SERVER_IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Test:

ssh -i deploy/hetzner/deploy-keys/cognitix_erp_deploy YOUR_SSH_USER@YOUR_SERVER_IP

5.3 GitHub Secrets

GitHub → Settings → Secrets and variables → Actions → New repository secret

Secret nameValue
DEPLOY_HOSTYOUR_SERVER_IP
DEPLOY_USERYOUR_SSH_USER
DEPLOY_PATH/var/www/cognitix-erp
DEPLOY_SSH_KEYFull private key text (-----BEGIN OPENSSH PRIVATE KEY----- …)

Copy private key (PowerShell):

Get-Content .\deploy\hetzner\deploy-keys\cognitix_erp_deploy -Raw | Set-Clipboard

5.4 GitHub Environment

Settings → Environments → New environment → name: production
(The workflow uses environment: production.)

5.5 Commit Licensing DLLs + run deploy

This buyer package builds Licensing from DLLs. Commit them or CI fails with missing Cognitix.Licensing.* / CS0234.

git add -f lib/Cognitix.Licensing/*.dll
git add .github/workflows/deploy.yml
git commit -m "Include Licensing DLLs for CI builds."
git push

Then: GitHub → Actions → Deploy → Run workflow (or push to the branch the workflow watches).

Success looks like: publish OK → rsync OK → cognitix-api active → health HTTP 200.

5.6 What CI does / does not do

  • Builds API + WebApp and copies files to the server
  • Restarts cognitix-api (needs the sudoers rule in section 4.7)
  • Does not overwrite appsettings.Production.json (keep secrets on the server)
  • Does not delete wwwroot/uploads (logos stay)

6. Setup Wizard after first deploy

Open https://yourcompany.com/setup after the first successful publish.

6.1 Public URLs (same origin)

ItemURL
Frontendhttps://yourcompany.com
Setup Wizardhttps://yourcompany.com/setup
Loginhttps://yourcompany.com/users/login
API root (for wizard)https://yourcompany.com
Healthhttps://yourcompany.com/api/system/health
In Setup Wizard, API URL = site origin (https://yourcompany.com). Do not append /api.

6.2 Step 1 — Database and URLs

FieldTypical value
Frontend URLhttps://yourcompany.com
API URLhttps://yourcompany.com (no /api)
Database EnginePostgreSQL (or SQL Server / MySQL)
DB Server127.0.0.1 (if DB is on the same VPS)
Port5432 (PostgreSQL) · 1433 (SQL Server) · 3306 (MySQL)
Database Nameyour DB name (e.g. cognitix_erp)
DB Username / Passwordvalues from section 4.3

Schema provisioning applies all 18 module DbContexts and usually takes several minutes — keep the tab open.

6.3 Step 2 — Administrator

Create the first admin account. No default password ships with the product. Step 1 must have created a headquarters branch first.

6.4 Step 3 — License / Trial

Activate your Envato purchase code or start the 14-day trial. Production needs internet plus CognitiveCircle keys in server appsettings.Production.json first (Licensing:ApiKey, Licensing:HmacSecret, SkipInDevelopment=false).

6.5 WebApp ApiBaseUrl

{
  "ApiBaseUrl": "https://yourcompany.com/"
}

Confirm webapp/appsettings.json (or wwwroot/appsettings.json after publish) matches after deploy. Copy the snippet from the wizard if it offers a download.

Wait a few seconds after Step 3 while the API restarts, then check health. Sign in at https://yourcompany.com/users/login.

7. Go-live checks

curl -i https://yourcompany.com/api/system/health

On the server:

ssh YOUR_SSH_USER@YOUR_SERVER_IP
sudo systemctl status cognitix-api
curl -i -H "Host: localhost" http://127.0.0.1:5100/api/system/health
  • Site loads over HTTPS
  • Login works with your admin account
  • Company logo loads (needs nginx /uploads/)
  • License status is Trial or Active (not DevelopmentSkipped)

Quick checklist

  1. VPS folders, database, appsettings.Production.json, systemd, nginx, SSL, sudoers
  2. Deploy key → public on server, private in DEPLOY_SSH_KEY
  3. Secrets: DEPLOY_HOST, DEPLOY_USER, DEPLOY_PATH, DEPLOY_SSH_KEY
  4. Commit Licensing DLLs + ensure .github/workflows/deploy.yml
  5. Run the deploy workflow (or copy a manual publish)
  6. Open /setup — Frontend URL and API URL = https://yourcompany.com (no /api)
  7. Create admin → activate license → /users/login

8. Troubleshooting

SymptomWhat to check
Cannot SSHIP, user, firewall, authorized_keys
GitHub deploy SSH failsDEPLOY_SSH_KEY is the full private key
Missing Licensing assembliesCommit lib/Cognitix.Licensing/*.dll
Health check HTTP 400 while API is upAllowedHosts must allow localhost (CI sends Host: localhost)
cognitix-api failedjournalctl -u cognitix-api -n 80 --no-pager
DB errorsConnection string / password / engine matches Setup Wizard
CORS errorsCors:AllowedOrigins includes https://yourcompany.com
502 Bad GatewayIs the API running? Is nginx proxy_pass http://127.0.0.1:5100?
Logo / uploads 401 or blankAdd /uploads/ and /api/uploads/ nginx locations (below)
CI cannot restart servicesudoers rule in section 4.7
Site does not openDNS A record → YOUR_SERVER_IP

nginx upload locations

Inside your site config, after location /api/:

location /uploads/ {
    proxy_pass         http://127.0.0.1:5100;
    proxy_http_version 1.1;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_set_header   Connection keep-alive;
    expires 7d;
    add_header Cache-Control "public";
}

location /api/uploads/ {
    proxy_pass         http://127.0.0.1:5100/uploads/;
    proxy_http_version 1.1;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   Connection keep-alive;
    expires 7d;
    add_header Cache-Control "public";
}
sudo nginx -t && sudo systemctl reload nginx

Optional PostgreSQL cleanup if old URLs contain /api/uploads/:

UPDATE branching."CompanySetups"
SET "CompanyLogoUrl" = REPLACE("CompanyLogoUrl", '/api/uploads/', '/uploads/'),
    "CompanyFaviconUrl" = REPLACE("CompanyFaviconUrl", '/api/uploads/', '/uploads/')
WHERE "CompanyLogoUrl" LIKE '%/api/uploads/%'
   OR "CompanyFaviconUrl" LIKE '%/api/uploads/%';

More product-wide issues: Troubleshooting FAQ.

9. Windows IIS (short)

  • Install .NET 10 Hosting Bundle + URL Rewrite
  • One HTTPS site for yourcompany.com
  • Serve WebApp static files; reverse-proxy /api/, /uploads/, /chat-hub to the API (same idea as nginx)
  • Set ASPNETCORE_ENVIRONMENT=Production and COGNITIX_JWT_KEY
  • Use the same URL table from section 2

For most buyers, Linux + nginx + optional GitHub Actions is simpler.

10. Please Contact us

  1. Sign up at https://cognitivebd.com
  2. Create a Support Ticket.
  3. Within 48hr we will reply.
  4. WhatsApp: +18632279760

Or email support@cognitivebd.com with your purchase code, version, and screenshots/logs.