Donetick
Overview
Donetick is the popular open source, self-hosted task and chore manager for individuals and groups. It offers recurring tasks, assignments and rotation between members, optional points to gamify who does what, circles (groups) that share task lists, and clear views of what is due. It is a privacy-respecting alternative to hosted chore and to-do apps, and you can deploy it in your own virtual network.
The SecureAnyCloud image runs the Donetick server (a single Go binary that serves both the REST API and the bundled web app) behind nginx as a reverse proxy, with an embedded SQLite database. The whole appliance runs on one disk with nothing else to deploy.
The server listens on port 2021 and is reached through nginx on port 80. A host firewall rule drops any traffic to 2021 that does not arrive on the loopback interface, so nginx on :80 is the only network-facing entry point.
On the first boot of every deployed VM, a one-shot service generates a fresh session-signing secret unique to that VM (nothing is baked into the image). The service seeds a single administrator account with a per-VM password through Donetick's own signup API, then disables open self-registration. The login is written to /root/donetick-credentials.txt with mode 0600.
What you get:
- Donetick 0.1.75 server binary at
/opt/donetick/donetick(REST API and web app in one, with an embedded web UI) - nginx reverse proxy on
:80in front of the Donetick server (port2021, restricted to loopback by a host firewall rule) - Embedded SQLite datastore at
/var/lib/donetick/donetick.db, with no external database to run - Per-VM administrator login generated at first boot, in a root-only file; per-VM session-signing secret; open self-registration disabled by default
donetick.service,nginx.serviceand adonetick-firewall.serviceas systemd units, enabled and active- 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.
Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. Donetick is lightweight and fits it comfortably.
For NSG inbound rules, allow 22/tcp from your management network. Allow 80/tcp (plus 443/tcp once you enable HTTPS) from the networks your users will reach Donetick on.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Donetick by SecureAnyCloud, and select Create.
On Basics, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80). Then choose Review + create, followed by Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:donetick-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name donetick \
--image sac1647283583153:donetick-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name donetick --port 80 --priority 1010Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>First-boot initialisation completes in under a minute. The credentials file is in place by the time SSH is ready.
Step 4 - Confirm the service is running
systemctl is-active donetick.service nginx.service curl -fsS -o /dev/null -w 'health endpoint -> HTTP %{http_code}\n' http://127.0.0.1/api/v1/healthBoth services report active, and the open health endpoint returns HTTP 200. This shows that the stack (nginx and the Donetick server) is serving. The whole appliance, including its SQLite database, lives on the single OS disk:
df -h / | tail -1 ls -l /var/lib/donetick/The output shows the service status, the open /api/v1/health endpoint returning HTTP 200, and the SQLite database directory on the OS disk.
Step 5 - Retrieve your administrator login
The administrator password is generated uniquely on the first boot of your VM and written to a root-only file:
sudo cat /root/donetick-credentials.txtThe file contains the Donetick URL, the administrator username (admin) and the password. You can confirm that the API authenticates end to end from the same session:
PASS=$(sudo grep '^donetick.admin.pass=' /root/donetick-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'no token -> HTTP %{http_code}\n' http://127.0.0.1/api/v1/users/profile
curl -s -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$PASS\"}" \
http://127.0.0.1/api/v1/auth/login | head -c 60; echoThe unauthenticated request returns HTTP 401, and the login call returns a JSON Web Token (access_token).
The output shows the root-only credentials file and an API authentication round trip: 401 without a token, and a JWT with the per-VM password.
Step 6 - First sign-in
Open a web browser and go to http://<vm-public-ip>/. Donetick presents its sign-in page. Enter the username admin and the password from /root/donetick-credentials.txt, then select Login.
The Donetick sign-in page, served on first boot with a per-VM administrator login.
Step 7 - Create tasks and chores
After you sign in, you land on the tasks overview. Select Create Task (or the + button) and give the task a name. Choose how often it repeats: Once, Daily, Weekly, Monthly or a custom interval. Optionally set who it is assigned to and how many points completing it is worth, then save.
Recurring chores automatically roll forward to their next due date when marked done.
The Donetick tasks overview, showing recurring household chores with due dates and points.
Step 8 - Assignments, points and completing a task
Open a task to see its details: its schedule, assignee, points and history. Mark a chore done from the overview or the detail view. Donetick records who completed it and when, awards the points, and (for a recurring chore) schedules the next occurrence.
Points accumulate per member, so a household or team can see who is pulling their weight.
A task detail view, showing the schedule, assignment, points and completion history.
Step 9 - Invite members and use the API
Donetick organises people into circles (groups) that share tasks. From Settings, you can view your circle and share its invite code so that family or team members can join, or create sub-accounts.
Open self-registration is disabled by default on this appliance, so only the administrator account exists until you invite members. To re-enable open self-registration, set DT_IS_USER_CREATION_DISABLED=false in /etc/donetick/donetick.env and restart:
sudo systemctl restart donetickEvery action in the web app is also available through the REST API at http://<vm-public-ip>/api/v1/. Authenticate with POST /api/v1/auth/login to obtain a token, then call the API with an Authorization: Bearer <token> header. For example, to create a task and mark it done:
PASS=$(sudo grep '^donetick.admin.pass=' /root/donetick-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$PASS\"}" \
http://127.0.0.1/api/v1/auth/login | grep -oE '"token":"[^"]+"' | head -1 | sed 's/.*:"//;s/"//')
ID=$(curl -s -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Sort the recycling","frequencyType":"weekly","frequency":1,"assignStrategy":"no_assignee","points":5}' \
http://127.0.0.1/api/v1/chores/ | grep -oE '"res":[0-9]+' | grep -oE '[0-9]+')
echo "created task id: $ID" curl -s -o /dev/null -w 'mark done -> HTTP %{http_code}\n' \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{}' \
http://127.0.0.1/api/v1/chores/$ID/doSecurity baseline
The image ships fully patched at capture time and keeps patching itself. Ubuntu's unattended-upgrades service is enabled, so security updates are installed automatically on your running VM. The Donetick server sits behind a host firewall rule, and open self-registration is disabled. Verify the state at any time:
systemctl is-enabled unattended-upgrades grep -h . /etc/apt/apt.conf.d/20auto-upgrades
sudo iptables -C INPUT -p tcp --dport 2021 ! -i lo -j DROP && echo 'app port 2021: loopback-only (DROP rule active)'
sudo ss -tlnp | grep -E ':2021 'The Donetick server listens on port 2021, but the host firewall drops any traffic to it that does not arrive on the loopback interface. nginx on :80 is the single network-facing entry point.
The output shows automatic security updates enabled, and the Donetick app port restricted to loopback by a host firewall rule.
Enabling HTTPS
For any production deployment, serve Donetick over HTTPS so that logins cannot be intercepted. The image ships with nginx, which certbot can configure automatically.
The following steps assume a DNS record that points your fully qualified domain name at the VM's public IP address, and 443/tcp open in the NSG:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d tasks.your-domain.example \
--non-interactive --agree-tos -m you@your-domain.example \
--redirectAfter certbot finishes, set the public URL so generated links are correct, then restart Donetick:
sudo sed -i 's|^DT_SERVER_PUBLIC_HOST=.*|DT_SERVER_PUBLIC_HOST=https://tasks.your-domain.example|' /etc/donetick/donetick.env
sudo systemctl restart donetickBackup and maintenance
Donetick keeps all of its state (tasks, circles, users, points and history) in a single SQLite database at /var/lib/donetick/donetick.db. Back it up with a consistent copy:
sudo systemctl stop donetick
sudo cp /var/lib/donetick/donetick.db <backup-dir>/donetick-$(date +%F).db
sudo systemctl start donetickKeep the OS patched with sudo apt update && sudo apt upgrade.
To upgrade Donetick, replace /opt/donetick/donetick with a newer release binary and restart. Database migrations run automatically on start. See https://docs.donetick.com/.
Support
This image is backed by 24/7 SecureAnyCloud support, with a guaranteed response within 24 hours and a one-hour average for critical issues. Contact sales@secureanycloud.com for help with deployment, upgrades, integrations, TLS termination and backups.
For general Donetick questions, consult the documentation at https://docs.donetick.com/. Donetick is a trademark of its respective owner. Its use here is nominative and does not imply affiliation or endorsement. All product and company names are trademarks or registered trademarks of their respective holders.
Deploy on Azure
Launch Donetick on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
Donetick is a free, open source, self-hosted task and chore manager for individuals, households and teams. It handles recurring schedules, assignments, points and shared circles or groups. It gives you a private alternative to hosted chore and to-do apps that you run entirely in your own AWS account.
This SecureAnyCloud image runs Donetick as a single self-contained Go binary that bundles the web application. Its data is kept in an embedded SQLite database, so there is no external database to provision. The application sits behind an nginx reverse proxy on port 80, and a host firewall rule protects the application port so that only nginx is reachable from the network.
A unique administrator password and a unique JWT session-signing secret are generated on the first boot of every instance, and open self-registration ships disabled. No shared secret and no default account are ever baked into the image.
What you get:
- Donetick 0.1.75 (a single Go binary at
/opt/donetick) managed by systemd, serving the API and the web app - nginx on port 80 fronting the application, which listens on port 2021
- A host firewall rule that drops any external traffic to the application port, so only nginx port 80 is reachable
- An embedded SQLite datastore at
/var/lib/donetick/donetick.db(no external database) - A unique administrator password generated on first boot and recorded in a root-only file
- A unique JWT session-signing secret generated on first boot, never baked into the image
- Open self-registration disabled by default, so only the seeded administrator exists
donetick.serviceandnginx.serviceas systemd units, enabled and active- A
/api/v1/healthendpoint for load-balancer health checks - 24/7 SecureAnyCloud support
Prerequisites
You need an AWS account, an EC2 key pair in the target region, and a VPC with a public subnet.
m5.large (2 vCPU / 8 GiB RAM) is the recommended instance type.
For security group inbound rules, allow 22/tcp from your management network for SSH, and 80/tcp for the web UI.
Step 1 - Launch the AMI
Subscribe to the listing in AWS Marketplace, choose Continue to Launch, and launch through the EC2 console or the AWS CLI. Select the m5.large instance type, your key pair, and a security group that opens ports 22 and 80. To launch from the AWS CLI, run:
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <security-group-id> \
--subnet-id <subnet-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=donetick}]'Step 2 - Connect to your instance
Connect over SSH as the default login user for the OS variant you launched. This listing may ship more than one OS variant, so use the matching login user.
For Ubuntu 24.04 LTS, the SSH login user is ubuntu. Connect with: ssh ubuntu@<instance-public-ip>
Step 3 - Confirm the services are running
Donetick runs behind nginx. A one-shot first-boot service generates the per-instance secret and admin password and seeds the administrator. Confirm that the two long-running services are healthy:
systemctl is-active donetick.service nginx.serviceBoth report active:
active activeStep 4 - Verify the stack and endpoints
Confirm that nginx is listening on port 80, the health probe answers through the proxy, the application port is protected by the host firewall rule, and the web UI refuses anonymous API access:
ss -tln | grep ':80 ' curl -s -o /dev/null -w 'health: HTTP %{http_code}\n' http://127.0.0.1/api/v1/health
sudo iptables -C INPUT -p tcp --dport 2021 ! -i lo -j DROP && echo 'app port 2021: external DROP rule present' curl -s -o /dev/null -w 'unauthenticated profile: HTTP %{http_code}\n' http://127.0.0.1/api/v1/users/profileThe output shows that nginx is listening on port 80 and /api/v1/health returns 200. It also shows that the firewall DROP rule that keeps the application port off the network is present, and that the unauthenticated profile endpoint returns 401 because authentication is enforced:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* health: HTTP 200 app port 2021: external DROP rule present unauthenticated profile: HTTP 401Step 5 - Read your per-instance admin credential
The image ships no shared or default login. On first boot, a unique administrator password is generated for this instance and written to a root-only file. Read the file details to confirm the permissions and the resolved URL:
sudo stat -c '%a %U:%G' /root/donetick-credentials.txt
sudo grep -E '^donetick\.(admin\.user|url)=' /root/donetick-credentials.txtThe file is 600 root:root. donetick.admin.user is your administrator username (admin), and donetick.url is the address to open in your browser:
600 root:root donetick.url=http://<instance-public-ip>/ donetick.admin.user=adminRun sudo cat /root/donetick-credentials.txt to also see the password.
Step 6 - Prove the login round trip from the command line
Confirm that the per-instance password authenticates against the API and returns a valid session token, exactly as your browser will:
PASS=$(sudo grep '^donetick.admin.pass=' /root/donetick-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$PASS\"}" \
http://127.0.0.1/api/v1/auth/login | grep -oE '"token":"[^"]+"' | head -1 | sed 's/.*:"//;s/"//')
curl -s -o /dev/null -w 'authenticated profile: HTTP %{http_code}\n' \
-H "Authorization: Bearer $TOKEN" http://127.0.0.1/api/v1/users/profileThe login returns a JWT and the authenticated profile request returns 200:
authenticated profile: HTTP 200Step 7 - Sign in to the web UI
Open http://<instance-public-ip>/ in your browser and sign in with the admin username and the password from the credentials file.
Step 8 - Create tasks and recurring chores
After you sign in, you land on the tasks view. Use the + button to create a chore and give it a name. Choose how often it recurs (once, daily, weekly, monthly or a custom interval), set a priority, and optionally assign it to a member.
Recurring chores automatically reschedule to their next due date when marked done.
Open any task to see its assignment, schedule, completion statistics and full history, and to mark it done, skip it or start it:
Step 9 - Invite family or group members
Open self-registration is disabled by default on this appliance, so only the seeded administrator exists. To share tasks with others, sign in as the administrator. Then either open a circle and share its invite code, or create sub-accounts under Settings.
To allow open self-registration instead, so that people can create their own accounts at your instance's URL, edit the per-instance environment file and restart the service:
sudo sed -i 's/^DT_IS_USER_CREATION_DISABLED=true/DT_IS_USER_CREATION_DISABLED=false/' /etc/donetick/donetick.env
sudo systemctl restart donetickStep 10 - Data, backups and TLS
Donetick keeps all of its data in the embedded SQLite database at /var/lib/donetick/donetick.db. Back it up with regular EBS snapshots or AWS Backup of the instance's volume.
For HTTPS, terminate TLS at your own domain and certificate in front of the instance, for example with an Application Load Balancer and an ACM certificate, or your own nginx or Caddy reverse proxy. Point it at port 80.
Security model
- The application binds to port 2021, but a host firewall rule drops any traffic to that port that does not arrive on the loopback interface. Only the nginx reverse proxy on port 80 is reachable from the network.
- A unique JWT session-signing secret is generated on each instance's first boot and is never baked into the image, so sessions minted on one deployment cannot be forged against another.
- A cryptographically random administrator password is generated on first boot and written only to the root-only file
/root/donetick-credentials.txt. - Open self-registration ships disabled. Only the seeded administrator exists until you choose to enable it or invite members.
- The application runs as an unprivileged
doneticksystem user under a hardened systemd unit withNoNewPrivileges,ProtectSystemandProtectHomeset.
Support
SecureAnyCloud provides 24/7 technical support for this product by email and live chat at sales@secureanycloud.com. We can help with deployment, reverse proxy termination with your own domain and TLS certificate, enabling registration and inviting members, and backup planning for your task data.
Deploy on AWS
Launch Donetick with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com