Skip to content

Deployment Unknowns & Prerequisites ​

Things that need to be sourced, provisioned, or decided before a production deployment can go live. None of these exist in the codebase — they were held by the third party and were never handed over.


External services (credentials needed) ​

These are live third-party integrations the app calls at runtime. Without valid credentials the relevant features will fail silently or error.

ServiceWhat it doesEnv var(s) neededStatus
SendGridTransactional emailSENDGRID_API_KEY✅ Account and key provided by third party — variable entry only
Google reCAPTCHA v3Contact form bot protectionDJANGO_GOOGLE_RECAPTCHA_TOKEN❓ Need site secret
Clear ChecksApplicant background checksCLEARCHECKS_URL, CLEARCHECKS_API_KEY⚠️ Marked deprecated in code (v2.1.0) — confirm if still needed

SendGrid — remaining steps ​

Credentials are in hand. Before go-live:

  • Update DEFAULT_FROM_EMAIL away from Medical Web Experts <devops@medicalwebexperts.com> to a Nova Home Care address
  • Verify the sending domain in SendGrid (add SPF + DKIM DNS records)
  • Set SENDGRID_API_KEY in the production secrets store

AWS resources (to be provisioned) ​

These don't exist yet and need to be created in the NHC AWS account.

S3 — two buckets required ​

The Django backend uses S3 for both static files and user-uploaded media. Two separate buckets are expected:

BucketPurposeACL
Public bucketcollectstatic output, public uploadspublic-read for static prefix
Private bucketPatient/employee documents, PDFsprivate — access via presigned URLs

Env vars: DJANGO_AWS_S3_PUBLIC_BUCKET_NAME, DJANGO_AWS_S3_PRIVATE_BUCKET_NAME, DJANGO_AWS_S3_REGION_NAME, DJANGO_AWS_ACCESS_KEY_ID, DJANGO_AWS_SECRET_ACCESS_KEY

An optional CloudFront distribution can front the public bucket: DJANGO_AWS_S3_CUSTOM_DOMAIN

IAM ​

A dedicated IAM user or role needs S3 read/write on both buckets. If running on EC2 or ECS, prefer an instance role / task role over long-lived access keys.


The signing certificate (nova.p12) ​

The app uses pyHanko to digitally sign PDF documents. It expects:

  • A .p12 file at secrets/nova.p12 inside the container
  • The certificate password in PYHANKO_P12_PASSWORD

This is a hard blocker — without it, the app starts and logs in normally but PDF signing fails silently. A user submits a form, the document stays stuck in a pending state indefinitely, and the Celery worker logs the error. No crash, no obvious alert — it just never completes.

Step 1 — identify what type of cert was used ​

Download any PDF that was signed on the third party's staging environment. Open it in Adobe Acrobat Reader and look at the signature panel:

What Adobe showsCertificate type
Green checkmark, "Certified by..." with a known issuerCommercial cert (DigiCert, GlobalSign, Sectigo, etc.)
Yellow warning, "The identity of the signer is unknown"Self-signed

If you cannot get a signed PDF from the third party's environment, assume self-signed and proceed to Step 3.

Step 2 — request the certificate from the third party ​

The cert was generated for Nova Home Care — it belongs to the client, not the developer. Request:

  • The nova.p12 file
  • The password used to protect it (PYHANKO_P12_PASSWORD)

If they cooperate, skip to Step 4.

Step 3 — if they won't or can't provide it ​

If self-signed — generate a replacement. There is no loss of functionality. New documents will be signed with the new cert; existing signed documents remain valid against the old cert (the public key is embedded in each PDF at signing time).

bash
# Run on any machine with OpenSSL installed
openssl req -x509 -newkey rsa:2048 -keyout nova.key -out nova.crt -days 3650 -nodes \
  -subj "/CN=Nova Home Care/O=Nova Home Care/C=US"

