[
  {
    "path": "Dockerfile",
    "content": "FROM alpine:latest\nMAINTAINER Etopian Inc. <contact@etopian.com>\n\nLABEL   devoply.type=\"site\" \\\n        devoply.cms=\"wordpress\" \\\n        devoply.framework=\"wordpress\" \\\n        devoply.language=\"php7\" \\\n        devoply.require=\"mariadb etopian/nginx-proxy\" \\\n        devoply.recommend=\"redis\" \\\n        devoply.description=\"WordPress on Nginx and PHP-FPM with WP-CLI.\" \\\n        devoply.name=\"WordPress\" \\\n        devoply.params=\"docker run -d --name {container_name} -e VIRTUAL_HOST={virtual_hosts} -v /data/sites/{domain_name}:/DATA etopian/alpine-php7-wordpress\"\n\n\n\nRUN echo 'http://dl-4.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories\\\n    && apk update \\\n    && apk add --no-cache \\\n    bash \\\n    less \\\n    vim \\\n    nginx \\\n    ca-certificates \\\n    php7-fpm \\\n    php7-json \\\n    php7-zlib \\\n    php7-xml \\\n    php7-pdo \\\n    php7-phar \\\n    php7-openssl \\\n    php7-pdo_mysql \\\n    php7-mysqli \\\n    php7-session \\\n    php7-gd \\\n    php7-iconv \\\n    php7-mcrypt \\\n    php7-curl \\\n    php7-opcache \\\n    php7-ctype \\\n    php7-apcu \\\n    php7-intl \\\n    php7-bcmath \\\n    php7-mbstring \\\n    php7-dom \\\n    php7-xmlreader \\\n    php7-simplexml \\\n    mysql-client \\\n    openssh-client \\\n    git \\\n    curl \\\n    rsync \\\n    musl \\\n    && apk --update --no-cache add tar\nRUN rm -rf /var/cache/apk/*\n\nENV TERM=\"xterm\" \\\n    DB_HOST=\"172.17.0.1\" \\\n    DB_NAME=\"\" \\\n    DB_USER=\"\"\\\n    DB_PASS=\"\"\n\n\nENV PATH /DATA/bin:$PATH\n\nRUN sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php7/php.ini && \\\n    sed -i \"s/nginx:x:100:101:nginx:\\/var\\/lib\\/nginx:\\/sbin\\/nologin/nginx:x:100:101:nginx:\\/DATA:\\/bin\\/bash/g\" /etc/passwd && \\\n    sed -i \"s/nginx:x:100:101:nginx:\\/var\\/lib\\/nginx:\\/sbin\\/nologin/nginx:x:100:101:nginx:\\/DATA:\\/bin\\/bash/g\" /etc/passwd-\n\n\nADD files/nginx.conf /etc/nginx/\nADD files/php-fpm.conf /etc/php7/\nADD files/run.sh /\nADD files/wp-config-devoply.php /usr/bin/wp-config-devoply\nRUN chmod +x /run.sh && chmod +x /usr/bin/wp-config-devoply\n\nRUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && chmod +x wp-cli.phar && mv wp-cli.phar /usr/bin/wp-cli && chown nginx:nginx /usr/bin/wp-cli\n\nEXPOSE 80\nVOLUME [\"/DATA\"]\n\nCMD [\"/run.sh\"]\n"
  },
  {
    "path": "README.md",
    "content": "# This image is DEPRECATED/DEAD.\n\nSee [https://github.com/devoply/wordpress](https://github.com/devoply/wordpress) for a newer image with a proper process manager.\n\n### OLD INFO\n\nFull documentation for this project can be found here: http://www.wordpressdocker.com/\n\nWe also have a development container: https://github.com/etopian/alpine-php-wordpress-dev\n\n# Lightweight WordPress PHP7 PHP-FPM7 & Nginx Docker Production Image\n\nLightweight Docker image for the (latest) PHP-FPM and Nginx to run WordPress based on [AlpineLinux](http://alpinelinux.org)\n\n* Image size only ~131MB !\n* Very new packages (alpine:edge) 2016-07-21:\n  * [PHP](http://pkgs.alpinelinux.org/package/main/x86/php) 7.0.13\n  * [Nginx](http://pkgs.alpinelinux.org/package/main/x86/nginx) nginx/1.10.2\n  * Memory usage is around 50mb on a simple install.\n\n## A simple example\n### Say you want to run a single site on a VPS with Docker\n\n```bash\n\nmkdir -p /data/sites/etopian.com/htdocs\n\nsudo docker run -e VIRTUAL_HOST=etopian.com,www.etopian.com -v /data/sites/etopian.com:/DATA -p 80:80 etopian/alpine-php-wordpress\n\n```\nThe following user and group id are used, the files should be set to this:\nUser ID: \nGroup ID: \n\n```bash\nchown -R 100:101 /data/sites/etopian.com/htdocs\n```\n\n### Say you want to run a multiple WP sites on a VPS with Docker\n\n```bash\n\nsudo docker run -p 80:80 etopian/nginx-proxy\nmkdir -p /data/sites/etopian.com/htdocs\n\nsudo docker run -e VIRTUAL_HOST=etopian.com,www.etopian.com -v /data/sites/etopian.com:/DATA etopian/alpine-php-wordpress\n\nmkdir -p /data/sites/etopian.net/htdocs\nsudo docker run -e VIRTUAL_HOST=etopian.net,www.etopian.net -v /data/sites/etopian.net:/DATA etopian/alpine-php-wordpress\n```\n\nPopulate /data/sites/etopian.com/htdocs and  /data/sites/etopian.net/htdocs with your WP files. See http://www.wordpressdocker.com if you need help on how to configure your database.\n\nThe following user and group id are used, the files should be set to this:\nUser ID: \nGroup ID: \n\n```bash\nchown -R 100:101 /data/sites/etopian.com/htdocs\n```\n\n\n\n### Volume structure\n\n* `htdocs`: Webroot\n* `logs`: Nginx/PHP error logs\n* \n\n### WP-CLI\n\nThis image now includes [WP-CLI](wp-cli.org) baked in... So you can. Please `su nginx` before executing or else you can potentially compromise your host.\n\n```\ndocker exec -it <container_name> bash\nsu nginx\ncd /DATA/htdocs\nwp-cli cli\n```\n\n### Multisite\n\nFor each multisite you need to give the domain as the -e VIRTUAL_HOST parameter. For instance VIRTUAL_HOST=site1.com,www.site1.com,site2.com,www.site2.com ... if you wish to add more sites you need to recreate the container.\n\n### Upload limit\n\nThe upload limit is 2 gigabyte.\n\n### Change php.ini value\nmodify files/php-fpm.conf\n\nTo modify php.ini variable, simply edit php-fpm.ini and add php_flag[variable] = value.\n\n```\nphp_flag[display_errors] = on\n```\n\nAdditional documentation on http://www.wordpressdocker.com\n\n## Questions or Support\n\nhttps://gitter.im/etopian/devoply\n\n## Docker WordPress Control Panel\n\nDEVOPly is a free hosting control panel which does everything taught in this tutorial automatically and much more, backups, staging/dev/prod, code editor, Github/Bitbucket deployments, DNS, WordPress Management. https://www.devoply.com\n\n\n"
  },
  {
    "path": "docker-build.sh",
    "content": "#!/bin/bash\n\ndocker build -t etopian/alpine-php-wordpress:latest .\n"
  },
  {
    "path": "files/fail2ban/filter.d/nginx-blocked.conf",
    "content": "# this file goes on the host in /etc/fail2ban/filter.d/nginx-blocked\n[Definition]\nfailregex = ^.* Blocked request from <HOST>.*$\nignoreregex =\n"
  },
  {
    "path": "files/fail2ban/filter.d/wordpress-auth.conf",
    "content": "[Definition]\nfailregex = <HOST>.*POST.*(wp-login\\.php|xmlrpc\\.php).* 403 \n"
  },
  {
    "path": "files/fail2ban/jail.conf",
    "content": "# nginx blocks  \n# this file goes on the host in /etc/fail2ban/jail.conf\n[nginx-blocked]\nenabled = true\nbantime  = 600\nmaxretry = 3\nbackend = auto\nfindtime = 30\nbanaction = iptables-multiport\nprotocol = tcp\nchain = INPUT\nport = 80,443\nfilter = nginx-blocked\nlogpath = /data/sites/*/logs/nginx/blocked.log\n\n[wordpress]\n\nenabled  = true\nport     = http,https\nfilter   = wordpress-auth\nlogpath  = /data/sites/*/logs/nginx/access.log\nmaxretry = 3\nbantime  = 3600\n"
  },
  {
    "path": "files/fail2ban/mu-plugins/fail2ban_login_failed.php",
    "content": "<?php\n# this file goes under <site_root>/wp-content/mu-plugins\n\nfunction fail2ban_login_failed_403() {\n    status_header( 403 );\n}\nadd_action( 'wp_login_failed', 'fail2ban_login_failed_403' );\n\n"
  },
  {
    "path": "files/nginx.conf",
    "content": "# run nginx in foreground\ndaemon off;\n\nerror_log /DATA/logs/nginx/error.log warn;\npid /var/run/nginx.pid;\nenv DB_HOST;\nenv DB_NAME;\nenv DB_USER;\nenv DB_PASS;\n\nworker_processes  auto;\nevents {\n    worker_connections  4096;\n}\n\nhttp {\n  sendfile on;\n  include    /etc/nginx/mime.types;\n  include    /etc/nginx/fastcgi.conf;\n  default_type application/octet-stream;\n  tcp_nopush   on;\n  client_body_temp_path /tmp/nginx/body 1 2;\n  fastcgi_temp_path /tmp/nginx/fastcgi_temp 1 2;\n  \n  #a new log format for detecting bad bots.\n  log_format blocked '$time_local: Blocked request from $http_x_real_ip $request';\n  \n  \n  ## This log format makes it so we can see real requester's IP address \\\n  ##    not just the reverse proxy server's IP address. Also note, that \\\n  ##    \"specialLog\" can be replaced with any name you would like to \\\n  ##    give to this log format.\n  log_format specialLog '$http_x_real_ip - $remote_user [$time_local]  '\n                        '\"$request\" $status $body_bytes_sent '\n                        '\"$http_referer\" \"$http_user_agent\"';  \n  \n  client_max_body_size 2G;\n  \n  server {\n\n    #listen       [::]:80; #uncomment for IPv6 support\n    listen       80;\n    \n    root /DATA/htdocs;\n    index  index.php index.html index.htm;\n    access_log /DATA/logs/nginx/access.log specialLog;\n    error_log /DATA/logs/nginx/error.log;\n    \n    disable_symlinks off;\n    \n    location = /robots.txt {\n      allow all;\n      log_not_found off;\n      access_log off;\n    }\n    \n    # deny dot-files\n    location ~ /\\. { \n      deny all;\n      access_log off;\n      log_not_found off; \n    }\n\n    #Yoast SEO Sitemaps\n    location ~ ([^/]*)sitemap(.*).x(m|s)l$ {\n      ## this redirects sitemap.xml to /sitemap_index.xml\n      rewrite ^/sitemap.xml$ /sitemap_index.xml permanent;\n      ## this makes the XML sitemaps work\n      rewrite ^/([a-z]+)?-?sitemap.xsl$ /index.php?xsl=$1 last;\n      rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last;\n      rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;\n      ## The following lines are optional for the premium extensions\n      ## News SEO\n      rewrite ^/news-sitemap.xml$ /index.php?sitemap=wpseo_news last;\n      ## Local SEO\n      rewrite ^/locations.kml$ /index.php?sitemap=wpseo_local_kml last;\n      rewrite ^/geo-sitemap.xml$ /index.php?sitemap=wpseo_local last;\n      ## Video SEO\n      rewrite ^/video-sitemap.xsl$ /index.php?xsl=video last;\n    } \n\n    location / {\n      try_files $uri $uri/ /index.php?$args;\n    }\n    \n    # Deny access to any files with a .php extension in the uploads directory\n    # Works in sub-directory installs and also in multisite network\n    # Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)\n    location ~* /(?:uploads|files)/.*\\.php$ {\n    \tdeny all;\n    }\n        \n    ## Disable .htaccess and other hidden files\n    location ~ /\\. {\n        deny all;\n        access_log off;\n        log_not_found off;\n    }\n\n    location ~* \\.(jpg|jpeg|gif|png|css|js|ico|xml)$ {\n        access_log        off;\n        log_not_found     off;\n        expires           360d;\n    }   \n\n    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000\n    location ~ [^/]\\.php(/|$) {\n      fastcgi_split_path_info ^(.+?\\.php)(/.*)$;\n      if (!-f $document_root$fastcgi_script_name) {\n        return 404;\n      }\n      fastcgi_pass 127.0.0.1:9000;\n      fastcgi_index index.php;\n      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n      include fastcgi_params;\n    }\n    \n    ## Block SQL injections\n    location ~* union.*select.*\\( { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* union.*all.*select.* { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* concat.*\\( { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    \n    ## Block common exploits\n    location ~* (<|%3C).*script.*(>|%3E) { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* base64_(en|de)code\\(.*\\) { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* (%24&x) { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* (%0|%A|%B|%C|%D|%E|%F|127\\.0) { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* \\.\\.\\/  { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* ~$ { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* proc/self/environ { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* /\\.(htaccess|htpasswd|svn) { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    \n    ## Block file injections\n    location ~* [a-zA-Z0-9_]=(\\.\\.//?)+ { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    \n    ## wordpress security\n    location ~* wp-config.php { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* wp-admin/includes { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* wp-app\\.log { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n    location ~* (licence|readme|license)\\.(html|txt) { access_log /DATA/logs/nginx/blocked.log blocked; deny all; }\n\n    gzip on;\n    gzip_disable \"msie6\";\n\n    gzip_vary on;\n    gzip_proxied any;\n    gzip_comp_level 6;\n    gzip_buffers 16 8k;\n    gzip_http_version 1.1;\n    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;\n\n    \n  }\n  \n}\n"
  },
  {
    "path": "files/php-fpm.conf",
    "content": "error_log = /DATA/logs/php-fpm/php-fpm.log \nlog_level = warning\n\n[www]\nuser = nginx\ngroup = www-data\nlisten = 127.0.0.1:9000\nlisten.owner = nginx\nlisten.group = www-data\npm = ondemand\n\n; Total RAM dedicated to the web server / Max child process size\npm.max_children = 75\n\npm.process_idle_timeout = 10s\npm.max_requests = 500\nchdir = /DATA/htdocs\nphp_flag[display_errors] = on\nphp_admin_value[memory_limit] = 128M\nphp_admin_value[upload_max_filesize] = 2G\nphp_admin_value[post_max_size] = 2G\nphp_admin_value[output_buffering] = 0\nphp_admin_value[max_input_time] = 3600\nphp_admin_value[openssl.cafile] = /etc/ssl/certs/ca-certificates.crt\nphp_admin_value[openssl.capath] = /etc/ssl/certs\nphp_admin_value[max_input_nesting_level] = 256\nphp_admin_value[max_input_vars] = 10000\n\n; Redirect worker stdout and stderr into main error log. If not set, stdout and\n; stderr will be redirected to /dev/null according to FastCGI specs.\n; Default Value: no\ncatch_workers_output = yes\n\n\n; Database variables passed via -e argument on Docker\nenv[\"DB_HOST\"] = \"$DB_HOST\"\nenv[\"DB_USER\"] = \"$DB_USER\"\nenv[\"DB_PASS\"] = \"$DB_PASS\"\nenv[\"DB_NAME\"] = \"$DB_NAME\"\n"
  },
  {
    "path": "files/run.sh",
    "content": "#!/bin/sh\n\n[ -f /run-pre.sh ] && /run-pre.sh\n\nchown -R nginx:nginx /DATA\n\nif [ ! -d /DATA/htdocs ] ; then\n  mkdir -p /DATA/htdocs\n#  chown nginx:nginx /DATA/htdocs\nfi\n\n\n# start php-fpm\nmkdir -p /DATA/logs/php-fpm\n# start nginx\nmkdir -p /DATA/logs/nginx\nmkdir -p /tmp/nginx\nchown nginx:nginx /tmp/nginx\nchown -R nginx:nginx /DATA\n\nif [ ! -d /DATA/bin ] ; then\n  mkdir /DATA/bin\n  chown nginx:nginx /DATA/bin\n  cp /usr/bin/wp-cli /DATA/bin/wp-cli\n\n  curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar\n  chmod +x wp-cli.phar \n  mv wp-cli.phar /DATA/bin/wp-cli \nfi\n\n\n\nphp-fpm7\nnginx\n"
  },
  {
    "path": "files/wp-config-devoply.php",
    "content": "#!/usr/bin/php\n<?php\n\n$filepath = '/DATA/htdocs/wp-config.php';\n\n$define = \"/** The Database Collate type. Don't change this if in doubt. */\";\n\n$ssl_content = <<<'EOF'\n/** DEVOPly Settings */\nif(isset(($_SERVER['HTTP_X_FORWARDED_PROTO'] )) ){\nif ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'){\nif(!defined('WP_HOME')){\n\tdefine('WP_HOME','https://'.$_SERVER[\"HTTP_HOST\"]);\n\tdefine('WP_SITEURL','https://'.$_SERVER[\"HTTP_HOST\"]);\n\tdefine('FORCE_SSL_ADMIN', true);\n\n\t$_SERVER['HTTPS']='on';\n\tdefine('WP_REDIS_HOST', DB_HOST);\n\tdefine('WP_CACHE_KEY_SALT', DB_NAME);\n}\n}\n}\n/** The Database Collate type. Don't change this if in doubt. */\nEOF;\n\n$config = file_get_contents($filepath);\n\nif(strpos($config, $ssl_content) !== false){\n  die();\n}\n\n$new_config = str_replace($define, $ssl_content, $config);\n\nfile_put_contents($filepath, $new_config);\n"
  }
]