A full-stack, self-hosted web application for Google Developer Groups on Campus (GDGoC) to generate, manage, and validate certificates.
This application provides:
- Admin Portal: Authenticated interface for GDGoC leaders to generate certificates (protected by authentik via Nginx Proxy Manager)
- Public Validation: Public page to validate certificate authenticity
- Email Notifications: Automatic email delivery of certificates via Brevo SMTP
- Proxy Authentication: Secure authentication using authentik Proxy Provider with Nginx Proxy Manager
- Frontend: React 18 with Vite
- Backend: Node.js with Express
- Database: PostgreSQL
- Authentication: authentik Proxy Provider with Nginx Proxy Manager
- Email: Brevo (formerly Sendinblue) SMTP
- Deployment: Docker & Docker Compose with Nginx Proxy Manager
This repository follows a monorepo structure:
.
├── backend/ # Node.js/Express API
│ ├── src/ # Source code
│ ├── schema.sql # Database schema
│ ├── Dockerfile # Docker build configuration
│ └── package.json
├── frontend/ # React application
│ ├── src/ # Source code
│ ├── Dockerfile # Docker build configuration
│ ├── nginx.conf # Nginx configuration for production
│ └── package.json
├── docker-compose.yml # Docker Compose configuration
├── .env.example # Environment variables template
├── DEPLOYMENT.md # Deployment documentation
└── README.md # This file
All source code and deployment files are maintained in this branch.
- Proxy Authentication: Uses authentik Proxy Provider with Nginx Proxy Manager for forward authentication
- Header-Based Auth: Application reads user information from proxy headers set by authentik
- Group-Based Access Control: Restrict access to users in the "GDGoC-Admins" group via authentik policies
- Automatic Provisioning: New users are automatically added to the database on first access
- Profile Setup: One-time organization name setup (cannot be changed later)
- Single Generation: Create individual certificates via form
- Bulk Upload: Generate multiple certificates from CSV file
- Unique IDs: Each certificate gets a unique, human-readable ID (format: GDGOC-YYYYMMDD-XXXXX)
- Email Delivery: Automatic email notification with certificate details
- Public Access: No authentication required
- Simple Interface: Enter certificate ID to validate
- Detailed Information: View all certificate details
The frontend uses hostname-based routing to serve different content:
sudo.certs-admin.certs.gdg-oncampus.dev→ Admin portalcerts.gdg-oncampus.dev→ Public validation page
- Node.js 18+ and npm
- PostgreSQL 14+
- authentik instance with Proxy Provider configured - Setup Guide
- Brevo account (for email) - Setup Guide
- Nginx Proxy Manager with forward authentication - Setup Guide
- Navigate to backend directory:
cd backend- Install dependencies:
npm install- Configure environment variables:
cp .env.example .env
# Edit .env with your configuration- Set up the database:
psql -U postgres -d gdgoc_certs -f schema.sql- Start the server:
npm startSee backend/README.md for detailed backend documentation.
- Navigate to frontend directory:
cd frontend- Install dependencies:
npm install- Configure environment variables:
cp .env.example .env
# Edit .env with your configuration- Start the development server:
npm run devSee frontend/README.md for detailed frontend documentation.
Stores authorized leaders who can generate certificates:
ocid(TEXT, PRIMARY KEY): Unique user identifier from authentik headersname(TEXT): Leader's full name (appears as issuer on certificates)email(TEXT, UNIQUE): Leader's emailorg_name(TEXT, NULLABLE): Organization name (set once, cannot be changed)can_login(BOOLEAN): Enable/disable access
Stores generated certificates:
id(UUID, PRIMARY KEY): Internal IDunique_id(TEXT, UNIQUE): Human-readable certificate IDrecipient_name(TEXT): Certificate recipient's namerecipient_email(TEXT): Recipient's email (optional)event_type(TEXT): 'workshop' or 'course'event_name(TEXT): Name of the eventissue_date(DATE): Date of issuanceissuer_name(TEXT): Name of the issuing leaderorg_name(TEXT): Organization namegenerated_by(TEXT): OCID of the leader who generated itpdf_url(TEXT): URL to certificate PDF (optional)
Note: Authentication is handled by authentik Proxy Provider via Nginx Proxy Manager. The application reads user information from headers set by the proxy.
POST /api/auth/login- Process login from proxy headers (auto-provision users)GET /api/auth/me- Get current user infoPUT /api/auth/profile- Update user profile
POST /api/certificates/generate- Generate single certificatePOST /api/certificates/generate-bulk- Generate from CSVGET /api/certificates- List user's certificates
GET /api/validate/:unique_id- Validate certificate (public, no authentication required)
The backend API only accepts requests from:
https://sudo.certs-admin.certs.gdg-oncampus.devhttps://certs.gdg-oncampus.dev
This is configured in the backend via the ALLOWED_ORIGINS environment variable.
For production deployment with Docker, see the comprehensive DEPLOYMENT.md guide.
Quick start:
cp .env.example .env
# Edit .env with your configuration
docker compose up -dThe application uses Docker Compose with three services:
- PostgreSQL database
- Node.js backend API
- React frontend with Nginx
All services run on a custom Docker network and are accessed via Nginx Proxy Manager (no ports exposed to host).
recipient_name,recipient_email,event_type,event_name
John Doe,john@example.com,workshop,Introduction to Web Development
Jane Smith,jane@example.com,course,Advanced React PatternsRequirements:
- First row must be the header
event_typemust be either "workshop" or "course"recipient_emailis optional
- Proxy-Based Authentication: All authentication is handled at the proxy layer by authentik
- Header Trust: Application trusts authentication headers set by Nginx Proxy Manager
- Group-Based Access: Only users in GDGoC-Admins group can access admin portal (configured in authentik)
- CORS: Strict CORS policy limiting allowed origins
- No Exposed Ports: Services communicate via Docker network, accessed only through proxy
- Environment Variables: Sensitive data stored in environment variables
- Application Isolation: Backend and frontend are not directly accessible, only through authenticated proxy
GNU AGPL v3
This is a project for GDGoC. Please follow the established patterns and conventions when contributing.
- Troubleshooting Guide - Common issues and solutions
- Deployment Guide - Docker deployment and operations
- authentik Proxy Provider Setup - Configure proxy authentication
- Brevo Setup - Configure SMTP email service
- Nginx Proxy Manager Setup - Configure forward authentication with authentik
For issues or questions:
- Check the Troubleshooting Guide
- Review logs:
docker compose logs -f - Contact the GDGoC team