feat(docker): add Docker deployment configuration
Add production-ready Docker setup with multi-stage Dockerfile, docker-compose orchestration for API, PostgreSQL, Redis, and Nginx services. Includes health checks, non-root user execution, and proper networking. - Add multi-stage Dockerfile with gunicorn/gevent workers - Add docker-compose.yml with api, db, redis, nginx services - Add nginx reverse proxy configuration with security headers - Update .env.example with Docker and production variables - Add email provider configuration (Mailgun, SendGrid) - Add requests dependency for HTTP client support - Update documentation with Docker deployment guide - Rebrand project name from Gatehouse to Secuird
This commit is contained in:
+33
-4
@@ -2,8 +2,24 @@ FLASK_APP=manage.py
|
|||||||
FLASK_ENV=development
|
FLASK_ENV=development
|
||||||
FLASK_DEBUG=1
|
FLASK_DEBUG=1
|
||||||
|
|
||||||
# Database
|
# ═════════════════════════════════════════════════════════════════════════════
|
||||||
DATABASE_URL=postgresql://user:password@localhost:5432/gatehouse_dev
|
# Docker / Production
|
||||||
|
# ═════════════════════════════════════════════════════════════════════════════
|
||||||
|
COMPOSE_PROJECT_NAME=authy2
|
||||||
|
FLASK_ENV=production
|
||||||
|
POSTGRES_USER=authy2
|
||||||
|
POSTGRES_PASSWORD=changeme-in-production
|
||||||
|
POSTGRES_DB=authy2
|
||||||
|
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
|
||||||
|
SQLALCHEMY_DATABASE_URI=${DATABASE_URL}
|
||||||
|
REDIS_URL=redis://redis:6379/0
|
||||||
|
SESSION_REDIS_URL=redis://redis:6379/0
|
||||||
|
RATELIMIT_STORAGE_URL=redis://redis:6379/1
|
||||||
|
HTTP_PORT=80
|
||||||
|
HTTPS_PORT=443
|
||||||
|
API_PORT=5000
|
||||||
|
|
||||||
|
# Database (overridden by Docker values above)
|
||||||
SQLALCHEMY_ECHO=False
|
SQLALCHEMY_ECHO=False
|
||||||
SQLALCHEMY_LOG_LEVEL=WARNING
|
SQLALCHEMY_LOG_LEVEL=WARNING
|
||||||
|
|
||||||
@@ -15,7 +31,7 @@ CA_ENCRYPTION_KEY=change-me-in-production
|
|||||||
BCRYPT_LOG_ROUNDS=12
|
BCRYPT_LOG_ROUNDS=12
|
||||||
|
|
||||||
# Session cookies
|
# Session cookies
|
||||||
SESSION_COOKIE_SECURE=False
|
SESSION_COOKIE_SECURE=True
|
||||||
SESSION_COOKIE_SAMESITE=Lax
|
SESSION_COOKIE_SAMESITE=Lax
|
||||||
# Only needed when sharing cookies across subdomains (e.g. api.example.com + ui.example.com)
|
# Only needed when sharing cookies across subdomains (e.g. api.example.com + ui.example.com)
|
||||||
# SESSION_COOKIE_DOMAIN=example.com
|
# SESSION_COOKIE_DOMAIN=example.com
|
||||||
@@ -61,7 +77,7 @@ OIDC_BASE_URL=http://localhost:5000
|
|||||||
# WebAuthn
|
# WebAuthn
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
WEBAUTHN_RP_ID=localhost
|
WEBAUTHN_RP_ID=localhost
|
||||||
WEBAUTHN_RP_NAME=Gatehouse
|
WEBAUTHN_RP_NAME=Secuird
|
||||||
WEBAUTHN_ORIGIN=http://localhost:8080
|
WEBAUTHN_ORIGIN=http://localhost:8080
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -81,6 +97,19 @@ SMTP_USERNAME=
|
|||||||
SMTP_PASSWORD=
|
SMTP_PASSWORD=
|
||||||
FROM_ADDRESS=noreply@gatehouse.local
|
FROM_ADDRESS=noreply@gatehouse.local
|
||||||
|
|
||||||
|
# Email Provider (smtp, mailgun, sendgrid)
|
||||||
|
# Note: SMTP is the default. Set to "mailgun" or "sendgrid" to use those providers
|
||||||
|
EMAIL_PROVIDER=smtp
|
||||||
|
|
||||||
|
# Mailgun Configuration (used when EMAIL_PROVIDER=mailgun)
|
||||||
|
# MAILGUN_API_KEY=your-mailgun-api-key
|
||||||
|
# MAILGUN_DOMAIN=mg.yourdomain.com
|
||||||
|
# MAILGUN_API_URL=https://api.mailgun.net/v3
|
||||||
|
|
||||||
|
# SendGrid Configuration (used when EMAIL_PROVIDER=sendgrid)
|
||||||
|
# SENDGRID_API_KEY=SG.your-sendgrid-api-key
|
||||||
|
# SENDGRID_FROM_EMAIL=noreply@yourdomain.com
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
# Logging
|
# Logging
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ Thumbs.db
|
|||||||
# Project specific
|
# Project specific
|
||||||
|
|
||||||
*.db
|
*.db
|
||||||
|
flask_session/
|
||||||
|
|
||||||
# Opencode files and folders
|
# Opencode files and folders
|
||||||
.opencode/
|
.opencode/
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
# Multi-stage build for Gatehouse Auth API
|
||||||
|
# Build stage
|
||||||
|
FROM python:3.11-slim as builder
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
libpq-dev \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create virtual environment
|
||||||
|
RUN python -m venv /opt/venv
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
|
||||||
|
# Copy requirements files
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements/base.txt requirements/base.txt
|
||||||
|
COPY requirements/production.txt requirements/production.txt
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN pip install --no-cache-dir --upgrade pip wheel && \
|
||||||
|
pip install --no-cache-dir -r requirements/production.txt
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
libpq5 \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN groupadd --gid 1000 appgroup && \
|
||||||
|
useradd --uid 1000 --gid appgroup --shell /bin/bash --create-home appuser
|
||||||
|
|
||||||
|
# Copy virtual environment from builder
|
||||||
|
COPY --from=builder /opt/venv /opt/venv
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
|
||||||
|
# Copy application code
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --chown=appuser:appgroup . .
|
||||||
|
|
||||||
|
# Create log and session directories
|
||||||
|
RUN mkdir -p /app/logs /app/flask_session && chown -R appuser:appgroup /app/logs /app/flask_session
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:5000/api/health || exit 1
|
||||||
|
|
||||||
|
# Run gunicorn with gevent workers
|
||||||
|
CMD ["gunicorn", "--bind", "0.0.0.0:5000", \
|
||||||
|
"--workers", "4", \
|
||||||
|
"--worker-class", "gevent", \
|
||||||
|
"--worker-connections", "1000", \
|
||||||
|
"--timeout", "120", \
|
||||||
|
"--access-logfile", "-", \
|
||||||
|
"--error-logfile", "-", \
|
||||||
|
"--log-level", "info", \
|
||||||
|
"wsgi:application"]
|
||||||
@@ -64,7 +64,7 @@ python scripts/init_db.py
|
|||||||
|
|
||||||
6. **Seed sample data** (optional):
|
6. **Seed sample data** (optional):
|
||||||
```bash
|
```bash
|
||||||
python scripts/seed_data.py
|
python -m scripts.seed_data
|
||||||
```
|
```
|
||||||
|
|
||||||
7. **Run the application**:
|
7. **Run the application**:
|
||||||
@@ -77,6 +77,71 @@ python wsgi.py
|
|||||||
The API will be available at `http://localhost:5000`
|
The API will be available at `http://localhost:5000`
|
||||||
|
|
||||||
|
|
||||||
|
## Docker Deployment
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- Docker 20.10+
|
||||||
|
- Docker Compose 2.0+
|
||||||
|
|
||||||
|
### Quick Start
|
||||||
|
|
||||||
|
1. **Start all services**:
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Initialize the database** (run migrations):
|
||||||
|
```bash
|
||||||
|
docker-compose exec api python manage.py db upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Seed sample data** (optional):
|
||||||
|
```bash
|
||||||
|
docker-compose exec api python scripts/seed_data.py
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Verify health**:
|
||||||
|
```bash
|
||||||
|
curl http://localhost:5000/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Useful Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View logs
|
||||||
|
docker-compose logs -f api
|
||||||
|
|
||||||
|
# Run migrations
|
||||||
|
docker-compose exec api python manage.py db upgrade
|
||||||
|
|
||||||
|
# Open shell in container
|
||||||
|
docker-compose exec api /bin/bash
|
||||||
|
|
||||||
|
# Rebuild after changes
|
||||||
|
docker-compose up -d --build
|
||||||
|
|
||||||
|
# Stop all services
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Copy `.env.example` to `.env` and configure:
|
||||||
|
- `POSTGRES_USER` / `POSTGRES_PASSWORD` - Database credentials
|
||||||
|
- `SECRET_KEY` - Flask secret key (required in production)
|
||||||
|
- `ENCRYPTION_KEY` - Data encryption key
|
||||||
|
- `CA_ENCRYPTION_KEY` - CA private key encryption
|
||||||
|
- `CORS_ORIGINS` - Allowed CORS origins (comma-separated)
|
||||||
|
|
||||||
|
### Production Considerations
|
||||||
|
|
||||||
|
- Use a strong `SECRET_KEY` (256-bit random)
|
||||||
|
- Enable HTTPS via nginx (configure SSL certificates)
|
||||||
|
- Set `BCRYPT_LOG_ROUNDS=13` for stronger password hashing
|
||||||
|
- Use Redis persistence (`--appendonly yes`)
|
||||||
|
- Configure log aggregation as needed
|
||||||
|
|
||||||
|
|
||||||
## API Endpoints
|
## API Endpoints
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
@@ -197,22 +262,45 @@ python manage.py db upgrade
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
## running seed
|
## Development Commands
|
||||||
python -m scripts.seed_data
|
|
||||||
|
|
||||||
## Running flask in dev
|
### Run Flask in Development
|
||||||
|
```bash
|
||||||
FLASK_ENV=development flask run --debug --port 8888
|
FLASK_ENV=development flask run --debug --port 8888
|
||||||
|
```
|
||||||
|
|
||||||
|
### Seed Sample Data
|
||||||
|
```bash
|
||||||
|
python -m scripts.seed_data
|
||||||
|
# Or with Docker:
|
||||||
|
docker-compose exec api python scripts/seed_data.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Migration
|
||||||
|
```bash
|
||||||
|
# Apply migrations
|
||||||
|
flask db upgrade
|
||||||
|
|
||||||
|
# With Docker:
|
||||||
|
docker-compose exec api python manage.py db upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
### SQLite Browser (Development)
|
||||||
|
```bash
|
||||||
|
sqlite_web instance/db_file.db --port 9999 --host 0.0.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
# Test creds
|
## Test Credentials
|
||||||
## OIDC Client
|
|
||||||
client_id: acme-portal-001
|
|
||||||
client_secret: acme_secret_portal_2024
|
|
||||||
|
|
||||||
## User
|
### OIDC Client
|
||||||
email: bob@acme-corp.com
|
| Field | Value |
|
||||||
password: UserPass123!
|
|-------|-------|
|
||||||
|
| client_id | `acme-portal-001` |
|
||||||
|
| client_secret | `acme_secret_portal_2024` |
|
||||||
|
|
||||||
|
### Test User
|
||||||
## Sqlite editor
|
| Field | Value |
|
||||||
sqlite_web instance/db_file.db --port 9999 --host 0.0.0.0
|
|-------|-------|
|
||||||
|
| email | `bob@acme-corp.com` |
|
||||||
|
| password | `UserPass123!` |
|
||||||
+13
-1
@@ -123,7 +123,7 @@ class BaseConfig:
|
|||||||
|
|
||||||
# WebAuthn Configuration
|
# WebAuthn Configuration
|
||||||
WEBAUTHN_RP_ID = os.getenv("WEBAUTHN_RP_ID", "localhost")
|
WEBAUTHN_RP_ID = os.getenv("WEBAUTHN_RP_ID", "localhost")
|
||||||
WEBAUTHN_RP_NAME = os.getenv("WEBAUTHN_RP_NAME", "Gatehouse")
|
WEBAUTHN_RP_NAME = os.getenv("WEBAUTHN_RP_NAME", "Secuird")
|
||||||
WEBAUTHN_ORIGIN = os.getenv("WEBAUTHN_ORIGIN", "https://ui.webauthn.local")
|
WEBAUTHN_ORIGIN = os.getenv("WEBAUTHN_ORIGIN", "https://ui.webauthn.local")
|
||||||
|
|
||||||
# Frontend URL (for OAuth callback redirects)
|
# Frontend URL (for OAuth callback redirects)
|
||||||
@@ -140,3 +140,15 @@ class BaseConfig:
|
|||||||
SMTP_USERNAME = os.getenv("SMTP_USERNAME", "")
|
SMTP_USERNAME = os.getenv("SMTP_USERNAME", "")
|
||||||
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")
|
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")
|
||||||
FROM_ADDRESS = os.getenv("FROM_ADDRESS", "noreply@gatehouse.local")
|
FROM_ADDRESS = os.getenv("FROM_ADDRESS", "noreply@gatehouse.local")
|
||||||
|
|
||||||
|
# Email Provider Configuration
|
||||||
|
EMAIL_PROVIDER = os.getenv("EMAIL_PROVIDER", "smtp").lower() # smtp, mailgun, sendgrid
|
||||||
|
|
||||||
|
# Mailgun Configuration (used when EMAIL_PROVIDER=mailgun)
|
||||||
|
MAILGUN_API_KEY = os.getenv("MAILGUN_API_KEY", "")
|
||||||
|
MAILGUN_DOMAIN = os.getenv("MAILGUN_DOMAIN", "")
|
||||||
|
MAILGUN_API_URL = os.getenv("MAILGUN_API_URL", "https://api.mailgun.net/v3")
|
||||||
|
|
||||||
|
# SendGrid Configuration (used when EMAIL_PROVIDER=sendgrid)
|
||||||
|
SENDGRID_API_KEY = os.getenv("SENDGRID_API_KEY", "")
|
||||||
|
SENDGRID_FROM_EMAIL = os.getenv("SENDGRID_FROM_EMAIL", "")
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- FLASK_ENV=production
|
||||||
|
- CORS_ORIGINS=http://192.168.50.124:8080,http://localhost:8080,http://localhost:5173
|
||||||
|
- DATABASE_URL=postgresql://${POSTGRES_USER:-gatehouse}:${POSTGRES_PASSWORD:-gatehouse}@db:5432/${POSTGRES_DB:-gatehouse}
|
||||||
|
- SQLALCHEMY_DATABASE_URI=postgresql://${POSTGRES_USER:-gatehouse}:${POSTGRES_PASSWORD:-gatehouse}@db:5432/${POSTGRES_DB:-gatehouse}
|
||||||
|
- REDIS_URL=redis://redis:6379/0
|
||||||
|
- SESSION_REDIS_URL=redis://redis:6379/0
|
||||||
|
- RATELIMIT_STORAGE_URL=redis://redis:6379/1
|
||||||
|
ports:
|
||||||
|
- "${API_PORT:-5000}:5000"
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
networks:
|
||||||
|
- authy2-network
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:5000/api/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${POSTGRES_USER:-gatehouse}
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-gatehouse}
|
||||||
|
- POSTGRES_DB=${POSTGRES_DB:-gatehouse}
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- authy2-network
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-gatehouse} -d ${POSTGRES_DB:-gatehouse}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
networks:
|
||||||
|
- authy2-network
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:1.27-alpine
|
||||||
|
volumes:
|
||||||
|
- ./docker/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
ports:
|
||||||
|
- "${HTTP_PORT:-80}:80"
|
||||||
|
- "${HTTPS_PORT:-443}:443"
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
networks:
|
||||||
|
- authy2-network
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nginx", "-t"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
networks:
|
||||||
|
authy2-network:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
redis_data:
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
worker_processes auto;
|
||||||
|
error_log /var/log/nginx/error.log warn;
|
||||||
|
pid /var/run/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
use epoll;
|
||||||
|
multi_accept on;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log main;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
tcp_nopush on;
|
||||||
|
tcp_nodelay on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
types_hash_max_size 2048;
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_comp_level 6;
|
||||||
|
gzip_min_length 256;
|
||||||
|
gzip_types text/plain text/css text/xml application/json application/javascript
|
||||||
|
application/xml application/xml+rss text/javascript application/x-javascript;
|
||||||
|
|
||||||
|
upstream api {
|
||||||
|
server api:5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
# Health check endpoint
|
||||||
|
location /health {
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_connect_timeout 30s;
|
||||||
|
proxy_send_timeout 30s;
|
||||||
|
proxy_read_timeout 30s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API routes
|
||||||
|
location /api/ {
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_connect_timeout 120s;
|
||||||
|
proxy_send_timeout 120s;
|
||||||
|
proxy_read_timeout 120s;
|
||||||
|
|
||||||
|
# Increase buffer for larger responses
|
||||||
|
proxy_buffering on;
|
||||||
|
proxy_buffer_size 4k;
|
||||||
|
proxy_buffers 8 16k;
|
||||||
|
proxy_busy_buffers_size 24k;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Catch-all proxy (for any other routes)
|
||||||
|
location / {
|
||||||
|
proxy_pass http://api;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
proxy_connect_timeout 120s;
|
||||||
|
proxy_send_timeout 120s;
|
||||||
|
proxy_read_timeout 120s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,5 +49,8 @@ Flask-Limiter==3.5.0
|
|||||||
python-json-logger==2.0.7
|
python-json-logger==2.0.7
|
||||||
qrcode[pil]
|
qrcode[pil]
|
||||||
|
|
||||||
|
# HTTP requests
|
||||||
|
requests>=2.31.0
|
||||||
|
|
||||||
# SSH CA Certificate signing
|
# SSH CA Certificate signing
|
||||||
sshkey-tools==0.11.3
|
sshkey-tools==0.11.3
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
# Gatehouse Scripts
|
# Secuird Scripts
|
||||||
|
|
||||||
This directory contains utility scripts for managing and configuring Gatehouse.
|
This directory contains utility scripts for managing and configuring Secuird.
|
||||||
|
|
||||||
## OAuth Provider Configuration Script
|
## OAuth Provider Configuration Script
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
OAuth Provider Configuration Script for Gatehouse
|
OAuth Provider Configuration Script for Secuird
|
||||||
|
|
||||||
This script allows administrators to configure OAuth providers at the application level
|
This script allows administrators to configure OAuth providers at the application level
|
||||||
using the new ApplicationProviderConfig architecture.
|
using the new ApplicationProviderConfig architecture.
|
||||||
@@ -457,7 +457,7 @@ def delete_provider(args):
|
|||||||
def main():
|
def main():
|
||||||
"""Main entry point for the script."""
|
"""Main entry point for the script."""
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Configure OAuth providers for Gatehouse authentication",
|
description="Configure OAuth providers for Secuird authentication",
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
epilog="""
|
epilog="""
|
||||||
Examples:
|
Examples:
|
||||||
|
|||||||
Reference in New Issue
Block a user