├── .gitignore ├── wp-sendmail.js ├── supervisord.conf ├── nginx-site.conf ├── Dockerfile ├── start.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /wp-sendmail.js: -------------------------------------------------------------------------------- 1 | 2 | var smtp = require("url").parse(process.env.SMTP || ""); 3 | 4 | module.exports = { 5 | 6 | port: 7914, 7 | 8 | keepBCC: false, 9 | 10 | uid: "nobody", 11 | gid: "nogroup", 12 | 13 | smtp:{ 14 | host: smtp.hostname || "localhost", 15 | port: smtp.port || (smtp.protocol == "smtps:" ? 465 : 25), 16 | options: { 17 | auth: smtp.auth ? { 18 | user: smtp.auth.split(":").shift() || "", 19 | pass: smtp.auth.split(":").slice(1).join(":") || "" 20 | } : false, 21 | secureConnection: smtp.protocol == "smtps:", 22 | 23 | debug: !!process.env.DEBUG && ["0", "false"].indexOf(process.env.DEBUG.toLowerCase().trim()) < 0 24 | } 25 | }, 26 | 27 | mysql: { 28 | url: "mysql://MYSQL_USER:MYSQL_PASSWORD@" + process.env.DB_PORT_3306_TCP_ADDR + "/MYSQL_DB", 29 | prefix: "MYSQL_PREFIX" 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /supervisord.conf: -------------------------------------------------------------------------------- 1 | [unix_http_server] 2 | file=/tmp/supervisor.sock ; (the path to the socket file) 3 | 4 | [supervisord] 5 | logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log) 6 | logfile_maxbytes=50MB ; (max main logfile bytes b4 rotation;default 50MB) 7 | logfile_backups=10 ; (num of main logfile rotation backups;default 10) 8 | loglevel=info ; (log level;default info; others: debug,warn,trace) 9 | pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid) 10 | nodaemon=false ; (start in foreground if true;default false) 11 | minfds=1024 ; (min. avail startup file descriptors;default 1024) 12 | minprocs=200 ; (min. avail process descriptors;default 200) 13 | 14 | ; the below section must remain in the config file for RPC 15 | ; (supervisorctl/web interface) to work, additional interfaces may be 16 | ; added by defining them in separate rpcinterface: sections 17 | [rpcinterface:supervisor] 18 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 19 | 20 | [supervisorctl] 21 | serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket 22 | 23 | [program:php5-fpm] 24 | command=/usr/sbin/php5-fpm -c /etc/php5/fpm 25 | 26 | ; [program:mysqld] 27 | ; command=/usr/bin/mysqld_safe 28 | 29 | [program:nginx] 30 | command=/usr/sbin/nginx 31 | 32 | [program:sshd] 33 | command=/usr/sbin/sshd -D 34 | 35 | [program:wp-sendmail] 36 | command=/usr/bin/wp-sendmaild 37 | stderr_logfile = /var/log/wp-sendmaild.log -------------------------------------------------------------------------------- /nginx-site.conf: -------------------------------------------------------------------------------- 1 | # You may add here your 2 | # server { 3 | # ... 4 | # } 5 | # statements for each of your virtual hosts to this file 6 | 7 | ## 8 | # You should look at the following URL's in order to grasp a solid understanding 9 | # of Nginx configuration files in order to fully unleash the power of Nginx. 10 | # http://wiki.nginx.org/Pitfalls 11 | # http://wiki.nginx.org/QuickStart 12 | # http://wiki.nginx.org/Configuration 13 | # 14 | # Generally, you will want to move this file somewhere, and start with a clean 15 | # file but keep this around for reference. Or just disable in sites-enabled. 16 | # 17 | # Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. 18 | ## 19 | 20 | server { 21 | listen 80; ## listen for ipv4; this line is default and implied 22 | listen [::]:80 default ipv6only=on; ## listen for ipv6 23 | server_tokens off; 24 | autoindex off; 25 | 26 | client_max_body_size 10m; 27 | client_body_buffer_size 128k; 28 | 29 | root /usr/share/nginx/www; 30 | index index.php index.html index.htm; 31 | 32 | # Define default caching of 24h 33 | # # Commented out as it caused problems with fresh installations 34 | # expires 86400s; 35 | # add_header Pragma public; 36 | # add_header Cache-Control "max-age=86400, public, must-revalidate, proxy-revalidate"; 37 | 38 | # Make site accessible from http://localhost/ 39 | server_name localhost; 40 | 41 | # Do not allow access to files giving away your WordPress version 42 | location ~ /(\.|wp-config.php|readme.html|licence.txt) { 43 | return 404; 44 | } 45 | 46 | # Add trailing slash to */wp-admin requests. 47 | rewrite /wp-admin$ $scheme://$host$uri/ permanent; 48 | 49 | # Don't log robots.txt requests 50 | location = /robots.txt { 51 | allow all; 52 | log_not_found off; 53 | access_log off; 54 | } 55 | 56 | # Aggressive caching for static files 57 | location ~* \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|otf|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|t?gz|tif|tiff|ttf|wav|webm|wma|woff|wri|xla|xls|xlsx|xlt|xlw|zip)$ { 58 | expires 31536000s; 59 | access_log off; 60 | log_not_found off; 61 | add_header Pragma public; 62 | add_header Cache-Control "max-age=31536000, public"; 63 | } 64 | 65 | location / { 66 | # First attempt to serve request as file, then 67 | # as directory, then fall back to index.html 68 | try_files $uri $uri/ /index.php?q=$uri&$args; 69 | # Uncomment to enable naxsi on this location 70 | # include /etc/nginx/naxsi.rules 71 | } 72 | 73 | # Deliver 404 instead of 403 "Forbidden" 74 | error_page 403 = 404; 75 | 76 | # redirect server error pages to the static page /50x.html 77 | error_page 500 502 503 504 /50x.html; 78 | location = /50x.html { 79 | root /usr/share/nginx/www; 80 | } 81 | 82 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 83 | # skip any php file that matches */uploads/* 84 | location ~* (^(?!(?:(?!(php|inc)).)*/uploads/).*?(php)) { 85 | try_files $uri = 404; 86 | fastcgi_split_path_info ^(.+\.php)(/.+)$; 87 | # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini 88 | 89 | # With php5-cgi alone: 90 | fastcgi_pass 127.0.0.1:9000; 91 | # With php5-fpm: 92 | # fastcgi_pass unix:/var/run/php5-fpm.sock; 93 | fastcgi_index index.php; 94 | include fastcgi_params; 95 | fastcgi_intercept_errors on; 96 | fastcgi_ignore_client_abort off; 97 | fastcgi_connect_timeout 60; 98 | fastcgi_send_timeout 180; 99 | fastcgi_read_timeout 180; 100 | fastcgi_buffer_size 128k; 101 | fastcgi_buffers 4 256k; 102 | fastcgi_busy_buffers_size 256k; 103 | fastcgi_temp_file_write_size 256k; 104 | } 105 | 106 | # deny access to .htaccess files, if Apache's document root 107 | # concurs with nginx's one 108 | location ~ /\. { 109 | deny all; 110 | access_log off; 111 | log_not_found off; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | # Forked from https://github.com/eugeneware/docker-wordpress-nginx 4 | # MAINTAINER Eugene Ware 5 | 6 | MAINTAINER Andris Reinman 7 | 8 | RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list 9 | RUN apt-get update 10 | RUN apt-get -y upgrade 11 | 12 | # Keep upstart from complaining 13 | # RUN dpkg-divert --local --rename --add /sbin/initctl 14 | # RUN ln -s /bin/true /sbin/initctl 15 | 16 | # Basic Requirements 17 | # RUN apt-get -y install mysql-server mysql-client nginx php5-fpm php5-mysql php-apc pwgen python-setuptools curl git unzip openssh-server vim 18 | RUN apt-get -y install mysql-client nginx php5-fpm php5-mysql php-apc pwgen python-setuptools curl git unzip openssh-server vim 19 | 20 | # Wordpress Requirements 21 | RUN apt-get -y install php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl libssh2-php 22 | 23 | # Email requirements 24 | RUN apt-get install -y python-software-properties software-properties-common python build-essential && add-apt-repository -y ppa:chris-lea/node.js && apt-get update && apt-get install -y nodejs 25 | RUN npm install --unsafe-perm -g wp-sendmail@0.1.5 26 | 27 | ADD ./wp-sendmail.js /etc/wp-sendmail.js 28 | 29 | # Create directory for sshd and set locale 30 | RUN mkdir -p /var/run/sshd && locale-gen en_US.utf8 && echo 'LC_ALL="en_US.utf8"' >> /etc/environment 31 | 32 | # mysql config 33 | # RUN sed -i -e "s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf 34 | # Uncomment this line if you want mysql logs to a log file instead of syslog 35 | # RUN sed -i -e "s/^syslog/log-error=error.log/" /etc/mysql/conf.d/mysqld_safe_syslog.cnf 36 | 37 | # nginx config 38 | RUN sed -i -e "s/keepalive_timeout\s*65/keepalive_timeout 2/" /etc/nginx/nginx.conf 39 | # since 'upload_max_filesize = 10M' in /etc/php5/fpm/php.ini 40 | RUN sed -i -e "s/keepalive_timeout 2/keepalive_timeout 2;\n\tclient_max_body_size 10m/;s/# server_tokens on;/server_tokens off;/" /etc/nginx/nginx.conf 41 | 42 | RUN echo "daemon off;" >> /etc/nginx/nginx.conf 43 | 44 | # php-fpm config 45 | # "allow_url_fopen" must be "On" for WordPress auto upgrade 46 | RUN sed -i -e "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g;s/upload_max_filesize = 2M/upload_max_filesize = 10M/;s/post_max_size = 8M/post_max_size = 10M/;s/expose_php = On/expose_php = Off/;s/max_execution_time = 30/max_execution_time = 60/;s/;ignore_user_abort = On/ignore_user_abort = Off/;s/disable_functions = /disable_functions = php_uname, getmyuid, getmypid, passthru, leak, listen, diskfreespace, tmpfile, link, ignore_user_abort, shell_exec, dl, set_time_limit, exec, system, highlight_file, source, show_source, fpaththru, virtual, posix_ctermid, posix_getcwd, posix_getegid, posix_geteuid, posix_getgid, posix_getgrgid, posix_getgrnam, posix_getgroups, posix_getlogin, posix_getpgid, posix_getpgrp, posix_getpid, posix, _getppid, posix_getpwnam, posix_getpwuid, posix_getrlimit, posix_getsid, posix_getuid, posix_isatty, posix_kill, posix_mkfifo, posix_setegid, posix_seteuid, posix_setgid, posix_setpgid, posix_setsid, posix_setuid, posix_times, posix_ttyname, posix_uname, proc_open, proc_close, proc_get_status, proc_nice, proc_terminate, phpinfo,/" /etc/php5/fpm/php.ini 47 | RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf 48 | RUN find /etc/php5/cli/conf.d/ -name "*.ini" -exec sed -i -re 's/^(\s*)#(.*)/\1;\2/g' {} \; 49 | RUN echo "php_admin_value[sendmail_path] = /usr/bin/wp-sendmail" >> /etc/php5/fpm/pool.d/www.conf && echo "env[DB_PORT_3306_TCP_ADDR] = \$DB_PORT_3306_TCP_ADDR" >> /etc/php5/fpm/pool.d/www.conf 50 | 51 | # User for the blog 52 | RUN useradd -s /bin/bash -d /home/wordpress -m wordpress && usermod -aG www-data wordpress 53 | 54 | # nginx site conf 55 | ADD ./nginx-site.conf /etc/nginx/sites-available/default 56 | 57 | # Supervisor Config 58 | RUN /usr/bin/easy_install supervisor 59 | ADD ./supervisord.conf /etc/supervisord.conf 60 | 61 | # Install Wordpress 62 | RUN wget http://et.wordpress.org/latest-et.tar.gz -O /wordpress.tar.gz 63 | RUN tar xvzf /wordpress.tar.gz -C /usr/share/nginx 64 | RUN mv /usr/share/nginx/www/5* /usr/share/nginx/wordpress 65 | RUN rm -rf /usr/share/nginx/www 66 | RUN mv /usr/share/nginx/wordpress /usr/share/nginx/www 67 | RUN chown -R wordpress:wordpress /usr/share/nginx/www 68 | 69 | # Wordpress Initialization and Startup Script 70 | ADD ./start.sh /start.sh 71 | RUN chmod 755 /start.sh 72 | 73 | # private expose 74 | EXPOSE 22 75 | EXPOSE 80 76 | 77 | CMD env | grep _ >> /etc/environment && /bin/bash /start.sh 78 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # DB_PASSWORD=$(awk -F "'" '/DB_PASSWORD/ {print $4}' /var/data/sources/wp-config.php) 4 | # DB_USER=$(awk -F "'" '/DB_USER/ {print $4}' /var/data/sources/wp-config.php) 5 | # DB_NAME=$(awk -F "'" '/DB_NAME/ {print $4}' /var/data/sources/wp-config.php) 6 | 7 | if [ ! -f /usr/share/nginx/www/wp-config.php ]; then 8 | 9 | # Set these with -e option 10 | # WORDPRESS_DB="wordpress" 11 | # MYSQLPASS="12345" 12 | 13 | MYSQL_USER_PASSWORD=`pwgen -c -n -1 12` 14 | SSH_ROOT_PASSWORD=`pwgen -c -n -1 12` 15 | SSH_USER_PASSWORD=`pwgen -c -n -1 12` 16 | 17 | # Expose passwords in logs 18 | echo MySQL user password: $MYSQL_USER_PASSWORD 19 | echo SSH root password: $SSH_ROOT_PASSWORD 20 | echo SSH user password: $SSH_USER_PASSWORD 21 | 22 | # Change SSH passwords 23 | echo "root:$SSH_ROOT_PASSWORD" | chpasswd 24 | echo "wordpress:$SSH_USER_PASSWORD" | chpasswd 25 | 26 | #mysql has to be started this way as it doesn't work to call from /etc/init.d 27 | # /usr/bin/mysqld_safe & 28 | # sleep 10s 29 | 30 | # setup directories 31 | WORDPRESS_ROOT="/usr/share/nginx/www" 32 | WORDPRESS_UPLOADS="uploads" 33 | mkdir -p "$WORDPRESS_ROOT/$WORDPRESS_UPLOADS" 34 | 35 | # create a link of wordpress directory to ssh user home 36 | ln -s $WORDPRESS_ROOT /home/wordpress/wordpress 37 | 38 | # Escape any unsopperted chars, eg "/" 39 | SAFE_WORDPRESS_UPLOADS=$(printf '%s\n' "$WORDPRESS_UPLOADS" | sed 's/[[\.*^$(){}?+|/]/\\&/g') 40 | SAFE_WORDPRESS_ROOT=$(printf '%s\n' "$WORDPRESS_ROOT/" | sed 's/[[\.*^$(){}?+|/]/\\&/g') 41 | 42 | # Create wp-config.php with selected values 43 | sed -e "s/database_name_here/$WORDPRESS_DB/ 44 | s/username_here/$WORDPRESS_DB/ 45 | s/password_here/$MYSQL_USER_PASSWORD/ 46 | /'DB_HOST'/s/'localhost'/getenv(\"DB_PORT_3306_TCP_ADDR\")/ 47 | /'AUTH_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 48 | /'SECURE_AUTH_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 49 | /'LOGGED_IN_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 50 | /'NONCE_KEY'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 51 | /'AUTH_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 52 | /'SECURE_AUTH_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 53 | /'LOGGED_IN_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 54 | /'NONCE_SALT'/s/put your unique phrase here/`pwgen -c -n -1 65`/ 55 | /'WP_DEBUG'/{G;s/$/define( 'UPLOADS', '$SAFE_WORDPRESS_UPLOADS' );/;} 56 | /'WP_DEBUG'/{G;s/$/define( 'FS_METHOD', 'ssh2' );/;} 57 | /'WP_DEBUG'/{G;s/$/define( 'FTP_BASE', '$SAFE_WORDPRESS_ROOT' );/;} 58 | /'WP_DEBUG'/{G;s/$/define( 'FTP_USER', 'wordpress' );/;} 59 | /'WP_DEBUG'/{G;s/$/define( 'FTP_HOST', 'localhost' );/;} 60 | /'WP_DEBUG'/{G;s/$/define( 'FTP_SSL', true );/;} 61 | /'WP_DEBUG'/{G;s/$/define( 'FTP_PUBKEY', false );/;} 62 | /'WP_DEBUG'/{G;s/$/define( 'FTP_PRIKEY', false );/;} 63 | /'WP_DEBUG'/{G;s/$/define( 'DISALLOW_FILE_EDIT', true );/;}" /usr/share/nginx/www/wp-config-sample.php > /usr/share/nginx/www/wp-config.php 64 | 65 | # Download nginx helper plugin 66 | curl -O `curl -i -s http://wordpress.org/plugins/nginx-helper/ | egrep -o "http://downloads.wordpress.org/plugin/[^']+"` 67 | unzip nginx-helper.*.zip -d /usr/share/nginx/www/wp-content/plugins 68 | chown -R wordpress:wordpress /usr/share/nginx/www/wp-content/plugins/nginx-helper 69 | 70 | # Activate nginx plugin and set up pretty permalink structure once logged in 71 | cat << ENDL >> /usr/share/nginx/www/wp-config.php 72 | \$plugins = get_option( 'active_plugins' ); 73 | if ( count( \$plugins ) === 0 ) { 74 | require_once(ABSPATH .'/wp-admin/includes/plugin.php'); 75 | \$wp_rewrite->set_permalink_structure( '/%postname%/' ); 76 | \$pluginsToActivate = array( 'nginx-helper/nginx-helper.php' ); 77 | foreach ( \$pluginsToActivate as \$plugin ) { 78 | if ( !in_array( \$plugin, \$plugins ) ) { 79 | activate_plugin( '/usr/share/nginx/www/wp-content/plugins/' . \$plugin ); 80 | } 81 | } 82 | } 83 | ENDL 84 | 85 | # Ensure proper file permissions and ownership 86 | chown wordpress:wordpress -R /usr/share/nginx/www 87 | chown www-data:www-data -R "$WORDPRESS_ROOT/$WORDPRESS_UPLOADS" 88 | find "$WORDPRESS_ROOT" -type d -exec chmod 755 {} \; 89 | find "$WORDPRESS_ROOT" -type f -exec chmod 644 {} \; 90 | 91 | # email settings 92 | sed -i -e "s/MYSQL_PASSWORD/$MYSQL_USER_PASSWORD/;s/MYSQL_PREFIX/wp_/;s/MYSQL_USER/$WORDPRESS_DB/;s/MYSQL_DB/$WORDPRESS_DB/" /etc/wp-sendmail.js 93 | chown root:root /etc/wp-sendmail.js 94 | chmod 0400 /etc/wp-sendmail.js 95 | rm -rf /etc/wp-sendmail.js-e 96 | 97 | # Create database user for WordPress database 98 | # echo mysqladmin -u root password $MYSQLPASS 99 | mysql -h $DB_PORT_3306_TCP_ADDR -uroot -p$MYSQLPASS -e "DROP DATABASE IF EXISTS $WORDPRESS_DB; CREATE DATABASE $WORDPRESS_DB; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX ON $WORDPRESS_DB.* TO '$WORDPRESS_DB'@'%' IDENTIFIED BY '$MYSQL_USER_PASSWORD'; FLUSH PRIVILEGES;" 100 | # killall mysqld 101 | fi 102 | 103 | # start all the services 104 | /usr/local/bin/supervisord -n 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-wordpress-nginx 2 | 3 | This is a fork of [eugeneware/docker-wordpress-nginx](https://github.com/eugeneware/docker-wordpress-nginx). I wanted to move some real world blogs to Docker and this project seemed like a nice basis for it. I changed a few things like allowing larger file uploads, made WordPress auto upgrade work through SSH, changed file permissions so that web user is only allowed to modify uploads directory (PHP files from this directory are not executed) etc. Wordpress user password for auto upgrade can be found from the logs as "ssh user password". 4 | 5 | For security reasons I created a sendmail replacement daemon that only sends messages to valid users found from the MySQL WordPress users table and not to arbitrary e-mail addresses. Downside is that you need to provide valid SMTP information for the container. 6 | 7 | One reason why you might not want to use this Dockerfile without modification is that the WordPress version installed is in Estonian language. You can change this [here](Dockerfile#L61). 8 | 9 | For upgrading WordPress version or adding themes/plugins through WordPress admin interface, use SSH user password found from the logs 10 | 11 | ---- 12 | 13 | A Dockerfile that installs the latest wordpress, nginx, php-apc and php-fpm. 14 | 15 | NB: A big thanks to [jbfink](https://github.com/jbfink/docker-wordpress) who did most of the hard work on the wordpress parts! 16 | 17 | You can check out his [Apache version here](https://github.com/jbfink/docker-wordpress). 18 | 19 | ## Installation 20 | 21 | ``` 22 | $ git clone https://github.com/eugeneware/docker-wordpress-nginx.git 23 | $ cd docker-wordpress-nginx 24 | $ sudo docker build -t="docker-wordpress-nginx" . 25 | ``` 26 | 27 | ## Usage 28 | 29 | To spawn a new instance of wordpress: 30 | 31 | ```bash 32 | $ sudo docker run -p 80 -d docker-wordpress-nginx 33 | ``` 34 | 35 | You'll see an ID output like: 36 | ``` 37 | d404cc2fa27b 38 | ``` 39 | 40 | Use this ID to check the port it's on: 41 | ```bash 42 | $ sudo docker port d404cc2fa27b 80 # Make sure to change the ID to yours! 43 | ``` 44 | 45 | This command returns the container ID, which you can use to find the external port you can use to access Wordpress from your host machine: 46 | 47 | ``` 48 | $ docker port 80 49 | ``` 50 | 51 | You can the visit the following URL in a browser on your host machine to get started: 52 | 53 | ``` 54 | http://127.0.0.1: 55 | ``` 56 | 57 | ### MySQL 58 | 59 | MySQL is not included. You can link another mysql container with -l option. Also set `MYSQL_ROOT_PASSWORD` and `WORDPRESS_DB` environment variables with -e option. 60 | 61 | ### E-mail 62 | 63 | If you want to send mail you need to provide SMTP connection data by adding `-e SMTP=smtpdata` option to `docker run`. This information is not exposed to the php user. 64 | 65 | For example if you want to use Gmail as your SMTP provider, use the following command (replace the user and password with your own). 66 | 67 | ```bash 68 | docker run -p 80 -d -e SMTP="smpt://user.name@gmail.com:password@smtp.gmail.com:587" docker-wordpress-nginx 69 | ``` 70 | 71 | ### Features 72 | 73 | * File uploads are limited to 10MB 74 | * You can use a SMTP provider for outgoing e-mail (SendGrid, Gmail, Mailgun etc.) 75 | * WordPress auto upgrade works through SSH and is preconfigured, only user password needs to be provided 76 | * Static files are aggressively cached 77 | * SSH access is enabled. There are two accounts: `admin` (root) and `wordpress` (user). You can find the passwords from container log. 78 | 79 | ### Security features 80 | 81 | * A lot of functions (including all shell functions and phpinfo) are disabled. 82 | * All outgoing e-mails are checked - if recipients can't be found from the users table or admin email option, the mail is discarded. Helps against trojans that are using PHP `mail()` command to send spam. 83 | * All WordPress files belong to user `wordpress`, php is executed as `www-data` 84 | * Only writable folder for user `www-data` is */uploads* - executing php scripts is forbidden from this directory. Helps against attackers that upload php files to server 85 | * Server and PHP version numbers are not advertised with HTTP headers. Access to meta files (like readme.html) that include WordPress version number is also restricted (WP version number is not completely hidden though and can be checked) 86 | * WordPress MySQL user has only required privileges (no access to `FILE` or `GRANT OPTION` or other nonsense) 87 | * No errors are shown to the user 88 | * 403 errors are displayed as 404 89 | * WordPress theme and plugin editor is disabled (and would not work anyway as theme and plugin directories are not writable for the php user) 90 | 91 | ### Security issues 92 | 93 | * You should block forwarding outgoing port 25 in the host machine (you can configure wp-sendmail to use another port). Helps against trojans that are using port 25 for SMTP to send spam. 94 | * `open_basedir` could be useful to use but currently is not set as it broke WordPress auto upgrading, didn't find the issue 95 | * `allow_url_fopen` is on - setting it off broke WordPress auto upgrade 96 | * `wp-config.php` should be only owner readable but `www-data` needs to access it too, so file permissions are not changed 97 | * Wordpress version can be detected from the RSS feed (generator tag) 98 | --------------------------------------------------------------------------------