Intellidwell Logo Docs
IntelliSignup App ↗

⚙️ Operations, Deployment & Configuration

IntelliSignup is deployed as a hardened, self-hosted web service on NelsonServer infrastructure. This guide covers service administration, environment secrets, Nginx reverse proxying, database migration lifecycles, and automated background jobs.

💡 Production Summary

The application runs on Python 3.12 under a dedicated virtualenv at /home/nelsonserver/websites/intellisignup/. Gunicorn listens on internal port 8581 behind an Nginx reverse proxy that handles SSL termination for intellisignup.net and www.intellisignup.net.

1. Production Architecture Overview

Web Ingress
Nginx (:80 / :443)

Let's Encrypt SSL, HTTP/2, 7-day static asset cache headers, proxy headers.

➔ HTTP :8581
Application
Gunicorn WSGI

Systemd daemon intellisignup.service, 4 workers, timeout 30s.

➔ 15m Timer
Background Worker
Reminder Worker

Systemd timer intellisignup-reminders.timer executing send_reminders.py.

2. Environment Variables Reference (.env)

Runtime secrets and service integrations are managed through environment variables stored in /home/nelsonserver/websites/intellisignup/.env (or systemd EnvironmentFile /etc/intellisignup/intellisignup.env):

Variable Name Required Default / Format Description
SECRET_KEY Yes Hex / Base64 string Cryptographic secret used for session cookies, CSRF protection, and serializer salts.
APP_ENCRYPTION_KEY Yes Fernet 32-byte key AES-256 Fernet key used to encrypt Google OAuth tokens and credentials at rest in the database.
PUBLIC_BASE_URL Yes https://intellisignup.net Canonical origin URL required for constructing absolute links in background email dispatches.
MAIL_SERVER Yes SMTP host (e.g. mail.intellidwell.net) Hostname of the outbound SMTP relay server.
MAIL_PORT Yes 587 or 465 SMTP port (587 for STARTTLS, 465 for SSL).
MAIL_USERNAME Yes Email address string Authentication user for the SMTP mail gateway.
MAIL_PASSWORD Yes Secret string Authentication password for the SMTP mail gateway.
MAIL_USE_TLS No true Enables STARTTLS security for SMTP connections on port 587.
MAIL_DEFAULT_SENDER Yes IntelliSignup <noreply@...> From header attached to all automated notifications.
GOOGLE_CLIENT_ID Optional Google OAuth Client ID Client ID from Google Cloud Console for 2-way Google Calendar integration.
GOOGLE_CLIENT_SECRET Optional Google OAuth Client Secret Client Secret from Google Cloud Console for calendar syncing.
GOOGLE_REDIRECT_URI Optional https://intellisignup.net/integrations/google/callback Whitelisted OAuth redirect URI configured in Google Developer Console.
TURNSTILE_SITE_KEY Optional Cloudflare Site Key Public widget key for Cloudflare Turnstile passive CAPTCHA on signup.
TURNSTILE_SECRET_KEY Optional Cloudflare Secret Key Private secret key for verifying Turnstile tokens against Cloudflare API.
APP_TIMEZONE No America/Denver Local timezone basis for reminder evaluation and event schedules.

3. Systemd Services & Timers

The service lifecycle is isolated into two managed systemd units under /etc/systemd/system/:

A. Web Service (intellisignup.service)

systemd Unit (intellisignup.service)
[Unit]
Description=IntelliSignup Gunicorn
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=nelsonserver
Group=nelsonserver
WorkingDirectory=/home/nelsonserver/websites/intellisignup
Environment="PATH=/home/nelsonserver/websites/intellisignup/.venv/bin"
Environment="PYTHONUNBUFFERED=1"
Environment="GUNICORN_BIND=127.0.0.1:8581"
ExecStart=/home/nelsonserver/websites/intellisignup/.venv/bin/gunicorn -c /home/nelsonserver/websites/intellisignup/gunicorn_config.py wsgi:app
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
TimeoutStopSec=30
KillMode=mixed
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
SyslogIdentifier=intellisignup

