Skip to content

Commit c2c8637

Browse files
authored
Merge branch 'master' into feature/add-legacy-support
2 parents b73a8d2 + 0eddf3c commit c2c8637

20 files changed

Lines changed: 1036 additions & 194 deletions

.env.example

Lines changed: 94 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,104 @@
1-
HOST=0.0.0.0
2-
PORT=8000
1+
# DevBin Backend Environment Configuration
32

4-
# Database configuration
5-
POSTGRES_USER: postgres
6-
POSTGRES_PASSWORD: postgres
7-
POSTGRES_DB: devbin
3+
# Environment (dev, staging, prod)
4+
APP_ENVIRONMENT=dev
85

9-
# Application configuration
10-
APP_DATABASE_URL=postgresql://postgres:postgres@devbin_db:5432/devbin
6+
# Server Configuration
7+
APP_PORT=8000
8+
APP_HOST=0.0.0.0
9+
APP_WORKERS=1
10+
APP_RELOAD=false
11+
APP_DEBUG=false
12+
13+
# Logging Configuration
14+
# Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
15+
APP_LOG_LEVEL=INFO
16+
# Log format: text (human-readable) or json (structured, for log aggregation)
17+
APP_LOG_FORMAT=text
18+
19+
# Database Configuration
20+
APP_DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/devbin
21+
22+
# Security - HTTPS
23+
# Set to true to redirect HTTP to HTTPS
24+
# Only enable if your deployment terminates SSL directly
25+
# Keep false if using reverse proxy (nginx, traefik, caddy, etc.)
26+
APP_ENFORCE_HTTPS=false
27+
28+
# Security - CORS
29+
# For development (allows all origins):
30+
APP_CORS_DOMAINS=["*"]
31+
APP_ALLOW_CORS_WILDCARD=true
32+
33+
# For production (specify exact domains):
34+
# APP_CORS_DOMAINS=["https://devbin.example.com","https://app.devbin.example.com"]
35+
# APP_ALLOW_CORS_WILDCARD=false
36+
37+
# Trusted Hosts (for X-Forwarded-For header)
38+
APP_TRUSTED_HOSTS=["127.0.0.1"]
39+
40+
# Paste Configuration
1141
APP_MAX_CONTENT_LENGTH=10000
1242
APP_BASE_FOLDER_PATH=./files
13-
# 1-9999999 or True for "os.cpu_count" ( how many cpu threads the machine has )
14-
# WARNING: Rate Limit / Cache is PER worker. e.g. expect 2x memore as both will cache different/doubles.
15-
APP_WORKERS=1
16-
APP_BYPASS_TOKEN= # Bypasses Rate limits
17-
APP_CORS_DOMAINS='["http://localhost:3000", "https://yourdomain.com"]'
18-
APP_CACHE_TTL=300
19-
APP_CACHE_SIZE_LIMIT=1000
2043
APP_MIN_STORAGE_MB=1024
44+
APP_KEEP_DELETED_PASTES_TIME_HOURS=336
2145

22-
# Debug / Development settings
23-
APP_SQLALCHEMY_ECHO=false
24-
APP_DEBUG=false
25-
RELOAD=false
46+
# Storage Configuration
47+
# Storage backend: local, s3, or minio (default: local)
48+
APP_STORAGE_TYPE=local
49+
50+
# S3 Configuration (when STORAGE_TYPE=s3)
51+
# APP_S3_BUCKET_NAME=devbin-pastes
52+
# APP_S3_REGION=us-east-1
53+
# APP_S3_ACCESS_KEY=your_access_key
54+
# APP_S3_SECRET_KEY=your_secret_key
55+
# APP_S3_ENDPOINT_URL= # Optional: custom S3 endpoint URL
56+
57+
# MinIO Configuration (when STORAGE_TYPE=minio)
58+
# APP_S3_BUCKET_NAME=devbin-pastes
59+
# APP_MINIO_ENDPOINT=minio:9000
60+
# APP_MINIO_ACCESS_KEY=minioadmin
61+
# APP_MINIO_SECRET_KEY=minioadmin
62+
# APP_MINIO_SECURE=true
63+
64+
# Compression settings
65+
# Compression is most effective for content >= 2KB (achieves 30-40% compression ratio)
66+
# Smaller content compresses poorly and wastes CPU cycles
67+
APP_COMPRESSION_ENABLED=true
68+
APP_COMPRESSION_THRESHOLD_BYTES=2048
69+
APP_COMPRESSION_LEVEL=6
70+
71+
# Caching
72+
# Cache backend: memory (default) or redis
73+
APP_CACHE_TYPE=memory
74+
APP_CACHE_SIZE_LIMIT=1000
75+
APP_CACHE_TTL=300
76+
77+
# Redis Configuration (when CACHE_TYPE=redis or LOCK_TYPE=redis)
78+
# APP_REDIS_HOST=localhost
79+
# APP_REDIS_PORT=6379
80+
# APP_REDIS_DB=0
81+
# APP_REDIS_PASSWORD= # Optional password
82+
83+
# Distributed Locking
84+
# Lock backend: file (default) or redis
85+
APP_LOCK_TYPE=file
86+
87+
# Privacy Settings
88+
APP_SAVE_USER_AGENT=false
89+
APP_SAVE_IP_ADDRESS=false
90+
91+
# Optional: Rate limit bypass token for trusted apps
92+
# APP_BYPASS_TOKEN=your_secret_bypass_token_here
93+
94+
# Metrics Authentication
95+
# Optional: Secure the Prometheus /metrics endpoint with Bearer token authentication
96+
# If not set, metrics endpoint remains publicly accessible
97+
# Production deployments should set this to a strong random token
98+
# APP_METRICS_TOKEN=your_secure_random_token_here
99+
# Example generation: openssl rand -hex 32
26100

