Skip to content

Birdninja1/AniCDN

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“‘ MangaCDN β€” Personal Raspberry Pi CDN

A self-hosted, WEBP-optimised CDN for your manga reader, running on Raspberry Pi
with Cloudflare Tunnel, USB Drive storage, and a full dark-theme management panel.


πŸ“¦ Project Structure

mangacdn/
β”œβ”€β”€ server.js                  ← Express CDN + Management API
β”œβ”€β”€ package.json
β”œβ”€β”€ ecosystem.config.js        ← PM2 process config
β”œβ”€β”€ cloudflared-config.yml     ← Cloudflare Tunnel config
β”œβ”€β”€ setup.sh                   ← One-shot install script
└── public/
    β”œβ”€β”€ panel/index.html       ← Management GUI (dark theme)
    └── reader/index.html      ← Test manga reader frontend

πŸš€ Quick Install (Raspberry Pi)

# Clone / copy project to your Pi
cd /home/pi
git clone <your-repo>  # or scp from your machine
cd mangacdn

chmod +x setup.sh
bash setup.sh

The script:

  • Installs Node.js 20 LTS
  • Installs PM2 (process manager)
  • Installs cloudflared (Cloudflare Tunnel daemon)
  • Detects and mounts your USB drive
  • Generates random credentials
  • Starts the server and enables boot autostart

πŸ”§ Manual Setup (Step by Step)

Step 1 β€” Install Node.js 20

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

Step 2 β€” Install dependencies

cd /home/pi/mangacdn
npm install

Step 3 β€” Mount USB Drive

# Find your USB device
lsblk

# Mount it (example: /dev/sda1, ext4)
sudo mkdir -p /mnt/usb/manga
sudo mount /dev/sda1 /mnt/usb

# Make it permanent (replace UUID)
UUID=$(sudo blkid -s UUID -o value /dev/sda1)
echo "UUID=$UUID  /mnt/usb  ext4  defaults,nofail  0  2" | sudo tee -a /etc/fstab

Folder structure on USB:

/mnt/usb/manga/
β”œβ”€β”€ chainsaw-man/
β”‚   β”œβ”€β”€ cover.webp            ← Series cover (optional)
β”‚   β”œβ”€β”€ chapter-001/
β”‚   β”‚   β”œβ”€β”€ 001.webp
β”‚   β”‚   β”œβ”€β”€ 002.webp
β”‚   β”‚   └── 003.webp
β”‚   └── chapter-002/
β”‚       └── ...
└── one-piece/
    └── ...

Step 4 β€” Configure Environment

Edit ecosystem.config.js:

env: {
  PORT:         3000,
  STORAGE_ROOT: '/mnt/usb/manga',   // ← USB mount path
  API_TOKEN:    'your-secret-token', // ← Used by API clients
  PANEL_PASS:   'your-panel-pass',   // ← Login to panel GUI
}

Step 5 β€” Start with PM2

npm install -g pm2

mkdir -p logs
pm2 start ecosystem.config.js
pm2 save

# Enable auto-start on Pi boot:
pm2 startup
# Copy+run the command it outputs (starts with "sudo env PATH=...")

Step 6 β€” Cloudflare Tunnel

# Install cloudflared (ARM64)
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64 \
  -o /tmp/cloudflared
sudo install -m 755 /tmp/cloudflared /usr/local/bin/cloudflared

# Authenticate with Cloudflare
cloudflared tunnel login

# Create tunnel
cloudflared tunnel create mangacdn
# Note the Tunnel ID it gives you!

# Edit cloudflared-config.yml:
#   Replace <TUNNEL_ID> and yourdomain.com
sudo cp cloudflared-config.yml /etc/cloudflared/config.yml
sudo nano /etc/cloudflared/config.yml

# Create DNS route
cloudflared tunnel route dns mangacdn cdn.yourdomain.com

# Install as system service
sudo cloudflared service install
sudo systemctl enable --now cloudflared

# Verify
cloudflared tunnel info mangacdn

🌐 Endpoints

