尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗A small, dependency-free web app that guides you through brushing your teeth zone by zone.
Brushing order: upper right → upper left, then lower left → lower right.
git clone https://github.com/norbsmaq/toothbrush-timer /opt/toothbrush-timer
cd /opt/toothbrush-timer
sudo ./setup-droplet.sh
The script asks for your domain name(s) and whether to enable HSTS (see below). Then it installs Docker if needed, opens ports 80 and 443 if ufw is active, turns on automatic updates, installs GoAccess for visitor stats, and starts the app. It finishes by printing the address to open.The container restarts automatically after reboots (restart: unless-stopped).
Point a DNS A record for each domain at the droplet's IP. For example, add records for both example.com and www.example.com. Then enter the domains when setup-droplet.sh asks, separated by spaces or commas:
Domains [none]: example.com www.example.com
The script warns you if a domain doesn't point at the droplet yet. Caddy gets and renews a Let's Encrypt certificate for each domain automatically, and serves the app on all of them. HTTPS is needed for the browser's keep-screen-awake feature and for installing the app on your phone. Everything else works over plain HTTP.
If you list both a domain and its www. version, the script also offers to redirect www.example.com to example.com (keeping the rest of the address). That way everyone ends up on one address, so an installed app and its saved settings always use the same one.
To change domains later, run sudo ./setup-droplet.sh again. It shows your current settings as defaults, so press Enter to keep any of them. Or edit .env directly (SITE_ADDRESS="example.com, www.example.com", REDIRECT_WWW=true) and run docker compose up -d.
By default the site sends an HSTS header. It tells browsers to always use HTTPS for your domain for the next year. Browsers ignore it over plain HTTP or an IP address, so it does no harm there.
If you're using a domain but might switch it back to plain HTTP later, answer n when the setup script asks about HSTS. Or set ENABLE_HSTS=false in .env and run docker compose up -d. Turning it off doesn't undo HSTS in browsers that have already received it; they keep it until it expires.
setup-droplet.sh turns on three kinds of automatic updates:
| What | How | When |
|---|---|---|
| Ubuntu security updates | unattended-upgrades | Daily. If an update needs a reboot, the droplet reboots at 04:00 and the app starts back up on its own. |
| Docker Engine | unattended-upgrades, from Docker's apt repository | Daily, along with the OS updates |
| The app and its Caddy web server | toothbrush-timer-update.timer runs update.sh | Daily around 03:30 |
update.sh makes the server's copy match the main branch on GitHub exactly, rebuilds on the newest Caddy image, restarts the container and removes old images. Anything pushed to main goes live on the next run. Any edits made directly to the repo's files on the server are overwritten. Your .env settings aren't part of the repo, so they're kept.
To update right away, run sudo ./update.sh. To see when the update last ran and when it runs next:
systemctl list-timers toothbrush-timer-update.timer
journalctl -u toothbrush-timer-update.service -n 50
To turn off the app auto-update: sudo systemctl disable --now toothbrush-timer-update.timer
.env is git-ignored, so your settings are kept across updates.
Caddy writes an access log for every request to logs/access.log in the app folder on the droplet. It starts a new file at 10 MB, compresses the old ones and deletes them after 90 days. setup-droplet.sh installs GoAccess, which turns the logs into a stats dashboard in your terminal. Nothing is published on the website.
To see the stats, SSH into the droplet and run:
cd /opt/toothbrush-timer
sudo ./stats.sh
It shows visitors, pages, browsers, operating systems and referrers per day, across the current and older log files. Use the arrow keys and Tab to move around, and press q to quit. Extra options are passed to GoAccess. For example, sudo ./stats.sh --ignore-crawlers hides search engine bots.
The logs include visitors' IP addresses and browser details. They stay on the droplet, readable only by root.
The app is a Progressive Web App (PWA). Once installed, it opens full-screen from your home screen and works offline.
Installing requires HTTPS, so set up a domain first (see above). Over plain http://IP it still works in the browser, but it won't install.
When you deploy a new version, an installed app picks it up the next time it's opened online.
To try the app or test changes without a server, get the code with git clone https://github.com/norbsmaq/toothbrush-timer (or Code → Download ZIP on GitHub), then either:
public/index.html in your browser. Everything works except offline mode and installing as an app.docker compose up, then open http://localhost.cd public && python3 -m http.server 8000, then open http://localhost:8000.public/ the app (index.html, style.css, app.js, icons)
manifest.webmanifest PWA manifest
sw.js service worker (offline support)
Caddyfile web server config
Dockerfile Caddy image with the app baked in
docker-compose.yml
setup-droplet.sh one-time droplet setup
update.sh pull + rebuild (run daily by a systemd timer)
stats.sh visitor stats from the access logs (GoAccess)
logs/ access logs on the server (git-ignored)