diff --git a/blog_static/blog.p2pfoundation.net/public_html/wp-content/themes/readme/header.php b/blog_static/blog.p2pfoundation.net/public_html/wp-content/themes/readme/header.php
new file mode 100644
index 0000000..8d61ca0
--- /dev/null
+++ b/blog_static/blog.p2pfoundation.net/public_html/wp-content/themes/readme/header.php
@@ -0,0 +1,141 @@
+
+
+
+ class="">
+
+
+
+
\ No newline at end of file
diff --git a/blog_static/docker-compose.p2pfoundation.yml b/blog_static/docker-compose.p2pfoundation.yml
new file mode 100644
index 0000000..79154e5
--- /dev/null
+++ b/blog_static/docker-compose.p2pfoundation.yml
@@ -0,0 +1,190 @@
+version: "3.8"
+
+services:
+ db:
+ image: mariadb:10.11
+ container_name: p2p-db
+ restart: unless-stopped
+ command: --max-connections=300 --wait-timeout=300 --interactive-timeout=300
+ environment:
+ MYSQL_ROOT_PASSWORD: p2p_secure_root_2025
+ volumes:
+ - db_data:/var/lib/mysql
+ - ./init-db:/docker-entrypoint-initdb.d
+ networks:
+ - p2p-internal
+ healthcheck:
+ test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
+ wiki:
+ image: mediawiki:1.41
+ container_name: p2p-wiki
+ restart: unless-stopped
+ environment:
+ - MEDIAWIKI_DB_HOST=db
+ - MEDIAWIKI_DB_NAME=p2p_wiki
+ - MEDIAWIKI_DB_USER=p2p_wiki
+ - MEDIAWIKI_DB_PASSWORD=wiki_secure_2025
+ volumes:
+ - wiki_data:/var/www/html/images
+ - ./wiki-config:/var/www/html/config
+ - ./robots-wiki.txt:/var/www/html/robots.txt:ro
+ - ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
+ depends_on:
+ db:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.p2p-wiki.rule=Host(`wiki.p2pfoundation.net`)"
+ - "traefik.http.services.p2p-wiki.loadbalancer.server.port=80"
+ networks:
+ - p2p-internal
+ - traefik-public
+
+ blog:
+ image: wordpress:6.4-php8.2-apache
+ container_name: p2p-blog
+ restart: unless-stopped
+ environment:
+ WORDPRESS_DB_HOST: db
+ WORDPRESS_DB_NAME: p2p_blog
+ WORDPRESS_DB_USER: p2p_blog
+ WORDPRESS_DB_PASSWORD: blog_secure_2025
+ volumes:
+ - blog_data:/var/www/html
+ - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
+ - ./robots.txt:/var/www/html/robots.txt:ro
+ - ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
+ - ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
+ depends_on:
+ db:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.p2p-blog.rule=Host(`blog.p2pfoundation.net`) || Host(`www.blog.p2pfoundation.net`)"
+ - "traefik.http.services.p2p-blog.loadbalancer.server.port=80"
+ networks:
+ - p2p-internal
+ - traefik-public
+
+ bloggr:
+ image: wordpress:6.4-php8.2-apache
+ container_name: p2p-bloggr
+ restart: unless-stopped
+ environment:
+ WORDPRESS_DB_HOST: db
+ WORDPRESS_DB_NAME: p2p_bloggr
+ WORDPRESS_DB_USER: p2p_bloggr
+ WORDPRESS_DB_PASSWORD: bloggr_secure_2025
+ volumes:
+ - bloggr_data:/var/www/html
+ - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
+ - ./robots.txt:/var/www/html/robots.txt:ro
+ - ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
+ - ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
+ depends_on:
+ db:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.p2p-bloggr.rule=Host(`bloggr.p2pfoundation.net`)"
+ - "traefik.http.services.p2p-bloggr.loadbalancer.server.port=80"
+ networks:
+ - p2p-internal
+ - traefik-public
+
+ blogfr:
+ image: wordpress:6.4-php8.2-apache
+ container_name: p2p-blogfr
+ restart: unless-stopped
+ environment:
+ WORDPRESS_DB_HOST: db
+ WORDPRESS_DB_NAME: p2p_blogfr
+ WORDPRESS_DB_USER: p2p_blogfr
+ WORDPRESS_DB_PASSWORD: blogfr_secure_2025
+ volumes:
+ - blogfr_data:/var/www/html
+ - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
+ - ./robots.txt:/var/www/html/robots.txt:ro
+ - ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
+ - ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
+ depends_on:
+ db:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.p2p-blogfr.rule=Host(`blogfr.p2pfoundation.net`)"
+ - "traefik.http.services.p2p-blogfr.loadbalancer.server.port=80"
+ networks:
+ - p2p-internal
+ - traefik-public
+
+ blognl:
+ image: wordpress:6.4-php8.2-apache
+ container_name: p2p-blognl
+ restart: unless-stopped
+ environment:
+ WORDPRESS_DB_HOST: db
+ WORDPRESS_DB_NAME: p2p_blognl
+ WORDPRESS_DB_USER: p2p_blognl
+ WORDPRESS_DB_PASSWORD: blognl_secure_2025
+ volumes:
+ - blognl_data:/var/www/html
+ - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
+ - ./robots.txt:/var/www/html/robots.txt:ro
+ - ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
+ - ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
+ depends_on:
+ db:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.p2p-blognl.rule=Host(`blognl.p2pfoundation.net`)"
+ - "traefik.http.services.p2p-blognl.loadbalancer.server.port=80"
+ networks:
+ - p2p-internal
+ - traefik-public
+
+ web:
+ image: wordpress:6.4-php8.2-apache
+ container_name: p2p-web
+ restart: unless-stopped
+ environment:
+ WORDPRESS_DB_HOST: db
+ WORDPRESS_DB_NAME: p2p_web
+ WORDPRESS_DB_USER: p2p_web
+ WORDPRESS_DB_PASSWORD: web_secure_2025
+ volumes:
+ - web_data:/var/www/html
+ - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini:ro
+ - ./robots.txt:/var/www/html/robots.txt:ro
+ - ./block-bots.conf:/etc/apache2/conf-enabled/block-bots.conf:ro
+ - ./rdata-analytics.php:/var/www/html/wp-content/mu-plugins/rdata-analytics.php:ro
+ depends_on:
+ db:
+ condition: service_healthy
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.p2p-web.rule=Host(`p2pfoundation.net`) || Host(`www.p2pfoundation.net`)"
+ - "traefik.http.services.p2p-web.loadbalancer.server.port=80"
+ networks:
+ - p2p-internal
+ - traefik-public
+
+volumes:
+ db_data:
+ wiki_data:
+ blog_data:
+ bloggr_data:
+ blogfr_data:
+ blognl_data:
+ web_data:
+
+networks:
+ p2p-internal:
+ driver: bridge
+ traefik-public:
+ external: true
diff --git a/blog_static/nginx.conf b/blog_static/nginx.conf
new file mode 100644
index 0000000..ec072f8
--- /dev/null
+++ b/blog_static/nginx.conf
@@ -0,0 +1,51 @@
+server {
+ listen 80;
+ server_name blog.p2pfoundation.net localhost;
+
+ # Default index file
+ index _index_ssl.html index.html;
+
+ # Serve WordPress core includes (CSS, JS, images)
+ location /wp-includes/ {
+ alias /usr/share/nginx/html/blog.p2pfoundation.net/public_html/wp-includes/;
+ expires 30d;
+ add_header Cache-Control "public, immutable";
+ }
+
+ # Serve wp-content assets (themes, uploads, minified CSS/JS)
+ location /wp-content/ {
+ alias /usr/share/nginx/html/blog.p2pfoundation.net/public_html/wp-content/;
+ expires 30d;
+ add_header Cache-Control "public, immutable";
+ }
+
+ # Health check endpoint
+ location /health {
+ return 200 'OK';
+ add_header Content-Type text/plain;
+ }
+
+ # Main location - serve cached pages
+ location / {
+ root /usr/share/nginx/html/blog.p2pfoundation.net/public_html/wp-content/cache/page_enhanced/blog.p2pfoundation.net;
+ try_files $uri/_index_ssl.html $uri/ $uri =404;
+ }
+
+ # Error pages
+ error_page 404 /404.html;
+ location = /404.html {
+ internal;
+ return 404 '
404 - Page Not FoundPage Not Found
The requested blog post could not be found.
Return to homepage
';
+ add_header Content-Type text/html;
+ }
+
+ # Inject Umami analytics (rData) into all HTML pages
+ sub_filter '' '';
+ sub_filter_once on;
+ sub_filter_types text/html;
+
+ # Gzip compression
+ gzip on;
+ gzip_types text/plain text/html text/css application/javascript application/json;
+ gzip_min_length 1000;
+}
diff --git a/blog_static/rdata-analytics.php b/blog_static/rdata-analytics.php
new file mode 100644
index 0000000..774e5c4
--- /dev/null
+++ b/blog_static/rdata-analytics.php
@@ -0,0 +1,16 @@
+' . "\n";
+}, 1);
diff --git a/web/index.html b/web/index.html
index 4bdf7be..338a37c 100644
--- a/web/index.html
+++ b/web/index.html
@@ -4,6 +4,7 @@
P2P Wiki AI
+