Vlad
July 6, 2022, 10:44am
#1
Good afternoon. I use my own docker images in production. It worked until the number of containers increased and it was necessary to install a reverse proxy. Over http, it works without errors. But if you install an ssl certificate and redirect 301 https, an error appears: “POST /backend/backend/auth/migrate HTTP/1.1” 403 333 “https://example.com/backend/backend/auth/migrate ” "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko).
i use docker-compose:
version: "3.7"
services:
app:
image: myoctober-v2:latest
container_name: kwest-v2-app
working_dir: /var/www/html
volumes:
- ../../:/var/www/html:rw
environment:
COMPOSER_MEMORY_LIMIT: -1
DB_CONNECTION: ${DB_CONNECTION}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_DATABASE: ${DB_DATABASE}
DB_USERNAME: ${DB_USERNAME}
DB_PASSWORD: ${DB_PASSWORD}
ENABLE_CRON: ${ENABLE_CRON}
PHP_DISPLAY_ERRORS: ${PHP_DISPLAY_ERRORS}
APP_DEBUG: ${APP_DEBUG}
CMS_LINK_POLICY: secure
networks:
default:
ipv4_address: 172.18.1.2
db:
image: mysql:5.7
container_name: kwest-db
restart: unless-stopped
environment:
MYSQL_DATABASE: kwest
MYSQL_ROOT_PASSWORD: 123qwer
MYSQL_PASSWORD: kwest
MYSQL_USER: kwest
volumes:
- ./mysql_data:/var/lib/mysql/
networks:
default:
ipv4_address: 172.18.1.3
haproxy:
image: "haproxy:2.2-alpine"
ports:
- 80:80
- 443:443
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
- ./ssl/example.com.pem:/etc/ssl/certs/example.com.pem
networks:
default:
ipv4_address: 172.18.1.10
networks:
default:
external:
name: develop
Config haproxy:
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http_frontend
bind *:80
bind *:443 ssl crt /etc/ssl/certs/example.com.pem
redirect scheme https code 301 if !{ ssl_fc }
acl is_app hdr_end(host) -i example.com
use_backend app if is_app
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
backend letsencrypt-backend
server letsencrypt 127.0.0.1:8888
backend app
server app 172.18.1.2:80 check
Сan’t find the reason, what am I doing wrong?
Vlad
July 6, 2022, 10:51am
#2
Dockerfile
FROM php:7.4-apache
RUN apt-get update && apt-get install -y cron git-core jq unzip vim zip \
libjpeg-dev libpng-dev libpq-dev libsqlite3-dev libwebp-dev libzip-dev && \
rm -rf /var/lib/apt/lists/* && \
docker-php-ext-configure zip --with-zip && \
docker-php-ext-configure gd --with-jpeg --with-webp && \
docker-php-ext-install exif gd mysqli opcache pdo_pgsql pdo_mysql zip
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=2'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} > /usr/local/etc/php/conf.d/docker-oc-opcache.ini
RUN { \
echo 'log_errors=on'; \
echo 'display_errors=off'; \
echo 'upload_max_filesize=32M'; \
echo 'post_max_size=32M'; \
echo 'memory_limit=128M'; \
} > /usr/local/etc/php/conf.d/docker-oc-php.ini
ENV COMPOSER_ALLOW_SUPERUSER=1
RUN curl -sS https://getcomposer.org/installer | php -- --1 --install-dir=/usr/local/bin --filename=composer && \
/usr/local/bin/composer global require hirak/prestissimo
RUN a2enmod rewrite
COPY config/docker /usr/src/octobercms-config-docker
COPY ../../* /var/www/html
RUN echo 'APP_ENV=docker' > .env && \
chown -R www-data:www-data /var/www/html && \
find . -type d \( -path './plugins' -or -path './storage' -or -path './themes' -or -path './plugins/*' -or -path './storage/*' -or -path './themes/*' \) -exec chmod g+ws {} \;
RUN echo "* * * * * /usr/local/bin/php /var/www/html/artisan schedule:run > /proc/1/fd/1 2>/proc/1/fd/2" > /etc/cron.d/october-cron && \
crontab /etc/cron.d/october-cron
RUN echo 'exec php artisan "$@"' > /usr/local/bin/artisan && \
echo 'exec php artisan tinker' > /usr/local/bin/tinker && \
echo '[ $# -eq 0 ] && exec php artisan october || exec php artisan october:"$@"' > /usr/local/bin/october && \
sed -i '1s;^;#!/bin/bash\n[ "$PWD" != "/var/www/html" ] \&\& echo " - Helper must be run from /var/www/html" \&\& exit 1\n;' /usr/local/bin/artisan /usr/local/bin/tinker /usr/local/bin/october && \
chmod +x /usr/local/bin/artisan /usr/local/bin/tinker /usr/local/bin/october
COPY docker-oc-entrypoint /usr/local/bin/
ENTRYPOINT ["docker-oc-entrypoint"]
CMD ["apache2-foreground"]
daft
July 7, 2022, 9:17am
#3
When using a reverse proxy, make sure you have no rules redirecting HTTP to HTTPS on the local server (backend.force_secure
). Also check that sessions are available across HTTP and HTTPS (session.http_only
).
Vlad
July 7, 2022, 10:12am
#4
Thanks for the reply. I change the parameters, but it doesn’t help.
config/session.php
‘http_only’ => false,
config/backend.php
‘force_secure’ => false,
there is an error in the browser: Mixed Content: The page at 'https://example.com/backend/backend/auth/migrate' was loaded over HTTPS, but requested an insecure stylesheet 'http://example.com/modules/system/assets/ui/storm.css?v=6adddf60'. This request has been blocked; the content must be served over HTTPS
in .env, such parameters are
PROJECT_NAME=kwest-back
ACTIVE_THEME=map
APP_DEBUG=true
APP_ENV=local
APP_KEY=******************************************
APP_LOCALE=en
APP_NAME=October_CMS
APP_URL=https://example.com
BACKEND_URI=/backend
BROADCAST_DRIVER=log
CACHE_DRIVER=file
CMS_ASSET_CACHE=false
CMS_DB_TEMPLATES=false
CMS_ROUTE_CACHE=false
COMPOSE_PROJECT_NAME=kwest-back
DB_CONNECTION=mysql
DB_DATABASE=kwest
DB_HOST=mysql-server
DB_PASSWORD=kwest
DB_PORT=3306
DB_USERNAME=kwest
DEFAULT_FILE_MASK=775
DEFAULT_FOLDER_MASK=775
LINK_POLICY=detect
LOG_CHANNEL=single
APP_URL=https:// and APP_URL=http:// - nothing changes
LINK_POLICY=secure or force - js and css start loading, but the POST request 403
Vlad
July 7, 2022, 12:42pm
#5
It worked in this configuration: haproxy+nginx+php-fpm
80 → haproxy → tcp port 443 → nginx ssl → php port-fpm 9000
I think the application needs the client’s real ip addresses. And reverse proxy did not pass such parameters. Docker’s internal ip addresses came out in the logs.
Am I thinking right or am I wrong?
Parameters with which it worked:
haproxy.cfg
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
log global
frontend http_frontend
bind *:80
redirect scheme https code 301 if !{ ssl_fc }
frontend https_frontend
bind *:443
option tcplog
mode tcp
default_backend nginx
stats uri /haproxy?stats
backend nginx
mode tcp
option ssl-hello-chk
balance roundrobin
server nginx 172.18.1.1:443 send-proxy
app.conf
server {
listen *:443 default_server ssl proxy_protocol;
server_name example.com;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html;
# server_tokens off;
ssl_certificate /lets/fullchain.pem;
ssl_certificate_key /lets/privkey.pem;
set_real_ip_from 172.18.1.0/24;
real_ip_header proxy_protocol;
client_max_body_size 8M;
location / {
proxy_max_temp_file_size 0;
try_files $uri $uri/ /index.php?$query_string;
}
location ~ ^/index.php {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
try_files $uri =404;
fastcgi_pass app:9000;
fastcgi_read_timeout 300;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~ ^/(.*\.(ac3|avi|bmp|bz2|css|cue|dat|doc|docx|dts|exe|flv|gif|gz|html|ico|img|iso|jpeg|jpg|js|mkv|mp3|mp4|mpeg|mpg|ogg|pdf|png|ppt|pptx|qt|rar|rm|swf|tar|tgz|txt|wav|xls|xlsx|zip|7z|svg|ttf|woff|woff2|eot))$ {
sendfile on;
access_log off;
expires max;
}
location ~ /\.ht {
deny all;
}
# Whitelist
## Let October handle if static file not exists
location ~ ^/favicon\.ico { try_files $uri /index.php; }
location ~ ^/sitemap\.xml { try_files $uri /index.php; }
location ~ ^/robots\.txt { try_files $uri /index.php; }
location ~ ^/humans\.txt { try_files $uri /index.php; }
location ~ ^/[0-9a-z]+.html { try_files $uri /index.php; }
location ~ ^/[0-9a-z]+.tar.gz {try_files $uri /index.php; }
## Let nginx return 404 if static file not exists
location ~ ^/.well-known { try_files $uri 404; }
location ~ ^/storage/app/uploads/public { try_files $uri 404; }
location ~ ^/storage/app/media { try_files $uri 404; }
location ~ ^/storage/temp/public { try_files $uri 404; }
location ~ ^/storage/app/cropped { try_files $uri 404; }
location ~ ^/storage/app/rss { try_files $uri 404; }
location ~ ^/storage/app/collections { try_files $uri 404; }
location ~ ^/modules/.*/assets { try_files $uri 404; }
location ~ ^/modules/.*/resources { try_files $uri 404; }
location ~ ^/modules/.*/behaviors/.*/assets { try_files $uri 404; }
location ~ ^/modules/.*/behaviors/.*/resources { try_files $uri 404; }
location ~ ^/modules/.*/widgets/.*/assets { try_files $uri 404; }
location ~ ^/modules/.*/widgets/.*/resources { try_files $uri 404; }
location ~ ^/modules/.*/formwidgets/.*/assets { try_files $uri 404; }
location ~ ^/modules/.*/formwidgets/.*/resources { try_files $uri 404; }
location ~ ^/modules/.*/reportwidgets/.*/assets { try_files $uri 404; }
location ~ ^/modules/.*/reportwidgets/.*/resources { try_files $uri 404; }
location ~ ^/plugins/.*/.*/assets { try_files $uri 404; }
location ~ ^/plugins/.*/.*/resources { try_files $uri 404; }
location ~ ^/plugins/.*/.*/behaviors/.*/assets { try_files $uri 404; }
location ~ ^/plugins/.*/.*/behaviors/.*/resources { try_files $uri 404; }
location ~ ^/plugins/.*/.*/reportwidgets/.*/assets { try_files $uri 404; }
location ~ ^/plugins/.*/.*/reportwidgets/.*/resources { try_files $uri 404; }
location ~ ^/plugins/.*/.*/formwidgets/.*/assets { try_files $uri 404; }
location ~ ^/plugins/.*/.*/formwidgets/.*/resources { try_files $uri 404; }
location ~ ^/plugins/.*/.*/widgets/.*/assets { try_files $uri 404; }
location ~ ^/plugins/.*/.*/widgets/.*/resources { try_files $uri 404; }
location ~ ^/themes/.*/assets { try_files $uri 404; }
location ~ ^/themes/.*/resources { try_files $uri 404; }
gzip on;
gzip_disable "msie6";
gzip_types
application/atom+xml
application/javascript
text/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
font/ttf
application/x-font-ttf
application/vnd.ms-fontobject
application/font-woff
application/font-woff2
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vnd.wap.wml
text/vtt
text/x-component
text/x-cross-domain-policy;
gzip_comp_level 6;
gzip_vary on;
gzip_static off;
gzip_proxied any;
}
server {
listen 80;
server_name example.com;
location / {
rewrite ^ https://$host$request_uri? permanent;
}
}
daft
July 8, 2022, 8:00am
#6
You may need to set the URL (app.url
) to something static and then force the schema with a link policy (system.link_policy
) set to force .