fpm image with a Nginx web server behind a Nginx reverse proxy
Still work in progress
This is a simple example for the Friendica fpm image with a Nginx web server behind a Nginx reverse proxy.
Additional settings like
- general Nginx settings
- optimzied tls configuration
- caching
- rate limiting
are not included.
The install using the autoinstall finishes. But registering the admin user in the login page fails.
This is the docker-compose file I use:
services:
db:
image: mariadb
restart: unless-stopped
volumes:
- db:/var/lib/mysql
networks:
- friendica
environment:
- MYSQL_USER=${MYSQL_USER:?error}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:?error}
- MYSQL_DATABASE=${MYSQL_DATABASE:?error}
- MYSQL_RANDOM_ROOT_PASSWORD=yes
app:
image: ${FRIENDICA_IMAGE:?error}
restart: unless-stopped
volumes:
- friendica:/var/www/html
- friendica_data:/var/www/data
- ./logs:/var/log
networks:
- friendica
environment:
- MYSQL_HOST=db
- MYSQL_USER=${MYSQL_USER:?error}
- MYSQL_PASSWORD=${MYSQL_PASSWORD:?error}
- MYSQL_DATABASE=${MYSQL_DATABASE:?error}
- FRIENDICA_ADMIN_MAIL=${FRIENDICA_ADMIN_MAIL:?error}
- FRIENDICA_UPGRADE=${FRIENDICA_UPGRADE}
- SMTP=${SMTP}
- SMTP_DOMAIN=${SMTP_DOMAIN}
- SMTP_AUTH_USER=${SMTP_AUTH_USER}
- SMTP_AUTH_PASS=${SMTP_AUTH_PASS}
- FRIENDICA_LOGFILE=${FRIENDICA_LOGFILE}
- FRIENDICA_LOGLEVEL=${FRIENDICA_LOGLEVEL}
- FRIENDICA_DEBUGGING=${FRIENDICA_DEBUGGING}
depends_on:
- db
web:
image: nginx
restart: unless-stopped
volumes:
- friendica:/var/www/html
- ./etc/nginx.conf:/etc/nginx/nginx.conf
- ./logs:/var/log
ports:
- "9080:80"
networks:
- friendica
depends_on:
- db
- app
volumes:
db:
friendica:
friendica_data:
networks:
friendica:
The Nginx web server configuration
Required directories are
/var/www/html html directory as defined in docker setup
##
# Friendica Nginx configuration
# by Olaf Conradi, modified by Philipp Holzer
#
worker_processes auto;
events {
worker_connections 1024;
}
error_log /var/log/nginx/error.log warn;
pid /tmp/nginx.pid;
http {
charset utf-8;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# If behind reverse proxy, forwards the correct IP
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from fc00::/7;
real_ip_header X-Real-IP;
real_ip_recursive on;
upstream php-handler {
server app:9000;
}
server {
listen 80 default_server;
server_name _;
index index.php;
root /var/www/html;
#Uncomment the following line to include a standard configuration file
#Note that the most specific rule wins and your standard configuration
#will therefore *add* to this file, but not override it.
#include standard.conf
# allow uploads up to 20MB in size
client_max_body_size 20m;
client_body_buffer_size 128k;
# rewrite to front controller as default rule
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?pagename=$1;
}
}
# make sure webfinger and other well known services aren't blocked
# by denying dot files and rewrite request to the front controller
location ^~ /.well-known/ {
allow all;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?pagename=$1;
}
}
# statically serve these file types when possible
# otherwise fall back to front controller
# allow browser to cache them
# added .htm for advanced source code editor library
location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|ttf|woff|woff2|svg|pcss)$ {
expires 30d;
try_files $uri /index.php?pagename=$uri&$args;
}
include mime.types;
# block these file types
location ~* \.(tpl|md|tgz|log|out)$ {
deny all;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
# or a unix socket
location ~* \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this
# server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on
# another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-handler;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# deny access to all dot files
location ~ /\. {
deny all;
}
location /healthz {
access_log off;
add_header Content-Type text/plain;
return 200 "OK";
}
}
}
The reverse proxy configuration
Required directories are
/var/www/default empty directory
/var/www/acme directory used for acme challenge with Certbot
/var/www/friendica empty directory
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/default;
# Allow access to the ACME Challenge for Let's Encrypt
location /.well-known/acme-challenge {
allow all;
root /var/www/acme;
try_files $uri =404;
}
location / {
if ($accept_redirect = 1) {
return 301 https://$host$request_uri;
}
return 444;
}
}
upstream friendica {
server localhost:9080;
keepalive 4;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic;
listen [::]:443 quic;
server_name friendica.your.domain;
ssl_certificate /etc/letsencrypt/live/friendica.your.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/friendica.your.domain/privkey.pem;
root /var/www/friendica;
location / {
# required for browsers to direct them to quic port
add_header Alt-Svc 'h3=":443"; ma=86400';
proxy_http_version 1.1;
proxy_set_header "Connection" "";
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_set_header Forwarded "for=$remote_addr; proto=$scheme; by=$server_addr";
proxy_set_header X-Real-IP $remote_addr;
proxy_hide_header X-Powered-By;
proxy_pass http://friendica;
}
}
Ping @SpencerDub to compare notes with your own configuration, although it looks awfully similar at first glance.
Thank you for the ping! It will be helpful to compare this to mine and see if I'm overlooking something.
Also thanks to @ne20002 for taking the initiative here!
@ne20002 I'm nearly done following a similar setup to this. How are you handling background task processing?
I'll admit, I'm asking because the documentation between this repo and the main Friendica one are leaving me very confused. I don't see a dedicated cron instance in your Docker Compose file, but I'm uncertain exactly how to apply the instructions from the main repo, as they're written for a non-containerized install and I presume trying to run a PHP worker outside of the container wouldn't do anything.
At any rate, I'd love to hear how you have it set it up so I can copy from your notes.
Hi @SpencerDub Yes, I do run a second friendica docker container as cron.
I'm not using docker compose, I run my setup as a pod with Podman and containers are started by systemd.
The docker compose above is the one I use for testing. So yes, the cron container is missing herein. I'll add it when I'm back end of next week.