A small PHP / MariaDB (MySQL) to-do list with lists, tags, recurring entries and statistics.
- Create a database and load
sql/install.sql. - Copy
config.sample.phptoconfig.phpand adapt it. - Serve the directory with PHP (mysqli) behind HTTP authentication and HTTPS, see below.
The application has no login of its own. It relies on the web server's HTTP authentication
(REMOTE_USER) and rejects every request without it. This is the last line of defence only,
set up the rest properly:
-
HTTPS only. Basic authentication sends the password with every request.
.htaccess(Apache) andnginx.conf.samplealready require it. TheX-Forwarded-Protoheader is never believed by them, as any client can send it; behind a proxy which terminates TLS see the notes in.htaccess, and$trust_forwarded_protoinconfig.sample.php. -
Strong password hashes:
htpasswd -B -C 12 -c <file> <user>(bcrypt). Keep the file outside of the web root. -
Limit password guessing. Basic authentication has no lockout. Use fail2ban (a filter on the
401responses of the access log, or onuser ... authentication failurein the Apache error log),mod_evasive, orlimit_reqin nginx (seenginx.conf.sample). -
All users share all data. The application does not separate the data of different HTTP-authenticated users (
TodoConstants::DefaultUserID): everyone who can log in can read, change and delete everything. -
Block internal files in the web server, not only in
.htaccess..htaccessis ignored ifAllowOverridedoes not allow it; then.git/,sql/,tests/,package*.jsonand editor backups (config.php~) would be downloadable. Copy the rules of.htaccessinto the virtual host (<Directory>/<FilesMatch>), or deploy a release without.git,tests,sql,scriptsandnode_modules.sh tests/apache-access.shchecks the rules. -
Keep
config.phpoutside of the web root and set the environment variableTODO_CONFIGto its path (SetEnv TODO_CONFIG /etc/todo/config.phpin Apache,env[TODO_CONFIG]in the php-fpm pool,fastcgi_param TODO_CONFIG ...;in nginx). -
Use a restricted database user, not
root:CREATE USER 'todo'@'localhost' IDENTIFIED BY '<password>'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES ON todo.* TO 'todo'@'localhost';
(
CREATE TEMPORARY TABLESis used when recurring entries are copied.) Applysql/update-*.sqlwith an administrative account. -
PHP:
expose_php = Offanddisplay_errors = Off(the application also sets the latter for its own pages).
See tests/README.md. The workflows in .github/workflows run them, check that vendor/ matches
package-lock.json and run npm audit.