diff --git a/.drone.jsonnet b/.drone.jsonnet
new file mode 100644
index 0000000..b5ba128
--- /dev/null
+++ b/.drone.jsonnet
@@ -0,0 +1,107 @@
+local PipelineBuild(os='linux', arch='amd64') = {
+ local tag = os + '-' + arch,
+ local version_tag = os + '-' + arch,
+ local file_suffix = std.strReplace(version_tag, '-', '.'),
+ kind: "pipeline",
+ name: version_tag,
+ platform: {
+ os: os,
+ arch: arch,
+ },
+ steps: [
+ {
+ name: 'dryrun',
+ image: 'plugins/docker:' + tag,
+ pull: 'always',
+ settings: {
+ dry_run: true,
+ tags: version_tag,
+ dockerfile: 'docker/Dockerfile.' + file_suffix,
+ repo: ' xoxys/ttrss',
+ username: { from_secret: "docker_username" },
+ password: { from_secret: "docker_password" },
+ },
+ },
+ {
+ name: 'publish',
+ image: 'plugins/docker:' + tag,
+ pull: 'always',
+ settings: {
+ auto_tag: true,
+ auto_tag_suffix: version_tag,
+ dockerfile: 'docker/Dockerfile.' + file_suffix,
+ repo: ' xoxys/ttrss',
+ username: { from_secret: "docker_username" },
+ password: { from_secret: "docker_password" },
+ },
+ when: {
+ ref: [
+ 'refs/heads/master',
+ 'refs/tags/**',
+ ],
+ },
+ },
+ ],
+};
+
+local PipelineNotifications(depends_on=[]) = {
+ kind: "pipeline",
+ name: "notifications",
+ platform: {
+ os: "linux",
+ arch: "amd64",
+ },
+ steps: [
+ {
+ image: "plugins/manifest",
+ name: "manifest",
+ pull: "always",
+ settings: {
+ ignore_missing: true,
+ username: { from_secret: "docker_username" },
+ password: { from_secret: "docker_password" },
+ spec: "docker/manifest.tmpl",
+ },
+ when: {
+ ref: [
+ 'refs/heads/master',
+ 'refs/tags/**',
+ ],
+ },
+ },
+ {
+ name: "microbadger",
+ image: "plugins/webhook",
+ pull: "always",
+ settings: {
+ urls: { from_secret: "microbadger_url" },
+ },
+ },
+ {
+ image: "plugins/matrix",
+ name: "matrix",
+ pull: 'always',
+ settings: {
+ homeserver: "https://matrix.rknet.org",
+ roomid: "MtidqQXWWAtQcByBhH:rknet.org",
+ template: "Status: **{{ build.status }}**
Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}
Message: {{ build.message }}",
+ username: { from_secret: "matrix_username" },
+ password: { from_secret: "matrix_password" },
+ },
+ when: {
+ status: [ "success", "failure" ],
+ },
+ },
+ ],
+ trigger: {
+ status: [ "success", "failure" ],
+ },
+ depends_on: depends_on,
+};
+
+[
+ PipelineBuild(os='linux', arch='amd64'),
+ PipelineNotifications(depends_on=[
+ "linux-amd64",
+ ])
+]
diff --git a/.drone.yml b/.drone.yml
new file mode 100644
index 0000000..8266139
--- /dev/null
+++ b/.drone.yml
@@ -0,0 +1,99 @@
+---
+kind: pipeline
+name: linux-amd64
+
+platform:
+ os: linux
+ arch: amd64
+
+steps:
+- name: dryrun
+ pull: always
+ image: plugins/docker:linux-amd64
+ settings:
+ dockerfile: docker/Dockerfile.linux.amd64
+ dry_run: true
+ password:
+ from_secret: docker_password
+ repo: xoxys/ttrss
+ tags: linux-amd64
+ username:
+ from_secret: docker_username
+
+- name: publish
+ pull: always
+ image: plugins/docker:linux-amd64
+ settings:
+ auto_tag: true
+ auto_tag_suffix: linux-amd64
+ dockerfile: docker/Dockerfile.linux.amd64
+ password:
+ from_secret: docker_password
+ repo: xoxys/ttrss
+ username:
+ from_secret: docker_username
+ when:
+ ref:
+ - refs/heads/master
+ - "refs/tags/**"
+
+---
+kind: pipeline
+name: notifications
+
+platform:
+ os: linux
+ arch: amd64
+
+steps:
+- name: manifest
+ pull: always
+ image: plugins/manifest
+ settings:
+ ignore_missing: true
+ password:
+ from_secret: docker_password
+ spec: docker/manifest.tmpl
+ username:
+ from_secret: docker_username
+ when:
+ ref:
+ - refs/heads/master
+ - "refs/tags/**"
+
+- name: microbadger
+ pull: always
+ image: plugins/webhook
+ settings:
+ urls:
+ from_secret: microbadger_url
+
+- name: matrix
+ pull: always
+ image: plugins/matrix
+ settings:
+ homeserver: https://matrix.rknet.org
+ password:
+ from_secret: matrix_password
+ roomid: MtidqQXWWAtQcByBhH:rknet.org
+ template: "Status: **{{ build.status }}**
Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}
Message: {{ build.message }}"
+ username:
+ from_secret: matrix_username
+ when:
+ status:
+ - success
+ - failure
+
+trigger:
+ status:
+ - success
+ - failure
+
+depends_on:
+- linux-amd64
+
+---
+kind: signature
+hmac: 61db8b8005c0b27eb1a77e27f8db95a6778716d3623ecea9f3cf2498d6230541
+
+...
diff --git a/Dockerfile.linux.amd64 b/Dockerfile.linux.amd64
new file mode 100644
index 0000000..3bc1e5f
--- /dev/null
+++ b/Dockerfile.linux.amd64
@@ -0,0 +1,34 @@
+FROM alpine:3.10.0
+
+ARG TTRSS_VERSION
+ARG TTRSS_TARBALL=https://git.tt-rss.org/git/tt-rss/archive/${TT_RSS_VERSION}.tar.gz
+ARG TTRSS_MASTER=https://git.tt-rss.org/fox/tt-rss.git
+
+RUN apk update && \
+ apk add gomplate openssl unzip nginx bash git ca-certificates s6 curl ssmtp mailx php7 php7-curl \
+ php7-fpm php7-xml php7-dom php7-opcache php7-iconv php7-pdo php7-pdo_mysql php7-mysqli php7-mysqlnd \
+ php7-pdo_pgsql php7-pgsql php7-gd php7-mcrypt php7-posix php7-ldap php7-json php7-mbstring \
+ php7-session php7-fileinfo php7-intl php7-pcntl && \
+ rm -rf /var/cache/apk/* && \
+ rm -rf /var/www/localhost && \
+ rm -f /etc/php7/php-fpm.d/www.conf && \
+ mkdir -p /var/www/app && \
+ if [ -z ${TTRSS_VERSION+x} ]; then \
+ git clone ${TTRSS_MASTER} /var/www/app; \
+ else \
+ curl -o /tmp/ttrss.tar.gz -L ${TTRSS_TARBALL}.tar.gz && \
+ tar xf /tmp/ttrss.tar.gz -C /var/www/app/ --strip-components=1 && \
+ rm -rf /tmp/*; \
+ fi
+
+ADD overlay/ /
+
+VOLUME /var/www/app/lock
+VOLUME /var/www/app/cache
+VOLUME /var/www/app/feed-icons
+
+EXPOSE 80
+
+ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
+WORKDIR /var/www/app
+CMD []
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..7e83eb7
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,20 @@
+version: '2'
+
+services:
+ ttrss:
+ image: xoxys/ttrss:latest
+ ports:
+ - "80:80"
+
+ db:
+ image: postgres
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: secure
+ POSTGRES_DB: ttrss
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+
+volumes:
+ postgres_data:
+ driver: local
diff --git a/manifest.tpl b/manifest.tpl
new file mode 100644
index 0000000..0ce0a2e
--- /dev/null
+++ b/manifest.tpl
@@ -0,0 +1,13 @@
+image: xoxys/ttrss:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
+{{#if build.tags}}
+tags:
+{{#each build.tags}}
+ - {{this}}
+{{/each}}
+{{/if}}
+manifests:
+ -
+ image: plugins/ansible:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
+ platform:
+ architecture: amd64
+ os: linux
diff --git a/overlay/etc/nginx/nginx.conf b/overlay/etc/nginx/nginx.conf
new file mode 100644
index 0000000..1e435eb
--- /dev/null
+++ b/overlay/etc/nginx/nginx.conf
@@ -0,0 +1,68 @@
+user nginx;
+worker_processes 1;
+pid /var/run/nginx.pid;
+
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ server_tokens off;
+ access_log off;
+ error_log /dev/stderr;
+
+ fastcgi_buffers 16 16k;
+ fastcgi_buffer_size 32k;
+
+ server {
+ listen 80;
+ server_name localhost;
+ index index.php;
+ root /var/www/app;
+ client_max_body_size 32M;
+
+ location / {
+ try_files $uri $uri/ /index.php$is_args$args;
+ }
+
+ location ~ \.php$ {
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass unix:/var/run/php-fpm.sock;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ }
+
+ location ~ /\.ht {
+ return 404;
+ }
+
+ location ~* ^.+\.(ico|jpg|gif|png|css|js|svg|eot|ttf|woff|woff2|otf)$ {
+ log_not_found off;
+ expires 7d;
+ etag on;
+ }
+
+ gzip on;
+ gzip_comp_level 3;
+ gzip_disable "msie6";
+ gzip_vary on;
+ gzip_types
+ text/javascript
+ application/javascript
+ application/json
+ text/xml
+ application/xml
+ application/rss+xml
+ text/css
+ text/plain;
+ }
+}
diff --git a/overlay/etc/php7/php-fpm.conf b/overlay/etc/php7/php-fpm.conf
new file mode 100644
index 0000000..d922e84
--- /dev/null
+++ b/overlay/etc/php7/php-fpm.conf
@@ -0,0 +1,21 @@
+[global]
+error_log = /dev/stderr
+log_level = warning
+daemonize = no
+
+[www]
+catch_workers_output = yes
+
+user = nginx
+group = nginx
+
+listen.owner = nginx
+listen.group = nginx
+listen = /var/run/php-fpm.sock
+
+pm = dynamic
+pm.max_children = 20
+pm.start_servers = 1
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+pm.max_requests = 2048
diff --git a/overlay/etc/php7/php.ini b/overlay/etc/php7/php.ini
new file mode 100644
index 0000000..744417e
--- /dev/null
+++ b/overlay/etc/php7/php.ini
@@ -0,0 +1,391 @@
+[PHP]
+user_ini.filename = ".user.ini"
+user_ini.cache_ttl = 300
+
+engine = On
+short_open_tag = Off
+
+precision = 14
+
+output_buffering = 0
+;output_handler =
+
+zlib.output_compression = Off
+;zlib.output_compression_level = -1
+;zlib.output_handler =
+
+implicit_flush = Off
+
+unserialize_callback_func =
+serialize_precision = 17
+
+;open_basedir =
+
+disable_functions =
+disable_classes =
+
+;highlight.string = #DD0000
+;highlight.comment = #FF9900
+;highlight.keyword = #007700
+;highlight.default = #0000BB
+;highlight.html = #000000
+
+;ignore_user_abort = On
+
+;realpath_cache_size = 16k
+;realpath_cache_ttl = 120
+
+zend.enable_gc = On
+;zend.multibyte = Off
+;zend.script_encoding =
+
+expose_php = Off
+
+max_execution_time = 30
+max_input_time = 60
+;max_input_nesting_level = 64
+;max_input_vars = 1000
+memory_limit = 128M
+
+error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
+display_errors = Off
+display_startup_errors = Off
+log_errors = On
+log_errors_max_len = 1024
+ignore_repeated_errors = Off
+ignore_repeated_source = Off
+report_memleaks = On
+;report_zend_debug = 0
+;xmlrpc_errors = 0
+;xmlrpc_error_number = 0
+html_errors = On
+;docref_root = "/phpmanual/"
+;docref_ext = .html
+;error_prepend_string = ""
+;error_append_string = ""
+error_log = php_errors.log
+;windows.show_crt_warning
+
+;arg_separator.output = "&"
+;arg_separator.input = ";&"
+
+variables_order = "GPCS"
+request_order = "GP"
+
+register_argc_argv = Off
+auto_globals_jit = On
+;enable_post_data_reading = Off
+post_max_size = 8M
+
+auto_prepend_file =
+auto_append_file =
+
+default_mimetype = "text/html"
+default_charset = "UTF-8"
+;internal_encoding =
+;input_encoding =
+;output_encoding =
+
+;include_path = ".:/php7/includes"
+
+doc_root =
+user_dir =
+
+extension_dir = "/usr/lib/php7/modules"
+;sys_temp_dir = "/tmp"
+enable_dl = Off
+
+;cgi.force_redirect = 1
+;cgi.nph = 1
+;cgi.redirect_status_env =
+cgi.fix_pathinfo = 0
+cgi.discard_path = 1
+
+;fastcgi.impersonate = 1
+;fastcgi.logging = 0
+;cgi.rfc2616_headers = 0
+;cgi.check_shebang_line = 1
+
+file_uploads = On
+;upload_tmp_dir =
+upload_max_filesize = 2M
+max_file_uploads = 20
+
+allow_url_fopen = On
+allow_url_include = Off
+
+;from="john@doe.com"
+;user_agent="PHP"
+
+default_socket_timeout = 60
+;auto_detect_line_endings = Off
+
+[CLI Server]
+cli_server.color = On
+
+[Date]
+date.timezone = Europe/Berlin
+;date.default_latitude = 31.7667
+;date.default_longitude = 35.2333
+;date.sunrise_zenith = 90.583333
+;date.sunset_zenith = 90.583333
+
+[filter]
+;filter.default = unsafe_raw
+;filter.default_flags =
+
+[iconv]
+;iconv.input_encoding =
+;iconv.internal_encoding =
+;iconv.output_encoding =
+
+[intl]
+;intl.default_locale =
+;intl.error_level = E_WARNING
+;intl.use_exceptions = 0
+
+[sqlite3]
+;sqlite3.extension_dir =
+
+[Pcre]
+;pcre.backtrack_limit = 100000
+;pcre.recursion_limit = 100000
+;pcre.jit = 1
+
+[Pdo]
+;pdo_odbc.connection_pooling = strict
+;pdo_odbc.db2_instance_name
+
+[Pdo_mysql]
+pdo_mysql.cache_size = 2000
+pdo_mysql.default_socket =
+
+[Phar]
+;phar.readonly = On
+;phar.require_hash = On
+;phar.cache_list =
+
+[mail function]
+SMTP = localhost
+smtp_port = 25
+;sendmail_path =
+
+;mail.force_extra_parameters =
+mail.add_x_header = On
+;mail.log =
+;mail.log = syslog
+
+[SQL]
+sql.safe_mode = On
+
+[ODBC]
+;odbc.default_db = Not yet implemented
+;odbc.default_user = Not yet implemented
+;odbc.default_pw = Not yet implemented
+;odbc.default_cursortype
+odbc.allow_persistent = On
+odbc.check_persistent = On
+odbc.max_persistent = -1
+odbc.max_links = -1
+odbc.defaultlrl = 4096
+odbc.defaultbinmode = 1
+;birdstep.max_links = -1
+
+[Interbase]
+ibase.allow_persistent = 1
+ibase.max_persistent = -1
+ibase.max_links = -1
+;ibase.default_db =
+;ibase.default_user =
+;ibase.default_password =
+;ibase.default_charset =
+ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
+ibase.dateformat = "%Y-%m-%d"
+ibase.timeformat = "%H:%M:%S"
+
+[MySQLi]
+;mysqli.allow_local_infile = On
+mysqli.max_persistent = -1
+mysqli.allow_persistent = On
+mysqli.max_links = -1
+mysqli.cache_size = 2000
+mysqli.default_port = 3306
+mysqli.default_socket =
+mysqli.default_host =
+mysqli.default_user =
+mysqli.default_pw =
+mysqli.reconnect = Off
+
+[mysqlnd]
+mysqlnd.collect_statistics = On
+mysqlnd.collect_memory_statistics = Off
+;mysqlnd.debug =
+;mysqlnd.log_mask = 0
+;mysqlnd.mempool_default_size = 16000
+;mysqlnd.net_cmd_buffer_size = 2048
+;mysqlnd.net_read_buffer_size = 32768
+;mysqlnd.net_read_timeout = 31536000
+;mysqlnd.sha256_server_public_key =
+
+[OCI8]
+;oci8.privileged_connect = Off
+;oci8.max_persistent = -1
+;oci8.persistent_timeout = -1
+;oci8.ping_interval = 60
+;oci8.connection_class =
+;oci8.events = Off
+;oci8.statement_cache_size = 20
+;oci8.default_prefetch = 100
+;oci8.old_oci_close_semantics = Off
+
+[PostgreSQL]
+pgsql.allow_persistent = On
+pgsql.auto_reset_persistent = Off
+pgsql.max_persistent = -1
+pgsql.max_links = -1
+pgsql.ignore_notice = 0
+pgsql.log_notice = 0
+
+[bcmath]
+bcmath.scale = 0
+
+[browscap]
+browscap = /etc/php7/browscap.ini
+
+[Session]
+session.save_handler = files
+;session.save_path = "/tmp"
+session.use_strict_mode = 0
+session.use_cookies = 1
+;session.cookie_secure =
+session.use_only_cookies = 1
+session.name = PHPSESSID
+session.auto_start = 0
+session.cookie_lifetime = 0
+session.cookie_path = /
+session.cookie_domain =
+session.cookie_httponly =
+session.serialize_handler = php
+session.gc_probability = 1
+session.gc_divisor = 1000
+session.gc_maxlifetime = 1440
+session.referer_check =
+;session.entropy_length = 32
+;session.entropy_file = /dev/urandom
+session.cache_limiter = nocache
+session.cache_expire = 180
+session.use_trans_sid = 0
+session.hash_function = 0
+session.hash_bits_per_character = 5
+url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
+;session.upload_progress.enabled = On
+;session.upload_progress.cleanup = On
+;session.upload_progress.prefix = "upload_progress_"
+;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
+;session.upload_progress.freq = "1%"
+;session.upload_progress.min_freq = "1"
+;session.lazy_write = On
+
+[Assertion]
+zend.assertions = -1
+;assert.active = On
+;assert.exception = On
+;assert.warning = On
+;assert.bail = Off
+;assert.callback = 0
+;assert.quiet_eval = 0
+
+[COM]
+;com.typelib_file =
+;com.allow_dcom = true
+;com.autoregister_typelib = true
+;com.autoregister_casesensitive = false
+;com.autoregister_verbose = true
+;com.code_page=
+
+[mbstring]
+;mbstring.language = Japanese
+;mbstring.internal_encoding =
+;mbstring.http_input =
+;mbstring.http_output =
+;mbstring.encoding_translation = Off
+;mbstring.detect_order = auto
+;mbstring.substitute_character = none
+;mbstring.func_overload = 0
+;mbstring.strict_detection = On
+;mbstring.http_output_conv_mimetype =
+
+[gd]
+;gd.jpeg_ignore_warning = 0
+
+[exif]
+;exif.encode_unicode = ISO-8859-15
+;exif.decode_unicode_motorola = UCS-2BE
+;exif.decode_unicode_intel = UCS-2LE
+;exif.encode_jis =
+;exif.decode_jis_motorola = JIS
+;exif.decode_jis_intel = JIS
+
+[Tidy]
+;tidy.default_config = /usr/local/lib/php7/default.tcfg
+tidy.clean_output = Off
+
+[soap]
+soap.wsdl_cache_enabled = 1
+soap.wsdl_cache_dir = "/tmp"
+soap.wsdl_cache_ttl = 86400
+soap.wsdl_cache_limit = 5
+
+[sysvshm]
+;sysvshm.init_mem = 10000
+
+[ldap]
+ldap.max_links = -1
+
+[mcrypt]
+;mcrypt.algorithms_dir =
+;mcrypt.modes_dir =
+
+[dba]
+;dba.default_handler =
+
+[opcache]
+;opcache.enable = 0
+;opcache.enable_cli = 0
+;opcache.memory_consumption = 64
+;opcache.interned_strings_buffer = 4
+;opcache.max_accelerated_files = 2000
+;opcache.max_wasted_percentage = 5
+;opcache.use_cwd = 1
+;opcache.validate_timestamps = 1
+;opcache.revalidate_freq = 2
+;opcache.revalidate_path = 0
+;opcache.save_comments = 1
+;opcache.fast_shutdown = 0
+;opcache.enable_file_override = 0
+;opcache.optimization_level = 0xffffffff
+;opcache.dups_fix = 0
+;opcache.blacklist_filename =
+;opcache.max_file_size = 0
+;opcache.consistency_checks = 0
+;opcache.force_restart_timeout = 180
+;opcache.error_log =
+;opcache.log_verbosity_level = 1
+;opcache.preferred_memory_model =
+;opcache.protect_memory = 0
+;opcache.restrict_api =
+;opcache.mmap_base =
+;opcache.file_cache =
+;opcache.file_cache_only = 0
+;opcache.file_cache_consistency_checks = 1
+;opcache.file_cache_fallback = 1
+;opcache.huge_code_pages = 1
+;opcache.validate_permission = 0
+;opcache.validate_root = 0
+
+[curl]
+curl.cainfo = /etc/ssl/certs/ca-certificates.crt
+
+[openssl]
+openssl.cafile = /etc/ssl/certs/ca-certificates.crt
+openssl.capath = /etc/ssl/certs
diff --git a/overlay/etc/services.d/.s6-svscan/finish b/overlay/etc/services.d/.s6-svscan/finish
new file mode 100644
index 0000000..1dadeea
--- /dev/null
+++ b/overlay/etc/services.d/.s6-svscan/finish
@@ -0,0 +1,2 @@
+#!/bin/sh
+/bin/true
diff --git a/overlay/etc/services.d/nginx/run b/overlay/etc/services.d/nginx/run
new file mode 100755
index 0000000..7bb9132
--- /dev/null
+++ b/overlay/etc/services.d/nginx/run
@@ -0,0 +1,2 @@
+#!/bin/execlineb -P
+nginx -g "daemon off;"
diff --git a/overlay/etc/services.d/php/run b/overlay/etc/services.d/php/run
new file mode 100755
index 0000000..21dd010
--- /dev/null
+++ b/overlay/etc/services.d/php/run
@@ -0,0 +1,2 @@
+#!/bin/execlineb -P
+php-fpm7 -F
diff --git a/overlay/etc/services.d/update-feeds/run b/overlay/etc/services.d/update-feeds/run
new file mode 100755
index 0000000..84efbee
--- /dev/null
+++ b/overlay/etc/services.d/update-feeds/run
@@ -0,0 +1,2 @@
+#!/bin/execlineb -P
+s6-setuidgid nginx php7 /var/www/app/update_daemon2.php > /dev/null 2>&1
diff --git a/overlay/etc/templates/config.php.tmpl b/overlay/etc/templates/config.php.tmpl
new file mode 100644
index 0000000..2a9c812
--- /dev/null
+++ b/overlay/etc/templates/config.php.tmpl
@@ -0,0 +1,180 @@
+ System), syslog - logs to system log.
+ // Setting this to blank uses PHP logging (usually to http server
+ // error.log).
+ // Note that feed updating daemons don't use this logging facility
+ // for normal output.
+
+ define('CONFIG_VERSION', {{ getenv "TTRSS_CONFIG_VERSION" "26" }});
+ // Expected config version. Please update this option in config.php
+ // if necessary (after migrating all new options from this file).
diff --git a/overlay/etc/templates/php.ini.tmpl b/overlay/etc/templates/php.ini.tmpl
new file mode 100644
index 0000000..3a57093
--- /dev/null
+++ b/overlay/etc/templates/php.ini.tmpl
@@ -0,0 +1,391 @@
+[PHP]
+user_ini.filename = ".user.ini"
+user_ini.cache_ttl = 300
+
+engine = On
+short_open_tag = Off
+
+precision = 14
+
+output_buffering = 0
+;output_handler =
+
+zlib.output_compression = Off
+;zlib.output_compression_level = -1
+;zlib.output_handler =
+
+implicit_flush = Off
+
+unserialize_callback_func =
+serialize_precision = 17
+
+;open_basedir =
+
+disable_functions =
+disable_classes =
+
+;highlight.string = #DD0000
+;highlight.comment = #FF9900
+;highlight.keyword = #007700
+;highlight.default = #0000BB
+;highlight.html = #000000
+
+;ignore_user_abort = On
+
+;realpath_cache_size = 16k
+;realpath_cache_ttl = 120
+
+zend.enable_gc = On
+;zend.multibyte = Off
+;zend.script_encoding =
+
+expose_php = {{ getenv "PHP_EXPOSE_PHP" "Off" }}
+
+max_execution_time = {{ getenv "PHP_MAX_EXECUTION_TIME" "30" }}
+max_input_time = {{ getenv "PHP_MAX_INPUT_TIME" "60" }}
+;max_input_nesting_level = 64
+;max_input_vars = 1000
+memory_limit = {{ getenv "PHP_MEMORY_LIMIT" "128M" }}
+
+error_reporting = {{ getenv "PHP_ERROR_REPORTING" "E_ALL & ~E_DEPRECATED & ~E_STRICT" }}
+display_errors = {{ getenv "PHP_DISPLAY_ERRORS" "Off" }}
+display_startup_errors = {{ getenv "PHP_DISPLAY_STARTUP_ERRORS" "Off" }}
+log_errors = {{ getenv "PHP_LOG_ERRORS" "On" }}
+log_errors_max_len = {{ getenv "PHP_LOG_ERRORS_MAX_LEN" "1024" }}
+ignore_repeated_errors = {{ getenv "PHP_IGNORE_REPEATED_ERRORS" "Off" }}
+ignore_repeated_source = {{ getenv "PHP_IGNORE_REPEATED_SOURCE" "Off" }}
+report_memleaks = {{ getenv "PHP_REPORT_MEMLEAKS" "On" }}
+;report_zend_debug = 0
+;xmlrpc_errors = 0
+;xmlrpc_error_number = 0
+html_errors = {{ getenv "PHP_HTML_ERRORS" "On" }}
+;docref_root = "/phpmanual/"
+;docref_ext = .html
+;error_prepend_string = ""
+;error_append_string = ""
+error_log = {{ getenv "PHP_ERROR_LOG" "php_errors.log"}}
+;windows.show_crt_warning
+
+;arg_separator.output = "&"
+;arg_separator.input = ";&"
+
+variables_order = "GPCS"
+request_order = "GP"
+
+register_argc_argv = Off
+auto_globals_jit = On
+;enable_post_data_reading = Off
+post_max_size = {{ getenv "PHP_POST_MAX_SIZE" "8M" }}
+
+auto_prepend_file =
+auto_append_file =
+
+default_mimetype = "text/html"
+default_charset = "UTF-8"
+;internal_encoding =
+;input_encoding =
+;output_encoding =
+
+;include_path = ".:/php7/includes"
+
+doc_root =
+user_dir =
+
+extension_dir = "/usr/lib/php7/modules"
+;sys_temp_dir = "/tmp"
+enable_dl = Off
+
+;cgi.force_redirect = 1
+;cgi.nph = 1
+;cgi.redirect_status_env =
+cgi.fix_pathinfo = 0
+cgi.discard_path = 1
+
+;fastcgi.impersonate = 1
+;fastcgi.logging = 0
+;cgi.rfc2616_headers = 0
+;cgi.check_shebang_line = 1
+
+file_uploads = On
+;upload_tmp_dir =
+upload_max_filesize = {{ getenv "PHP_UPLOAD_MAX_FILESIZE" "2M" }}
+max_file_uploads = 20
+
+allow_url_fopen = {{ getenv "PHP_ALLOW_URL_FOPEN" "On" }}
+allow_url_include = Off
+
+;from="john@doe.com"
+;user_agent="PHP"
+
+default_socket_timeout = 60
+;auto_detect_line_endings = Off
+
+[CLI Server]
+cli_server.color = On
+
+[Date]
+date.timezone = {{ getenv "PHP_DATE_TIMEZONE" "Europe/Berlin" }}
+;date.default_latitude = 31.7667
+;date.default_longitude = 35.2333
+;date.sunrise_zenith = 90.583333
+;date.sunset_zenith = 90.583333
+
+[filter]
+;filter.default = unsafe_raw
+;filter.default_flags =
+
+[iconv]
+;iconv.input_encoding =
+;iconv.internal_encoding =
+;iconv.output_encoding =
+
+[intl]
+;intl.default_locale =
+;intl.error_level = E_WARNING
+;intl.use_exceptions = 0
+
+[sqlite3]
+;sqlite3.extension_dir =
+
+[Pcre]
+;pcre.backtrack_limit = 100000
+;pcre.recursion_limit = 100000
+;pcre.jit = 1
+
+[Pdo]
+;pdo_odbc.connection_pooling = strict
+;pdo_odbc.db2_instance_name
+
+[Pdo_mysql]
+pdo_mysql.cache_size = 2000
+pdo_mysql.default_socket =
+
+[Phar]
+;phar.readonly = On
+;phar.require_hash = On
+;phar.cache_list =
+
+[mail function]
+SMTP = localhost
+smtp_port = 25
+;sendmail_path =
+
+;mail.force_extra_parameters =
+mail.add_x_header = On
+;mail.log =
+;mail.log = syslog
+
+[SQL]
+sql.safe_mode = {{ getenv "PHP_SQL_SAFE_MODE" "On" }}
+
+[ODBC]
+;odbc.default_db = Not yet implemented
+;odbc.default_user = Not yet implemented
+;odbc.default_pw = Not yet implemented
+;odbc.default_cursortype
+odbc.allow_persistent = On
+odbc.check_persistent = On
+odbc.max_persistent = -1
+odbc.max_links = -1
+odbc.defaultlrl = 4096
+odbc.defaultbinmode = 1
+;birdstep.max_links = -1
+
+[Interbase]
+ibase.allow_persistent = 1
+ibase.max_persistent = -1
+ibase.max_links = -1
+;ibase.default_db =
+;ibase.default_user =
+;ibase.default_password =
+;ibase.default_charset =
+ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
+ibase.dateformat = "%Y-%m-%d"
+ibase.timeformat = "%H:%M:%S"
+
+[MySQLi]
+;mysqli.allow_local_infile = On
+mysqli.max_persistent = -1
+mysqli.allow_persistent = On
+mysqli.max_links = -1
+mysqli.cache_size = 2000
+mysqli.default_port = 3306
+mysqli.default_socket =
+mysqli.default_host =
+mysqli.default_user =
+mysqli.default_pw =
+mysqli.reconnect = Off
+
+[mysqlnd]
+mysqlnd.collect_statistics = On
+mysqlnd.collect_memory_statistics = Off
+;mysqlnd.debug =
+;mysqlnd.log_mask = 0
+;mysqlnd.mempool_default_size = 16000
+;mysqlnd.net_cmd_buffer_size = 2048
+;mysqlnd.net_read_buffer_size = 32768
+;mysqlnd.net_read_timeout = 31536000
+;mysqlnd.sha256_server_public_key =
+
+[OCI8]
+;oci8.privileged_connect = Off
+;oci8.max_persistent = -1
+;oci8.persistent_timeout = -1
+;oci8.ping_interval = 60
+;oci8.connection_class =
+;oci8.events = Off
+;oci8.statement_cache_size = 20
+;oci8.default_prefetch = 100
+;oci8.old_oci_close_semantics = Off
+
+[PostgreSQL]
+pgsql.allow_persistent = On
+pgsql.auto_reset_persistent = Off
+pgsql.max_persistent = -1
+pgsql.max_links = -1
+pgsql.ignore_notice = 0
+pgsql.log_notice = 0
+
+[bcmath]
+bcmath.scale = 0
+
+[browscap]
+browscap = /etc/php7/browscap.ini
+
+[Session]
+session.save_handler = files
+;session.save_path = "/tmp"
+session.use_strict_mode = 0
+session.use_cookies = 1
+;session.cookie_secure =
+session.use_only_cookies = 1
+session.name = PHPSESSID
+session.auto_start = 0
+session.cookie_lifetime = 0
+session.cookie_path = /
+session.cookie_domain =
+session.cookie_httponly =
+session.serialize_handler = php
+session.gc_probability = 1
+session.gc_divisor = 1000
+session.gc_maxlifetime = 1440
+session.referer_check =
+;session.entropy_length = 32
+;session.entropy_file = /dev/urandom
+session.cache_limiter = nocache
+session.cache_expire = 180
+session.use_trans_sid = 0
+session.hash_function = 0
+session.hash_bits_per_character = 5
+url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
+;session.upload_progress.enabled = On
+;session.upload_progress.cleanup = On
+;session.upload_progress.prefix = "upload_progress_"
+;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
+;session.upload_progress.freq = "1%"
+;session.upload_progress.min_freq = "1"
+;session.lazy_write = On
+
+[Assertion]
+zend.assertions = -1
+;assert.active = On
+;assert.exception = On
+;assert.warning = On
+;assert.bail = Off
+;assert.callback = 0
+;assert.quiet_eval = 0
+
+[COM]
+;com.typelib_file =
+;com.allow_dcom = true
+;com.autoregister_typelib = true
+;com.autoregister_casesensitive = false
+;com.autoregister_verbose = true
+;com.code_page=
+
+[mbstring]
+;mbstring.language = Japanese
+;mbstring.internal_encoding =
+;mbstring.http_input =
+;mbstring.http_output =
+;mbstring.encoding_translation = Off
+;mbstring.detect_order = auto
+;mbstring.substitute_character = none
+;mbstring.func_overload = 0
+;mbstring.strict_detection = On
+;mbstring.http_output_conv_mimetype =
+
+[gd]
+;gd.jpeg_ignore_warning = 0
+
+[exif]
+;exif.encode_unicode = ISO-8859-15
+;exif.decode_unicode_motorola = UCS-2BE
+;exif.decode_unicode_intel = UCS-2LE
+;exif.encode_jis =
+;exif.decode_jis_motorola = JIS
+;exif.decode_jis_intel = JIS
+
+[Tidy]
+;tidy.default_config = /usr/local/lib/php7/default.tcfg
+tidy.clean_output = Off
+
+[soap]
+soap.wsdl_cache_enabled = 1
+soap.wsdl_cache_dir = "/tmp"
+soap.wsdl_cache_ttl = 86400
+soap.wsdl_cache_limit = 5
+
+[sysvshm]
+;sysvshm.init_mem = 10000
+
+[ldap]
+ldap.max_links = -1
+
+[mcrypt]
+;mcrypt.algorithms_dir =
+;mcrypt.modes_dir =
+
+[dba]
+;dba.default_handler =
+
+[opcache]
+;opcache.enable = 0
+;opcache.enable_cli = 0
+;opcache.memory_consumption = 64
+;opcache.interned_strings_buffer = 4
+;opcache.max_accelerated_files = 2000
+;opcache.max_wasted_percentage = 5
+;opcache.use_cwd = 1
+;opcache.validate_timestamps = 1
+;opcache.revalidate_freq = 2
+;opcache.revalidate_path = 0
+;opcache.save_comments = 1
+;opcache.fast_shutdown = 0
+;opcache.enable_file_override = 0
+;opcache.optimization_level = 0xffffffff
+;opcache.dups_fix = 0
+;opcache.blacklist_filename =
+;opcache.max_file_size = 0
+;opcache.consistency_checks = 0
+;opcache.force_restart_timeout = 180
+;opcache.error_log =
+;opcache.log_verbosity_level = 1
+;opcache.preferred_memory_model =
+;opcache.protect_memory = 0
+;opcache.restrict_api =
+;opcache.mmap_base =
+;opcache.file_cache =
+;opcache.file_cache_only = 0
+;opcache.file_cache_consistency_checks = 1
+;opcache.file_cache_fallback = 1
+;opcache.huge_code_pages = 1
+;opcache.validate_permission = 0
+;opcache.validate_root = 0
+
+[curl]
+curl.cainfo = /etc/ssl/certs/ca-certificates.crt
+
+[openssl]
+openssl.cafile = /etc/ssl/certs/ca-certificates.crt
+openssl.capath = /etc/ssl/certs
diff --git a/overlay/usr/local/bin/entrypoint.sh b/overlay/usr/local/bin/entrypoint.sh
new file mode 100755
index 0000000..50f1b03
--- /dev/null
+++ b/overlay/usr/local/bin/entrypoint.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+/usr/bin/gomplate -V -o /etc/php7/php.ini -f /etc/templates/php.ini.tmpl
+/usr/bin/gomplate -V -o /var/www/app/config.php -f /etc/templates/config.php.tmpl
+
+chown -R nginx:nginx /var/www/app/lock
+chown -R nginx:nginx /var/www/app/cache
+chown -R nginx:nginx /var/www/app/feed-icons
+
+s6-setuidgid nginx php7 /var/www/app/docker_setup.php
+
+exec /bin/s6-svscan /etc/services.d
diff --git a/overlay/var/www/app/docker_setup.php b/overlay/var/www/app/docker_setup.php
new file mode 100644
index 0000000..3eadf15
--- /dev/null
+++ b/overlay/var/www/app/docker_setup.php
@@ -0,0 +1,114 @@
+getMessage() . PHP_EOL;
+ return null;
+ }
+}
+
+if (file_exists("/var/www/app/config.php")) {
+ echo "Loading config.php" . PHP_EOL;
+ require_once "/var/www/app/config.php";
+
+ $pdo = pdo_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_TYPE, DB_PORT);
+ if (!$pdo) {
+ exit(2);
+ }
+
+ echo "Running sanity check.";
+ $errors = sanity_check(DB_TYPE);
+ if (count($errors) > 0) {
+ foreach ($errors as $error) {
+ echo "$error";
+ }
+ }
+
+ echo "Connected to the database" . PHP_EOL;
+
+ $res = $pdo->query("SELECT true FROM ttrss_feeds");
+ if ($res && $res->fetch()) {
+ echo "Some tt-rss data already exists in this database, skipping database installation" . PHP_EOL;
+ exit(0);
+ }
+ echo "tt-rss data not found, initializing the database" . PHP_EOL;
+
+ $lines = explode(";", preg_replace("/[\r\n]/", "",
+ file_get_contents("/var/www/app/schema/ttrss_schema_".basename(DB_TYPE).".sql")));
+
+ $dbInitError = 0;
+ foreach ($lines as $line) {
+ if (strpos($line, "--") !== 0 && $line) {
+ $res = $pdo->query($line);
+
+ if (!$res) {
+ echo "Query: $line" . PHP_EOL;
+ echo "Error: " . implode(", ", $this->pdo->errorInfo()) . PHP_EOL;
+ $dbInitError++;
+ }
+ }
+ }
+
+ if($dbInitError == 0) {
+ echo "Database initialization completed." . PHP_EOL;
+ exit(0);
+ } else {
+ echo "Database initialization failed." . PHP_EOL;
+ exit(1);
+ }
+}