27101
# Frontend configurations
28-
API_BASE_URL=http://backend_container_name:port
102+
API_BASE_URL=http://devbin:8000
29103
PORT=3000
30104
ORIGIN=http://localhost:3000 # prevent cross-site post req forbidden from frontend because node can't resolve it's origin

.github/workflows/build-images.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Build Images
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
types: [opened, synchronize]
8+
workflow_dispatch:
9+
10+
jobs:
11+
setup_build:
12+
runs-on: ubuntu-latest
13+
outputs:
14+
backend_changed: ${{ steps.changed_files.outputs.backend == 'true' || github.event_name == 'workflow_dispatch' }}
15+
frontend_changed: ${{ steps.changed_files.outputs.frontend == 'true' || github.event_name == 'workflow_dispatch' }}
16+
repo_lc: ${{ steps.lowercase_repo.outputs.REPO_LC }}
17+
18+
steps:
19+
- name: Checkout repo
20+
uses: actions/checkout@v5
21+
22+
- name: Get changes
23+
uses: tj-actions/changed-files@v45
24+
id: changed_files
25+
with:
26+
files_yaml: |
27+
backend:
28+
- 'backend/**'
29+
- '!backend/**/*.md'
30+
frontend:
31+
- 'frontend/**'
32+
- '!frontend/**/*.md'
33+
base_sha: ${{ github.event.pull_request.base.sha || github.sha }}
34+
35+
- name: Set lowercase repository variable
36+
id: lowercase_repo
37+
env:
38+
REPOSITORY: ${{ github.repository }}
39+
run: |
40+
REPO_LC=$(echo "$REPOSITORY" | tr '[:upper:]' '[:lower:]')
41+
echo "REPO_LC=$REPO_LC" >> $GITHUB_OUTPUT
42+
43+
build-backend:
44+
needs: setup_build
45+
if: ${{ needs.setup_build.outputs.backend_changed == 'true' }}
46+
uses: ./.github/workflows/docker-build.yml
47+
with:
48+
image_name: backend
49+
context: backend
50+
additional_tags: ghcr.io/${{ needs.setup_build.outputs.repo_lc }}-backend-preview:${{ github.event.pull_request.number || github.ref_name }}
51+
52+
build-frontend:
53+
needs: setup_build
54+
if: ${{ needs.setup_build.outputs.frontend_changed == 'true' }}
55+
uses: ./.github/workflows/docker-build.yml
56+
with:
57+
image_name: frontend
58+
context: frontend
59+
additional_tags: ghcr.io/${{ needs.setup_build.outputs.repo_lc }}-frontend-preview:${{ github.event.pull_request.number || github.ref_name }}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Build Release Images
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version tag (e.g., 0.0.1-alpha)'
8+
required: true
9+
type: string
10+
set_latest_tag:
11+
description: 'Set latest tag'
12+
required: false
13+
default: true
14+
type: boolean
15+
16+
jobs:
17+
setup:
18+
runs-on: ubuntu-latest
19+
outputs:
20+
repo_lc: ${{ steps.normalize.outputs.repo_lc }}
21+
version: ${{ steps.normalize.outputs.version }}
22+
backend_tags: ${{ steps.tags.outputs.backend }}
23+
frontend_tags: ${{ steps.tags.outputs.frontend }}
24+
25+
steps:
26+
- name: Normalize inputs
27+
id: normalize
28+
env:
29+
VERSION_INPUT: ${{ inputs.version }}
30+
REPOSITORY: ${{ github.repository }}
31+
run: |
32+
VERSION=$(echo "$VERSION_INPUT" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9.]/-/g')
33+
REPO_LC=$(echo "$REPOSITORY" | tr '[:upper:]' '[:lower:]')
34+
echo "version=$VERSION" >> $GITHUB_OUTPUT
35+
echo "repo_lc=$REPO_LC" >> $GITHUB_OUTPUT
36+
37+
- name: Build tag strings
38+
id: tags
39+
env:
40+
REPO_LC: ${{ steps.normalize.outputs.repo_lc }}
41+
VERSION: ${{ steps.normalize.outputs.version }}
42+
SET_LATEST: ${{ inputs.set_latest_tag }}
43+
run: |
44+
BACKEND_TAGS="ghcr.io/${REPO_LC}-backend:${VERSION}"
45+
FRONTEND_TAGS="ghcr.io/${REPO_LC}-frontend:${VERSION}"
46+
if [[ "$SET_LATEST" == "true" ]]; then
47+
BACKEND_TAGS="${BACKEND_TAGS}
48+
ghcr.io/${REPO_LC}-backend:latest"
49+
FRONTEND_TAGS="${FRONTEND_TAGS}
50+
ghcr.io/${REPO_LC}-frontend:latest"
51+
fi
52+
echo "backend<<EOF" >> $GITHUB_OUTPUT
53+
echo "$BACKEND_TAGS" >> $GITHUB_OUTPUT
54+
echo "EOF" >> $GITHUB_OUTPUT
55+
echo "frontend<<EOF" >> $GITHUB_OUTPUT
56+
echo "$FRONTEND_TAGS" >> $GITHUB_OUTPUT
57+
echo "EOF" >> $GITHUB_OUTPUT
58+
59+
build-backend:
60+
needs: setup
61+
uses: ./.github/workflows/docker-build.yml
62+
with:
63+
image_name: backend
64+
context: backend
65+
additional_tags: ${{ needs.setup.outputs.backend_tags }}
66+
67+
build-frontend:
68+
needs: setup
69+
uses: ./.github/workflows/docker-build.yml
70+
with:
71+
image_name: frontend
72+
context: frontend
73+
additional_tags: ${{ needs.setup.outputs.frontend_tags }}

