Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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