Everything you need to go from zero to a fully running Pinpoint 311 deployment, step by step.
You need a Linux server (Ubuntu recommended). Use any cloud provider — Oracle Cloud (free tier), AWS, Google Cloud, DigitalOcean, or an on-premise machine.
| Minimum Specs | Details |
|---|---|
| CPU | 1 vCPU (2+ recommended for production) |
| RAM | 1 GB minimum (2+ GB recommended) |
| Disk | 20 GB+ |
| OS | Ubuntu 22.04 or 24.04 LTS recommended |
From your local machine, connect to the server using SSH:
💡 All remaining steps are run on the server, not your local machine.
First, check if Docker is already installed:
If Docker is not installed, run these commands:
SSH back in, then verify Docker is working:
💡 If Docker is already installed, skip this step entirely.
Your cloud provider's firewall (security groups / network rules) must allow inbound traffic on these ports:
| Port | Protocol | Purpose |
|---|---|---|
| 22 | TCP | SSH access (already open if you can connect) |
| 80 | TCP | HTTP — web traffic & Let's Encrypt certificate validation |
| 443 | TCP | HTTPS — secure web traffic (auto-enabled with a domain) |
Where to configure this depends on your cloud provider:
| Provider | Where to Open Ports |
|---|---|
| Oracle Cloud | Networking → Virtual Cloud Networks → Security Lists → Add Ingress Rules |
| AWS | EC2 → Security Groups → Edit Inbound Rules |
| Google Cloud | VPC Network → Firewall → Create Firewall Rule |
| DigitalOcean | Networking → Firewalls → Create Firewall |
If your server also has a local firewall (e.g. ufw on Ubuntu), open the ports there too:
docker compose up.| Service | Why |
|---|---|
| Google Cloud | Maps, Vertex AI (Gemini), Translate, Secret Manager |
| Auth0 Account | Staff SSO, MFA, passkeys — free tier |
| Custom Domain | e.g. 311.yourtown.gov |
| SMTP Server | Confirmation & status emails |
On your server, download and extract the latest release:
💡 Or download directly from the Releases page — click the latest version and download "Source code (tar.gz)".
.env file never leaves your server. This ensures your API keys and Resident Data stay securely within your own infrastructure.311.yourcity.gov), you MUST point your DNS A-Record to this server's IP address before moving to Step 4. If you set DOMAIN below but the DNS is not pointed, the server will fail to start and throw SSL Protocol errors.| Variable | What to set |
|---|---|
DOMAIN |
Your domain (e.g., 311.yourcity.gov), or localhost for local testing |
DB_PASSWORD |
A strong, unique database password |
SECRET_KEY |
Paste the secure key you generated above |
ADMIN_EMAIL |
Your admin contact email |
You should see backend, frontend, db,
redis, caddy, and worker — all Up or healthy.
| Portal | URL |
|---|---|
| Resident Portal | http://localhost/ |
| Staff Dashboard | http://localhost/staff |
| Admin Console | http://localhost/admin |
| Research Lab | http://localhost/research |
| API Docs | http://localhost/api/docs |
After the containers start, you need to log into the Admin Console to configure your system.
http://your-server-ip/login in your browser💡 If your browser shows an SSL error, use port 8000 instead: http://your-server-ip:8000/login
Alternatively, run this on the server:
Copy the login_url from the JSON response and open it in your browser.
docker compose ps — all services should show "healthy".Go to auth0.com and create a free account (or use your organization's existing tenant). The free tier supports up to 7,000 active users.
| Setting | Value |
|---|---|
| Allowed Callback URLs | https://311.yourtown.gov/api/auth/callback |
| Allowed Logout URLs | https://311.yourtown.gov/staff |
| Allowed Web Origins | https://311.yourtown.gov |
/api/auth/callback appended. A single typo here will cause staff logins to fail silently.In the Auth0 Dashboard, go to Security → Multi-factor Auth and enable MFA. Staff will be prompted to set up a second factor on their first login.
Under Authentication → Social, add Google and Microsoft connections so staff can log in with their existing work accounts.
Go to Setup & Integration → Auth0, enter your Auth0 Domain, Client ID, and Client Secret, and save.
Go to console.cloud.google.com and create a new project or select an existing one. Note your Project ID (not the project name).
Go to APIs & Services → Library and enable all four:
| API | What it powers |
|---|---|
| Cloud KMS API | PII encryption at rest (HSM-backed, FIPS 140-2) |
| Cloud Translation API | Multi-language support (109 languages) |
| Vertex AI API | AI request analysis, priority scoring, photo assessment, duplicate detection |
| Secret Manager API | Enterprise secrets vault for production credentials |
Navigate to Security → Key Management:
pinpoint311) and select a location (e.g., us-central1)pii-encryption), purpose: Symmetric encrypt/decryptGo to IAM & Admin → Service Accounts → Create. Grant it these roles:
| Role | Purpose |
|---|---|
Cloud KMS CryptoKey Encrypter/Decrypter |
Encrypt/decrypt PII data |
Cloud Translation API User |
Translate submissions |
Vertex AI User |
AI-powered analysis |
Secret Manager Admin |
Manage secrets vault |
On the Service Account page, go to Keys → Add Key → Create new key → JSON. Download and keep this file secure — it's your master credential.
Go to Setup & Integration → Google Cloud:
Click Migrate to Secret Manager to vault all API credentials (Maps key, SMTP password, Twilio token, etc.) into GCP.
GCP_SERVICE_ACCOUNT_JSON and GOOGLE_CLOUD_PROJECT) always stay in the local DB — they're the master keys needed to access Secret Manager itself.| Restriction | Value |
|---|---|
| API restrictions | Maps JavaScript, Places, Geocoding |
| Website restrictions | https://311.yourtown.gov/* |
Go to Setup & Integration → Google Maps and paste your API key. If you activated Secret Manager in Step 7, this key is automatically vaulted into GCP.
For 45° tilt, rotation, and 3D buildings on the map:
In the Admin Console, go to Staff Management and add your team:
| Role | Access Level | Best For |
|---|---|---|
| Admin | Full Admin Console + all operations | IT staff, department heads |
| Staff | View, manage, and resolve requests | Field workers, dispatchers |
| Researcher | Privacy-preserved analytics only | Analysts, council members |
Staff log in via Auth0 SSO — no passwords stored in the system.
| Provider | Host | Port | Username |
|---|---|---|---|
| Gmail | smtp.gmail.com |
587 |
Your Gmail address |
| SendGrid | smtp.sendgrid.net |
587 |
apikey (literal) |
| Org relay | Your server's SMTP host | Varies | Varies |
Enter the host, port, from address, username, and password in Admin Console → Setup & Integration → Email (SMTP) and click Save SMTP Settings.
If you have an existing SMS gateway, select "Custom HTTP API" and provide your endpoint URL. Pinpoint sends a POST request with:
Requests outside the boundary are automatically rejected. Get your file from:
Upload in Setup & Integration → Municipality Boundaries.
In Admin Console → Services, create categories (Pothole, Streetlight, etc.):
| Setting | Description |
|---|---|
| Routing | Township Handled, Third-Party, or Road-Based |
| Department | Which team handles it |
| Questions | Follow-up questions per service |
In Admin Console → Branding:
Auto-applied to Resident Portal, all emails, SMS, and Staff Dashboard.
In Branding → Legal Documents:
All support Markdown formatting. Sensible defaults included.
| Type | Name | Value |
|---|---|---|
| A | 311.yourtown.gov |
Your server IP |
Caddy auto-provisions SSL and redirects HTTP → HTTPS.
| ✓ | Item |
|---|---|
| ☐ | Secure DB_PASSWORD and SECRET_KEY (not defaults) |
| ☐ | Auth0 configured, bootstrap disabled |
| ☐ | Google Maps key working |
| ☐ | Municipality boundary uploaded |
| ☐ | At least one service category |
| ☐ | At least one department with staff |
| ☐ | SMTP email configured and tested |
| ☐ | Branding set (logo, name, colors) |
| ☐ | Legal documents reviewed |
| ☐ | Custom domain with HTTPS |
| ☐ | Full lifecycle test: submit → staff → resolve → email |
Automated (recommended): Configure S3-compatible storage in Admin Console → Setup & Integration → Database Backups:
| Field | Description |
|---|---|
S3 Bucket |
Your bucket name (AWS S3, Oracle Object Storage, MinIO, etc.) |
Access Key |
IAM access key with s3:PutObject, s3:GetObject permissions |
Secret Key |
Corresponding secret key |
Encryption Key |
Passphrase for AES-256 backup encryption — store this securely |
Endpoint |
Optional: Custom endpoint for Oracle/MinIO (leave blank for AWS) |
Manual: Take a one-off backup any time:
Migrations run automatically on startup. To run manually:
| State | Period |
|---|---|
| Texas | 10 years |
| NJ, PA, WI | 7 years |
| NY, MI, WA, CT | 6 years |
| CA, FL, most | 5 years (default) |
| GA, MA | 3 years |
Need help? We're here for you.
© 2024–2026 Pinpoint 311 · MIT License · Fiscally sponsored by Hack Club 501(c)(3)