.github/workflows/docker-build.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Reusable Docker Build
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
image_name:
7+
description: 'Image name suffix (backend/frontend)'
8+
required: true
9+
type: string
10+
context:
11+
description: 'Docker build context path'
12+
required: true
13+
type: string
14+
additional_tags:
15+
description: 'Additional tags (newline-separated)'
16+
required: false
17+
type: string
18+
default: ''
19+
push:
20+
description: 'Push image to registry'
21+
required: false
22+
type: boolean
23+
default: true
24+
25+
jobs:
26+
build:
27+
runs-on: ubuntu-latest
28+
environment: production
29+
permissions:
30+
packages: write
31+
contents: read
32+
attestations: write
33+
id-token: write
34+
35+
steps:
36+
- name: Checkout repo
37+
uses: actions/checkout@v5
38+
39+
- name: Set up Docker Buildx
40+
uses: docker/setup-buildx-action@v3
41+
42+
- name: Normalize repository name
43+
id: repo
44+
env:
45+
REPOSITORY: ${{ github.repository }}
46+
run: |
47+
echo "name=$(echo "$REPOSITORY" | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
48+
49+
- name: Login to GitHub Container Registry
50+
uses: docker/login-action@v3
51+
with:
52+
registry: ghcr.io
53+
username: ${{ github.actor }}
54+
password: ${{ secrets.GITHUB_TOKEN }}
55+
56+
- name: Extract metadata (tags, labels)
57+
id: meta
58+
uses: docker/metadata-action@v5
59+
with:
60+
images: ghcr.io/${{ steps.repo.outputs.name }}-${{ inputs.image_name }}
61+
62+
- name: Build and push
63+
uses: docker/build-push-action@v6
64+
with:
65+
context: ${{ inputs.context }}
66+
push: ${{ inputs.push }}
67+
tags: |
68+
${{ steps.meta.outputs.tags }}
69+
${{ inputs.additional_tags }}
70+
labels: ${{ steps.meta.outputs.labels }}
71+
cache-from: type=gha
72+
cache-to: type=gha,mode=max

.github/workflows/lint-backend.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Lint Backend
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
paths:
8+
- "backend/**"
9+
pull_request:
10+
branches:
11+
- master
12+
paths:
13+
- "backend/**"
14+
15+
jobs:
16+
lint:
17+
runs-on: ubuntu-latest
18+
defaults:
19+
run:
20+
working-directory: ./backend
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v5
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@v5
28+
with:
29+
python-version: '3.13'
30+
31+
- name: Install uv
32+
uses: astral-sh/setup-uv@v5
33+
with:
34+
version: "0.9.18"
35+
enable-cache: true
36+
cache-dependency-glob: "backend/uv.lock"
37+
38+
- name: Install dependencies
39+
run: uv sync
40+
41+
- name: Run ruff check
42+
run: uv run ruff check --output-format=github .
43+
44+
- name: Run ruff format check
45+
run: uv run ruff format --check --diff .

0 commit comments

Comments
 (0)