This commit is contained in:
Freya Murphy 2024-05-23 12:15:02 -04:00
parent 8d544d58af
commit 1715987906
Signed by: freya
GPG key ID: 744AB800E383AE52
12 changed files with 226 additions and 145 deletions

View file

@ -1,5 +1,21 @@
FROM alpine:3.19
RUN apk add --no-cache postgresql16-client tini
# install packages
RUN apk add --no-cache postgresql16-client tini shadow
RUN rm -fr /var/cache/apk/*
# setup main user
RUN adduser -D init
RUN groupmod --gid 1000 init
RUN usermod --uid 1000 init
# copy scripts
COPY ./init /usr/local/bin/init
# remove build packages
RUN apk del shadow
# do the
USER init
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/init"]

View file

@ -1,21 +1,37 @@
#!/bin/sh
errors=$(mktemp)
step() {
printf '\x1b[34;1m>> %s\x1b[0m\n' "$*"
}
error() {
printf '\x1b[31;1merror: \x1b[0m%s\n' "$*"
{
printf '\x1b[31;1merror: \x1b[0m%s\n' "$*";
grep -v 'current transaction is aborted' < "$errors";
printf "\x1b[31m;1error: \x1b[0mAborting migrations, fix file(s) then restart process.";
} 1>&2;
}
export PGPASSWORD=$POSTGRES_PASSWORD
try() {
"$@" 2> "$errors";
count=$(grep -c 'ERROR' < "$errors")
if [ "$count" -eq 0 ]; then
return 0;
else
return 1;
fi
}
export PGPASSWORD="$POSTGRES_PASSWORD"
psql() {
/usr/bin/psql \
-h db \
-p 5432 \
-d $POSTGRES_DB \
-U $POSTGRES_USER \
-d "$POSTGRES_DB" \
-U "$POSTGRES_USER" \
"$@"
}
@ -23,9 +39,8 @@ pg_isready() {
/usr/bin/pg_isready \
-h db \
-p 5432 \
-d $POSTGRES_DB \
-U $POSTGRES_USER \
"$@"
-d "$POSTGRES_DB" \
-U "$POSTGRES_USER"
}
curr_revision() {
@ -49,17 +64,12 @@ run_migrations() {
while true; do
name=$(printf "%04d" "$i");
file="/db/migrations/$name.sql"
if [ -f $file ]; then
psql -f $file 2> /errors
errors=$(cat /errors | grep 'ERROR' | wc -l)
if [ "$errors" -eq 0 ]; then
if [ -f "$file" ]; then
if try psql -f "$file"; then
i=$((i+1));
continue;
else
error "An error occoured during a migration (rev $name)"
cat /errors | grep -v 'current transaction is aborted';
error "Aborting migrations, fix file(s) then restart process."
return 1;
fi
else
@ -69,24 +79,19 @@ run_migrations() {
}
init_api() {
psql -f /db/rest/rest.sql 2> /errors;
errors=$(cat /errors | grep 'ERROR' | wc -l)
if [ "$errors" -eq 0 ]; then
if try psql -f /db/rest/rest.sql; then
return 0;
else
error "An error occoured during api initialization"
cat /errors | grep -v 'current transaction is aborted';
error "Aborting api initialization, fix file(s) then restart process."
return 1;
fi
}
update_jwt() {
psql -c "UPDATE sys.database_info SET jwt_secret = '$JWT_SECRET' WHERE name = current_database();"
errors=$(cat /errors | grep 'ERROR' | wc -l)
if [ "$errors" -eq 0 ]; then
if try psql -c "UPDATE sys.database_info SET jwt_secret = '$JWT_SECRET' WHERE name = current_database();"; then
return 0;
else
error "Could not update JWT"
return 1;
fi
}
@ -98,7 +103,7 @@ load_ext() {
init () {
# reomve ready status
# so php ignores requests
rm -fr /status/ready
rm -f /status/ready
step 'Waiting for database';
# make sure the database is running
@ -116,31 +121,22 @@ init () {
step "Database at revision: $REV"
# run each migration that is
# higher than our current revision
run_migrations "$REV"
CODE=$?;
if [ $CODE -ne 0 ]; then
return $CODE;
if ! run_migrations "$REV"; then
return 1;
fi
step 'Initalizing the api';
# reinit the api schema for
# postgrest
init_api;
CODE=$?;
if [ $CODE -ne 0 ]; then
return $CODE;
if ! init_api; then
return 1;
fi
step 'Updating JWT secret';
# make sure postgres has the corrent
# jwt secret
update_jwt;
CODE=$?;
if [ $CODE -ne 0 ]; then
return $CODE;
if ! update_jwt; then
return 1;
fi
step 'Database is initialized'
@ -149,3 +145,4 @@ init () {
}
init
rm "$errors"

21
build/nginx/Dockerfile Normal file
View file

@ -0,0 +1,21 @@
FROM alpine:3.19
# install packages
RUN apk add --no-cache nginx shadow tini
RUN rm -fr /var/cache/apk/*
# update nginx user
RUN groupmod --gid 1000 nginx
RUN usermod --uid 1000 nginx
# remove build packages
RUN apk del shadow
# make log syms
RUN ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log
# do the
USER nginx
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/sbin/nginx", "-c", "/etc/nginx/nginx.conf"]

View file

@ -1,4 +1,17 @@
FROM php:fpm-alpine
RUN apk add --no-cache postgresql-dev runuser
# install packages
RUN apk add --no-cache postgresql-dev runuser shadow
RUN rm -fr /var/cache/apk/*
# update php user
RUN groupmod --gid 1000 www-data
RUN usermod --uid 1000 www-data
# install php packages
RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql
RUN docker-php-ext-install pdo pdo_pgsql
# remove build packages
RUN apk del shadow
USER www-data

View file

@ -1,6 +1,21 @@
FROM postgres:16-alpine
RUN apk add --no-cache make git
# install packages
RUN apk add --no-cache make git shadow
RUN rm -fr /var/cache/apk/*
# install pgjwt
RUN git clone https://github.com/michelp/pgjwt.git /tmp/pgjwt
WORKDIR /tmp/pgjwt
RUN make install
# update postgres user
RUN groupmod --gid 1000 postgres
RUN usermod --uid 1000 postgres
# remove build packages
RUN apk del make git shadow
# fix workdir
WORKDIR /
USER postgres

View file

@ -1,9 +1,30 @@
FROM alpine:3.19
# install packages
RUN apk add --no-cache tini shadow
RUN rm -fr /var/cache/apk/*
# setup main user
RUN adduser -D postgrest
RUN groupmod --gid 1000 postgrest
RUN usermod --uid 1000 postgrest
# install postgrest
COPY ./postgrest.tar.xz /tmp/postgrest.tar.xz
RUN tar xJf /tmp/postgrest.tar.xz -C /tmp
RUN cp /tmp/postgrest /usr/local/bin/postgrest
RUN tar xJf /tmp/postgrest.tar.xz -C /usr/local/bin
RUN rm /tmp/postgrest.tar.xz
# copy scripts
COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh
# remove build packages
RUN apk del shadow
# make the dirs
RUN mkdir -p /etc/postgrest.d && \
chown postgrest:postgrest /etc/postgrest.d
# do the
USER postgrest
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/entrypoint.sh"]

View file

@ -1,6 +1,5 @@
#!/bin/sh
mkdir /etc/postgrest.d
config=/etc/postgrest.d/postgrest.conf
PGRST_DB_URI="postgres://authenticator:postgrest@db:5432/$POSTGRES_DB"
@ -9,12 +8,14 @@ PGRST_SCHEMA="api"
rm -fr "$config"
touch "$config"
printf 'db-uri = "%s"\n' "$PGRST_DB_URI" >> $config
printf 'db-anon-role = "%s"\n' "$PGRST_ROLE" >> $config
printf 'db-schemas = "%s"\n' "$PGRST_SCHEMA" >> $config
printf 'jwt-secret = "%s"\n' "$JWT_SECRET" >> $config
printf 'jwt-secret-is-base64 = false\n' >> $config
printf 'server-host = "*"\n' >> $config
printf 'server-port = 3000\n' >> $config
{
printf 'db-uri = "%s"\n' "$PGRST_DB_URI";
printf 'db-anon-role = "%s"\n' "$PGRST_ROLE";
printf 'db-schemas = "%s"\n' "$PGRST_SCHEMA";
printf 'jwt-secret = "%s"\n' "$JWT_SECRET";
printf 'jwt-secret-is-base64 = false\n';
printf 'server-host = "*"\n';
printf 'server-port = 3000\n';
} >> $config
exec /usr/local/bin/postgrest $config
exec /usr/local/bin/postgrest "$config"

72
conf/nginx/nginx.conf Normal file
View file

@ -0,0 +1,72 @@
worker_processes 4;
daemon off;
pid /tmp/nginx.pid;
error_log /var/log/nginx/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 70;
server_tokens off;
client_max_body_size 2m;
access_log /var/log/nginx/access.log;
upstream postgrest {
server rest:3000;
}
server {
listen 8080;
root /opt/xssbook;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Accept-Encoding "";
proxy_redirect off;
default_type application/json;
add_header 'Access-Control-Allow-Origin' '*';
add_header Content-Location /api/$upstream_http_content_location;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://postgrest/;
}
location /favicon.ico {
add_header 'Access-Control-Allow-Origin' '*';
root /opt/xssbook/public;
add_header Cache-Control "public, max-age=108000";
}
location /public {
add_header 'Access-Control-Allow-Origin' '*';
try_files $uri =404;
add_header Cache-Control "public, max-age=108000";
}
location / {
add_header 'Access-Control-Allow-Origin' '*';
root /opt/xssbook/web;
include fastcgi_params;
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
}

View file

@ -1,72 +0,0 @@
server_tokens off;
upstream postgrest {
server rest:3000 fail_timeout=0;
}
upstream swagger {
server swagger:3000 fail_timeout=0;
}
server {
listen 80;
server_name localhost;
keepalive_timeout 70;
sendfile on;
client_max_body_size 2m;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /opt/xssbook;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Accept-Encoding "";
proxy_redirect off;
default_type application/json;
add_header 'Access-Control-Allow-Origin' '*';
add_header Content-Location /api/$upstream_http_content_location;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://postgrest/;
}
location /apidocs {
add_header 'Access-Control-Allow-Origin' '*';
proxy_http_version 1.1;
proxy_pass http://swagger;
}
location /favicon.ico {
add_header 'Access-Control-Allow-Origin' '*';
root /opt/xssbook/public;
add_header Cache-Control "public, max-age=108000";
}
location /public {
add_header 'Access-Control-Allow-Origin' '*';
try_files $uri =404;
add_header Cache-Control "public, max-age=108000";
}
location / {
add_header 'Access-Control-Allow-Origin' '*';
root /opt/xssbook/web;
include fastcgi_params;
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}

View file

@ -1,15 +1,14 @@
services:
web:
image: nginx:alpine
build: ./build/nginx
restart: unless-stopped
ports:
- '80:80'
- '80:8080'
volumes:
- ./src:/opt/xssbook:ro
- ./conf/nginx:/etc/nginx/conf.d:ro
- ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- rest
- swagger
- php
php:
@ -25,7 +24,6 @@ services:
- db
db:
#image: postgres:16-alpine
build: ./build/postgres
restart: unless-stopped
env_file:
@ -66,13 +64,3 @@ services:
- ./data/shim/:/data:ro
depends_on:
- db
swagger:
image: swaggerapi/swagger-ui
restart: unless-stopped
environment:
SWAGGER_JSON_URL: '/api'
BASE_URL: '/apidocs'
PORT: 3000
depends_on:
- db

View file

@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
<?php if ($this->main->session): ?>
var jwtStr = <?=json_encode($this->main->session['jwt'])?>;

View file

@ -1,8 +1,5 @@
<?php /* Copyright (c) 2024 Freya Murphy */
session_save_path('/var/lib/php/session');
session_start();
$webroot = dirname(__FILE__);
// load all the helper files
@ -21,6 +18,16 @@ require($webroot . '/core/database.php');
require($webroot . '/core/loader.php');
require($webroot . '/core/router.php');
session_save_path('/var/lib/php/session');
session_set_cookie_params(
60 * 60 * 24 * 365, // lifetime (seconds),
'/', // path
NULL, // domain,
FALSE, // secure,
FALSE // http only
);
session_start();
function __init() {
$load = new Loader();
$router = new Router($load);