[Install]
WantedBy=multi-user.target

B. Reminder Engine (intellisignup-reminders.timer)

systemd Timer (intellisignup-reminders.timer)
[Unit]
Description=Run IntelliSignup reminder email job

[Timer]
OnBootSec=5m
OnUnitActiveSec=15m
Persistent=true
Unit=intellisignup-reminders.service

[Install]
WantedBy=timers.target

Essential Service Commands

Bash
# Check live web application status
sudo systemctl status intellisignup

# Restart web application
sudo systemctl restart intellisignup

# Check active reminder timers
sudo systemctl list-timers intellisignup-reminders.timer

# View live application logs
sudo journalctl -u intellisignup -f

# View reminder execution history
sudo journalctl -u intellisignup-reminders -n 50 --no-pager

4. Nginx Reverse Proxy & SSL Configuration

Nginx sits at the edge, serving static CSS/JS assets directly from disk with aggressive 7-day immutable caching headers while passing dynamic requests to Gunicorn:

Nginx Configuration (intellisignup.conf)
server {
    server_name intellisignup.net www.intellisignup.net;

    access_log /var/log/nginx/intellisignup.access.log;
    error_log /var/log/nginx/intellisignup.error.log;

    # Static Asset Offloading with 7-Day Immutable Cache
    location /static/ {
        alias /home/nelsonserver/websites/intellisignup/app/static/;
        expires 7d;
        add_header Cache-Control "public, max-age=604800, immutable";
    }

    # Proxy Pass to Local Gunicorn Socket
    location / {
        proxy_pass http://127.0.0.1:8581;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 60;
    }
}

5. Alembic Database Migrations

Database schema changes are managed through Alembic and Flask-Migrate under migrations/versions/. The migration tree records evolutionary milestones:

  • e1b9d3f4c2a1: Adds email verification fields (email_verified, email_verified_at) to User.
  • 9a12b6c4d5e7: Implements SignupWaitlistEntry schema for waitlist queuing.
  • 166cec55f218: Introduces CustomForm, CustomFormField, and CustomFormResponse questionnaires.
  • 67196f9e3862: Adds share_token and share_responses_enabled for public results sharing.
  • b5c8fce869f3: Adds publishing state and reusable SignupTemplate tables.
  • 7c64b6b00f3a & b7585d431d05: Adds GoogleCalendarConnection and event/claim calendar sync IDs.
  • 6f3a1d2c4b8e: Introduces RateLimitEvent for sliding-window anti-spam auditing.
  • c3f9a7b21d4e: Adds privacy-preserving AnalyticsPageView table.
Bash (Database Upgrade)
cd /home/nelsonserver/websites/intellisignup
source .venv/bin/activate
flask db upgrade

6. NelsonServer Dual-Push Git Deployment

The codebase is configured with a unified dual-remote Git pipeline. Running a single push updates both the local bare production repository and GitHub simultaneously:

Bash
# Deploy to local server and GitHub in one step:
git push origin main
  • Local Bare Repository: /srv/git/intellisignup.git
  • GitHub Remote: git@github.com:TannerNelson16/intellisignup.git
  • Secret Isolation: All sensitive credentials (.env), SQLite databases (instance/*.db), and email activity logs are shielded via .gitignore, ensuring only clean source code reaches public or external remotes.

7. Monitoring & Troubleshooting Guide

🔍 Inspect Outbound Email Activity

Monitor real-time SMTP delivery attempts, skipped claims, or delivery failures: tail -n 50 -f /home/nelsonserver/websites/intellisignup/instance/email_activity.log

🚦 Test Anti-Spam Registration Traps

Run the automated security suite to test disposable email rejection, rate limiting, and honeypot traps: python test_signup_security.py

⏰ Trigger Immediate Reminders

Force an immediate manual sweep of due reminder emails without waiting for the 15-minute systemd timer: python send_reminders.py

🔒 Verify Turnstile Verification

If registration challenges fail, check outgoing HTTPS connectivity from the server to challenges.cloudflare.com:443.