URL Description
https://cdn.yourdomain.com/files/<path> Public CDN file endpoint
https://cdn.yourdomain.com/panel/ Management panel (password)
https://cdn.yourdomain.com/reader/ Test manga reader
https://cdn.yourdomain.com/api/list?path=/ List directory (API)
https://cdn.yourdomain.com/health Health check

πŸ“‹ Management API Reference

All API calls require the header X-Api-Token: <your-token> (or ?token= in URL).

List a directory

GET /api/list?path=/chainsaw-man
{
  "path": "/chainsaw-man",
  "items": [
    { "name": "chapter-001", "type": "folder", "path": "/chainsaw-man/chapter-001", "url": null },
    { "name": "cover.webp",  "type": "file",   "path": "/chainsaw-man/cover.webp",  "url": "/files/chainsaw-man/cover.webp" }
  ]
}

Create a folder

POST /api/folder
Content-Type: application/json

{ "path": "/chainsaw-man/chapter-003" }

Delete a file or folder

DELETE /api/delete
Content-Type: application/json

{ "path": "/chainsaw-man/old-chapter" }

Rename

PUT /api/rename
Content-Type: application/json

{ "oldPath": "/chainsaw-man/ch-1", "newPath": "/chainsaw-man/chapter-001" }

Upload files

POST /api/upload?path=/chainsaw-man/chapter-001
X-Api-Token: your-token
Content-Type: multipart/form-data

files: [file1.webp, file2.webp, ...]

Storage stats

GET /api/stats
{ "total": 64000000000, "used": 12000000000, "available": 52000000000 }

πŸ–₯ Frontend Integration

const CDN   = 'https://cdn.yourdomain.com';
const TOKEN = 'your-api-token';

// Fetch list of series
const { items } = await fetch(`${CDN}/api/list?path=/&token=${TOKEN}`).then(r => r.json());

// Fetch chapters in a series
const chapters = await fetch(`${CDN}/api/list?path=/chainsaw-man&token=${TOKEN}`).then(r => r.json());

// Fetch pages in a chapter
const pages = await fetch(`${CDN}/api/list?path=/chainsaw-man/chapter-001&token=${TOKEN}`).then(r => r.json());

// Load image directly (no token needed for /files)
const img = new Image();
img.src = `${CDN}/files/chainsaw-man/chapter-001/001.webp`;

⚑ WEBP Performance Tips

  • Name pages numerically: 001.webp, 002.webp for correct sort order
  • Add cover.webp to each series folder β€” the reader shows it as the thumbnail
  • Convert to WEBP: cwebp -q 80 input.jpg -o output.webp (install: sudo apt install webp)
  • Batch convert: for f in *.jpg; do cwebp -q 80 "$f" -o "${f%.jpg}.webp"; done
  • Cloudflare automatically serves compressed, cached responses from edge nodes

πŸ” Security Notes

  • Change API_TOKEN and PANEL_PASS from defaults before going public
  • The /files endpoint is public (no auth) β€” designed for direct CDN access
  • The /api/* and /panel routes require auth
  • Panel password is only used to issue the API token (stored in sessionStorage)
  • Consider adding Cloudflare Access (zero-trust) to /panel for extra protection

πŸ›  Common Commands

pm2 status                  # check if running
pm2 logs mangacdn           # view logs
pm2 restart mangacdn        # restart server
pm2 stop mangacdn           # stop

# Check Cloudflare tunnel
sudo systemctl status cloudflared
sudo journalctl -u cloudflared -f

# Check USB mount
df -h /mnt/usb
lsblk

πŸ—‚ Recommended USB Drive Format

Format your USB drive as ext4 for best Linux performance:

# ⚠ This erases all data on /dev/sda
sudo mkfs.ext4 -L "mangacdn" /dev/sda1
sudo mkdir -p /mnt/usb/manga

Or exFAT if you need to also read it on Windows/Mac:

sudo apt install exfatprogs
sudo mkfs.exfat -n "mangacdn" /dev/sda1

About

Official AniMangy CDN System.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors