*_build.tar.gz with protected modules). This page covers greenfield
deployment on a clean host for both paths. After the server is up, use
First Login & Administrator Account and
PROJECT_SETUP_GUIDE.md (in your delivery package) for license UI, admin checks, and onboarding.
Choose your edition
| Community Edition | Enterprise Edition | |
|---|---|---|
| License | AGPL v3; free community key (up to 100 users) | Commercial key (per contract) |
| Code | Full Python source (.py) | Cython or Nuitka (.so / binary modules) |
| Obtain | GitHub, source archive from secboard.online Customer packages | *_build.tar.gz from license server / delivery |
| Python ABI | 3.12+ — no SOABI/glibc match to build host | 3.12 — match version, SOABI, and glibc to artifact |
| Runbook | README.md, commands.txt, deploy/ in repo | DEPLOYMENT_INSTRUCTIONS.md in package |
Goal & audience
Mid-level Linux / DevOps engineers: prepare a clean host, install dependencies, configure .env,
run check --deploy, migrate, and collectstatic, activate a license key, run Gunicorn on
SecBoard.wsgi:application on loopback behind nginx with TLS, and — where used —
Celery worker and Celery beat with Redis, all from the same venv, paths, and .env.
Hardware (indicative)
| Resource | Minimum (light load) | Production (typical) |
|---|---|---|
| CPU | 2 vCPU | 4+ vCPU, tune to load |
| RAM | 4 GB | 8+ GB; separate DB host preferred |
| Disk | 20 GB free | 40+ GB; plan for logs and media/ |
| Network | Outbound HTTPS for pip and license checks | DNS to this host for TLS (e.g. Let's Encrypt) |
Software & network
- OS: Ubuntu Server LTS or Debian (systemd). For Enterprise compiled builds, align glibc with the build host (gate E8).
- Python 3.12+ +
python3.12-venv; nginx; DB client libs perrequirements.txt. - Database (MySQL 8+ / MariaDB 10.6+ or PostgreSQL per your
.env) created and reachable. - Redis if Celery background tasks are enabled.
sudo apt-get update
sudo apt-get install -y python3.12 python3.12-venv python3.12-dev nginx curl ca-certificates build-essential git
# Add libpq-dev OR default-libmysqlclient-dev per requirements.txt
Architecture (brief)
Client → nginx :443 → Gunicorn (127.0.0.1:PORT) → Django → DB / Redis
↑
Celery worker / beat (if present)
Gunicorn listens on loopback only; expose 80/443 via nginx.
Placeholders
| Placeholder | Meaning |
|---|---|
/srv/SecBoard_yoursite | Install root (empty on greenfield). |
yoursite | Public DNS hostname. |
secboard_yoursite.service | Your systemd unit name for Gunicorn. |
youruser:yourgroup | OS user/group for Gunicorn/Celery (venv and manage.py must use the same user). |
Community Edition — source install (recommended for Open Source)
.py source, no compiled-module ABI gates.
Request a free community license key (up to 100 users) after install — see
secboard.online (Personal Cabinet → license request).
Obtain source
Option A — GitHub (public repo):
sudo mkdir -p /srv/SecBoard_yoursite
sudo git clone https://github.com/Dimcas2012/SecBoard.git /srv/SecBoard_yoursite
sudo chown -R youruser:yourgroup /srv/SecBoard_yoursite
Option B — source archive from secboard.online Customer packages
(Community Edition *_build.tar.gz is source-only, not Cython/Nuitka). Verify SHA256 on the change ticket.
tar -tzf Community_Edition_*_build.tar.gz | head
sudo tar -xzf /path/to/Community_Edition_*_build.tar.gz -C /srv/SecBoard_yoursite --strip-components=1
sudo chown -R youruser:yourgroup /srv/SecBoard_yoursite
Pre-flight (Community)
| # | Check |
|---|---|
| C1 | python3.12 --version — 3.12 or newer. |
| C2 | Database reachable; credentials ready for .env. |
| C3 | Outbound HTTPS for pip install -r requirements.txt. |
| C4 | Install root exists and is empty (or fresh git clone). |
| C5 | (If Celery) Redis installed/reachable; REDIS_* in .env. |
| C6 | Outbound HTTPS to license.secboard.online for activation and heartbeats. |
venv, Django, license
cd /srv/SecBoard_yoursite
python3.12 -m venv venv
source venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
cp -n .env.example .env
# Edit .env: DB_*, SECRET_KEY, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS,
# CORS_*, REDIS_*, PUBLIC_BASE_URL, SITE_*, DEBUG=0
python3.12 manage.py check --deploy
mkdir -p logs media staticfiles
python3.12 manage.py migrate --noinput
python3.12 manage.py init_site_settings
python3.12 manage.py collectstatic --noinput
chmod -R 755 staticfiles media
chmod -R 775 logs
python3.12 manage.py get_hardware_id
# Request community key at https://secboard.online — then:
python3.12 manage.py activate_license YOUR_COMMUNITY_KEY
# Or activate in UI: /about/license/activate/
See README.md and commands.txt in the repository for optional seed commands
(e.g. load_company_types, setup_all_periodic_tasks). Production samples:
deploy/secboard_base.service.example, deploy/nginx.example.conf.
After any .env change: restart Gunicorn and (if used) Celery —
stale env can cause DisallowedHost and misleading HTTP 400.
Enterprise Edition — compiled build archive
*_build.tar.gz with protected modules
(Cython or Nuitka). Match Python 3.12 (version, SOABI, patch where relevant)
and glibc to the build host. The authoritative runbook is DEPLOYMENT_INSTRUCTIONS.md in your package.
Pre-flight (Enterprise)
| # | Check |
|---|---|
| E1 | python3.12 --version matches the build / release notes. |
| E1b | python3.12 -c "import sysconfig; print(sysconfig.get_config_var('SOABI'))" — record on change ticket. |
| E2 | Know Cython vs Nuitka for your artifact. |
| E3 | Archive path and SHA256 on the change ticket. |
| E4 | Database reachable; credentials for .env. |
| E5 | Outbound HTTPS for pip install -r requirements.txt. |
| E6 | OS packages and DB client libraries per requirements.txt. |
| E7 | Install root empty before extract. |
| E8 | ldd --version | head -n1 — compare glibc with build host. |
| E9 | (If Celery) Redis active before worker/beat. |
Extract archive
Run tar -tzf your_build.tar.gz | head once. If there is exactly one top-level directory, use
--strip-components=1; if files sit at archive root, omit it.
sudo systemctl stop secboard_yoursite.service 2>/dev/null || true
sudo mkdir -p /srv/SecBoard_yoursite
tar -tzf /path/to/yoursite_build.tar.gz | head
sudo tar -xzf /path/to/yoursite_build.tar.gz -C /srv/SecBoard_yoursite --strip-components=1
sudo chown -R youruser:yourgroup /srv/SecBoard_yoursite
cd /srv/SecBoard_yoursite
python3.12 -c "import sys; print(sys.version)"
python3.12 -c "import sysconfig; print(sysconfig.get_config_var('SOABI'))"
ldd --version | head -n1
python3.12 -m venv venv
source venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
cp -n .env.example .env
# Do NOT keep a bundled .env from the build machine.
python3.12 manage.py check --deploy
mkdir -p logs media staticfiles
python3.12 manage.py migrate --noinput
python3.12 manage.py collectstatic --noinput
chmod -R 755 staticfiles media
chmod -R 775 logs
Optional: compiled module smoke test
cd /srv/SecBoard_yoursite && source venv/bin/activate
ls -la app_conf/*.so 2>/dev/null || ls -la app_conf/
python3.12 -c "from app_conf import models; print('OK:', models.__file__)"
Full numbered steps (rollback, troubleshooting) — DEPLOYMENT_INSTRUCTIONS.md next to PROJECT_SETUP_GUIDE.md.
rm -rf over data you need. Before replacing an install, back up the database,
media/, and configs; prefer mv the old directory aside (see DEPLOYMENT_INSTRUCTIONS.md).
Celery worker, Redis, and Celery beat
When background tasks are used: Redis must run before worker/beat; REDIS_* in .env must match.
Prefer separate systemd units for Gunicorn, worker, and beat — same User=, WorkingDirectory=, venv PATH,
DJANGO_SETTINGS_MODULE=SecBoard.settings. With ProtectSystem=strict, include the install directory in ReadWritePaths=.
Many builds use django-celery-beat with --scheduler=django_celery_beat.schedulers:DatabaseScheduler.
See deploy/*.service samples (Community) or DEPLOYMENT_INSTRUCTIONS.md (Enterprise). After code updates, restart Celery.
Gunicorn (WSGI)
Use only SecBoard.wsgi:application. Put --bind 127.0.0.1:PORT in systemd; nginx proxy_pass targets that loopback port.
Use exactly one process manager: systemd or Supervisor, not both.
gunicorn SecBoard.wsgi:application \
--bind 127.0.0.1:8000 \
--workers 3 \
--timeout 60 \
--max-requests 1000 \
--max-requests-jitter 100
nginx & TLS
Terminate TLS at nginx; forward Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto to Gunicorn.
After edits: sudo nginx -t then reload. Obtain certificates when DNS points to this host (e.g. Certbot).
Post-deploy checks
When SECURE_SSL_REDIRECT is on, probe through nginx on 443 (not raw Gunicorn TLS):
curl -fsS --resolve "yoursite:443:127.0.0.1" "https://yoursite/" || exit 1
systemctl is-active secboard_yoursite.service 2>/dev/null || true
tail -n 80 /srv/SecBoard_yoursite/logs/gunicorn_error.log
Optional firewall
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
Allow SSH (22/tcp) before ufw enable. The platform needs outbound HTTPS to
license.secboard.online for license verification and heartbeats.
Rollback (high level)
Stop Gunicorn and Celery → sudo mv /srv/SecBoard_yoursite /srv/SecBoard_yoursite_backup_$(date +%s) → redeploy known-good
source (git checkout / fresh clone) or Enterprise archive. Avoid destructive rm -rf when data matters.