# It will prompt for an export password — set one and record it as PYHANKO_P12_PASSWORD
openssl pkcs12 -export -out nova.p12 -inkey nova.key -in nova.crt \
  -name "Nova Home Care Signing"

# Clean up — only nova.p12 is needed going forward
rm nova.key nova.crt

If commercial — purchase a new document signing certificate. The new cert will have a different issuer fingerprint but the app does not care — pyHanko only needs a valid .p12. Existing signed PDFs are unaffected.

Recommended issuers (all support PKCS12 / .p12 export):

IssuerApproximate cost
Sectigo (Comodo)~$100/year
DigiCert~$200/year
GlobalSign~$150/year

Step 4 — deploy the certificate ​

Never commit nova.p12 to the repo. In production, store it as a binary secret and mount it at runtime:

bash
# Copy to the secrets directory on the EC2 instance
sudo mkdir -p /opt/nhc-portals/django-api/secrets
sudo cp nova.p12 /opt/nhc-portals/django-api/secrets/nova.p12
sudo chmod 600 /opt/nhc-portals/django-api/secrets/nova.p12

Set PYHANKO_P12_PASSWORD in django-api/.env to the certificate password.

Verify it works by running the PDF smoke test in the Smoke Tests checklist before signing off on the migration.


Frontend — what replaces Netlify ​

The portals .env.development.example references https://develop--novahomecaresite.netlify.app — that's the third party's Netlify deployment. It needs to be replaced.

In production the React/Vite app is a static build (not a dev server). Options:

  • S3 + CloudFront — natural fit since S3 is already used for Django storage
  • Cloudflare Pages — already proven for this org (docs are deployed this way)

VITE_SITE_BASE_URL must be updated to the new domain once decided.


Django secret key ​

DJANGO_SECRET_KEY must be a long random string unique to production. Never reuse the development value. Generate one:

bash
python -c "import secrets; print(secrets.token_urlsafe(50))"

ALLOWED_HOSTS and CORS origins ​

Once the production domain is known, set:

  • DJANGO_ALLOWED_HOSTS — the API domain (e.g. api.novavirtual.site)
  • DJANGO_ALLOWED_ORIGINS — the frontend domain (e.g. https://app.novavirtual.site)

The EC2 private IP is auto-detected from the EC2 metadata endpoint and added to ALLOWED_HOSTS automatically for ALB health checks — no manual config needed for that.


Organization tokens ​

Three org tokens are hardcoded across the codebase and in the testing .env:

TokenOrg
5ae807a7-df99-4bc2-8d51-fa808b81a41eNova Health First, Inc
e9686292-0b70-4019-9ef1-c1a275a9723dEssential Home Health Care
9f66eef3-be72-482b-a6a9-c1eb647367f8Aurora Home Health (also in DJANGO_AURORA_ORG_TOKEN)

These tokens are set in the database via fixtures. Confirm the production database is loaded from the same fixtures and these tokens match.


Summary checklist ​

  • [x] SendGrid — account and key provided, variable entry only
  • [ ] SendGrid — update sender identity away from medicalwebexperts.com
  • [ ] SendGrid — verify sending domain (SPF + DKIM)
  • [ ] Google reCAPTCHA v3 site key + secret
  • [ ] nova.p12 — request from third party (belongs to Nova HC); regenerate if unavailable
  • [ ] S3 public bucket created
  • [ ] S3 private bucket created
  • [ ] IAM role/user with S3 access
  • [ ] Django secret key generated for production
  • [ ] Decision on frontend hosting (S3+CloudFront or Cloudflare Pages)
  • [ ] Production domains decided (DJANGO_ALLOWED_HOSTS, DJANGO_ALLOWED_ORIGINS, VITE_SITE_BASE_URL)
  • [ ] Clear Checks — confirm deprecated and disable, or provide sandbox/prod key
  • [ ] Database loaded with correct fixtures and org tokens verified

Nova Home Care — Internal Operational Docs