Automating Shoko Server Setup with Ansible (No GUI Required)
How to fully automate Shoko Server deployment — including admin user creation, AniDB credential configuration, and import folder setup — without ever opening the web UI.
The Problem
Shoko Server's first-run experience requires you to:
- Open the web UI and create an admin account
- Enter your AniDB credentials
- Complete the setup wizard
- Configure import folders for your anime collection
For IaC deployments, all of this should happen automatically. Shoko exposes a v3 REST API that makes full automation possible, though the API has some quirks that aren't immediately obvious from the documentation.
Prerequisites
- Docker and Docker Compose
- An AniDB account (free, required for anime metadata)
- (Optional) Ansible for full automation
Step 1: Deploy the Container
Shoko uses SQLite internally — no external database needed:
services:
shoko-server:
image: shokoanime/server:latest
container_name: shoko-server
environment:
- PUID=1000
- PGID=100
- TZ=America/New_York
ports:
- "8111:8111"
volumes:
- ./shoko-config:/home/shoko/.shoko # Persistent config (SQLite DB)
- ./anime:/anime # Anime library
- ./drop:/drop # Drop folder for new files
restart: unless-stopped
Step 2: Wait for Startup and Check Status
Shoko has a startup state machine. After launching, check its status:
curl -s http://localhost:8111/api/v3/Init/Status | jq
States:
- "Waiting" — first run, ready for setup
- "Starting" — server is initializing
- "Started" — fully running, setup already completed
Step 3: Create Admin User
When in Waiting state, create the default admin user:
curl -sf -X POST "http://localhost:8111/api/v3/Init/DefaultUser" \
-H "Content-Type: application/json" \
-d '{
"Username": "admin",
"Password": "your-secure-password"
}'
Note the PascalCase field names — Shoko's API uses .NET conventions.
Step 4: Configure AniDB Credentials
Shoko uses RFC 6902 JSON Patch for settings updates (not regular JSON):
curl -sf -X PATCH "http://localhost:8111/api/v3/Settings" \
-H "Content-Type: application/json-patch+json" \
-d '[
{"op": "replace", "path": "/AniDb/Username", "value": "your-anidb-username"},
{"op": "replace", "path": "/AniDb/Password", "value": "your-anidb-password"}
]'
Key detail: The
Content-Typemust beapplication/json-patch+json, notapplication/json. The settings endpoint uses RFC 6902 patch operations.
Test AniDB Connection
Verify the credentials work before completing setup:
curl -sf -X POST "http://localhost:8111/api/v3/Settings/AniDB/TestLogin" \
-H "Content-Type: application/json" \
-d '{
"Username": "your-anidb-username",
"Password": "your-anidb-password"
}'
Step 5: Complete Setup
The endpoint to finish setup is StartServer, not CompleteSetup:
curl -sf "http://localhost:8111/api/v3/Init/StartServer"
This is a GET request, not POST. After calling it, Shoko transitions from Waiting → Starting → Started. Wait for it:
# Poll until started (with timeout)
for i in $(seq 1 60); do
STATE=$(curl -s http://localhost:8111/api/v3/Init/Status | jq -r '.State')
[ "$STATE" = "Started" ] && break
sleep 5
done
Step 6: Authenticate
Once started, get an API key for subsequent requests:
API_KEY=$(curl -sf -X POST "http://localhost:8111/api/auth" \
-H "Content-Type: application/json" \
-d '{
"user": "admin",
"pass": "your-secure-password",
"device": "automation"
}' | jq -r '.apikey')
The API key is persistent — store it securely for future use.
Step 7: Add Import Folders
Check existing folders and add new ones:
# List existing folders
curl -s "http://localhost:8111/api/v3/ImportFolder" \
-H "apikey: $API_KEY" | jq '.[].Path'
# Add anime library folder
curl -sf -X POST "http://localhost:8111/api/v3/ImportFolder" \
-H "apikey: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Path": "/anime",
"Name": "Anime",
"DropFolderType": 1,
"WatchForNewFiles": true
}'
# Add drop folder (for new file imports)
curl -sf -X POST "http://localhost:8111/api/v3/ImportFolder" \
-H "apikey: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"Path": "/drop",
"Name": "Drop",
"DropFolderType": 0,
"WatchForNewFiles": true
}'
DropFolderType values:
- 0 — Drop/source folder (Shoko moves files from here)
- 1 — Destination folder (where organized files live)
API Quirks and Gotchas
-
PascalCase everywhere — field names use .NET PascalCase:
Username,Password,DropFolderType, not camelCase. -
Settings use RFC 6902 PATCH — don't send a regular JSON body to
PATCH /api/v3/Settings. Use JSON Patch operations (op,path,value) withContent-Type: application/json-patch+json. -
StartServer, notCompleteSetup— the endpoint name in the API doesn't match what you'd expect from the UI terminology. -
ImportFolder, notManagedFolder— the API endpoint usesImportFolder, even though the UI may refer to "managed folders." -
GET /api/v3/Init/StartServer— this is a GET request, not POST. Unusual but that's how the API works. -
Auth header is
apikey, notAuthorization— Shoko uses a custom header, not Bearer tokens. -
Wait for
Startedstate — after callingStartServer, the server needs time to initialize. Don't try to authenticate or add folders untilState == "Started".
Force Clean
Shoko uses SQLite, so a fresh start only requires wiping the config directory:
# Stop the container
docker compose down
# Wipe config (includes SQLite DB)
rm -rf ./shoko-config
# Recreate and restart
mkdir -p ./shoko-config
docker compose up -d
Ansible Automation Summary
The full Ansible playbook follows this sequence:
- Fetch secrets from your secret store (AniDB creds, Shoko admin creds)
- (Optional) Wipe config directory if
force_clean=true - Deploy the container
- Wait for readiness —
GET /api/v3/Init/Statusreturns 200 - Check setup state — if
State == "Waiting", run first-time setup: a. Create admin user —POST /api/v3/Init/DefaultUserb. Configure AniDB —PATCH /api/v3/Settings(JSON Patch) c. Test AniDB login —POST /api/v3/Settings/AniDB/TestLogind. Complete setup —GET /api/v3/Init/StartServere. Wait forStartedstate - Authenticate —
POST /api/authto get API key - Store API key back in your secret store
- Add import folders —
POST /api/v3/ImportFolder(idempotent with existence check)
API Reference
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/api/v3/Init/Status |
GET | None | Check server state |
/api/v3/Init/DefaultUser |
POST | None (setup only) | Create admin user |
/api/v3/Settings |
PATCH | None (setup) / apikey | Update settings (JSON Patch) |
/api/v3/Settings/AniDB/TestLogin |
POST | None (setup) / apikey | Test AniDB credentials |
/api/v3/Init/StartServer |
GET | None (setup only) | Complete setup and start server |
/api/auth |
POST | None | Get persistent API key |
/api/v3/ImportFolder |
GET/POST | apikey | List/create import folders |
References
- Shoko Website
- Shoko Documentation
- Shoko Server GitHub
- Shoko API v3 Swagger (if available on your instance at
/swagger) - AniDB — free account required for metadata