Skip to content

Add docs for macOS HTTPS local development (mkcert or OpenSSL) #1

@XxUnkn0wnxX

Description

@XxUnkn0wnxX

[Docs] macOS local HTTPS setup for satisfactory-solver

Request: Please add these macOS steps (or link them) so contributors can run the app locally over HTTPS. This includes the one‑line settings.py change for django_extensions, a trusted setup using mkcert, and a simple mkcert‑free self‑signed fallback.


Environment

  • OS: macOS (requires Homebrew — Install Homebrew)
  • Project: satisfactory-solver (Django)
  • Dev target (example): https://127.0.0.1:8100/

Python packages (for HTTPS in dev)

From the project’s virtualenv:

pip install django-extensions pyopenssl Werkzeug
# optional ASGI alternative
pip install uvicorn

Why

  • django-extensions → provides runserver_plus (HTTPS‑capable dev server)
  • pyopenssl & Werkzeug → TLS support required by runserver_plus
  • uvicorn → alternative ASGI server with --ssl-* flags

Minimal settings.py change (1 line)

Add django_extensions to INSTALLED_APPS in satopt/settings.py:

INSTALLED_APPS = [
    # ...
    'django.contrib.staticfiles',
    'django_extensions',  # ← enables runserver_plus
]

Option A — Trusted HTTPS with mkcert (recommended on macOS)

Yields a browser‑trusted localhost cert (no warnings).

Prerequisite: Homebrew must be installed. See brew.sh for installation steps.

A.1 Install mkcert & trust its local CA

brew install mkcert
# For Firefox trust store (optional):
brew install nss

# Add mkcert’s local CA to macOS (and Firefox if NSS is present)
mkcert -install

Tips:

  • Show CA folder: mkcert -CAROOT
  • Undo later: mkcert -uninstall (then delete CA files under $(mkcert -CAROOT)).

A.2 Generate project‑local cert/key

From the project root:

mkdir -p certs
mkcert -key-file certs/localhost-key.pem -cert-file certs/localhost.pem \
  localhost 127.0.0.1 ::1

# keep certs out of git
echo -e "
# dev TLS
certs/*.pem" >> .gitignore

A.3 Run the app over HTTPS (two choices)

A) Django WSGI dev server with TLS

python manage.py runserver_plus \
  --cert-file certs/localhost.pem \
  --key-file  certs/localhost-key.pem \
  127.0.0.1:8100
# open https://127.0.0.1:8100/

B) ASGI with uvicorn (dev‑only workaround may be needed)

# This project performs a sync DB call at startup; under ASGI that can raise
# SynchronousOnlyOperation. For local dev you can use this env var:
DJANGO_ALLOW_ASYNC_UNSAFE=true \
uvicorn satopt.asgi:application --host 127.0.0.1 --port 8100 \
  --ssl-certfile certs/localhost.pem \
  --ssl-keyfile  certs/localhost-key.pem
# open https://127.0.0.1:8100/

Option B — Simple HTTPS without mkcert (self‑signed)

Avoids mkcert entirely. Browsers will warn unless you manually trust the cert.

B.1 Create a SAN‑correct self‑signed cert with OpenSSL

mkdir -p certs
cat > certs/localhost-openssl.cnf <<'EOF'
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
CN = localhost

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
IP.1 = 127.0.0.1
IP.2 = ::1
EOF

openssl req -x509 -newkey rsa:2048 -nodes -days 825 \
  -keyout certs/localhost-key.pem -out certs/localhost.pem \
  -config certs/localhost-openssl.cnf

B.2 Run HTTPS with the self‑signed cert

A) runserver_plus

python manage.py runserver_plus \
  --cert-file certs/localhost.pem \
  --key-file  certs/localhost-key.pem \
  127.0.0.1:8100
# open https://127.0.0.1:8100/

B) uvicorn

# (same ASGI caveat; use the env var if needed)
DJANGO_ALLOW_ASYNC_UNSAFE=true \
uvicorn satopt.asgi:application --host 127.0.0.1 --port 8100 \
  --ssl-certfile certs/localhost.pem \
  --ssl-keyfile  certs/localhost-key.pem
# open https://127.0.0.1:8100/

B.3 (Optional) Trust the self‑signed cert

  • Safari/Chrome: import certs/localhost.pem into Keychain Access → set Always Trust.
  • Firefox: Settings → Privacy & Security → Certificates → View Certificates → AuthoritiesImport.

B.4 Alternative all‑pip approach

Install: pip install django-sslserver pyopenssl

settings.py

INSTALLED_APPS = [
    # ...
    'django.contrib.staticfiles',
    'sslserver',  # enables runsslserver
]

Run:

a) python manage.py runsslserver 127.0.0.1:8100
(auto‑generates a self‑signed cert with a browser warning)

or

b) python manage.py runsslserver --certificate certs/localhost.pem --key certs/localhost-key.pem 127.0.0.1:8100


Troubleshooting (HTTPS)

  • “Bad request version / HTTPS on HTTP port”: ensure you’re hitting the HTTPS URL (https://…) on the port where you enabled TLS. If you send HTTP to an HTTPS socket, the dev server prints TLS gibberish errors.
  • ASGI SynchronousOnlyOperation: the app does sync DB access during startup; in dev you can use DJANGO_ALLOW_ASYNC_UNSAFE=true with uvicorn, or use runserver_plus.
  • Firefox distrusts cert: install nss, rerun mkcert -install, or manually import the cert as an Authority.

Summary

  • pip: django-extensions, pyopenssl, Werkzeug (optional: uvicorn, django-sslserver).
  • settings.py: added 'django_extensions' to INSTALLED_APPS.
  • mkcert path (trusted): install mkcert (and nss), run mkcert -install, generate ./certs/localhost.pem + ./certs/localhost-key.pem, run with runserver_plus or uvicorn over HTTPS.
  • mkcert‑free path: generate a self‑signed SAN cert with OpenSSL (or use django-sslserver), run with runserver_plus/uvicorn.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions