Public Access
Initial
This commit is contained in:
commit
6765ec8991
17 files changed
+825
No files matched your search
@@ -0,0 +1,7 @@
|
||||
.git
|
||||
.gitignore
|
||||
.env
|
||||
backup
|
||||
secrets
|
||||
data
|
||||
*.zip
|
||||
@@ -0,0 +1,21 @@
|
||||
COMPOSE_PROJECT_NAME=egeya
|
||||
|
||||
EGEYA_VERSION=4199
|
||||
EGEYA_URL=
|
||||
EGEYA_SHA256=
|
||||
EGEYA_DB_NAME=egeya
|
||||
EGEYA_DB_USER=egeya
|
||||
|
||||
MARIADB_VERSION=10.11
|
||||
|
||||
HTTP_BIND=127.0.0.1
|
||||
HTTP_PORT=8080
|
||||
NGINX_SERVER_NAME=_
|
||||
|
||||
PHP_MEMORY_LIMIT=512M
|
||||
PHP_UPLOAD_MAX_FILESIZE=512M
|
||||
PHP_POST_MAX_SIZE=1024M
|
||||
PHP_MAX_EXECUTION_TIME=300
|
||||
PHP_MAX_INPUT_TIME=300
|
||||
|
||||
TZ=Europe/Berlin
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
.env
|
||||
backup/*
|
||||
!backup/.gitkeep
|
||||
data/*
|
||||
!data/user/
|
||||
!data/user/.gitkeep
|
||||
!data/pictures/
|
||||
!data/pictures/.gitkeep
|
||||
!data/tmp/
|
||||
!data/tmp/.gitkeep
|
||||
secrets/*
|
||||
!secrets/.gitkeep
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
ARG EGEYA_VERSION=4199
|
||||
ARG EGEYA_URL=""
|
||||
ARG EGEYA_SHA256=""
|
||||
|
||||
FROM debian:bookworm-slim AS egeya-source
|
||||
|
||||
ARG EGEYA_VERSION
|
||||
ARG EGEYA_URL
|
||||
ARG EGEYA_SHA256
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends ca-certificates curl unzip; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
archive_url="${EGEYA_URL:-https://blogengine.ru/download/e2_distr_v${EGEYA_VERSION}.zip}"; \
|
||||
work_dir="$(mktemp -d)"; \
|
||||
curl -fL \
|
||||
--retry 5 \
|
||||
--retry-delay 2 \
|
||||
--connect-timeout 20 \
|
||||
--user-agent "egeya-docker/${EGEYA_VERSION}" \
|
||||
"$archive_url" \
|
||||
-o "$work_dir/egeya.zip"; \
|
||||
if [ -n "$EGEYA_SHA256" ]; then \
|
||||
echo "$EGEYA_SHA256 $work_dir/egeya.zip" | sha256sum -c -; \
|
||||
fi; \
|
||||
mkdir -p "$work_dir/unpacked" /opt/egeya-release; \
|
||||
unzip -q "$work_dir/egeya.zip" -d "$work_dir/unpacked"; \
|
||||
if [ -f "$work_dir/unpacked/index.php" ]; then \
|
||||
source_dir="$work_dir/unpacked"; \
|
||||
else \
|
||||
source_dir="$(find "$work_dir/unpacked" -maxdepth 2 -type f -name index.php -printf '%h\n' | head -n 1)"; \
|
||||
fi; \
|
||||
test -n "$source_dir"; \
|
||||
cp -a "$source_dir"/. /opt/egeya-release/; \
|
||||
test -f /opt/egeya-release/index.php; \
|
||||
rm -rf "$work_dir"
|
||||
|
||||
FROM php:8.2-fpm-bookworm AS php
|
||||
|
||||
ENV EGEYA_ROOT=/var/www/html \
|
||||
EGEYA_DATA_DIR=/var/www/egeya-data \
|
||||
EGEYA_DEFAULTS_DIR=/opt/egeya-defaults
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libavif-dev \
|
||||
libfreetype6-dev \
|
||||
libjpeg62-turbo-dev \
|
||||
libpng-dev \
|
||||
libwebp-dev \
|
||||
libzip-dev; \
|
||||
docker-php-ext-configure gd \
|
||||
--with-avif \
|
||||
--with-freetype \
|
||||
--with-jpeg \
|
||||
--with-webp; \
|
||||
docker-php-ext-install -j"$(nproc)" \
|
||||
exif \
|
||||
gd \
|
||||
mbstring \
|
||||
opcache \
|
||||
pdo_mysql \
|
||||
zip; \
|
||||
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=egeya-source /opt/egeya-release/ /var/www/html/
|
||||
|
||||
RUN set -eux; \
|
||||
mkdir -p "$EGEYA_DEFAULTS_DIR/user" "$EGEYA_DEFAULTS_DIR/pictures"; \
|
||||
if [ -d "$EGEYA_ROOT/user" ]; then \
|
||||
cp -a "$EGEYA_ROOT/user"/. "$EGEYA_DEFAULTS_DIR/user"/; \
|
||||
fi; \
|
||||
if [ -d "$EGEYA_ROOT/pictures" ]; then \
|
||||
cp -a "$EGEYA_ROOT/pictures"/. "$EGEYA_DEFAULTS_DIR/pictures"/; \
|
||||
fi; \
|
||||
rm -rf "$EGEYA_ROOT/user" "$EGEYA_ROOT/pictures"; \
|
||||
ln -s "$EGEYA_DATA_DIR/user" "$EGEYA_ROOT/user"; \
|
||||
ln -s "$EGEYA_DATA_DIR/pictures" "$EGEYA_ROOT/pictures"; \
|
||||
chown -R www-data:www-data "$EGEYA_ROOT" "$EGEYA_DEFAULTS_DIR"
|
||||
|
||||
COPY docker/php/egeya-entrypoint.sh /usr/local/bin/egeya-entrypoint
|
||||
COPY docker/php/www-egeya.conf /usr/local/etc/php-fpm.d/zz-egeya.conf
|
||||
|
||||
RUN chmod 0755 /usr/local/bin/egeya-entrypoint
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=5 \
|
||||
CMD php -r '$s=@fsockopen("127.0.0.1",9000,$e,$m,2); if(!$s){exit(1);} fclose($s);'
|
||||
|
||||
ENTRYPOINT ["egeya-entrypoint"]
|
||||
CMD ["php-fpm"]
|
||||
|
||||
FROM nginx:1.28-bookworm AS nginx
|
||||
|
||||
ENV EGEYA_ROOT=/var/www/html \
|
||||
EGEYA_DATA_DIR=/var/www/egeya-data
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
apt-get install -y --no-install-recommends curl; \
|
||||
rm -rf /var/lib/apt/lists/*; \
|
||||
if getent passwd www-data >/dev/null; then \
|
||||
sed -ri 's/^user[[:space:]]+[^;]+;/user www-data;/' /etc/nginx/nginx.conf; \
|
||||
fi
|
||||
|
||||
COPY --from=egeya-source /opt/egeya-release/ /var/www/html/
|
||||
|
||||
RUN set -eux; \
|
||||
rm -rf "$EGEYA_ROOT/user" "$EGEYA_ROOT/pictures"; \
|
||||
ln -s "$EGEYA_DATA_DIR/user" "$EGEYA_ROOT/user"; \
|
||||
ln -s "$EGEYA_DATA_DIR/pictures" "$EGEYA_ROOT/pictures"; \
|
||||
rm -f /etc/nginx/conf.d/default.conf
|
||||
|
||||
COPY docker/nginx/egeya.conf.template /etc/nginx/templates/egeya.conf.template
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
HEALTHCHECK --interval=15s --timeout=5s --start-period=20s --retries=5 \
|
||||
CMD curl -fsS http://127.0.0.1/ >/dev/null || exit 1
|
||||
@@ -0,0 +1,316 @@
|
||||
# Egeya 11.5 v4199 in Docker
|
||||
|
||||
Stack:
|
||||
|
||||
- nginx
|
||||
- PHP-FPM 8.2
|
||||
- MariaDB 10.11
|
||||
- Egeya v4199
|
||||
|
||||
The layout intentionally follows a tested nginx + PHP-FPM deployment rather than the older Apache-based Docker example.
|
||||
|
||||
## Why nginx + PHP-FPM
|
||||
|
||||
Egeya 11 supports PHP up to 8.2. The nginx configuration uses synthetic URLs through:
|
||||
|
||||
```nginx
|
||||
location / {
|
||||
log_not_found off;
|
||||
rewrite ^(.*)$ /index.php?go=$1 last;
|
||||
}
|
||||
```
|
||||
|
||||
Do not replace this with:
|
||||
|
||||
```nginx
|
||||
try_files $uri $uri/ /index.php?go=$uri;
|
||||
```
|
||||
|
||||
The rewrite form preserves the original query string used by Egeya upload requests, including fields such as `entity` and `entity-id`.
|
||||
|
||||
The PHP location also passes:
|
||||
|
||||
```nginx
|
||||
fastcgi_param E2_SYNTH_URLS true;
|
||||
```
|
||||
|
||||
Direct access to PHP files under `/system` and `/user`, `user/settings.json`, `*.psa`, and `.ht*` is blocked.
|
||||
|
||||
## Upload temporary directory
|
||||
|
||||
The `data` directory is mounted once at `/var/www/egeya-data`.
|
||||
|
||||
Persistent paths are:
|
||||
|
||||
```text
|
||||
/var/www/egeya-data/user
|
||||
/var/www/egeya-data/pictures
|
||||
/var/www/egeya-data/tmp
|
||||
```
|
||||
|
||||
Inside both application images, `/var/www/html/user` and `/var/www/html/pictures` are symbolic links into this single mount.
|
||||
|
||||
PHP is configured with:
|
||||
|
||||
```ini
|
||||
upload_tmp_dir = /var/www/egeya-data/tmp
|
||||
sys_temp_dir = /var/www/egeya-data/tmp
|
||||
```
|
||||
|
||||
This is deliberate. A standard container `/tmp` is on the container filesystem, while `pictures` is on a bind mount. Moving an uploaded file between them may cross mount boundaries and fail with `EXDEV`. Keeping the upload temporary directory and `pictures` under the same mount avoids that class of failure.
|
||||
|
||||
## Project structure
|
||||
|
||||
```text
|
||||
Dockerfile
|
||||
compose.yaml
|
||||
.env.example
|
||||
.dockerignore
|
||||
.gitignore
|
||||
docker/nginx/egeya.conf.template
|
||||
docker/php/egeya-entrypoint.sh
|
||||
docker/php/www-egeya.conf
|
||||
scripts/prepare.sh
|
||||
scripts/migrate-files.sh
|
||||
scripts/import-db.sh
|
||||
data/user
|
||||
data/pictures
|
||||
data/tmp
|
||||
backup
|
||||
secrets
|
||||
```
|
||||
|
||||
Create the structure manually if required:
|
||||
|
||||
```bash
|
||||
mkdir -p docker/nginx docker/php scripts data/user data/pictures data/tmp backup secrets
|
||||
touch Dockerfile compose.yaml .env.example .dockerignore .gitignore \
|
||||
docker/nginx/egeya.conf.template \
|
||||
docker/php/egeya-entrypoint.sh docker/php/www-egeya.conf \
|
||||
scripts/prepare.sh scripts/migrate-files.sh scripts/import-db.sh \
|
||||
data/user/.gitkeep data/pictures/.gitkeep data/tmp/.gitkeep \
|
||||
backup/.gitkeep secrets/.gitkeep
|
||||
```
|
||||
|
||||
## Prepare
|
||||
|
||||
```bash
|
||||
chmod +x scripts/*.sh
|
||||
./scripts/prepare.sh
|
||||
```
|
||||
|
||||
Review `.env` before starting.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
docker compose build --pull
|
||||
```
|
||||
|
||||
Both `nginx` and `php` targets are built from the same Egeya source stage, so the static files seen by nginx and the PHP code executed by PHP-FPM are from the same Egeya release.
|
||||
|
||||
Optional source integrity check:
|
||||
|
||||
```text
|
||||
EGEYA_SHA256=<sha256 of e2_distr_v4199.zip>
|
||||
```
|
||||
|
||||
## Start
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
|
||||
docker compose ps
|
||||
|
||||
docker compose logs --tail=100 nginx php db
|
||||
```
|
||||
|
||||
By default nginx listens only on:
|
||||
|
||||
```text
|
||||
127.0.0.1:8080
|
||||
```
|
||||
|
||||
This is suitable when another reverse proxy terminates HTTPS on the Docker host.
|
||||
|
||||
## Data model
|
||||
|
||||
The application code is immutable and comes from the Docker images.
|
||||
|
||||
Persistent data is limited to:
|
||||
|
||||
- `data/user`
|
||||
- `data/pictures`
|
||||
- `data/tmp`
|
||||
- MariaDB named volume `db_data`
|
||||
|
||||
Do not copy an old `/system` directory into the container. Updating the image updates `/system` and the bundled application files.
|
||||
|
||||
Custom additions stored below `user`, including `user/extras`, migrate together with the user data.
|
||||
|
||||
## Migration from a bare-metal installation
|
||||
|
||||
Assume the current installation is:
|
||||
|
||||
```text
|
||||
/var/www/blog
|
||||
```
|
||||
|
||||
### 1. Stop writes on the old installation
|
||||
|
||||
Stop the web application or otherwise prevent writes for the final synchronization.
|
||||
|
||||
### 2. Create a database dump
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
mysqldump \
|
||||
--single-transaction \
|
||||
--quick \
|
||||
--triggers \
|
||||
--default-character-set=utf8mb4 \
|
||||
egeya > egeya.sql
|
||||
```
|
||||
|
||||
Copy the dump to:
|
||||
|
||||
```text
|
||||
backup/egeya.sql
|
||||
```
|
||||
|
||||
### 3. Copy file data
|
||||
|
||||
If the old blog tree is locally available:
|
||||
|
||||
```bash
|
||||
./scripts/migrate-files.sh /var/www/blog ./data
|
||||
```
|
||||
|
||||
For a remote source, an equivalent rsync is:
|
||||
|
||||
```bash
|
||||
rsync -aHAX old-host:/var/www/blog/user/ ./data/user/
|
||||
rsync -aHAX old-host:/var/www/blog/pictures/ ./data/pictures/
|
||||
```
|
||||
|
||||
Do not copy `/system`.
|
||||
|
||||
Do not copy the old nginx configuration into the application image. Use `docker/nginx/egeya.conf.template`.
|
||||
|
||||
### 4. Prepare secrets and configuration
|
||||
|
||||
```bash
|
||||
./scripts/prepare.sh
|
||||
```
|
||||
|
||||
Set the target database name and user in `.env` before initializing MariaDB.
|
||||
|
||||
### 5. Start MariaDB and import the dump
|
||||
|
||||
```bash
|
||||
./scripts/import-db.sh backup/egeya.sql
|
||||
```
|
||||
|
||||
### 6. Start PHP and nginx
|
||||
|
||||
```bash
|
||||
docker compose up -d php nginx
|
||||
```
|
||||
|
||||
### 7. Validate
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
|
||||
docker compose logs --tail=200 php nginx
|
||||
```
|
||||
|
||||
Check at least:
|
||||
|
||||
- public pages
|
||||
- author login
|
||||
- note editor
|
||||
- image upload
|
||||
- audio/video upload if used
|
||||
- editing an existing note
|
||||
- built-in security check
|
||||
- access to `/system/core.php` returns 403
|
||||
- access to `/user/settings.json` returns 403
|
||||
|
||||
For upload diagnostics, the application log is available at:
|
||||
|
||||
```text
|
||||
data/user/logs/main.log
|
||||
```
|
||||
|
||||
It is created by the PHP container entrypoint if absent.
|
||||
|
||||
## Database credentials
|
||||
|
||||
Egeya receives database settings through its supported environment variables:
|
||||
|
||||
```text
|
||||
E2_DB_SERVER
|
||||
E2_DB_USER_NAME
|
||||
E2_DB_PASSW
|
||||
E2_DB_NAME
|
||||
```
|
||||
|
||||
The Compose file does not place the password directly in its environment section. It mounts a Docker secret and the PHP entrypoint exports its contents as `E2_DB_PASSW` immediately before starting PHP-FPM.
|
||||
|
||||
PHP-FPM is explicitly configured with `clear_env = no` so the Egeya process can see these variables.
|
||||
|
||||
## Updating Egeya
|
||||
|
||||
Change:
|
||||
|
||||
```text
|
||||
EGEYA_VERSION=<new build number>
|
||||
```
|
||||
|
||||
If necessary also set `EGEYA_URL` and `EGEYA_SHA256`.
|
||||
|
||||
Then rebuild and recreate the application containers:
|
||||
|
||||
```bash
|
||||
docker compose build --pull php nginx
|
||||
docker compose up -d --no-deps --force-recreate php nginx
|
||||
```
|
||||
|
||||
The persistent `user`, `pictures`, and database data are not replaced.
|
||||
|
||||
Before an update, make a database dump and a copy of `data`.
|
||||
|
||||
## Useful commands
|
||||
|
||||
Validate Compose rendering:
|
||||
|
||||
```bash
|
||||
docker compose config
|
||||
```
|
||||
|
||||
PHP configuration:
|
||||
|
||||
```bash
|
||||
docker compose exec php php -i | grep -E 'upload_tmp_dir|sys_temp_dir|upload_max_filesize|post_max_size'
|
||||
```
|
||||
|
||||
Verify that temp and pictures resolve to the same mounted filesystem:
|
||||
|
||||
```bash
|
||||
docker compose exec php sh -c 'df -T /var/www/egeya-data/tmp /var/www/egeya-data/pictures'
|
||||
```
|
||||
|
||||
Check the nginx configuration:
|
||||
|
||||
```bash
|
||||
docker compose exec nginx nginx -T
|
||||
```
|
||||
|
||||
Check protected paths:
|
||||
|
||||
```bash
|
||||
curl -i http://127.0.0.1:8080/system/core.php
|
||||
curl -i http://127.0.0.1:8080/user/settings.json
|
||||
```
|
||||
Whitespace-only changes.
+131
@@ -0,0 +1,131 @@
|
||||
name: ${COMPOSE_PROJECT_NAME:-egeya}
|
||||
|
||||
services:
|
||||
db:
|
||||
image: mariadb:${MARIADB_VERSION:-10.11}
|
||||
restart: unless-stopped
|
||||
|
||||
environment:
|
||||
MARIADB_DATABASE: ${EGEYA_DB_NAME:-egeya}
|
||||
MARIADB_USER: ${EGEYA_DB_USER:-egeya}
|
||||
MARIADB_PASSWORD_FILE: /run/secrets/db_password
|
||||
MARIADB_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
|
||||
TZ: ${TZ:-UTC}
|
||||
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
|
||||
secrets:
|
||||
- db_password
|
||||
- db_root_password
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 20s
|
||||
|
||||
networks:
|
||||
- backend
|
||||
|
||||
php:
|
||||
build:
|
||||
context: .
|
||||
target: php
|
||||
args:
|
||||
EGEYA_VERSION: ${EGEYA_VERSION:-4199}
|
||||
EGEYA_URL: ${EGEYA_URL:-}
|
||||
EGEYA_SHA256: ${EGEYA_SHA256:-}
|
||||
|
||||
image: ${EGEYA_PHP_IMAGE:-local/egeya-php}:${EGEYA_VERSION:-4199}
|
||||
restart: unless-stopped
|
||||
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
environment:
|
||||
E2_DB_SERVER: db
|
||||
E2_DB_USER_NAME: ${EGEYA_DB_USER:-egeya}
|
||||
E2_DB_PASSW_FILE: /run/secrets/db_password
|
||||
E2_DB_NAME: ${EGEYA_DB_NAME:-egeya}
|
||||
PHP_MEMORY_LIMIT: ${PHP_MEMORY_LIMIT:-512M}
|
||||
PHP_UPLOAD_MAX_FILESIZE: ${PHP_UPLOAD_MAX_FILESIZE:-512M}
|
||||
PHP_POST_MAX_SIZE: ${PHP_POST_MAX_SIZE:-1024M}
|
||||
PHP_MAX_EXECUTION_TIME: ${PHP_MAX_EXECUTION_TIME:-300}
|
||||
PHP_MAX_INPUT_TIME: ${PHP_MAX_INPUT_TIME:-300}
|
||||
TZ: ${TZ:-UTC}
|
||||
|
||||
volumes:
|
||||
- ./data:/var/www/egeya-data
|
||||
|
||||
secrets:
|
||||
- db_password
|
||||
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- php
|
||||
- -r
|
||||
- '$$s=@fsockopen("127.0.0.1",9000,$$e,$$m,2); if(!$$s){exit(1);} fclose($$s);'
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
networks:
|
||||
- backend
|
||||
|
||||
nginx:
|
||||
build:
|
||||
context: .
|
||||
target: nginx
|
||||
args:
|
||||
EGEYA_VERSION: ${EGEYA_VERSION:-4199}
|
||||
EGEYA_URL: ${EGEYA_URL:-}
|
||||
EGEYA_SHA256: ${EGEYA_SHA256:-}
|
||||
|
||||
image: ${EGEYA_NGINX_IMAGE:-local/egeya-nginx}:${EGEYA_VERSION:-4199}
|
||||
restart: unless-stopped
|
||||
|
||||
depends_on:
|
||||
php:
|
||||
condition: service_healthy
|
||||
|
||||
environment:
|
||||
NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_}
|
||||
NGINX_CLIENT_MAX_BODY_SIZE: ${PHP_POST_MAX_SIZE:-1024M}
|
||||
TZ: ${TZ:-UTC}
|
||||
|
||||
ports:
|
||||
- "${HTTP_BIND:-127.0.0.1}:${HTTP_PORT:-8080}:80"
|
||||
|
||||
volumes:
|
||||
- ./data:/var/www/egeya-data:ro
|
||||
|
||||
networks:
|
||||
- frontend
|
||||
- backend
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
|
||||
networks:
|
||||
frontend:
|
||||
driver: bridge
|
||||
|
||||
backend:
|
||||
driver: bridge
|
||||
internal: true
|
||||
|
||||
secrets:
|
||||
db_password:
|
||||
file: ./secrets/db_password
|
||||
|
||||
db_root_password:
|
||||
file: ./secrets/db_root_password
|
||||
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.
@@ -0,0 +1,54 @@
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
server_name ${NGINX_SERVER_NAME};
|
||||
|
||||
keepalive_timeout 70;
|
||||
client_max_body_size ${NGINX_CLIENT_MAX_BODY_SIZE};
|
||||
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
location ~* ^.+\.(jpg|jpeg|gif|css|html|htm|png|js|webp|avif|svg|mp3|ogg|mp4|mov)$ {
|
||||
access_log off;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
error_page 404 /errors/404.html;
|
||||
|
||||
location / {
|
||||
log_not_found off;
|
||||
rewrite ^(.*)$ /index.php?go=$1 last;
|
||||
}
|
||||
|
||||
location ~ ^/(system|user)/.*\.php$ {
|
||||
deny all;
|
||||
return 403;
|
||||
}
|
||||
|
||||
location = /user/settings.json {
|
||||
deny all;
|
||||
return 403;
|
||||
}
|
||||
|
||||
location = /user/settings.psa {
|
||||
deny all;
|
||||
return 403;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param E2_SYNTH_URLS true;
|
||||
fastcgi_pass php:9000;
|
||||
fastcgi_index index.php;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~ \.psa$ {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
EGEYA_DATA_DIR="${EGEYA_DATA_DIR:-/var/www/egeya-data}"
|
||||
EGEYA_DEFAULTS_DIR="${EGEYA_DEFAULTS_DIR:-/opt/egeya-defaults}"
|
||||
PHP_RUNTIME_INI="/usr/local/etc/php/conf.d/zz-egeya-runtime.ini"
|
||||
|
||||
PHP_MEMORY_LIMIT="${PHP_MEMORY_LIMIT:-512M}"
|
||||
PHP_UPLOAD_MAX_FILESIZE="${PHP_UPLOAD_MAX_FILESIZE:-512M}"
|
||||
PHP_POST_MAX_SIZE="${PHP_POST_MAX_SIZE:-1024M}"
|
||||
PHP_MAX_EXECUTION_TIME="${PHP_MAX_EXECUTION_TIME:-300}"
|
||||
PHP_MAX_INPUT_TIME="${PHP_MAX_INPUT_TIME:-300}"
|
||||
|
||||
copy_defaults_if_empty() {
|
||||
local name="$1"
|
||||
local source_dir="${EGEYA_DEFAULTS_DIR}/${name}"
|
||||
local target_dir="${EGEYA_DATA_DIR}/${name}"
|
||||
|
||||
mkdir -p "$target_dir"
|
||||
|
||||
if [ -d "$source_dir" ] && [ -z "$(find "$target_dir" -mindepth 1 -print -quit)" ]; then
|
||||
cp -a "$source_dir"/. "$target_dir"/
|
||||
fi
|
||||
}
|
||||
|
||||
read_secret_to_env() {
|
||||
local env_name="$1"
|
||||
local file_env_name="${env_name}_FILE"
|
||||
local file_path="${!file_env_name:-}"
|
||||
|
||||
if [ -n "$file_path" ]; then
|
||||
if [ ! -r "$file_path" ]; then
|
||||
printf 'Secret file is not readable: %s\n' "$file_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf -v "$env_name" '%s' "$(cat "$file_path")"
|
||||
export "$env_name"
|
||||
fi
|
||||
}
|
||||
|
||||
copy_defaults_if_empty user
|
||||
copy_defaults_if_empty pictures
|
||||
|
||||
mkdir -p \
|
||||
"$EGEYA_DATA_DIR/tmp" \
|
||||
"$EGEYA_DATA_DIR/tmp/sessions" \
|
||||
"$EGEYA_DATA_DIR/user/logs"
|
||||
|
||||
touch "$EGEYA_DATA_DIR/user/logs/main.log"
|
||||
|
||||
chown -R www-data:www-data \
|
||||
"$EGEYA_DATA_DIR/user" \
|
||||
"$EGEYA_DATA_DIR/pictures" \
|
||||
"$EGEYA_DATA_DIR/tmp"
|
||||
|
||||
chmod 0700 "$EGEYA_DATA_DIR/tmp" "$EGEYA_DATA_DIR/tmp/sessions"
|
||||
|
||||
read_secret_to_env E2_DB_PASSW
|
||||
|
||||
cat > "$PHP_RUNTIME_INI" <<EOF_INI
|
||||
memory_limit = ${PHP_MEMORY_LIMIT}
|
||||
upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE}
|
||||
post_max_size = ${PHP_POST_MAX_SIZE}
|
||||
max_execution_time = ${PHP_MAX_EXECUTION_TIME}
|
||||
max_input_time = ${PHP_MAX_INPUT_TIME}
|
||||
upload_tmp_dir = ${EGEYA_DATA_DIR}/tmp
|
||||
sys_temp_dir = ${EGEYA_DATA_DIR}/tmp
|
||||
session.save_path = ${EGEYA_DATA_DIR}/tmp/sessions
|
||||
EOF_INI
|
||||
|
||||
exec /usr/local/bin/docker-php-entrypoint "$@"
|
||||
@@ -0,0 +1,4 @@
|
||||
[www]
|
||||
clear_env = no
|
||||
catch_workers_output = yes
|
||||
decorate_workers_output = no
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
DUMP_FILE="${1:-${PROJECT_DIR}/backup/egeya.sql}"
|
||||
|
||||
if [ ! -r "$DUMP_FILE" ]; then
|
||||
printf 'SQL dump not found or not readable: %s\n' "$DUMP_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
docker compose up -d db
|
||||
|
||||
docker compose exec -T db sh -ec '
|
||||
exec mariadb \
|
||||
-u"$MARIADB_USER" \
|
||||
-p"$(cat /run/secrets/db_password)" \
|
||||
"$MARIADB_DATABASE"
|
||||
' < "$DUMP_FILE"
|
||||
|
||||
printf 'Imported database dump: %s\n' "$DUMP_FILE"
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
SOURCE_BLOG_DIR="${1:-/var/www/blog}"
|
||||
TARGET_DATA_DIR="${2:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/data}"
|
||||
|
||||
for name in user pictures; do
|
||||
source_dir="${SOURCE_BLOG_DIR}/${name}"
|
||||
target_dir="${TARGET_DATA_DIR}/${name}"
|
||||
|
||||
if [ ! -d "$source_dir" ]; then
|
||||
printf 'Source directory not found: %s\n' "$source_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$target_dir"
|
||||
rsync -aHAX --delete "$source_dir"/ "$target_dir"/
|
||||
done
|
||||
|
||||
mkdir -p "${TARGET_DATA_DIR}/tmp"
|
||||
|
||||
printf 'Copied user and pictures from %s to %s\n' "$SOURCE_BLOG_DIR" "$TARGET_DATA_DIR"
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENV_FILE="${PROJECT_DIR}/.env"
|
||||
ENV_EXAMPLE="${PROJECT_DIR}/.env.example"
|
||||
SECRETS_DIR="${PROJECT_DIR}/secrets"
|
||||
DATA_DIR="${PROJECT_DIR}/data"
|
||||
|
||||
create_secret() {
|
||||
local path="$1"
|
||||
|
||||
if [ ! -s "$path" ]; then
|
||||
umask 077
|
||||
openssl rand -base64 48 | tr -d '\n' > "$path"
|
||||
printf '\n' >> "$path"
|
||||
fi
|
||||
}
|
||||
|
||||
mkdir -p \
|
||||
"$SECRETS_DIR" \
|
||||
"$DATA_DIR/user" \
|
||||
"$DATA_DIR/pictures" \
|
||||
"$DATA_DIR/tmp"
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
cp "$ENV_EXAMPLE" "$ENV_FILE"
|
||||
fi
|
||||
|
||||
create_secret "$SECRETS_DIR/db_password"
|
||||
create_secret "$SECRETS_DIR/db_root_password"
|
||||
|
||||
chmod 0600 \
|
||||
"$SECRETS_DIR/db_password" \
|
||||
"$SECRETS_DIR/db_root_password"
|
||||
|
||||
printf 'Project prepared: %s\n' "$PROJECT_DIR"
|
||||
Whitespace-only changes.
Reference in new issue
Block a user