Compare commits
2 Commits
7605ca9918
...
9d348ca893
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d348ca893 | ||
|
|
fbb620bd85 |
@@ -3,6 +3,11 @@ server {
|
|||||||
listen 8080;
|
listen 8080;
|
||||||
server_name ${PUBLIC_HOST};
|
server_name ${PUBLIC_HOST};
|
||||||
if ($host != ${PUBLIC_HOST}) { return 400; }
|
if ($host != ${PUBLIC_HOST}) { return 400; }
|
||||||
|
# Resolve through Docker's embedded DNS at request time. This prevents
|
||||||
|
# Nginx from exiting during a Swarm rollout when the API task is briefly
|
||||||
|
# unavailable or still creating its database schema.
|
||||||
|
resolver 127.0.0.11 ipv6=off valid=10s;
|
||||||
|
set $api_upstream api:8000;
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index ${WEB_INDEX};
|
index ${WEB_INDEX};
|
||||||
|
|
||||||
@@ -17,7 +22,7 @@ server {
|
|||||||
location /api/ {
|
location /api/ {
|
||||||
limit_req zone=api_limit burst=100 nodelay;
|
limit_req zone=api_limit burst=100 nodelay;
|
||||||
limit_req_status 429;
|
limit_req_status 429;
|
||||||
proxy_pass http://api:8000;
|
proxy_pass http://$api_upstream;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-Host $host;
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ version: "3.8"
|
|||||||
|
|
||||||
x-app-environment: &app-environment
|
x-app-environment: &app-environment
|
||||||
APP_ENV: production
|
APP_ENV: production
|
||||||
DATABASE_URL: postgresql://dtf_app:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@db:5432/dtf
|
DATABASE_HOST: db
|
||||||
|
DATABASE_NAME: dtf
|
||||||
|
DATABASE_USER: dtf_app
|
||||||
|
DATABASE_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||||
S3_ENDPOINT: ${R2_ENDPOINT:?set R2_ENDPOINT}
|
S3_ENDPOINT: ${R2_ENDPOINT:?set R2_ENDPOINT}
|
||||||
S3_PUBLIC_ENDPOINT: ${R2_ENDPOINT:?set R2_ENDPOINT}
|
S3_PUBLIC_ENDPOINT: ${R2_ENDPOINT:?set R2_ENDPOINT}
|
||||||
S3_BUCKET: ${R2_BUCKET:?set R2_BUCKET}
|
S3_BUCKET: ${R2_BUCKET:?set R2_BUCKET}
|
||||||
@@ -51,7 +54,10 @@ services:
|
|||||||
image: ${API_IMAGE:-gitea.blyzer.com.br/blyzer/dtf-api}:${IMAGE_TAG:-latest}
|
image: ${API_IMAGE:-gitea.blyzer.com.br/blyzer/dtf-api}:${IMAGE_TAG:-latest}
|
||||||
command: python -m local.bootstrap
|
command: python -m local.bootstrap
|
||||||
environment:
|
environment:
|
||||||
DATABASE_ADMIN_URL: postgresql://dtf_admin:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@db:5432/dtf
|
DATABASE_ADMIN_HOST: db
|
||||||
|
DATABASE_ADMIN_NAME: dtf
|
||||||
|
DATABASE_ADMIN_USER: dtf_admin
|
||||||
|
DATABASE_ADMIN_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||||
APP_DB_USER: dtf_app
|
APP_DB_USER: dtf_app
|
||||||
APP_DB_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
APP_DB_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||||
networks: [backend]
|
networks: [backend]
|
||||||
|
|||||||
@@ -4,9 +4,21 @@ from pathlib import Path
|
|||||||
import psycopg
|
import psycopg
|
||||||
from psycopg import sql
|
from psycopg import sql
|
||||||
|
|
||||||
|
|
||||||
|
def admin_connect():
|
||||||
|
if os.environ.get('DATABASE_ADMIN_HOST'):
|
||||||
|
return psycopg.connect(
|
||||||
|
host=os.environ['DATABASE_ADMIN_HOST'],
|
||||||
|
dbname=os.environ['DATABASE_ADMIN_NAME'],
|
||||||
|
user=os.environ['DATABASE_ADMIN_USER'],
|
||||||
|
password=os.environ['DATABASE_ADMIN_PASSWORD'],
|
||||||
|
)
|
||||||
|
return psycopg.connect(os.environ['DATABASE_ADMIN_URL'])
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
role = os.environ['APP_DB_USER']
|
role = os.environ['APP_DB_USER']
|
||||||
with psycopg.connect(os.environ['DATABASE_ADMIN_URL']) as c:
|
with admin_connect() as c:
|
||||||
admin, database = c.execute('SELECT current_user,current_database()').fetchone()
|
admin, database = c.execute('SELECT current_user,current_database()').fetchone()
|
||||||
if role == admin:
|
if role == admin:
|
||||||
raise RuntimeError('Application and database administrator must differ')
|
raise RuntimeError('Application and database administrator must differ')
|
||||||
|
|||||||
12
local/db.py
12
local/db.py
@@ -4,9 +4,19 @@ import psycopg
|
|||||||
from psycopg.rows import dict_row
|
from psycopg.rows import dict_row
|
||||||
|
|
||||||
def connect():
|
def connect():
|
||||||
|
# Production passes credentials as discrete libpq fields. This avoids
|
||||||
|
# treating characters in a generated password as URL syntax. Local and
|
||||||
|
# test environments retain DATABASE_URL compatibility.
|
||||||
|
if os.environ.get('DATABASE_HOST'):
|
||||||
|
return psycopg.connect(
|
||||||
|
host=os.environ['DATABASE_HOST'],
|
||||||
|
dbname=os.environ['DATABASE_NAME'],
|
||||||
|
user=os.environ['DATABASE_USER'],
|
||||||
|
password=os.environ['DATABASE_PASSWORD'],
|
||||||
|
row_factory=dict_row,
|
||||||
|
)
|
||||||
return psycopg.connect(os.environ['DATABASE_URL'], row_factory=dict_row)
|
return psycopg.connect(os.environ['DATABASE_URL'], row_factory=dict_row)
|
||||||
|
|
||||||
def initialize():
|
def initialize():
|
||||||
with connect() as c:
|
with connect() as c:
|
||||||
c.execute(Path(__file__).with_name('schema.sql').read_text())
|
c.execute(Path(__file__).with_name('schema.sql').read_text())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user