A lightweight CDN server with a simple frontend & API.
https://cdn.ziemlich-schnell.de
docker run --name qcdn -p 3000:3000 \
-e NODE_ENV=production \
-e SECURITY=enabled \
-e API_KEYS=none \
-e PASSWORDS=CHANGEME \
-e HEAD_TAGS='<link rel="stylesheet" href="https://cdn.example.com/styles.css">,<script src="https://cdn.example.com/script.js"></script>' \
-e SESSION_SECRET=your-secret-key \
-e USE_HTTPS=true \
-e DOMAIN=localhost \
-e PORT=3000 \
-v ./data:/usr/src/app/data --restart unless-stopped \
ghcr.io/arthur2500/qcdn:latest
or
mkdir qCDN &&
cd qCDN &&
wget https://raw.githubusercontent.com/Arthur2500/qCDN/main/docker-compose.yml &&
docker-compose up -d
git clone https://github.com/Arthur2500/qCDN.git &&
docker-compose -f docker-compose.local.yml up -d --build
Node.js >= 16
ffmpeg
git clone https://github.com/Arthur2500/qCDN.git
npm install
SECURITY=enabled \
PASSWORDS=your-passwords-here \
API_KEYS=your-api-key-here \
HEAD_TAGS='<link rel="stylesheet" href="https://cdn.example.com/styles.css">,<script src="https://cdn.example.com/script.js"></script>' \
PRIVACY_LINK=https://example.com/privacy \
TERMS_LINK=https://example.com/terms \
IMPRINT_LINK=https://example.com/imprint \
SESSION_SECRET=your-secret-key \
USE_HTTPS=true \
DOMAIN=your-domain-here \
PORT=3000 \
node server.js
docker-compose.yml
Environment Settings:
SECURITY: [enabled/disabled]
: Enables/disables security features such as rate limiting and Helmet protectionPASSWORDS: [$PASSWORDS]
: Comma-separated passwords to secure frontendAPI_KEYS: [none/$CUSTOM_KEYS]
: Comma-separated API tokens (if set to "none", API is disabled)HEAD_TAGS
: HTML elements to be included in<head>
PRIVACY_LINK
: Privacy policy linkTERMS_LINK
: Terms of service linkIMPRINT_LINK
: Imprint linkSESSION_SECRET
: Secret key for session managementUSE_HTTPS
: Iftrue
, uses HTTPS protocolDOMAIN
: Server domain namePORT
: Port if run locally
Allows authenticated users to upload files via API and receive a URL for accessing them.
x-api-token
: API authentication token.
file
: File to upload (multipart/form-data).
- Success:
{
"success": true,
"url": "https://example.com/<hash>/<originalName>"
}
- Failure:
{
"success": false,
"message": "Error message"
}
curl -X POST http://localhost:3000/api/upload \
-H "x-api-token: YOUR_API_TOKEN" \
-F "file=@/path/to/your/file.txt"
import requests
url = "http://localhost:3000/api/upload"
headers = {"x-api-token": "YOUR_API_TOKEN"}
files = {"file": open("/path/to/your/file.txt", "rb")}
response = requests.post(url, headers=headers, files=files)
if response.status_code == 200:
data = response.json()
if data.get("success"):
print("File uploaded successfully:", data["url"])
else:
print("Error:", data)
else:
print("Error:", response.text)
Allows authenticated users to delete an uploaded file by hash.
x-api-token
: API authentication token.
- Success:
{
"success": true
}
- Failure:
{
"success": false,
"message": "Error message"
}
curl -X DELETE http://localhost:3000/api/delete/<hash> \
-H "x-api-token: YOUR_API_TOKEN"
import requests
url = "http://localhost:3000/api/delete/<hash>"
headers = {"x-api-token": "YOUR_API_TOKEN"}
response = requests.delete(url, headers=headers)
if response.status_code == 200:
data = response.json()
if data.get("success"):
print("File deleted successfully")
else:
print("Error:", data)
else:
print("Error:", response.text)