Skip to content

Installation

Two paths: a quick local dev checkout, or a single-server install with generated secrets you can paste straight in.

Prerequisites

  • Python 3.13 (installed via uv in a project venv)
  • PostgreSQL 17 or 18 (nulls_distinct=False needs PG 15+)
  • Redis (for the RQ job queues)
  • Linux for the user-level systemd services; the app itself runs anywhere Django runs

Install on a server

A start-to-finish install on a fresh Ubuntu/Debian box. Commands assume sudo.

Your secrets are generated below — in your browser

Every value in the blocks on this page (DJANGO_SECRET_KEY, the database password, the admin password) is randomly generated in your browser when the page loads, so no two installs share a "default". Hit ↻ Regenerate for a fresh set. The same secret is reused consistently across the steps (the DB password in the SQL matches the one in your .env), so you can copy each block as-is. Store them somewhere safe — and you can always rotate them later (see Rotating secrets).

1. System packages

sudo apt update
sudo apt install -y postgresql redis-server git curl
# uv (installs/manages Python 3.13)
curl -LsSf https://astral.sh/uv/install.sh | sh

2. PostgreSQL role + database

Creates the danbyte role with your generated password and its database:

sudo -u postgres psql <<SQL
CREATE ROLE danbyte LOGIN PASSWORD '';
CREATE DATABASE danbyte OWNER danbyte;
SQL

3. Get the code + Python deps

Danbyte's systemd units are user-level and rooted at ~/danbyte, so clone it into your home directory (not /opt):

git clone …/danbyte ~/danbyte && cd ~/danbyte
uv python install 3.13
uv venv --python 3.13 .venv
VIRTUAL_ENV=$PWD/.venv uv pip install -r requirements.txt

4. Configure .env

Write this to ~/danbyte/.env (set ALLOWED_HOSTS to your server's hostname or IP). The secret key, DB password, and admin password are pre-filled with your generated values:

DJANGO_SECRET_KEY=
DEBUG=False
ALLOWED_HOSTS=your-server.example.com

DB_NAME=danbyte
DB_USER=danbyte
DB_PASSWORD=
DB_HOST=127.0.0.1
DB_PORT=5432

REDIS_URL=redis://localhost:6379/0

# Admin user created by `make bootstrap` on first run:
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@your-org.example
DJANGO_SUPERUSER_PASSWORD=

Change the admin password after first login

The generated DJANGO_SUPERUSER_PASSWORD gets you in safely on a fresh box. It's still a single shared-with-your-clipboard secret — sign in, then change it under User → Preferences, and drop the line from .env.

5. Migrate + first-run bootstrap

bootstrap is idempotent: it sets up the default Organization + built-in Status catalog and, because the DJANGO_SUPERUSER_* vars are set, creates your admin user.

cd ~/danbyte
.venv/bin/python manage.py migrate
.venv/bin/python manage.py bootstrap

6. Build the frontend + collect static

make frontend-install     # one-time: node deps
make frontend-build       # build the SSR frontend → frontend/dist
make collectstatic        # gather Django admin/DRF static → staticfiles/

7. Run the production processes

Danbyte runs as a few small processes, each a user-level systemd unit:

Process Unit Serves
gunicorn danbyte-web HTTP (the Django WSGI app) on 127.0.0.1:8000
daphne danbyte-ws WebSockets (presence) on 127.0.0.1:8002
node danbyte-frontend-prod the built SSR frontend on 127.0.0.1:3000
RQ worker danbyte-workers background jobs (scans, deploys)
scheduled timers danbyte-* drift dispatch, cleanup, materialise, …

Why daphne and gunicorn

gunicorn serves all plain HTTP; daphne serves only the /ws/ routes. Keeping the ASGI server off the HTTP path is deliberate — putting it in front of everything wedges ordinary requests.

make install-services        # workers + timers + the (dev) units
make install-prod-services   # gunicorn + daphne + built-frontend units
make workers-up
systemctl --user enable --now danbyte-web danbyte-ws danbyte-frontend-prod
make status

8. nginx + TLS

Put everything behind one HTTPS origin with the production nginx template (static served from disk, /ws/ → daphne, /api/ + /admin/ → gunicorn):

make proxy-install \
  NGINX_TMPL=deploy/nginx/danbyte.prod.conf.template \
  PROXY_HOST=danbyte.example.com

This generates a self-signed cert by default — fine for a LAN, but for a public host install a real CA cert (e.g. Let's Encrypt / certbot) and re-point CERT / KEY, or drop the cert paths into /etc/ssl/danbyte/.

Open https://danbyte.example.com/ and sign in as admin.

Shipping updates later

Backend: git pull && .venv/bin/python manage.py migrate && make collectstatic then systemctl --user restart danbyte-web danbyte-ws danbyte-workers. Frontend: make frontend-build && systemctl --user restart danbyte-frontend-prod.

Rotating secrets

Any of these can be changed later without a reinstall:

  • Admin passwordUser → Preferences (or manage.py changepassword).
  • DJANGO_SECRET_KEY — edit .env, make restart. (Invalidates active sessions — everyone signs in again.)
  • DB passwordALTER ROLE danbyte PASSWORD '…'; in psql, update .env, make restart.

Security checklist

  • DEBUG=False and ALLOWED_HOSTS set to your real host(s).
  • nginx + TLS in front; Danbyte not exposed directly on :8000.
  • Admin password changed after first login; superuser line removed from .env.
  • .env is chmod 600 and never committed.
  • Postgres/Redis bound to localhost (or firewalled).

Local development

git clone …/danbyte && cd danbyte
uv python install 3.13
uv venv --python 3.13 .venv
VIRTUAL_ENV=$PWD/.venv uv pip install -r requirements.txt

# Postgres role + db (dev creds are fine locally)
sudo -u postgres psql <<'SQL'
CREATE ROLE danbyte LOGIN PASSWORD 'danbyte';
CREATE DATABASE danbyte OWNER danbyte;
SQL

DB_HOST=127.0.0.1 DB_USER=danbyte DB_PASSWORD=danbyte DB_NAME=danbyte \
  .venv/bin/python manage.py migrate

# Optional: opt-in demo data
DB_HOST=127.0.0.1 DB_USER=danbyte DB_PASSWORD=danbyte DB_NAME=danbyte \
  .venv/bin/python manage.py seed_demo

make install-services
make backend-up

Open http://localhost:8000/prefixes/.

Settings env vars

Variable Default Purpose
DB_HOST 127.0.0.1 PostgreSQL host
DB_PORT 5432 PostgreSQL port
DB_NAME danbyte Database name
DB_USER danbyte DB role
DB_PASSWORD danbyte DB password
ALLOWED_HOSTS localhost,127.0.0.1 Comma-separated. Set on a server / VPN host
DJANGO_SECRET_KEY dev-key-change-in-prod Required when DEBUG=False
DEBUG True Disable in prod
CORS_ALLOWED_ORIGINS http://localhost:3000 Frontend origin(s)
DJANGO_SUPERUSER_USERNAME / _EMAIL / _PASSWORD bootstrap creates this admin when set

See danbyte/settings.py for the full list.

Verifying

make status       # all services
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8000/prefixes/

Expected: 200.