Maintenance
Backups, updates, monitoring, and troubleshooting for production instances.
Backups
TimeTiles uses restic for encrypted, deduplicated backups with optional S3 offsite storage.
Commands
timetiles backup # Full backup (database + uploads)
timetiles backup --offsite # Full backup with S3 sync
timetiles backup db # Database only
timetiles backup uploads # Uploads only
timetiles backup list # List snapshots
timetiles backup verify # Verify integrity
timetiles backup prune # Apply retention policy
timetiles backup auto # Set up daily cron jobtimetiles backup writes two snapshots, not one: a db-tagged snapshot and an uploads-tagged snapshot. This
matters for recovery — see below.
Restore
Restore operates on one snapshot at a time, and each snapshot holds either the database or the uploads. A full recovery is therefore two commands.
timetiles backup list # Find the snapshot IDs and their tags
timetiles restore abc123 # Restore that snapshot
timetiles restore abc123 --offsite # Restore it from S3Full disaster recovery
# 1. List snapshots and note the newest `db` id and the newest `uploads` id
timetiles backup list
# 2. Restore the database
timetiles restore <newest-db-id>
# 3. Restore the uploads
timetiles restore <newest-uploads-id>Do not use timetiles restore latest for disaster recovery. latest resolves to the newest snapshot of any tag,
and because a full backup writes the database first and the uploads second, that is always the uploads snapshot. It
restores your files and leaves the database exactly as it was — which on a rebuilt host means empty. The command
reports which half it restored (Restore complete! Restored: uploads); read that line, it is the only signal that the
database was not touched.
timetiles restore with no arguments lists the available snapshots, same as timetiles backup list.
Offsite Storage (S3)
Configure in .env.production:
RESTIC_OFFSITE_REPOSITORY=s3:s3.amazonaws.com/your-bucket/timetiles
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secretFor write-only credentials (recommended), use S3 lifecycle rules to expire old backups instead of timetiles backup prune.
Retention Policy
Default retention: 7 daily, 4 weekly, 12 monthly. All backups are encrypted with RESTIC_PASSWORD.
Updates
# 1. Back up first
timetiles backup
# 2. Pull latest images and redeploy
timetiles update
# 3. Verify
curl https://your-domain.com/api/healthDatabase migrations run automatically on container startup — no manual intervention needed.
Monitoring
Health Checks
# Application health
curl https://your-domain.com/api/health
# Container status
timetiles status
# Live logs
timetiles logs -fRecommended schedule: health endpoint every 5 minutes, service status hourly, log review daily.
Resource Usage
# Container CPU and memory
docker stats
# Database size
docker compose -f deployment/docker-compose.prod.yml exec postgres \
psql -U timetiles_user -d timetiles -c \
"SELECT pg_size_pretty(pg_database_size('timetiles'));"
# Disk space
df -hLog Management
All containers use JSON logging with 50 MB max per file, 5 files retained.
timetiles logs web # Web application logs
timetiles logs worker-ingest # Import worker logs
timetiles logs postgres # Database logs
timetiles logs nginx # Reverse proxy logsDatabase Maintenance
Run weekly for optimal performance:
-- Connect: docker compose exec postgres psql -U timetiles_user timetiles
VACUUM ANALYZE;Slow Query Debugging
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
SELECT mean_exec_time, calls, query
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;SSL Certificates
Certificates auto-renew every 12 hours via the certbot container. Verify monthly:
# Check certificate status
timetiles logs certbot
# Force renewal if needed
docker compose -f deployment/docker-compose.prod.yml exec certbot certbot renew --force-renewal
docker compose -f deployment/docker-compose.prod.yml restart nginxHealth Check
TimeTiles exposes a health endpoint for monitoring and load balancer integration:
curl https://your-instance.com/api/healthReturns 200 when the system is healthy. Use this for Docker health checks or uptime monitoring (e.g., UptimeRobot , Gatus ).
Troubleshooting
| Problem | Diagnosis | Solution |
|---|---|---|
| App won’t start | timetiles logs web | Check DATABASE_URL and PAYLOAD_SECRET in .env.production |
| Imports stuck | Check /dashboard/payload-jobs | Workers may be down — timetiles restart worker-ingest |
| High memory | docker stats | Restart: timetiles restart web. If persistent, set NODE_OPTIONS="--max-old-space-size=4096" |
| SSL expired | timetiles logs certbot | DNS must resolve to your server. Force renewal (see above) |
| Disk full | df -h and docker system df | Prune Docker: docker system prune. Prune backups: timetiles backup prune |
| Slow queries | Enable pg_stat_statements | Add indexes, run VACUUM ANALYZE, check PostGIS query plans |
Debug Mode
# Enable detailed logging
# Edit deployment/.env.production:
LOG_LEVEL=debug
timetiles restart
timetiles logs -f webNext Steps
- Configure environment variables and feature flags
- Customize the UI with themes and branding
- Set usage limits for trust levels and quotas