Skip to content
Getting Started

Installation

Four ways to run RedScribe, from fully automated HTTPS via Tailscale to local development without Docker.

There are four ways to run RedScribe. The only real question is how much TLS certificate setup you want to do yourself. Pick the row below that matches your situation, follow its steps, and you’ll land at the same place either way: First run, where you generate the instance’s encryption key and create your first admin account.

Just want to try it out first? The Quickstart covers the same no-TLS setup as Method 3 below, in fewer words, for a machine only you need to reach.

Method Best for TLS
1. Tailscale Fully automated HTTPS, zero certificate management Automatic
2. Your own certificate Your own domain, a certificate from anywhere You supply it
3. Plain HTTP Trying it out locally or on a private network None
4. Local development Working on RedScribe’s own code None (loopback only)

Every method needs the same two secrets in place first, as file-based Docker secrets rather than .env values (see Environment variables for why).

  1. Copy the template:

    Terminal window
    cp .env.example .env
  2. Generate a random signing key for Django’s own session and CSRF protection, straight into its secret file:

    Terminal window
    python3 -c "import secrets, string; print(''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(50)))" > secrets/django_secret_key.txt
  3. Put a database password of your own choosing into its own secret file:

    Terminal window
    openssl rand -base64 32 > secrets/postgres_password.txt
  4. Create an empty placeholder for the instance’s root encryption key, so Compose has a file to mount. You’ll fill in the real value in First run, after the app is up:

    Terminal window
    touch secrets/root_key.txt

The instance’s master encryption key, REDSCRIBE_ROOT_KEY, isn’t generated here (only the empty placeholder file above). It needs RedScribe’s own generator command, so it’s covered in First run instead, after the app is up.

Section titled “Method 1: Docker Compose + Tailscale (recommended)”

Choose this if the machine is already on a Tailscale network with MagicDNS and HTTPS certificates turned on. RedScribe handles the certificate entirely from there: no manual renewal, no certificate authority to deal with, nothing else to configure.

  1. In .env, set NGINX_SERVER_NAME=<your-machine>.<tailnet>.ts.net (find it by running tailscale status --self --json and reading the DNSName field), and add that same hostname to DJANGO_ALLOWED_HOSTS.

  2. Set DJANGO_SETTINGS_MODULE=config.settings.prod in .env.

  3. Start everything:

    Terminal window
    docker compose --profile tailscale up -d --build

That’s the whole setup. A background service requests the first certificate and keeps renewing it for as long as the stack runs, and the web server picks up each renewal automatically. Continue at First run.

Want it reachable from the public internet too, not just your tailnet? See exposing it with Tailscale Funnel in the deployment deep dive.

Method 2: Docker Compose + your own TLS certificate

Section titled “Method 2: Docker Compose + your own TLS certificate”

Already have a certificate for your own domain, from Let’s Encrypt, a corporate certificate authority, or anywhere else? RedScribe picks it up automatically, including future renewals, as long as it lands in the right place.

  1. In .env, set NGINX_SERVER_NAME=<your-domain>, add that domain to DJANGO_ALLOWED_HOSTS, and set DJANGO_SETTINGS_MODULE=config.settings.prod.

  2. Copy your certificate files into place, using exactly these two filenames (see certs/README.md for details):

    Terminal window
    cp /path/to/your/fullchain.pem certs/fullchain.pem
    cp /path/to/your/privkey.pem certs/privkey.pem
  3. Start everything:

    Terminal window
    docker compose up -d --build

The web server waits for both files to exist before it starts, and reloads automatically whenever it notices the certificate has changed. That means your own renewal process, a certbot timer or whatever else you already run, gets picked up within the hour without you touching this stack at all. Continue at First run.

No TLS at all. Fine for trying things out locally or on a private network you already trust. Not fine for anything reachable beyond that.

Terminal window
docker compose up -d --build

Leave DJANGO_SETTINGS_MODULE at its .env.example default (config.settings.dev). Skip straight to http://localhost:8000/, which is bound to the host machine only, rather than going through the web server at all. Continue at First run.

Method 4: Local development without Docker

Section titled “Method 4: Local development without Docker”

For working on RedScribe’s own code, without a full container rebuild every time something changes:

Terminal window
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
docker compose up -d db # just the database
cp .env.example .env # fill in DJANGO_SECRET_KEY/POSTGRES_PASSWORD as plain values, POSTGRES_HOST=localhost
python manage.py migrate
python manage.py generate_root_key # put the output in .env as REDSCRIBE_ROOT_KEY
python manage.py bootstrap_superadmin --username admin --email admin@example.com
python manage.py runserver

This already creates the root key and the first admin account as part of the same steps, so skip First run, you’re done. See Local development for the rest of the day to day loop, including rebuilding frontend assets after a template or CSS change.

One thing worth knowing: how the web server sees your visitors

Section titled “One thing worth knowing: how the web server sees your visitors”

The web server container runs a little differently than you might expect, in a way that matters for audit logs and login lockouts recording the right IP address. See why nginx uses host networking in the deployment deep dive if you’re curious.