Remote Server & Docker
Run XianScan on a server or NAS with Docker or systemd, and reach it safely from anywhere with a Cloudflare Tunnel.
1. Docker
The image runs on any Linux x86_64 host, including NAS systems such as Unraid, TrueNAS and Synology. It uses the CPU only; for a GPU, use the native binary with systemd (section 2).
Docker Compose
services:
xianscan:
image: ghcr.io/arbenapura/xianscan:latest
container_name: xianscan
restart: unless-stopped
ports:
- "8124:8124"
volumes:
- xianscan-config:/config
volumes:
xianscan-config:
Start it with docker compose up -d. Your library, settings and caches are kept in the volume under /config.
Access token
A container is always in LAN mode, and its connections do not come from loopback, so every browser (including one on the Docker host), Mihon and the importer need the token once:
docker exec xianscan /app/xianscan --print-token
To make it reachable from the host only, publish the port on loopback: "127.0.0.1:8124:8124".
2. Linux systemd Service
Put the extracted release in /home/ubuntu/xianscan, then create /etc/systemd/system/xianscan.service:
[Unit]
Description=XianScan
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/xianscan
ExecStart=/home/ubuntu/xianscan/xianscan
Restart=always
RestartSec=5
Environment=PORT=8124
# For an NVIDIA GPU: folders that hold the CUDA 13 and cuDNN libraries
Environment=LD_LIBRARY_PATH=/home/ubuntu/xianscan:/usr/local/cuda/lib64
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now xianscan
sudo -u ubuntu /home/ubuntu/xianscan/xianscan --print-token # the token, if needed
XianScan listens on loopback only, which is what you want behind a Cloudflare Tunnel (section 4). For devices on your network to connect directly, add --lan to ExecStart. Data is stored in the service user's ~/.local/share/xianscan/data; to put it elsewhere, set Environment=XDG_DATA_HOME=/srv/xianscan.
For GPU setup, see GPU Acceleration.
3. Windows Server (Runs at Startup)
Register XianScan as a scheduled task under the SYSTEM account, so it runs at boot and survives logging off:
# 1. Allow the web port through the firewall (port 8123 is internal and must stay closed)
New-NetFirewallRule -Name "XianScan-Web-8124" -DisplayName "XianScan" -Protocol TCP -LocalPort 8124 -Action Allow -Profile Any
# 2. Start XianScan at boot, with LAN access
$action = New-ScheduledTaskAction -Execute "C:\xianscan\xianscan.exe" -Argument "--lan" -WorkingDirectory "C:\xianscan"
$trigger = New-ScheduledTaskTrigger -AtStartup
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
Register-ScheduledTask -TaskName "XianScan" -Action $action -Trigger $trigger -Principal $principal -Force
Start-ScheduledTask -TaskName "XianScan"
The task runs as SYSTEM, so its data and token live in the SYSTEM profile, not yours: xianscan.exe --print-token run as Administrator prints a different token. Read the service's token from C:\Windows\System32\config\systemprofile\AppData\Roaming\XianScan\data\access-token, or open Settings -> Network & Access in a browser on the server.
4. Cloudflare Tunnel (Access From Anywhere)
A tunnel gives XianScan an HTTPS address without opening ports on your router. It also puts XianScan on the internet, so protect it with Cloudflare Access (step 5) before you share the address.
- Install
cloudflaredon the server (instructions). - Log in and create a tunnel:
cloudflared tunnel login
cloudflared tunnel create xianscan
- Route your hostname to XianScan in
~/.cloudflared/config.yml:
tunnel: <TUNNEL_UUID>
credentials-file: /home/ubuntu/.cloudflared/<TUNNEL_UUID>.json
ingress:
- hostname: manga.yourdomain.com
service: http://localhost:8124
- service: http_status:404
- Run the tunnel as a service:
cloudflared tunnel route dns xianscan manga.yourdomain.com
sudo cloudflared service install
sudo systemctl start cloudflared
- Required: protect the hostname with Cloudflare Access. In Cloudflare Zero Trust, create an Access application for
manga.yourdomain.comwith a policy that only lets you in. XianScan still asks each new browser for the access token once, because tunnel traffic is never treated as local.
Mihon cannot complete an interactive Cloudflare login. Give it a way through Access (for example a bypass rule for /api/mihon/* and /api/pages/* and /api/covers/*), and keep the XianScan access token set in the extension, which still protects those routes.