{"id":45977753,"url":"https://github.com/chrislongros/anki-sync-server-enhanced","last_synced_at":"2026-02-28T17:04:23.493Z","repository":{"id":335895458,"uuid":"1147408868","full_name":"chrislongros/anki-sync-server-enhanced","owner":"chrislongros","description":"Self-hosted Anki sync server with multi-user support, auto-updates, healthchecks, and Docker secrets. Built from official Anki source.","archived":false,"fork":false,"pushed_at":"2026-02-01T20:11:14.000Z","size":58,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-02T02:50:22.692Z","etag":null,"topics":["anki","docker","flashcards","self-hosted","spaced-repetition","sync-server"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/chrislongros/anki-sync-server-enhanced","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrislongros.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-01T17:44:57.000Z","updated_at":"2026-02-01T20:29:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/chrislongros/anki-sync-server-enhanced","commit_stats":null,"previous_names":["chrislongros/anki-sync-server-enhanced"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/chrislongros/anki-sync-server-enhanced","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrislongros%2Fanki-sync-server-enhanced","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrislongros%2Fanki-sync-server-enhanced/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrislongros%2Fanki-sync-server-enhanced/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrislongros%2Fanki-sync-server-enhanced/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrislongros","download_url":"https://codeload.github.com/chrislongros/anki-sync-server-enhanced/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrislongros%2Fanki-sync-server-enhanced/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29943690,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T13:49:17.081Z","status":"ssl_error","status_checked_at":"2026-02-28T13:48:50.396Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anki","docker","flashcards","self-hosted","spaced-repetition","sync-server"],"created_at":"2026-02-28T17:04:23.066Z","updated_at":"2026-02-28T17:04:23.485Z","avatar_url":"https://github.com/chrislongros.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anki Sync Server Enhanced\n\n[![Docker Hub](https://img.shields.io/docker/pulls/chrislongros/anki-sync-server-enhanced)](https://hub.docker.com/r/chrislongros/anki-sync-server-enhanced)\n[![GitHub Actions](https://github.com/chrislongros/anki-sync-server-enhanced/actions/workflows/build.yml/badge.svg)](https://github.com/chrislongros/anki-sync-server-enhanced/actions)\n[![Anki Version](https://img.shields.io/badge/anki-25.09.2-green)](https://github.com/ankitects/anki/releases/tag/25.09.2)\n\nProduction-ready Docker image for self-hosted Anki sync server with backups, monitoring, dashboard, and security features.\n\n![Dashboard](docs/dashboard.png)\n\n\n## Why This Image?\n\nThe official Anki project provides sync server source code but no pre-built Docker images. This project provides:\n\n- **Zero build time** - Pre-compiled for amd64, arm64, and arm/v7\n- **Auto-updates** - Daily builds automatically track the latest Anki release\n- **Enterprise features** - Backups, monitoring, alerts, and security out of the box\n- **NAS-ready** - Works on TrueNAS SCALE, Unraid, Synology, and any Docker host\n\n## Features\n\n| Feature | This Image |\n|---------|------------|\n| Pre-built Docker image | ✅ |\n| Auto-updates (daily builds) | ✅ |\n| Multi-arch (amd64, arm64, arm/v7) | ✅ |\n| Automated backups with retention | ✅ |\n| S3/MinIO backup upload | ✅ |\n| Prometheus metrics | ✅ |\n| Web dashboard | ✅ |\n| Discord/Telegram/Slack/Email alerts | ✅ |\n| Docker secrets support | ✅ |\n| Hashed passwords | ✅ |\n| Fail2ban integration | ✅ |\n| Rate limiting | ✅ |\n| Built-in TLS (Let's Encrypt/self-signed) | ✅ |\n| User management CLI | ✅ |\n| PUID/PGID support | ✅ |\n\n## Quick Start\n\n```bash\ndocker run -d \\\n  --name anki-sync \\\n  -p 8080:8080 \\\n  -e SYNC_USER1=user:password \\\n  -v anki_data:/data \\\n  chrislongros/anki-sync-server-enhanced:25.09.2-1\n```\n\nThen configure your Anki client to sync to `http://your-server:8080/`\n\n## Docker Compose\n\n```yaml\nservices:\n  anki-sync-server:\n    image: chrislongros/anki-sync-server-enhanced:25.09.2-1\n    container_name: anki-sync\n    ports:\n      - \"8080:8080\"   # Sync server (HTTP)\n      - \"8443:8443\"   # Sync server (HTTPS, if TLS_ENABLED)\n      - \"8081:8081\"   # Dashboard (optional)\n      - \"9090:9090\"   # Metrics (optional)\n    environment:\n      - SYNC_USER1=alice:password1\n      - SYNC_USER2=bob:password2\n      - TZ=Europe/Berlin\n      - BACKUP_ENABLED=true\n      - METRICS_ENABLED=true\n      - DASHBOARD_ENABLED=true\n    volumes:\n      - anki_data:/data\n      - anki_backups:/backups\n    restart: unless-stopped\n\nvolumes:\n  anki_data:\n  anki_backups:\n```\n\n## Web Dashboard\n\nEnable with `DASHBOARD_ENABLED=true` and access at `http://server:8081/`\n\n**Features:**\n- **Overview** - Server status, uptime, user count, data size, sync operations\n- **Users** - Per-user statistics with data size and last sync time\n- **Backups** - List backups, create new backups with one click\n- **Logs** - View sync, auth, and backup logs with color-coded entries\n- **System** - Disk usage, memory usage, load average\n\nProtect with basic auth using `DASHBOARD_AUTH=admin:password`\n\n\u003c!-- \nScreenshot placeholder - add actual screenshot\n![Dashboard Screenshot](docs/dashboard.png)\n--\u003e\n\n## Configuration Reference\n\n### Core\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `SYNC_USER1`-`SYNC_USER99` | User credentials (user:pass) | Required |\n| `SYNC_HOST` | Listen address | `0.0.0.0` |\n| `SYNC_PORT` | Listen port | `8080` |\n| `LOG_LEVEL` | debug/info/warn/error | `info` |\n| `TZ` | Timezone | `UTC` |\n| `PUID` / `PGID` | File permissions | `1000` |\n| `PASSWORDS_HASHED` | Use hashed passwords | `0` |\n\n### Backups\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `BACKUP_ENABLED` | Enable backups | `false` |\n| `BACKUP_SCHEDULE` | Cron schedule | `0 3 * * *` |\n| `BACKUP_RETENTION_DAYS` | Keep days | `7` |\n\n### S3 Upload\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `S3_BACKUP_ENABLED` | Upload to S3 | `false` |\n| `S3_ENDPOINT` | S3 endpoint (MinIO/Garage) | - |\n| `S3_BUCKET` | Bucket name | - |\n| `S3_ACCESS_KEY` | Access key | - |\n| `S3_SECRET_KEY` | Secret key | - |\n| `S3_REGION` | Region | `us-east-1` |\n\n### Monitoring\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `METRICS_ENABLED` | Prometheus metrics | `false` |\n| `METRICS_PORT` | Metrics port | `9090` |\n| `DASHBOARD_ENABLED` | Web dashboard | `false` |\n| `DASHBOARD_PORT` | Dashboard port | `8081` |\n| `DASHBOARD_AUTH` | Auth (user:pass) | - |\n\n### Notifications\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `NOTIFY_ENABLED` | Enable webhooks | `false` |\n| `NOTIFY_TYPE` | discord/telegram/slack/ntfy | `discord` |\n| `NOTIFY_WEBHOOK_URL` | Webhook URL | - |\n| `EMAIL_ENABLED` | Enable email | `false` |\n| `EMAIL_HOST` | SMTP host | - |\n| `EMAIL_PORT` | SMTP port | `587` |\n| `EMAIL_USER` / `EMAIL_PASS` | SMTP credentials | - |\n| `EMAIL_FROM` / `EMAIL_TO` | Email addresses | - |\n\n### Security\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `FAIL2BAN_ENABLED` | Enable fail2ban | `false` |\n| `FAIL2BAN_MAX_RETRIES` | Max failures | `5` |\n| `FAIL2BAN_BAN_TIME` | Ban seconds | `3600` |\n| `RATE_LIMIT_ENABLED` | Enable rate limit | `false` |\n| `RATE_LIMIT_REQUESTS` | Max requests | `100` |\n| `RATE_LIMIT_WINDOW` | Window seconds | `60` |\n\n\n### TLS / HTTPS\n\nBuilt-in TLS support via Caddy reverse proxy. Three modes available:\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `TLS_ENABLED` | Enable TLS | `false` |\n| `TLS_PORT` | HTTPS port | `8443` |\n| `TLS_DOMAIN` | Domain for Let's Encrypt | - |\n| `TLS_EMAIL` | Email for Let's Encrypt | - |\n| `TLS_CERT` | Path to manual certificate | - |\n| `TLS_KEY` | Path to manual private key | - |\n\n**Mode 1: Let's Encrypt (automatic)**\n```bash\ndocker run -d \\\n  -p 80:80 -p 443:443 \\\n  -e SYNC_USER1=user:password \\\n  -e TLS_ENABLED=true \\\n  -e TLS_DOMAIN=anki.yourdomain.com \\\n  -e TLS_EMAIL=you@email.com \\\n  -v anki_data:/data \\\n  -v anki_config:/config \\\n  chrislongros/anki-sync-server-enhanced:25.09.2-1\n```\n\n**Mode 2: Manual certificates**\n```bash\ndocker run -d \\\n  -p 8443:8443 \\\n  -e SYNC_USER1=user:password \\\n  -e TLS_ENABLED=true \\\n  -e TLS_CERT=/config/certs/fullchain.pem \\\n  -e TLS_KEY=/config/certs/privkey.pem \\\n  -v ./certs:/config/certs:ro \\\n  -v anki_data:/data \\\n  chrislongros/anki-sync-server-enhanced:25.09.2-1\n```\n\n**Mode 3: Self-signed (local/testing)**\n```bash\ndocker run -d \\\n  -p 8080:8080 -p 8443:8443 \\\n  -e SYNC_USER1=user:password \\\n  -e TLS_ENABLED=true \\\n  -v anki_data:/data \\\n  chrislongros/anki-sync-server-enhanced:25.09.2-1\n```\n\nThen configure clients to use `https://your-server:8443/`\n\n\u003e **Note:** Self-signed certificates will show browser warnings. For local networks, you may prefer using HTTP or a proper certificate.\n## CLI Tools\n\n```bash\n# User management\ndocker exec anki-sync user-manager.sh list\ndocker exec anki-sync user-manager.sh add john\ndocker exec anki-sync user-manager.sh add john mypassword\ndocker exec anki-sync user-manager.sh reset john newpass\ndocker exec anki-sync user-manager.sh hash mypassword\ndocker exec anki-sync user-manager.sh stats\n\n# Backup management\ndocker exec anki-sync backup.sh\ndocker exec anki-sync restore.sh --list\ndocker exec anki-sync restore.sh --list-s3\ndocker exec anki-sync restore.sh backup_file.tar.gz\ndocker exec anki-sync restore.sh --s3 backup_file.tar.gz\n```\n\n## Client Configuration\n\n### Desktop (Windows/Mac/Linux)\n\n1. Open Anki\n2. Go to **Tools → Preferences → Syncing**\n3. Set custom sync server to: `http://your-server:8080/`\n4. Click **Sync** and enter your credentials\n\n### AnkiDroid (Android)\n\n1. Open AnkiDroid\n2. Go to **Settings → Sync → Custom sync server**\n3. Set sync URL: `http://your-server:8080/`\n4. Set media URL: `http://your-server:8080/msync/`\n5. Sync with your credentials\n\n### AnkiMobile (iOS)\n\n1. Open AnkiMobile\n2. Go to **Settings → Sync → Custom server**\n3. Enter: `http://your-server:8080/`\n4. Sync with your credentials\n\n\u003e **Tip:** Enable built-in TLS with `TLS_ENABLED=true` or use a reverse proxy (Traefik, Caddy, nginx) for secure remote access.\n\n## Prometheus Metrics\n\nAvailable at `http://server:9090/metrics` when `METRICS_ENABLED=true`:\n\n| Metric | Description |\n|--------|-------------|\n| `anki_sync_users_total` | Configured user count |\n| `anki_sync_data_bytes` | Total data size |\n| `anki_sync_backup_count` | Number of backups |\n| `anki_sync_uptime_seconds` | Server uptime |\n| `anki_sync_operations_total` | Total sync operations |\n| `anki_auth_success_total` | Successful logins |\n| `anki_auth_failed_total` | Failed logins |\n\n## Docker Secrets\n\nFor secure credential management:\n\n```yaml\nservices:\n  anki-sync-server:\n    image: chrislongros/anki-sync-server-enhanced:25.09.2-1\n    environment:\n      - SYNC_USER1_FILE=/run/secrets/anki_user1\n    secrets:\n      - anki_user1\n\nsecrets:\n  anki_user1:\n    file: ./secrets/user1.txt  # Contains: username:password\n```\n\n## Image Sources\n\n| Registry | Image |\n|----------|-------|\n| Docker Hub | `chrislongros/anki-sync-server-enhanced:25.09.2-1` |\n\n## NAS Installation\n\n- **TrueNAS SCALE:** See [truenas/README.md](truenas/README.md)\n- **Unraid:** Use [unraid/anki-sync-server.xml](unraid/anki-sync-server.xml)\n\n## Troubleshooting\n\n**Can't connect to server:**\n- Ensure port 8080 is exposed and not blocked by firewall\n- Check container logs: `docker logs anki-sync`\n- Verify the sync URL ends with `/` (e.g., `http://server:8080/`)\n\n**Sync fails with large collections:**\n- If using a reverse proxy, increase `client_max_body_size` (nginx) or equivalent\n- Set `MAX_SYNC_PAYLOAD_MEGS` environment variable if needed\n\n**Authentication issues:**\n- Ensure username doesn't contain special characters\n- Check auth log: `docker exec anki-sync cat /var/log/anki/auth.log`\n- Try resetting password: `docker exec anki-sync user-manager.sh reset username newpassword`\n\n**Dashboard not loading:**\n- Ensure `DASHBOARD_ENABLED=true` is set\n- Check port 8081 is exposed\n- View logs: `docker logs anki-sync | grep dashboard`\n\n## Building Locally\n\n```bash\n# Auto-detect latest Anki version\ndocker build -t anki-sync-server-enhanced .\n\n# Specify Anki version\ndocker build --build-arg ANKI_VERSION=25.09.2 -t anki-sync-server-enhanced:25.09.2-1 .\n```\n\n## Credits\n\nBuilt from the official [Anki](https://github.com/ankitects/anki) sync server by Ankitects.\n\n## License\n\nAGPL-3.0 - © 2026 Christos Longros - see [LICENSE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrislongros%2Fanki-sync-server-enhanced","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrislongros%2Fanki-sync-server-enhanced","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrislongros%2Fanki-sync-server-enhanced/lists"}